Skip to content

Ignore content type parameters when matching it#235

Open
anuraaga wants to merge 5 commits intoconnectrpc:mainfrom
anuraaga:json-charset-tests
Open

Ignore content type parameters when matching it#235
anuraaga wants to merge 5 commits intoconnectrpc:mainfrom
anuraaga:json-charset-tests

Conversation

@anuraaga
Copy link
Copy Markdown
Collaborator

@anuraaga anuraaga commented Apr 29, 2026

Fixes #234

I had intended to have similar handling of content type as Go but realized they treat it quite differently on server vs client side and missed that. This takes the simplest approach of just splitting on ; and ignoring parameters - I don't think anyone will miss the use case of being able to match on them with custom codecs. Note that custom codecs and header matching isn't defined in the protocol spec and i.e. connect-es don't support custom codecs FWICT. We may not have either but it is important for supporting different protobuf implementations.

For reference, Go, which does canonicalization in a way that technically custom codecs can match on parameters. Digging in, it looks like their somewhat complicated loop is to avoid two passes for both finding a ; and uppercase (2 passes goes from 9ns to 11ns on my machine). As we can't write such fast loops in Python, I take the typical approach of always calling .strip().lower().

https://github.com/connectrpc/connect-go/blob/a5a6c30f3776b06ae05a66ab3bdd2d60c46db6db/protocol.go#L361

Signed-off-by: Anuraag Agrawal <anuraaga@gmail.com>
Signed-off-by: Anuraag Agrawal <anuraaga@gmail.com>
@anuraaga anuraaga changed the title Add tests for JSON with charset Ignore content type parameters when matching it Apr 30, 2026
Signed-off-by: Anuraag Agrawal <anuraaga@gmail.com>
codec_name = protocol.codec_name_from_content_type(
headers.get("content-type", ""), stream=not is_unary
)
codec = self._codecs.get(codec_name.lower())
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also noticed a couple of spots of random lowercasing and consolidated them, with some cleanup to WSGI

Signed-off-by: Anuraag Agrawal <anuraaga@gmail.com>
Signed-off-by: Anuraag Agrawal <anuraaga@gmail.com>
Copy link
Copy Markdown
Member

@stefanvanburen stefanvanburen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, assuming we don't need to worry about the grpc case (e.g. application/grpc+json; charset=utf-8)? I don't see that mentioned in https://connectrpc.com/docs/multi-protocol/ / https://chromium.googlesource.com/external/github.com/grpc/grpc/+/HEAD/doc/PROTOCOL-HTTP2.md but perhaps in practice it ... could happen? 😄

def validate_response(
self, request_codec_name: str, status_code: int, response_content_type: str
) -> None:
response_content_type = _normalize_content_type(response_content_type)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit that we're double-normalizing the content type between here and codec_name_from_content_type below, but no real suggestions on a refactor — probably fine to leave.

Comment thread test/test_http.py


@pytest.mark.parametrize("header", _charset_content_type_cases)
def test_json_charset_content_type(header: str) -> None:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would it also be good to flex streaming in these tests? I see we have validate_stream_response; presumably a well-behaved connect server wouldn't have an issue, though...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Server returns 415 for Content-Types with parameters (e.g., application/json; charset=utf-8)

2 participants