Goaccess: WebSocket error 400

Created on 20 Jun 2016  路  17Comments  路  Source: allinurl/goaccess

I've got the following error when using web socket:

WebSocket connection to 'ws://site.com:9879' failed: Unexpected response code: 400

I run go access with the following parameters:

goaccess -f /var/log/nginx/access.log --log-format COMMON -o /var/www/stats/index.html --real-time-html --port=9879 --ws-url=site.com --origin=site.com
question

Most helpful comment

I'm running into the same issue

Debugging revealed the funny thing with parsing Host: header

(gdb) s
ws_set_header_fields (line=0x7fdc34002b40 "Host: cp2-apache.goaccess.beget:7890", headers=0x7fdc34000a70) at src/websocket.c:1091
1091    {
4: method = 0x7fdc3c12add0 " \256\022<\334\177"
5: proto = 0x433b40 <xmalloc+24> "H\211E\370H\203}\370"
6: path = 0x7fdc3c12ae20 "P\256\022<\334\177"
7: list = (int *) 0x0
8: line = 0x7fdc34002b40 "Host: cp2-apache.goaccess.beget:7890"
(gdb) n
1092      char *path = NULL, *method = NULL, *proto = NULL, *p, *value;
4: method = 0x7fdc3c12add0 " \256\022<\334\177"
5: proto = 0x433b40 <xmalloc+24> "H\211E\370H\203}\370"
6: path = 0x7fdc3c12ae20 "P\256\022<\334\177"
7: list = (int *) 0x0
8: line = 0x7fdc34002b40 "Host: cp2-apache.goaccess.beget:7890"
(gdb) 
1094      if (line[0] == '\n' || line[0] == '\r')
4: method = 0x0
5: proto = 0x0
6: path = 0x0
7: list = (int *) 0x0
8: line = 0x7fdc34002b40 "Host: cp2-apache.goaccess.beget:7890"
(gdb) 
1097      if ((strstr (line, "GET")) || (strstr (line, "get"))) {
4: method = 0x0
5: proto = 0x0
6: path = 0x0
7: list = (int *) 0x0
8: line = 0x7fdc34002b40 "Host: cp2-apache.goaccess.beget:7890"
(gdb) 
1098        if ((path = ws_parse_request (line, &method, &proto)) == NULL)
4: method = 0x0
5: proto = 0x0
6: path = 0x0
7: list = (int *) 0x0
8: line = 0x7fdc34002b40 "Host: cp2-apache.goaccess.beget:7890"
(gdb) 
1099          return 1;

if we got get substring in Host: header - then parser thinks it contains request and tries to parse it once again

maybe we should check only GET substing in line to decide whether it is request or not

All 17 comments

Great question. Actually the browser sends the origin header with the protocol included, so it should be exactly how it's accessed.

--origin=http://site.com

or

--origin=http://www.site.com

BTW, I just updated the man page option.

Unfortunately that doesn't work either :/

Request URL:ws://site.com:7890/
Host:site.com:7890
Origin:http://site.com
Pragma:no-cache
Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: XXXXXXXXXXXX==
Sec-WebSocket-Version:13
Upgrade:web socket

WebSocket connection to 'ws://site.com:7890/' failed: Error during WebSocket handshake: Unexpected response code: 400

I have it deployed on EC2 if that makes any difference. Firewall port is open since I get 400 back after some delay.

Have you tried running goaccess without --origin to narrow down the issue? Thanks.

Yeah I removed that because it picks up the right origin anyway, based on browser logs. However I still receive 400. It waits for about 10 seconds then returns 400..

Are you accessing the report through https? that could be the issue as well since the current version does not support wss. Just for testing purposes, you can test the connection via telnet to the ws server.

# telnet site.com 7890 

I use plain HTTP. Connection works fine. But then as I type in telnet somewhat http headers, then it returns HTTP/1.1 400 Invalid Request. 馃憥 Pretty much the same response as in browser.

It would return 400 if no valid ws headers are sent. At this point is probably easier to run it through gdb (if you are willing to).

$ curl tar.goaccess.io/goaccess-1.0.1.tar.gz | tar xvz
$ cd goaccess-1.0.1/
$ ./configure --enable-debug
$ make
$ gdb --args ./goaccess -f /var/log/nginx/access.log --log-format COMMON -o /var/www/stats/index.html --real-time-html --port=9879 --ws-url=site.com
(gdb) b ws_get_handshake <enter>
(gdb) r <enter>

Then try to open the generated report in your browser and use n to continue to the next line or s to step into a function call. A line within this function will give you the 400 status code.

I use Amazon EC2 so it could be it's the problem with AWS. I don't use load balancers though. I'll run it through debugger to see if I can get any more information on why it fails. Thank you!

Closing this as it appears to be a server config issue. Feel free to reopen it if needed. Thanks.

I'm running into the same issue

Debugging revealed the funny thing with parsing Host: header

(gdb) s
ws_set_header_fields (line=0x7fdc34002b40 "Host: cp2-apache.goaccess.beget:7890", headers=0x7fdc34000a70) at src/websocket.c:1091
1091    {
4: method = 0x7fdc3c12add0 " \256\022<\334\177"
5: proto = 0x433b40 <xmalloc+24> "H\211E\370H\203}\370"
6: path = 0x7fdc3c12ae20 "P\256\022<\334\177"
7: list = (int *) 0x0
8: line = 0x7fdc34002b40 "Host: cp2-apache.goaccess.beget:7890"
(gdb) n
1092      char *path = NULL, *method = NULL, *proto = NULL, *p, *value;
4: method = 0x7fdc3c12add0 " \256\022<\334\177"
5: proto = 0x433b40 <xmalloc+24> "H\211E\370H\203}\370"
6: path = 0x7fdc3c12ae20 "P\256\022<\334\177"
7: list = (int *) 0x0
8: line = 0x7fdc34002b40 "Host: cp2-apache.goaccess.beget:7890"
(gdb) 
1094      if (line[0] == '\n' || line[0] == '\r')
4: method = 0x0
5: proto = 0x0
6: path = 0x0
7: list = (int *) 0x0
8: line = 0x7fdc34002b40 "Host: cp2-apache.goaccess.beget:7890"
(gdb) 
1097      if ((strstr (line, "GET")) || (strstr (line, "get"))) {
4: method = 0x0
5: proto = 0x0
6: path = 0x0
7: list = (int *) 0x0
8: line = 0x7fdc34002b40 "Host: cp2-apache.goaccess.beget:7890"
(gdb) 
1098        if ((path = ws_parse_request (line, &method, &proto)) == NULL)
4: method = 0x0
5: proto = 0x0
6: path = 0x0
7: list = (int *) 0x0
8: line = 0x7fdc34002b40 "Host: cp2-apache.goaccess.beget:7890"
(gdb) 
1099          return 1;

if we got get substring in Host: header - then parser thinks it contains request and tries to parse it once again

maybe we should check only GET substing in line to decide whether it is request or not

@mlosev, Thanks for reporting and debugging this. I've pushed a commit that should fix this. Please feel free to build from development and let me know if that solves the issue for you.

@allinurl thanks for merging. I was testing this patch yesterday and it worked like a charm :wink:

Real-time html report is great, thank you for developing this!

real.html:1210 WebSocket connection to 'ws://myip:9870/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED

Exception... "Favicon at "http://myip/favicon.ico" failed to load: Not Found." nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: resource:///modules/FaviconLoader.jsm :: onStopRequest :: line 227" data: no] FaviconLoader.jsm:227:22
onStopRequest resource:///modules/FaviconLoader.jsm:227

thanks

@narayan1599 your port is probably not open.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

SergioDG-YCC picture SergioDG-YCC  路  3Comments

Tassleh0ff picture Tassleh0ff  路  4Comments

vivekkrish picture vivekkrish  路  3Comments

eroldru picture eroldru  路  3Comments

konungrl picture konungrl  路  3Comments