diff --git a/brother_ql_web/web.py b/brother_ql_web/web.py index ebf9428..cbad5a8 100644 --- a/brother_ql_web/web.py +++ b/brother_ql_web/web.py @@ -53,7 +53,18 @@ def labeldesigner() -> dict[str, Any]: def get_label_parameters(request: bottle.BaseRequest) -> LabelParameters: - d = request.params.decode() # UTF-8 decoded form data + # As we have strings, *bottle* would try to generate Latin-1 bytes from it + # before decoding it back to UTF-8. This seems to break some umlauts, thus + # resulting in UnicodeEncodeErrors being raised when going back to UTF-8. + # For now, we just state that we always receive clean UTF-8 data and thus + # the recode operations just can be omitted. All external API users are + # responsible for passing clean data. + # References: + # * https://github.com/bottlepy/bottle/blob/99341ff3791b2e7e705d7373e71937e9018eb081/bottle.py#L2197-L2203 # noqa: E501 + # * https://github.com/FriedrichFroebel/brother_ql_web/issues/9 + parameters = request.params + parameters.recode_unicode = False + d = parameters.decode() # UTF-8 decoded form data font_family = d.get("font_family").rpartition("(")[0].strip() font_style = d.get("font_family").rpartition("(")[2].rstrip(")") diff --git a/tests/test_web.py b/tests/test_web.py index 43f022e..7f3ab0d 100644 --- a/tests/test_web.py +++ b/tests/test_web.py @@ -203,6 +203,35 @@ def test_plain_bytes(self) -> None: with as_file(reference) as path: self.assertEqual(path.read_bytes(), response.content) + def test_special_characters(self) -> None: + self.run_server() + # Minimal copy from the Firefox developer tools. + headers = { + "Content-Type": "multipart/form-data; boundary=---------------------------381934621323024354152349680295" # noqa: E501 + } + body = """ +-----------------------------381934621323024354152349680295 +Content-Disposition: form-data; name="text" + +abcdefgö+ëŠ +-----------------------------381934621323024354152349680295 +Content-Disposition: form-data; name="font_family" + +Roboto (Medium) +-----------------------------381934621323024354152349680295 +Content-Disposition: form-data; name="label_size" + +62 +-----------------------------381934621323024354152349680295-- +""".encode() + response = requests.post( + "http://localhost:8013/api/preview/text?return_format=png", + data=body, + headers=headers, + ) + self.assertEqual(200, response.status_code) + self.assertLessEqual(14000, len(response.content)) # 14061 bytes + class PrintTextTestCase(TestCase): def test_error(self) -> None: