HybridConnection for HttpRequest on rendezvous url: The FIN flag of the last frame of the big post body(>64kb) is not set.
Neilpang opened this issue · comments
Actual Behavior
- The FIN flag of the Last Websocket frame of the post body is NOT set.
Expected Behavior
- The FIN flag of the Websocket frame of the post body is set.
I was writing my own AzureRelayListener implementation, As in the spec here: https://docs.microsoft.com/en-us/azure/service-bus-relay/relay-hybrid-connections-protocol#request-message-1
The Fin flag of the last binary frame of the post body should be set.
This is ok for normal inline request(body < 64kB).
But with body > 64KB, when I connect to the rendezvous address to read the request, the first json frame is good. It's ok to read all the POST body(> 64kB) data frames, but the FIN flag of the last Frame is NOT set.
From the http client side, I used curl to POST file:
The file size is 100kB= 102400 Bytes
curl -vv -H ServiceBusAuthorization:"SharedAccessSignature sr=sb%3a%2f%2fxxxxxxxxx%2fhc1&sig=xxxxxxxxxxxx&skn=RootManageSharedAccessKey" \
https://xxxxxx.servicebus.windows.net/xxxxx1 \
--data-binary @100kb.dat
> POST /xxx1 HTTP/1.1
> Host: xxxxxxx.servicebus.windows.net
> User-Agent: curl/7.47.0
> Accept: */*
> ServiceBusAuthorization:SharedAccessSignature sr=sb%3a%2f%2xxxxxxxx%2fhc1&sig=xxxxxxxskn=RootManageSharedAccessKey
> Content-Length: 102400
> Content-Type: application/x-www-form-urlencoded
> Expect: 100-continue
>
* Done waiting for 100-continue
* We are completely uploaded and fine
The client is even setting "Content-Length" value.
But from the Listener side, I received 3 body frames:
Log: AzureRelayListenerLog:[Body]EOM=False Length:32768
Log: AzureRelayListenerLog:[Body]EOM=False Length:32768
Log: AzureRelayListenerLog:[Body]EOM=False Length:32768
Log: AzureRelayListenerLog:[Body]EOM=False Length:4096
The total size is 32768*3+4096 = 102400
, which is ok. but the EOM(FIN) flag of every frame are NON-SET(false) for me.
It is expected that the EOM(FIN) flag of the last frame is SET. so that I know it's the request ending.
This caused trouble for me, I don't know when to stop. Because the content-length header is swallowed by AzureRelay. I don't know how many bytes the body contains.
This can also be a problem in the official sample code here:
https://github.com/Azure/azure-relay/blob/master/samples/hybrid-connections/dotnet/simple-http/Server/Program.cs#L43
if I insert the code to read the inputStream.length property, it hangs.
// Provide an HTTP request handler
listener.RequestHandler = (context) =>
{
Console.WriteLine(context.Request.Headers);
// reading Length property makes it hang here.
Console.WriteLine("context.Request.InputStream.Length=" + context.Request.InputStream.Length);
Thanks.
The end of the HTTP Request body will be indicated with one additional WebSocket fragment/packet with 0 bytes and EOM == true. Here's an example when I send/receive 100K
Listener: Received Type = Text, EOM = True, Count = 612: {"request":{ ... , "body":true } }
Listener: Received Type = Binary, EOM = False, Count = 16380
Listener: Received Type = Binary, EOM = False, Count = 16384
Listener: Received Type = Binary, EOM = False, Count = 4
Listener: Received Type = Binary, EOM = False, Count = 16380
Listener: Received Type = Binary, EOM = False, Count = 16384
Listener: Received Type = Binary, EOM = False, Count = 4
Listener: Received Type = Binary, EOM = False, Count = 16380
Listener: Received Type = Binary, EOM = False, Count = 16384
Listener: Received Type = Binary, EOM = False, Count = 4
Listener: Received Type = Binary, EOM = False, Count = 4096
Listener: Received Type = Binary, EOM = True, Count = 0
Are you able to receive more more packet off the wire indicating Binary, 0 bytes, and EOM=true?
With the Microsoft provided library you should be able to call context.Request.InputStream.Read until that Read call returns 0 bytes read. That's how one reads to the end of a non-seekable Stream in .NET.
Regarding the context.Request.InputStream.Length hanging is that with the Microsoft provided library or yours? Technically since the Stream of a large message should report CanSeek==false calling get_Length should throw a NotSupportedException. If the Microsoft library's InputStream doesn't report CanSeek == false and throw NotSupportedException when request body is > 64KB then an issue should be created to fix this.
Also if you're forking your library from Microsoft.Azure.Relay.dll (https://github.com/Azure/azure-relay-dotnet) make sure you pick from the the latest version of dev
branch right now. It will be merged into master soon with the next release.
@dlstucki Thanks a lot.
I will try again, and update this thread later.
Regarding the context.Request.InputStream.Length hanging is that with the Microsoft provided library or yours?
It's the official lib, not mine.
https://github.com/Azure/azure-relay/blob/master/samples/hybrid-connections/dotnet/simple-http/Server/Program.cs#L43
Thanks.