~nhanb/mcross

c55e6f4f6e9fde5335c5263f9462ef4db654b36a — Bùi Thành Nhân 5 months ago 32d55a2 0.5.16
fix empty body/charset case; use regex
2 files changed, 31 insertions(+), 39 deletions(-)

M src/mcross/gui/controller.py
M src/mcross/transport.py
M src/mcross/gui/controller.py => src/mcross/gui/controller.py +18 -22
@@ 161,21 161,23 @@ class Controller:
        )

        # Support whatever encoding that python supports
        try:
            body_string = resp.body.decode(resp.charset)
        except LookupError:
            await self.put_gui_op(
                self.model.update_content,
                "\n".join(
                    [
                        "Error:",
                        f"{resp.status} {resp.meta}",
                        f"Unsupported charset: {resp.charset}",
                    ]
                ),
                "text/plain",
            )
            return resp
        body_string = ""
        if resp.body and resp.charset:
            try:
                body_string = resp.body.decode(resp.charset)
            except LookupError:
                await self.put_gui_op(
                    self.model.update_content,
                    "\n".join(
                        [
                            "Error:",
                            f"{resp.status} {resp.meta}",
                            f"Unsupported charset: {resp.charset}",
                        ]
                    ),
                    "text/plain",
                )
                return resp

        # Sucessfully decoded body string!
        if resp.status.startswith("2"):


@@ 185,13 187,7 @@ class Controller:
        else:
            await self.put_gui_op(
                self.model.update_content,
                "\n".join(
                    [
                        "Error:",
                        f"{resp.status} {resp.meta}",
                        body_string if resp.body else "",
                    ]
                ),
                f"Error:\n{resp.status} {resp.meta}\n{body_string}",
                "text/plain",
            )
        return resp

M src/mcross/transport.py => src/mcross/transport.py +13 -17
@@ 31,10 31,19 @@ def _parse_resp_header(header, pattern=re.compile(r"^(\d\d)\s+(.{,1024})\r\n$"))
    match = pattern.match(header)
    assert match is not None, f"Malformed response header: {header}"
    status = match.group(1)
    meta = match.group(2)
    meta = match.group(2).strip()
    return status, meta


def _parse_meta(meta, pattern=re.compile(r"^(\S+)\s*;\s*charset=(\S+)$")):
    match = pattern.match(meta)
    if not match:
        return None, None
    mime_type = match.group(1)
    charset = match.group(2)
    return mime_type, charset


# TODO: GeminiUrl's context-aware parse() method probably doesn't belong
# in a "transport" module.



@@ 138,22 147,9 @@ async def raw_get(url: GeminiUrl):

        status, meta = _parse_resp_header(header.decode())

        # If success, extract mime type & charset from meta
        mime_type = None
        charset = None
        if status.startswith("2"):
            if not meta:
                mime_type = "text/gemini"
                charset = "utf-8"
            else:
                meta_parts = meta.split(";")
                mime_type = meta_parts[0].strip() or "text/gemini"
                charset = ""
                if len(meta_parts) == 2:
                    charset_part = meta_parts[1].strip()
                    if charset_part.startswith("charset="):
                        charset = charset_part[len("charset=") :]
                charset = charset or "utf-8"
        mime_type, charset = _parse_meta(meta)
        mime_type = mime_type or "text/gemini"
        charset = charset or "utf-8"

        resp = Response(
            status=status, meta=meta, url=url, mime_type=mime_type, charset=charset