devashishdxt / tonic-web-wasm-client

Other
104 stars 28 forks source link

ClientError::HeaderParsingError when Client recieves GRPC Stream Response #11

Closed isosphere closed 2 years ago

isosphere commented 2 years ago

Proto in use:

syntax = "proto3";
package user;

service GetCurrencies {
    rpc GetCurrencyRequest (CurrencyRequest) returns (stream CurrencyStreamItem);
}

message CurrencyRequest {}

message CurrencyStreamItem {
    int64 id = 1;
    string label = 2;
}

This is the value of body for a successful non-stream Response at this line, for a type defined like message Response{}:

b"grpc-status:0\r\n\n"

The value of the parsed header for the above body is [Header { name: "grpc-status", value: "0" }]

Here's a stream Response which triggers ClientError::HeaderParsingError (as would be see by httparse::parse_headers):

b"\x08\x02\x12\x03GBP\0\0\0\0\x07\x08\x03\x12\x03CAD\0\0\0\0\x07\x08\x04\x12\x03CNY\0\0\0\0\x07\x08\x05\x12\x03EUR\0\0\0\0\x07\x08\x06\x12\x03JPY\0\0\0\0\x07\x08\x07\x12\x03NZD\0\0\0\0\x07\x08\x08\x12\x03RUB\0\0\0\0\x07\x08\t\x12\x03USD\0\0\0\0\x07\x08\n\x12\x03AFN\0\0\0\0\x07\x08\x0b\x12\x03ALL\0\0\0\0\x07\x08\x0c\x12\x03DZD\0\0\0\0\x07\x08\r\x12\x03AOA\0\0\0\0\x07\x08\x0e\x12\x03ARS\0\0\0\0\x07\x08\x0f\x12\x03AMD\0\0\0\0\x07\x08\x10\x12\x03AWG\0\0\0\0\x07\x08\x11\x12\x03AZN\0\0\0\0\x07\x08\x12\x12\x03BSD\0\0\0\0\x07\x08\x13\x12\x03BHD\0\0\0\0\x07\x08\x14\x12\x03BDT\0\0\0\0\x07\x08\x15\x12\x03BBD\0\0\0\0\x07\x08\x16\x12\x03BYN\0\0\0\0\x07\x08\x17\x12\x03BZD\0\0\0\0\x07\x08\x18\x12\x03BMD\0\0\0\0\x07\x08\x19\x12\x03BTN\0\0\0\0\x07\x08\x1a\x12\x03BOB\0\0\0\0\x07\x08\x1b\x12\x03BAM\0\0\0\0\x07\x08\x1c\x12\x03BWP\0\0\0\0\x07\x08\x1d\x12\x03BRL\0\0\0\0\x07\x08\x1e\x12\x03BND\0\0\0\0\x07\x08\x1f\x12\x03BGN\0\0\0\0\x07\x08 \x12\x03MMK\0\0\0\0\x07\x08!\x12\x03BIF\0\0\0\0\x07\x08\"\x12\x03KHR\0\0\0\0\x07\x08#\x12\x03CVE\0\0\0\0\x07\x08$\x12\x03KYD\0\0\0\0\x07\x08%\x12\x03XAF\0\0\0\0\x07\x08&\x12\x03XPF\0\0\0\0\x07\x08'\x12\x03CLP\0\0\0\0\x07\x08(\x12\x03COP\0\0\0\0\x07\x08)\x12\x03KMF\0\0\0\0\x07\x08*\x12\x03CDF\0\0\0\0\x07\x08+\x12\x03CRC\0\0\0\0\x07\x08,\x12\x03HRK\0\0\0\0\x07\x08-\x12\x03CUC\0\0\0\0\x07\x08.\x12\x03CUP\0\0\0\0\x07\x08/\x12\x03CZK\0\0\0\0\x07\x080\x12\x03DKK\0\0\0\0\x07\x081\x12\x03DJF\0\0\0\0\x07\x082\x12\x03DOP\0\0\0\0\x07\x083\x12\x03XCD\0\0\0\0\x07\x084\x12\x03EGP\0\0\0\0\x07\x085\x12\x03ERN\0\0\0\0\x07\x086\x12\x03ETB\0\0\0\0\x07\x087\x12\x03FKP\0\0\0\0\x07\x088\x12\x03FJD\0\0\0\0\x07\x089\x12\x03GMD\0\0\0\0\x07\x08:\x12\x03GEL\0\0\0\0\x07\x08;\x12\x03GHS\0\0\0\0\x07\x08<\x12\x03GIP\0\0\0\0\x07\x08=\x12\x03GTQ\0\0\0\0\x07\x08>\x12\x03GNF\0\0\0\0\x07\x08?\x12\x03GYD\0\0\0\0\x07\x08@\x12\x03HTG\0\0\0\0\x07\x08A\x12\x03HNL\0\0\0\0\x07\x08B\x12\x03HKD\0\0\0\0\x07\x08C\x12\x03HUF\0\0\0\0\x07\x08D\x12\x03ISK\0\0\0\0\x07\x08E\x12\x03INR\0\0\0\0\x07\x08F\x12\x03IDR\0\0\0\0\x07\x08G\x12\x03IRR\0\0\0\0\x07\x08H\x12\x03IQD\0\0\0\0\x07\x08I\x12\x03ILS\0\0\0\0\x07\x08J\x12\x03JMD\0\0\0\0\x07\x08K\x12\x03JOD\0\0\0\0\x07\x08L\x12\x03KZT\0\0\0\0\x07\x08M\x12\x03KES\0\0\0\0\x07\x08N\x12\x03KWD\0\0\0\0\x07\x08O\x12\x03KGS\0\0\0\0\x07\x08P\x12\x03LAK\0\0\0\0\x07\x08Q\x12\x03LBP\0\0\0\0\x07\x08R\x12\x03LSL\0\0\0\0\x07\x08S\x12\x03LRD\0\0\0\0\x07\x08T\x12\x03LYD\0\0\0\0\x07\x08U\x12\x03MOP\0\0\0\0\x07\x08V\x12\x03MKD\0\0\0\0\x07\x08W\x12\x03MGA\0\0\0\0\x07\x08X\x12\x03MWK\0\0\0\0\x07\x08Y\x12\x03MYR\0\0\0\0\x07\x08Z\x12\x03MVR\0\0\0\0\x07\x08[\x12\x03MRU\0\0\0\0\x07\x08\\\x12\x03MUR\0\0\0\0\x07\x08]\x12\x03MXN\0\0\0\0\x07\x08^\x12\x03MDL\0\0\0\0\x07\x08_\x12\x03MNT\0\0\0\0\x07\x08`\x12\x03MAD\0\0\0\0\x07\x08a\x12\x03MZN\0\0\0\0\x07\x08b\x12\x03NAD\0\0\0\0\x07\x08c\x12\x03NPR\0\0\0\0\x07\x08d\x12\x03ANG\0\0\0\0\x07\x08e\x12\x03TWD\0\0\0\0\x07\x08f\x12\x03NIO\0\0\0\0\x07\x08g\x12\x03NGN\0\0\0\0\x07\x08h\x12\x03KPW\0\0\0\0\x07\x08i\x12\x03NOK\0\0\0\0\x07\x08j\x12\x03OMR\0\0\0\0\x07\x08k\x12\x03PKR\0\0\0\0\x07\x08l\x12\x03PAB\0\0\0\0\x07\x08m\x12\x03PGK\0\0\0\0\x07\x08n\x12\x03PYG\0\0\0\0\x07\x08o\x12\x03PEN\0\0\0\0\x07\x08p\x12\x03PHP\0\0\0\0\x07\x08q\x12\x03PLN\0\0\0\0\x07\x08r\x12\x03QAR\0\0\0\0\x07\x08s\x12\x03RON\0\0\0\0\x07\x08t\x12\x03RWF\0\0\0\0\x07\x08u\x12\x03SHP\0\0\0\0\x07\x08v\x12\x03WST\0\0\0\0\x07\x08w\x12\x03STN\0\0\0\0\x07\x08x\x12\x03SAR\0\0\0\0\x07\x08y\x12\x03RSD\0\0\0\0\x07\x08z\x12\x03SCR\0\0\0\0\x07\x08{\x12\x03SLL\0\0\0\0\x07\x08|\x12\x03SGD\0\0\0\0\x07\x08}\x12\x03SBD\0\0\0\0\x07\x08~\x12\x03SOS\0\0\0\0\x07\x08\x7f\x12\x03ZAR\0\0\0\0\x08\x08\x80\x01\x12\x03KRW\0\0\0\0\x08\x08\x81\x01\x12\x03SSP\0\0\0\0\x08\x08\x82\x01\x12\x03LKR\0\0\0\0\x08\x08\x83\x01\x12\x03SDG\0\0\0\0\x08\x08\x84\x01\x12\x03SRD\0\0\0\0\x08\x08\x85\x01\x12\x03SZL\0\0\0\0\x08\x08\x86\x01\x12\x03SEK\0\0\0\0\x08\x08\x87\x01\x12\x03CHF\0\0\0\0\x08\x08\x88\x01\x12\x03SYP\0\0\0\0\x08\x08\x89\x01\x12\x03TJS\0\0\0\0\x08\x08\x8a\x01\x12\x03TZS\0\0\0\0\x08\x08\x8b\x01\x12\x03THB\0\0\0\0\x08\x08\x8c\x01\x12\x03TOP\0\0\0\0\x08\x08\x8d\x01\x12\x03TTD\0\0\0\0\x08\x08\x8e\x01\x12\x03TND\0\0\0\0\x08\x08\x8f\x01\x12\x03TRY\0\0\0\0\x08\x08\x90\x01\x12\x03TMT\0\0\0\0\x08\x08\x91\x01\x12\x03UGX\0\0\0\0\x08\x08\x92\x01\x12\x03UAH\0\0\0\0\x08\x08\x93\x01\x12\x03AED\0\0\0\0\x08\x08\x94\x01\x12\x03UYU\0\0\0\0\x08\x08\x95\x01\x12\x03UZS\0\0\0\0\x08\x08\x96\x01\x12\x03VUV\0\0\0\0\x08\x08\x97\x01\x12\x03VED\0\0\0\0\x08\x08\x98\x01\x12\x03VES\0\0\0\0\x08\x08\x99\x01\x12\x03VND\0\0\0\0\x08\x08\x9a\x01\x12\x03XOF\0\0\0\0\x08\x08\x9b\x01\x12\x03YER\0\0\0\0\x08\x08\x9c\x01\x12\x03ZMW\x80\0\0\0\x0fgrpc-status:0\r\n\n"

which is a bunch of int64's followed by some string labels, as it should be.

I've made a separate client using only tonic and it parses the above without complaint. The GUI GRPC client "Kreya" is also happy with the response body above.

isosphere commented 2 years ago

Same Code Works with grpc-web-client

If I swap out tonic-web-wasm-client for grpc-web-client @ https://github.com/titanous/grpc-web-client.git the same code works without any other modifications, but it does require adjusting all tonic related dependencies as it's just a prototype that is not actively maintained and was last updated about a year ago.

Regardless, grpc-web-client isn't a huge project and we can probably ~steal~ learn the solution from there. It looks like it's leveraging tonic::Request to parse this kind of data instead of rolling its own header parsing code from scratch, but it's also able to directly create such an object from the web_sys::Request object.

Bytes issue?

It looks like we intend for httparse::parse_headers to only get the trailers because of the use of body.split_to(len as usize).freeze() @ this line but that does not appear to be working for a stream response, body seems to remain unmodified despite this call. That might be the underlying problem; it's getting the entire data packet.

Perhaps len is not being picked up correctly? Indeed, with my large data packet above the total length is reported as 7. That would explain the behaviour and this bug. That's the length of an individual stream's frame; the same length you'd see in a client like Kreya for each individual message for this stream.

This is the full larger body before we advance by parsing any of it:

'b"\0\0\0\0\x07\x08\x01\x12\x03AUD\0\0\0\0\x07\x08\x02\x12\x03GBP\0\0\0\0\x07\x08\x03\x12\x03CAD\0\0\0\0\x07\x08\x04\x12\x03CNY\0\0\0\0\x07\x08\x05\x12\x03EUR\0\0\0\0\x07\x08\x06\x12\x03JPY\0\0\0\0\x07\x08\x07\x12\x03NZD\0\0\0\0\x07\x08\x08\x12\x03RUB\0\0\0\0\x07\x08\t\x12\x03USD\0\0\0\0\x07\x08\n\x12\x03AFN\0\0\0\0\x07\x08\x0b\x12\x03ALL\0\0\0\0\x07\x08\x0c\x12\x03DZD\0\0\0\0\x07\x08\r\x12\x03AOA\0\0\0\0\x07\x08\x0e\x12\x03ARS\0\0\0\0\x07\x08\x0f\x12\x03AMD\0\0\0\0\x07\x08\x10\x12\x03AWG\0\0\0\0\x07\x08\x11\x12\x03AZN\0\0\0\0\x07\x08\x12\x12\x03BSD\0\0\0\0\x07\x08\x13\x12\x03BHD\0\0\0\0\x07\x08\x14\x12\x03BDT\0\0\0\0\x07\x08\x15\x12\x03BBD\0\0\0\0\x07\x08\x16\x12\x03BYN\0\0\0\0\x07\x08\x17\x12\x03BZD\0\0\0\0\x07\x08\x18\x12\x03BMD\0\0\0\0\x07\x08\x19\x12\x03BTN\0\0\0\0\x07\x08\x1a\x12\x03BOB\0\0\0\0\x07\x08\x1b\x12\x03BAM\0\0\0\0\x07\x08\x1c\x12\x03BWP\0\0\0\0\x07\x08\x1d\x12\x03BRL\0\0\0\0\x07\x08\x1e\x12\x03BND\0\0\0\0\x07\x08\x1f\x12\x03BGN\0\0\0\0\x07\x08 \x12\x03MMK\0\0\0\0\x07\x08!\x12\x03BIF\0\0\0\0\x07\x08\"\x12\x03KHR\0\0\0\0\x07\x08#\x12\x03CVE\0\0\0\0\x07\x08$\x12\x03KYD\0\0\0\0\x07\x08%\x12\x03XAF\0\0\0\0\x07\x08&\x12\x03XPF\0\0\0\0\x07\x08'\x12\x03CLP\0\0\0\0\x07\x08(\x12\x03COP\0\0\0\0\x07\x08)\x12\x03KMF\0\0\0\0\x07\x08*\x12\x03CDF\0\0\0\0\x07\x08+\x12\x03CRC\0\0\0\0\x07\x08,\x12\x03HRK\0\0\0\0\x07\x08-\x12\x03CUC\0\0\0\0\x07\x08.\x12\x03CUP\0\0\0\0\x07\x08/\x12\x03CZK\0\0\0\0\x07\x080\x12\x03DKK\0\0\0\0\x07\x081\x12\x03DJF\0\0\0\0\x07\x082\x12\x03DOP\0\0\0\0\x07\x083\x12\x03XCD\0\0\0\0\x07\x084\x12\x03EGP\0\0\0\0\x07\x085\x12\x03ERN\0\0\0\0\x07\x086\x12\x03ETB\0\0\0\0\x07\x087\x12\x03FKP\0\0\0\0\x07\x088\x12\x03FJD\0\0\0\0\x07\x089\x12\x03GMD\0\0\0\0\x07\x08:\x12\x03GEL\0\0\0\0\x07\x08;\x12\x03GHS\0\0\0\0\x07\x08<\x12\x03GIP\0\0\0\0\x07\x08=\x12\x03GTQ\0\0\0\0\x07\x08>\x12\x03GNF\0\0\0\0\x07\x08?\x12\x03GYD\0\0\0\0\x07\x08@\x12\x03HTG\0\0\0\0\x07\x08A\x12\x03HNL\0\0\0\0\x07\x08B\x12\x03HKD\0\0\0\0\x07\x08C\x12\x03HUF\0\0\0\0\x07\x08D\x12\x03ISK\0\0\0\0\x07\x08E\x12\x03INR\0\0\0\0\x07\x08F\x12\x03IDR\0\0\0\0\x07\x08G\x12\x03IRR\0\0\0\0\x07\x08H\x12\x03IQD\0\0\0\0\x07\x08I\x12\x03ILS\0\0\0\0\x07\x08J\x12\x03JMD\0\0\0\0\x07\x08K\x12\x03JOD\0\0\0\0\x07\x08L\x12\x03KZT\0\0\0\0\x07\x08M\x12\x03KES\0\0\0\0\x07\x08N\x12\x03KWD\0\0\0\0\x07\x08O\x12\x03KGS\0\0\0\0\x07\x08P\x12\x03LAK\0\0\0\0\x07\x08Q\x12\x03LBP\0\0\0\0\x07\x08R\x12\x03LSL\0\0\0\0\x07\x08S\x12\x03LRD\0\0\0\0\x07\x08T\x12\x03LYD\0\0\0\0\x07\x08U\x12\x03MOP\0\0\0\0\x07\x08V\x12\x03MKD\0\0\0\0\x07\x08W\x12\x03MGA\0\0\0\0\x07\x08X\x12\x03MWK\0\0\0\0\x07\x08Y\x12\x03MYR\0\0\0\0\x07\x08Z\x12\x03MVR\0\0\0\0\x07\x08[\x12\x03MRU\0\0\0\0\x07\x08\\\x12\x03MUR\0\0\0\0\x07\x08]\x12\x03MXN\0\0\0\0\x07\x08^\x12\x03MDL\0\0\0\0\x07\x08_\x12\x03MNT\0\0\0\0\x07\x08`\x12\x03MAD\0\0\0\0\x07\x08a\x12\x03MZN\0\0\0\0\x07\x08b\x12\x03NAD\0\0\0\0\x07\x08c\x12\x03NPR\0\0\0\0\x07\x08d\x12\x03ANG\0\0\0\0\x07\x08e\x12\x03TWD\0\0\0\0\x07\x08f\x12\x03NIO\0\0\0\0\x07\x08g\x12\x03NGN\0\0\0\0\x07\x08h\x12\x03KPW\0\0\0\0\x07\x08i\x12\x03NOK\0\0\0\0\x07\x08j\x12\x03OMR\0\0\0\0\x07\x08k\x12\x03PKR\0\0\0\0\x07\x08l\x12\x03PAB\0\0\0\0\x07\x08m\x12\x03PGK\0\0\0\0\x07\x08n\x12\x03PYG\0\0\0\0\x07\x08o\x12\x03PEN\0\0\0\0\x07\x08p\x12\x03PHP\0\0\0\0\x07\x08q\x12\x03PLN\0\0\0\0\x07\x08r\x12\x03QAR\0\0\0\0\x07\x08s\x12\x03RON\0\0\0\0\x07\x08t\x12\x03RWF\0\0\0\0\x07\x08u\x12\x03SHP\0\0\0\0\x07\x08v\x12\x03WST\0\0\0\0\x07\x08w\x12\x03STN\0\0\0\0\x07\x08x\x12\x03SAR\0\0\0\0\x07\x08y\x12\x03RSD\0\0\0\0\x07\x08z\x12\x03SCR\0\0\0\0\x07\x08{\x12\x03SLL\0\0\0\0\x07\x08|\x12\x03SGD\0\0\0\0\x07\x08}\x12\x03SBD\0\0\0\0\x07\x08~\x12\x03SOS\0\0\0\0\x07\x08\x7f\x12\x03ZAR\0\0\0\0\x08\x08\x80\x01\x12\x03KRW\0\0\0\0\x08\x08\x81\x01\x12\x03SSP\0\0\0\0\x08\x08\x82\x01\x12\x03LKR\0\0\0\0\x08\x08\x83\x01\x12\x03SDG\0\0\0\0\x08\x08\x84\x01\x12\x03SRD\0\0\0\0\x08\x08\x85\x01\x12\x03SZL\0\0\0\0\x08\x08\x86\x01\x12\x03SEK\0\0\0\0\x08\x08\x87\x01\x12\x03CHF\0\0\0\0\x08\x08\x88\x01\x12\x03SYP\0\0\0\0\x08\x08\x89\x01\x12\x03TJS\0\0\0\0\x08\x08\x8a\x01\x12\x03TZS\0\0\0\0\x08\x08\x8b\x01\x12\x03THB\0\0\0\0\x08\x08\x8c\x01\x12\x03TOP\0\0\0\0\x08\x08\x8d\x01\x12\x03TTD\0\0\0\0\x08\x08\x8e\x01\x12\x03TND\0\0\0\0\x08\x08\x8f\x01\x12\x03TRY\0\0\0\0\x08\x08\x90\x01\x12\x03TMT\0\0\0\0\x08\x08\x91\x01\x12\x03UGX\0\0\0\0\x08\x08\x92\x01\x12\x03UAH\0\0\0\0\x08\x08\x93\x01\x12\x03AED\0\0\0\0\x08\x08\x94\x01\x12\x03UYU\0\0\0\0\x08\x08\x95\x01\x12\x03UZS\0\0\0\0\x08\x08\x96\x01\x12\x03VUV\0\0\0\0\x08\x08\x97\x01\x12\x03VED\0\0\0\0\x08\x08\x98\x01\x12\x03VES\0\0\0\0\x08\x08\x99\x01\x12\x03VND\0\0\0\0\x08\x08\x9a\x01\x12\x03XOF\0\0\0\0\x08\x08\x9b\x01\x12\x03YER\0\0\0\0\x08\x08\x9c\x01\x12\x03ZMW\x80\0\0\0\x0fgrpc-status:0\r\n\n"', 

It does not appear to be pre-pended with a length; the 64bit integers take up 8 bytes which leaves only a single byte before the data, a 0x00 null byte (possibly indicating no compression). Either body arrives incomplete into this function for streams, or streams need to be handled differently.

devashishdxt commented 2 years ago

Hi. Thanks, for creating this issue. Can you give me some sample code for your server so that I can generate same response as you're generating to reproduce this?

devashishdxt commented 2 years ago

I've published a new release on crates.io. Can you verify if it works?

isosphere commented 2 years ago

I've published a new release on crates.io. Can you verify if it works?

Yup, I can confirm it works! Thank you, that was quick!