-
Notifications
You must be signed in to change notification settings - Fork 108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Client should verify response content-type #679
Conversation
@@ -511,6 +511,21 @@ func (cc *connectUnaryClientConn) validateResponse(response *http.Response) *Err | |||
} | |||
cc.responseTrailer[strings.TrimPrefix(k, connectUnaryTrailerPrefix)] = v | |||
} | |||
err := connectValidateUnaryResponseContentType( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be moved into the validate response function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is. Do you mean inlined? I had made it a separate function to make it easier to test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry misread, thought the method on the duplexcall was due to it not being part of this function, but thats for the request params.
response.Status, | ||
getHeaderCanonical(response.Header, headerContentType), | ||
) | ||
if err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we scope err
to the if
block? It's visually a little ugly, but the functions in this portion of the code are long enough that I'd love to minimize scope where possible. Same below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had not done so just because I find it a bit hard to read when the if
keyword is far from the actual condition. But if that's accepted style, and even preferred in this case, I'll change it.
This also formats the grpc version of the check so it is consistent with the other two. Addresses comment in prior PR: #679 (comment)
The query-frontend accidentally leaked content-type and content-encoding information from the underlying connectgrpc implementation, which is used to schedule queries on to the workers (queriers). This will filter those out, so they won't be passed on through the frontend. This could be observed by errors like this: ``` $ profilecli query series level=info msg="query series from querier" url=http://localhost:8080 from=2024-06-18T15:46:19.932471+01:00 to=2024-06-18T16:46:19.932472+01:00 labelNames=[] error: failed to query: unknown: invalid content-type: "application/grpc,application/proto"; expecting "application/grpc" exit status 1 ``` Which themselves were produced only because envoy (involved on our GC ingress), converted headers from this: ``` content-type: application/grpc content-type: application/proto ``` to ``` content-type: application/grpc,application/proto ``` This then triggered a validation recently added to connect-go: connectrpc/connect-go#679
The query-frontend accidentally leaked content-type and content-encoding information from the underlying connectgrpc implementation, which is used to schedule queries on to the workers (queriers). This will filter those out, so they won't be passed on through the frontend. This could be observed by errors like this: ``` $ profilecli query series level=info msg="query series from querier" url=http://localhost:8080 from=2024-06-18T15:46:19.932471+01:00 to=2024-06-18T16:46:19.932472+01:00 labelNames=[] error: failed to query: unknown: invalid content-type: "application/grpc,application/proto"; expecting "application/grpc" exit status 1 ``` Which themselves were produced only because envoy (involved on our GC ingress), converted headers from this: ``` content-type: application/grpc content-type: application/proto ``` to ``` content-type: application/grpc,application/proto ``` This then triggered a validation recently added to connect-go: connectrpc/connect-go#679
The query-frontend accidentally leaked content-type and content-encoding information from the underlying connectgrpc implementation, which is used to schedule queries on to the workers (queriers). This will filter those out, so they won't be passed on through the frontend. This could be observed by errors like this: ``` $ profilecli query series level=info msg="query series from querier" url=http://localhost:8080 from=2024-06-18T15:46:19.932471+01:00 to=2024-06-18T16:46:19.932472+01:00 labelNames=[] error: failed to query: unknown: invalid content-type: "application/grpc,application/proto"; expecting "application/grpc" exit status 1 ``` Which themselves were produced only because envoy (involved on our GC ingress), converted headers from this: ``` content-type: application/grpc content-type: application/proto ``` to ``` content-type: application/grpc,application/proto ``` This then triggered a validation recently added to connect-go: connectrpc/connect-go#679
@smaye81 found some more bugs with new conformance test cases.
The client is not verifying that the response has the correct content-type. So this change adds that verification.
Some tests, that had simple handlers that weren't setting a valid content-type, had to be updated. Sorry for the large diff stats, but it's not as bad as it looks. This PR adds three new table-driven tests that account for 75% of the lines of code.