I am building my own Http Server with built in Support for Websockets for a school project.
I mainly tested everything on Chrome and everything looks good, but I am having problems with Safari (10.0.2).
When establishing the Handshake WebSocket connection to 'ws://192.168.0.213' failed: Status line contains non-ASCII character appears as an Error in the development console, keep in mind, Chrome works as expected.
Here are the Exchanged Headers
Request Header (Safari => Server)
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: 192.168.0.213
Origin: http://192.168.0.213
Cookie: session=MDQ5M2UzYTctODg5NC00ZTEwLWJlOWEtYjBiZTRkNzdiYTRj
Pragma: no-cache
Cache-Control: no-cache
Sec-WebSocket-Key: 9/Mj26XS0JxG+Y+lDTvMcQ==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: x-webkit-deflate-frame
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12
Response Header (Server => Safari)
HTTP/1.1 101 Switching Protocols
Connection:Upgrade
Upgrade:websocket
Sec-WebSocket-Accept:rpx9CefKAgOdM7RzjhLuWEcCIso=
Raw Response Header
[72][84][84][80][47][49][46][49][32][49]
[48][49][32][83][119][105][116][99][104][105]
[110][103][32][80][114][111][116][111][99][111]
[108][115][13][10][67][111][110][110][101][99]
[116][105][111][110][58][85][112][103][114][97]
[100][101][13][10][85][112][103][114][97][100]
[101][58][87][101][98][115][111][99][107][101]
[116][13][10][83][101][99][45][87][101][98]
[83][111][99][107][101][116][45][65][99][99]
[101][112][116][58][53][120][86][118][113][57]
[52][121][97][53][84][56][51][88][65][82]
[115][78][119][74][69][88][97][78][97][108]
[99][61][13][10][13][10]
How it is beeng generated (C#)
string handshakeString = $"HTTP/1.1 {(int)StatusCode.SwitchingProtocols} {StatusCode.SwitchingProtocols.GetStatusMessage()}" + Environment.NewLine
+ "Connection:Upgrade" + Environment.NewLine
+ "Upgrade:Websocket" + Environment.NewLine
+ "Sec-WebSocket-Accept:" + Convert.ToBase64String($"{_initHeader["Sec-WebSocket-Key"]}258EAFA5-E914-47DA-95CA-C5AB0DC85B11".Sha1()) + Environment.NewLine
+ Environment.NewLine;
byte[] handshake = Encoding.ASCII.GetBytes(handshakeString); // <- There is the ASCII part
await SendFrameData(OpCode.Text, handshake); // This frame neither gets fragmented or masked
I understand, that there must be an issue with the encoding of the header, but this header gets encoded as ASCII and send with an OpCode 0x1 (Text) to the Client and it is working in Chrome. Am I missing some header keys/values?
Thanks,
David
Answering my own Question. Thanks Remy Lebeau!
The Handshake was wrapped in a Websocket frame. This violates RFC 5455. So the handshake directly needs to be send over the socket.
Related
I have started using HP Loadrunner as part of a performance testing project.
We are trying to hit an initial URL which redirects to an identity server and then redirects to the web portal login screen.
For now I am trying in parallel to see the message exchange in both loadrunner log and browser log (just to compare the two request response messages). For some reason even though the initial HTTP GET message seems to be the same as the browser one the response coming back from the web portal is not the same. So at the location property when i get the rediction url the path is missing the port number at the redirect_uri point (...../url:portnumber2/.....). that creates an issue with the second redirection as instead of getting me to the proper redirection url it takes me to the error page redirection.
so the message exchange in browser looks like below:
Request URL:https://urladdress:portnumber1/
Request Method:GET
Status Code:302
Remote Address:10.33.5.83:4020
Referrer Policy:no-referrer-when-downgrade
Response Headers
content-length:0
date:Fri, 25 Aug 2017 06:50:47 GMT
location:/connect/authorize?client_id=...&redirect_uri=https%3A%2F%2Furladdress%3Aportnumber%2F....sign........
server:.......
set-cookie:.AspNetCore.OpenIdConnect........
set-cookie:.AspNetCore.........
status:302
x-powered-by:ASP.NET
x-ua-compatible:IE=Edge,chrome=1
Request Headers
:authority:urladdress:portnumber1
:method:GET
:path:/
:scheme:https
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
accept-encoding:gzip, deflate, br
accept-language:en-US,en;q=0.8
upgrade-insecure-requests:1
user-agent:.......
second redirection
Request URL:https://urladdress:portnumber2/connect/authorize?......
Request Method:GET
Status Code:302
Remote Address:ipaddress:portnumber2
Referrer Policy:no-referrer-when-downgrade
Response Headers
content-length:0
date:Fri, 25 Aug 2017 06:50:47 GMT
location:https://urladdress:portnumber2/account/login?.......
server:......
status:302
x-powered-by:ASP.NET
Request Headers
:authority:urladdress:portnumber2
:method:GET
:path:/connect/authorize?......
:scheme:https
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
accept-encoding:gzip, deflate, br
accept-language:en-US,en;q=0.8
cookie:.AspNetCore.......
upgrade-insecure-requests:1
user-agent:..........
and the message exchange in loadrunner looks the same with the only difference of not including the portnumber2 after the end of the return_uri property.
That results in being redirected to an error page instead of the second redirection.
The script we are using is shown below:
web_set_sockets_option("SSL_VERSION", "TLS1.2");
web_cleanup_cookies();
web_cache_cleanup();
web_add_auto_header("Accept-Encoding","gzip, deflate, br");
web_add_auto_header("Accept-Language","en-US,en;q=0.8");
web_add_auto_header("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
web_add_auto_header("Upgrade-Insecure-Requests","1");
web_add_auto_header("User-Agent","Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36");
web_set_option("MaxRedirectionDepth","0",LAST);
web_set_max_html_param_len("10000000");
web_reg_save_param_ex("ParamName=url1",
"LB=Location: ",
"RB=\r\n",
LAST);
web_url("urladdress:portnumber1",
"URL=https://urladdress:portnumber1",
"Resource=0",
"RecContentType=text/html",
"Referer=",
"Mode=HTTP",
LAST);
lr_message("redirected address 1 = %s " ,lr_eval_string("{url1}"));
web_reg_save_param_ex("ParamName=url2",
"LB=Location: ",
"RB=\r\n",
LAST);
web_url("connect",
"URL={url1}",
"Resource=0",
"RecContentType=text/html",
"Referer=https://urladdress:portnumber1",
"Mode=HTTP",
LAST);
return 0;
I need to know why the port number on a url is not fetched by the http response message( perhaps there is a configuration I need to create).
Any other comments that might help would be much appreciated.
Have you considered that having a double redirection, particularly ones which are temporary, are going to extract a large performance hit. You have two double handshakes in a row. This is bad magic, independent of the testing tool being used. It is poor architecture on the part of your designers/developers. Cite the defect - Go for a max redirect level of one.
I have followed Option #4 in here:
https://github.com/Microsoft/BotFramework-WebChat/blob/speech/samples/speech/index.html
and used my COGNITIVE_SPEECH_API_KEY. But I keep getting a 403 forbidden even though the code seems to be passing in the Authorization header in the request as expected by the docs.
Here is the Request and Response I captured from Chrome Developer tools:
Request
URL: wss://speech.platform.bing.com/speech/recognition/interactive/cognitiveservices/v1?format=simple&language=en-US&Authorization=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzY29wZSI6Imh0dHBzOi8vd2VzdHVzLmFwaS5jb2duaXRpdmUubWljcm9zb2Z0LmNvbS9jdXN0b21zcGVlY2giLCJzdWJzY3JpcHRpb24taWQiOiJhN2ZmNzJmZmZhNDA0YmQ2ODU5MjNjYzBmMmU2ODdhZiIsInByb2R1Y3QtaWQiOiJDUklTLlMwIiwiY29nbml0aXZlLXNlcnZpY2VzLWVuZHBvaW50IjoiaHR0cHM6Ly9hcGkuY29nbml0aXZlLm1pY3Jvc29mdC5jb20vaW50ZXJuYWwvdjEuMC8iLCJhenVyZS1yZXNvdXJjZS1pZCI6Ii9zdWJzY3JpcHRpb25zLzkwOThmZTJjLTk5NjItNDMxNS1iZGQxLWFiNTEzMDA0YjBiNC9yZXNvdXJjZUdyb3Vwcy9EZW52ZXJJZ25pdGlvbi9wcm92aWRlcnMvTWljcm9zb2Z0LkNvZ25pdGl2ZVNlcnZpY2VzL2FjY291bnRzL2lnbml0aW9udGVzdGJvdHNwZWVjaCIsImlzcyI6InVybjptcy5jb2duaXRpdmVzZXJ2aWNlcyIsImF1ZCI6InVybjptcy5jdXN0b21zcGVlY2giLCJleHAiOjE0OTU5ODQ4MzF9.kK1bx_kWllytyDvdqSZlb0_HUwaLX-V6OGJGeJ3fI2k&X-ConnectionId=9B408F2612DE4902A2D37EEACC8FB350
Request Method:GET
Status Code:403 Forbidden
Response Headers
Content-Length:0
Date:Sun, 28 May 2017 15:10:31 GMT
Server:Microsoft-IIS/10.0
X-MSEdge-Ref:Ref A: B1DBE1CCBEEA44A6B0213CB1CF8B8CA6 Ref B: DEN02EDGE0314 Ref C: Sun May 28 08:10:31 2017 PST
Request Headers
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache
Connection:Upgrade
Cookie:_IFAV=A=422B5EB35D6227B47A899A55FFFFFFFF&COUNT=0&SEEALL=2&VRSN=2;
SRCHD=AF=NOFORM; SRCHUSR=DOB=20160521;
MSFPC=ID=a0c448564466a044a98c006abcccbaf0&CS=3&LV=201608&V=1;
_RwBf=s=10&o=0&A=422B5EB35D6227B47A899A55FFFFFFFF; MUID=2350DC04198E61F62654DA0E1D8E6287;
_U=1Y4QobYDPj3fzheUKiZ5uMdlvmGHvPLxng61hD9XLEWEhcPAfnXyj4UgFgyOMlw6jiTZJaP9wfqB4D6B2UYIV7_jbXnm5WTRM0ycCG-1F5YbfcPhiTR4SdgSkfPadkYRd;
WLID=qgIk0rgVNCI8HNV2Z4g8xFSkWTapYBjrDBYC04Zh/6JNzAhx2KtSiq+zTmKuyODQY3+IA3XDFhKybijk6ArfNlzdJ448JV1JBNO/mmbbcGQ=;
ANON=A=422B5EB35D6227B47A899A55FFFFFFFF&E=13d0&W=1;
NAP=V=1.9&E=1376&C=GKfvIsAF38G7JJpiBtQFE1j-85HTsObRYo50Mrr-fkR1HpimpRoSRA&W=1;
ULC=T=CCC1|4:3; SRCHHPGUSR=CW=1329&CH=716&DPR=2&UTC=-360
Host:speech.platform.bing.com
Origin:https://ignitiontestbotweb.azurewebsites.net
Pragma:no-cache
Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits
Sec-WebSocket-Key:+oV+WOyiaN3VFOIYmX1t3w==
Sec-WebSocket-Version:13
Upgrade:websocket
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110
Safari/537.36
The bing Speech API seems to be randomly accepting the calls. One in 10 connection attempts get through with a 101 Switch Protocols status code. for the same request.
Success
Request URL:wss://speech.platform.bing.com/speech/recognition/interactive/cognitiveservices/v1?format=detailed&language=en-US&Ocp-Apim-Subscription-Key=0825dc93563445aca227aa125404c299&X-ConnectionId=2679C505D3D742A5809D1F08A1934E08
Request Method:GET
Status Code:101 Switching Protocols
Failure (for same request)
Request URL: wss://speech.platform.bing.com/speech/recognition/interactive/cognitiveservices/v1?format=simple&language=en-US&Ocp-Apim-Subscription-Key=0825dc93563445aca227aa125404c299&X-ConnectionId=2A47A79398D941ACB3F67A9580B908E3
Request Method:GET
Status Code:403 Forbidden
As discussed in the comments, the key you are trying to use corresponds to Custom Speech Service API, and the sample you are trying to run needs a Bing Speech API key. Bing Speech is the service that offers Speech to Text capabilites.
I'm trying to make a static files to be cached in the browser for a small amount of time (10 sec). It seems to be working properly when refreshing page.
- 200 if you are new
- 200 served from cache if you soft-refresh during the first 10 sec
- 304 if you come after more than 10 seconds.
Whenever I add the Http header 'Vary': 'Accept-Encoding' it stops working, meaning that browser cache does not work any more (I always hit the server). This happens because the Http request stop sending if-modified-since or if-none-match whenever I add the Http header 'Vary'.
Are cache-control and vary compatible working together?
I leave the Http Request and Response in case someone can suggest some solution:
Request Header
accept:*/*
accept-encoding:gzip, deflate, sdch
accept-language:en-US,en;q=0.8
cache-control:max-age=0
cookie:XXXXX
referer:XXXXXXXXX
user-agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36
Response Header
cache-control:max-age=10
content-encoding:gzip
content-type:application/javascript
date:Wed, 13 Apr 2016 12:34:57 GMT
etag:W/"XXXXXXXXXXXXXX"
last-modified:Wed, 13 Apr 2016 12:34:25 GMT
server:nginx/1.9.14
status:200
vary:Accept-Encoding
x-powered-by:Express
In Express I have this configuration to set response headers for static files:
var setHeaders = function(res, path)
{
res.setHeader('Cache-Control', 'max-age=10');
res.vary('Accept-Encoding');
};
app.use('/static', express.static('./app/static', {setHeaders: setHeaders}));
I had a self certificate issue. It seems that it was causing the issue. Without the header vary everything seems to be working properly even if the certificate was not installed. Despite of that, when using the vary header issues were showing up for the cache.
Installing the self certificate made it work.
Solution came from: Why browser does not send "If-None-Match" header?
I am creating a WebSocket that works in Chrome Version 47.0.2526.106 (64-bit) but fails on Safari Version 9.0.2 (11601.3.9). The error is Invalid UTF-8 sequence in header value. It appears that Safari is requiring certain headers to be included and in certain formats but I cannot find which.
I used the open source WebSocketHandshake line
if (valueStr.isNull()) {
m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "invalid UTF-8 sequence in header value", 0, clientOrigin(), 0);
return 0;
}
The request is as follows:
General
Request URL:wss://example.server.io/query?string=test
Request Method:GET
Status Code:101 Switching Protocols
Response Headers
Connection:Upgrade
Sec-WebSocket-Accept:R3JnbOI454z48aMONLd+8HP6Asg=
Set-Cookie:
Upgrade:websocket
Request Headers
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8,fr;q=0.6,fr-CA;q=0.4
Cache-Control:no-cache
Connection:Upgrade
DNT:1
Host:example.server.io
Origin:http://localhost:3000
Pragma:no-cache
Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits
Sec-WebSocket-Key:QUuX6/L23NIezYa4aZJbFw==
Sec-WebSocket-Version:13
Upgrade:websocket
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36
Query String Parameters
string:test
Safari/WebKit does not like empty headers. In this particular case, the problem is the empty Set-Cookie: header. It is a bug in Webkit.
Chrome had that problem too but they fixed it in Blink.
Remove that header in the server response and it should work.
I'm calling a server site on our internal server. This domain looks like this:
http://server.domain:12345/x.html
Now, with IE this works just fine, I'm getting the data. (My problem there is that IE caches the website after the first call forever, but never mind).
Now, if I'm trying to do exactly the same in Firefox, it won't work, the same in Google Chrome.
Firebug says this:
Answer-Header
Connection Keep-Alive
Content-Length 109
Content-Type text/html; charset=UTF-8
Keep-Alive timeout=5000
Server AbWeb Version SRSG 1.34
Set-Cookie sessionkey=80da7dfe-1c9c-4460-9592-3ce55cecb379
Request-Header
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Encoding gzip, deflate
Accept-Language de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
Connection keep-alive
Host server.domain:12345
Origin http://otherserver.domain
Referer http://otherserver.domain/test/
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:5.0) Gecko/20100101 Firefox/5.0
Chrome says this:
X XMLHttpRequest cannot load http://server.domain:12345/x.html. Origin http://otherservere.domain is not allowed by Access-Control-Allow-Origin.
server.domain:12345/x.html
X Failed to load resource
It seems you perform cross-domain JavaScript calls. The target server must set the Access-Control-Allow-Origin HTTP header. In your case the server http://server.domain must set a header like:
Access-Control-Allow-Origin: http://otherserver.domain
I do not know why it works for IE, it may have to do with your security domains as your just working in the intranet.
See another example:
Jquery form doesn't show submission message on web server but it shows submission message on local host