Fixed a small issue with RFC 5987 headers arriving as unicode in parser
Also added API docs regarding header encoding, incl support for RFC 5987 for filename fields in Content-Disposition headers in multipart/form-data parts, incl. an example of an upload request with a utf-8 encoded filename.
This commit is contained in:
parent
13728c231c
commit
2b22d26eac
4 changed files with 65 additions and 16 deletions
|
|
@ -161,18 +161,10 @@ Upload file
|
|||
Content-Disposition: form-data; name="file"; filename="whistle_v2.gcode"
|
||||
Content-Type: application/octet-stream
|
||||
|
||||
;Generated with Cura_SteamEngine 13.11.2
|
||||
M109 T0 S220.000000
|
||||
T0
|
||||
;Sliced at: Wed 11-12-2013 16:53:12
|
||||
;Basic settings: Layer height: 0.2 Walls: 0.8 Fill: 20
|
||||
;Print time: #P_TIME#
|
||||
;Filament used: #F_AMNT#m #F_WGHT#g
|
||||
;Filament cost: #F_COST#
|
||||
;M190 S70 ;Uncomment to add your own bed temperature line
|
||||
;M109 S220 ;Uncomment to add your own temperature line
|
||||
G21 ;metric values
|
||||
G90 ;absolute positioning
|
||||
G21
|
||||
G90
|
||||
...
|
||||
------WebKitFormBoundaryDeC2E3iWbTv1PwMC
|
||||
Content-Disposition: form-data; name="select"
|
||||
|
|
@ -188,7 +180,7 @@ Upload file
|
|||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
Location: http://example.com/api/files/sdcard/whistle_.gcode
|
||||
Location: http://example.com/api/files/sdcard/whistle_v2.gcode
|
||||
|
||||
{
|
||||
"files": {
|
||||
|
|
@ -208,6 +200,46 @@ Upload file
|
|||
}
|
||||
}
|
||||
},
|
||||
"done": false
|
||||
}
|
||||
|
||||
**Example with UTF-8 encoded filename following RFC 5987**
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/files/local HTTP/1.1
|
||||
Host: example.com
|
||||
X-Api-Key: abcdef...
|
||||
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryDeC2E3iWbTv1PwMC
|
||||
|
||||
------WebKitFormBoundaryDeC2E3iWbTv1PwMC
|
||||
Content-Disposition: form-data; name="file"; filename*=utf-8''20mm-%C3%BCml%C3%A4ut-b%C3%B6x.gcode
|
||||
Content-Type: application/octet-stream
|
||||
|
||||
M109 T0 S220.000000
|
||||
T0
|
||||
G21
|
||||
G90
|
||||
...
|
||||
------WebKitFormBoundaryDeC2E3iWbTv1PwMC--
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
Location: http://example.com/api/files/local/20mm-umlaut-box.gcode
|
||||
|
||||
{
|
||||
"files": {
|
||||
"local": {
|
||||
"name": "20mm-umlaut-box",
|
||||
"origin": "local",
|
||||
"refs": {
|
||||
"resource": "http://example.com/api/files/local/whistle_v2.gcode",
|
||||
"download": "http://example.com/downloads/files/local/whistle_v2.gcode"
|
||||
}
|
||||
}
|
||||
},
|
||||
"done": true
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,19 @@ Encoding
|
|||
|
||||
OctoPrint uses UTF-8 as charset.
|
||||
|
||||
.. _sec-api-cross-origin:
|
||||
That also includes headers in ``multipart/form-data`` requests, in order to allow the full UTF-8 range of characters
|
||||
for uploaded filenames. If a ``multipart/form-data`` sub header cannot be decoded as UTF-8, OctoPrint will also attempt
|
||||
to decode it as ISO-8859-1.
|
||||
|
||||
Additionally, OctoPrint supports replacing the ``filename`` field in the ``Content-Disposition`` header of a
|
||||
multipart field with a ``filename*`` field following `RFC 5987, Section 3.2 <https://tools.ietf.org/html/rfc5987#section-3.2>`_,
|
||||
which allows defining the charset used for encoding the filename. If both ``filename`` and ``filename*`` fields are
|
||||
present, following the recommendation of the RFC ``filename*`` will be used.
|
||||
|
||||
For an example on how to send a request utilizing RFC 5987 for the ``filename*`` attribute, see the second example
|
||||
in :ref:`Upload file <sec-api-fileops-uploadfile>`.
|
||||
|
||||
.. _sec-api-general-crossorigin:
|
||||
|
||||
Cross-origin requests
|
||||
=====================
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ class UploadStorageFallbackHandler(tornado.web.RequestHandler):
|
|||
filename = _extended_header_value(filename)
|
||||
except:
|
||||
# parse error, this is not RFC 5987 compliant after all
|
||||
self._logger.warn("extended filename* value {!r} is not RFC 5987 compliant")
|
||||
self._logger.warn("extended filename* value {!r} is not RFC 5987 compliant".format(filename))
|
||||
self.send_error(400)
|
||||
return
|
||||
else:
|
||||
|
|
@ -494,11 +494,11 @@ def _extended_header_value(value):
|
|||
# RFC 5987 section 3.2
|
||||
from urllib import unquote
|
||||
encoding, _, value = value.split("'", 2)
|
||||
return unquote(value).decode(encoding)
|
||||
return unquote(octoprint.util.to_str(value, encoding="iso-8859-1")).decode(encoding)
|
||||
|
||||
else:
|
||||
# no encoding provided, strip potentially present quotes and call it a day
|
||||
return _strip_value_quotes(value)
|
||||
return octoprint.util.to_unicode(_strip_value_quotes(value), encoding="utf-8")
|
||||
|
||||
|
||||
class WsgiInputContainer(object):
|
||||
|
|
|
|||
|
|
@ -76,9 +76,14 @@ class StripValueQuotesTest(unittest.TestCase):
|
|||
class ExtendedHeaderValueTest(unittest.TestCase):
|
||||
|
||||
@data(
|
||||
("", u""),
|
||||
(u"", u""),
|
||||
(None, None),
|
||||
(u'"quoted-string"', u"quoted-string"),
|
||||
(u'"qüöted-string"', u"qüöted-string"),
|
||||
(u"iso-8859-1'en'%A3%20rates", u"£ rates"),
|
||||
(u"UTF-8''%c2%a3%20and%20%e2%82%ac%20rates", u"£ and € rates"),
|
||||
('"quoted-string"', u"quoted-string"),
|
||||
('"qüöted-string"', u"qüöted-string"),
|
||||
("iso-8859-1'en'%A3%20rates", u"£ rates"),
|
||||
("UTF-8''%c2%a3%20and%20%e2%82%ac%20rates", u"£ and € rates")
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue