py3: Be able to parse non-RFC-compliant request lines · openstack/swift@93b49c5 (original) (raw)

`@@ -35,7 +35,8 @@

`

35

35

``

36

36

`from swift.common import utils, constraints

`

37

37

`from swift.common.storage_policy import BindPortsCache

`

38

``

`-

from swift.common.swob import Request, wsgi_unquote

`

``

38

`+

from swift.common.swob import Request, wsgi_quote, wsgi_unquote, \

`

``

39

`+

wsgi_quote_plus, wsgi_unquote_plus, wsgi_to_bytes, bytes_to_wsgi

`

39

40

`from swift.common.utils import capture_stdio, disable_fallocate, \

`

40

41

`drop_privileges, get_logger, NullLogger, config_true_value, \

`

41

42

`validate_configuration, get_hub, config_auto_int_value, \

`

`@@ -433,6 +434,36 @@ def get_default_type(self):

`

433

434

`'''If the client didn't provide a content type, leave it blank.'''

`

434

435

`return ''

`

435

436

``

``

437

`+

def parse_request(self):

`

``

438

`+

if not six.PY2:

`

``

439

`+

request lines should be ascii per the RFC, but historically

`

``

440

`+

we've allowed (and even have func tests that use) arbitrary

`

``

441

`+

bytes. This breaks on py3 (see https://bugs.python.org/issue33973

`

``

442

`+

) but the work-around is simple: munge the request line to be

`

``

443

`+

properly quoted. py2 will do the right thing without this, but it

`

``

444

`+

doesn't hurt to re-write the request line like this and it

`

``

445

`+

simplifies testing.

`

``

446

`+

if self.raw_requestline.count(b' ') >= 2:

`

``

447

`+

parts = self.raw_requestline.split(b' ', 2)

`

``

448

`+

path, q, query = parts[1].partition(b'?')

`

``

449

`+

unquote first, so we don't over-quote something

`

``

450

`+

that was correctly quoted

`

``

451

`+

path = wsgi_to_bytes(wsgi_quote(wsgi_unquote(

`

``

452

`+

bytes_to_wsgi(path))))

`

``

453

`+

query = b'&'.join(

`

``

454

`+

sep.join([

`

``

455

`+

wsgi_to_bytes(wsgi_quote_plus(wsgi_unquote_plus(

`

``

456

`+

bytes_to_wsgi(key)))),

`

``

457

`+

wsgi_to_bytes(wsgi_quote_plus(wsgi_unquote_plus(

`

``

458

`+

bytes_to_wsgi(val))))

`

``

459

`+

])

`

``

460

`+

for part in query.split(b'&')

`

``

461

`+

for key, sep, val in (part.partition(b'='), ))

`

``

462

`+

parts[1] = path + q + query

`

``

463

`+

self.raw_requestline = b' '.join(parts)

`

``

464

`+

else, mangled protocol, most likely; let base class deal with it

`

``

465

`+

return wsgi.HttpProtocol.parse_request(self)

`

``

466

+

436

467

``

437

468

`class SwiftHttpProxiedProtocol(SwiftHttpProtocol):

`

438

469

`"""

`