Closed isosphere closed 1 year ago
I'm not familiar with this codebase; here's my attempt at troubleshooting the above. I'll edit this post as I proceed.
The "malformed response" seems to be defined here: https://github.com/devashishdxt/tonic-web-wasm-client/blob/ca7f5c9d1152000d862810accb2df9c60ba2d963/src/error.rs#L34
This is referenced twice: https://github.com/devashishdxt/tonic-web-wasm-client/blob/ca7f5c9d1152000d862810accb2df9c60ba2d963/src/response_body.rs#L303-L306
I changed the first usage to return a new error that I defined called PartyMode
- this would at least let me identify which is responsible for the MalformedResponse
error. Responses then print Error: Unknown, "party mode"
in the console, so we know that this is responsible:
The only way I can think of to validate this is by using a different client that I trust, so I'll use Kreya.
[22:17:52.114] KreyaCallStart
disableServerCertificateValidation: false
mode: Grpc
[22:17:52.116] CallStart
method: /auth.AuthenticationService/GetAuthenticationToken
[22:17:52.116] RequestStart
host: 127.0.0.1
method: POST
pathAndQuery: /auth.AuthenticationService/GetAuthenticationToken
port: 5000
scheme: http
[22:17:52.120] ConnectionEstablished
versionMajor: 2
versionMinor: 0
[22:17:52.184] MessageSent
[22:17:52.206] RequestStop 90ms
[22:17:52.209] CallFailed
statusCode: 5 <--- "NotFound", which is what I'm returning
[22:17:52.209] CallStop 93ms
[22:17:52.211] KreyaCallStop
Seems fine.
The following is the HTTP response from the GRPC server.
HTTP/1.1 200 OK
content-type: application/grpc-web+proto
grpc-status: 5
grpc-message: Not%20found
access-control-allow-origin: http://127.0.0.1:8080
vary: origin
vary: access-control-request-method
vary: access-control-request-headers
content-length: 0 <-- maybe this is the issue?
date: Fri, 10 Mar 2023 02:31:11 GMT
485454502f312e3120323030204f4b0d0a636f6e74656e742d747970653a206170706c69636174696f6e2f677270632d7765622b70726f746f0d0a677270632d7374617475733a20350d0a677270632d6d6573736167653a204e6f74253230666f756e640d0a6163636573732d636f6e74726f6c2d616c6c6f772d6f726967696e3a20687474703a2f2f3132372e302e302e313a383038300d0a766172793a206f726967696e0d0a766172793a206163636573732d636f6e74726f6c2d726571756573742d6d6574686f640d0a766172793a206163636573732d636f6e74726f6c2d726571756573742d686561646572730d0a636f6e74656e742d6c656e6774683a20300d0a646174653a204672692c203130204d617220323032332030323a33313a313120474d540d0a0d0a
Hi. Thanks for creating this issue.
I've created a PR to test error responses from server and the test seems to pass: #32.
Can you share your server code so that I have more context on what you're trying to do?
Here's a very abbreviated pseudo-code snippet. This is using Tonic 0.8
with tonic_web::GrpcWebLayer 0.5.0
:
async fn main() -> Result<...> {
let authentication_service_state = MyAuthTokenServer{some_parameter = true};
let cors = CorsLayer::new()
.allow_methods([Method::GET, Method::POST, Method::OPTIONS])
.allow_headers(Any)
.allow_origin(format!("http://{}:8080", matches.grpc_address).parse::<HeaderValue>().unwrap());
Server::builder()
.accept_http1(true) // required for tonic-web; as of this writing it presents as HTTP/1.1
.layer(cors)
.layer(CookieManagerLayer::new())
.layer(GrpcWebLayer::new())
.add_service(AuthenticationServiceServer::new(authentication_service_state))
.serve(addr)
.await?;
Ok(())
}
stuct MyAuthTokenServer{some_parameter: type}
#[tonic::async_trait]
impl AuthenticationService for MyAuthTokenServer {
async fn get_authentication_token(&self, request: Request<AuthTokenRequest>) -> Result<Response<AuthTokenReponse>, Status> {
let user_instance = match get_customer_by_email(&mut connection, &request_packet.username) {
Ok(u) => u,
Err(e) => {
warn!("Failed to find user with email {:?}: {:?}", &request_packet.username, e);
return Err(Status::not_found("Not found"));
}
};
}
}
This PR: #32 has almost the same test case which passes. I'm not sure if anything can be done on this crate to fix your issue.
Maybe you can review your cors
configuration. Here's a sample: https://github.com/devashishdxt/tonic-web-wasm-client/blob/ca7f5c9d1152000d862810accb2df9c60ba2d963/test-suite/simple/server/src/main.rs#L116.
Closing this issue for now. If you still see the error, please create PR with a test case that fails and feel free to reopen.
I copied and pasted your CorsLayer
invocation and it resolved the issue, good call.
After some digging I discovered the exact problem was that my lack of a .expose_headers
invocation implicitly did not include "grpc-status". How can my code report the status code if I have forbidden the header that provides it? Then presumably the tonic-web-wasm-client
code goes looking for that code, doesn't find it, and so returns "malformed response", which makes sense.
Version Housekeeping
rustc
1.67.1tonic-web-wasm-client
ca7f5c9d1152000d862810accb2df9c60ba2d963Backend:
tonic
0.8tonic-web
0.5Report
I think that there might be an issue with error response handling.
I'm implementing an authentication system. If the user inputs a user that doesn't exist, my backend responds with a tonic::Status of Unauthenticated. This has a grpc-status code of 16.
In testing the client-side portion of this, I'm doing the following:
If I enter valid credentials authentication proceeds within the
Ok(...)
block as expected.If I enter invalid credentials, my code does not have appropriate information to provide a good error message to the user. The error
e
always has the following debug print value:However if I inspect the response in the Firefox development console, I see an appropriate grpc-status header code of 16 with an appropriately matching grpc-message header.
I have also tried responding with
NotFound
which is code 5, but that doesn't change what is exposed ase
.