Why isn't Nginx changing the protocol to WebSocket? - laravel

I am trying to run Laracvel-echo.
Host configuration:
location /socket.io {
proxy_pass http://127.0.0.1:6002/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
I catch headers with Socat:
socat -v TCP-LISTEN:6002,fork TCP:127.0.0.1:6001
On my DEV server, I see that everything is ok, the protocol is changing (HTTP/1.1 101 Switching Protocols):
2020/10/22 13:51:36.147102 length=175 from=0 to=174
HTTP/1.1 101 Switching Protocols\r
Upgrade: websocket\r
Connection: Upgrade\r
Sec-WebSocket-Accept: yU0AKhFOQaw5j9cQS8oq2bjx1pw=\r
Sec-WebSocket-Extensions: permessage-deflate\r
But in PRODUCTION server i see GET protocol (GET /socket.io HTTP/1.1):
2020/10/22 13:50:34.161919 length=588 from=0 to=587
GET /socket.io HTTP/1.1\r
Upgrade: websocket\r
Connection: Upgrade\r
Host: localhost:6002\r
Pragma: no-cache\r
Cache-Control: no-cache\r
Authorization: Basic YWlkYXI6MTIzMTIz\r
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36\r
Origin: chrome-extension://pfdhoblngboilpfeibdedpjgfnlcodoo\r
Sec-WebSocket-Version: 13\r
Accept-Encoding: gzip, deflate\r
Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7\r
Sec-WebSocket-Key: rq5CaFXEzZ/vWSnOJ5H3PA==\r
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r
My question is related to this: WebSocket with Laravel-echo-server: 502 Bad gateway
Is the NGINX problem or am I wrong?
Help me please!)

I don't know what the problem is, but I found a solution.
I've updated a lot: updated Nginx to 1.19.1, possibly installed some additional modules. Installed npm not globally, but locally.
And it worked ...
Attention: this only works if you write location /socket.io.

Related

I can't access my apollo server through a proxy

I've set up apollo server on port 3000 on local host and it works fine. I can use the playground and make queries and they all work. ( some text pixilated for privacy )
However my front end is a Svelte application being served from port 8080 on localhost via snowpack. I've setup the snowpack config to proxy localhost:8080/api to localhost:3000
proxy: {
"/api": "http://localhost:3000/"
},
If I try to access the playground via http://localhost:8080/api then the web UI appears but there seem to be errors with the graphql protocol. The UI complains that the server cannot be reached
If I enter developer mode I see the following request failing
POST /api HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 1468
accept: */*
Apollo-Query-Plan-Experimental: 1
X-Apollo-Tracing: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36
DNT: 1
content-type: application/json
Origin: http://localhost:8080
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:8080/api/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-AU,en;q=0.9,de-AT;q=0.8,de;q=0.7,en-GB;q=0.6,en-US;q=0.5
with request body
The response given back is
HTTP/1.1 400 Bad Request
connection: close
Date: Thu, 12 Nov 2020 18:40:59 GMT
Content-Length: 0
Does something need to be configured with the server to allow it to work through a proxy like this?

Nginx sending "Connection: close" instead of "Connection: upgrade" to Golang back end

I'm trying to proxy_pass a websocket with Nginx but I'm getting "502 Bad Gateway" and my Golang back end responds: "websocket: the client is not using the websocket protocol: 'upgrade' token not found in 'Connection' header".
Nginx config:
server {
listen 80;
server_name eg.example.com;
location / {
include proxy_params;
proxy_pass http://localhost:8000/;
}
location ~* /chatclientws/[\w\-]+ {
include proxy_params;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
# Added a dummy header to see if Nginx is passing the request properly.
proxy_set_header Dummy "Test";
proxy_pass "http://localhost:8000/chatclientws/$1/";
}
}
Proxy_params:
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-NginX-Proxy true;
httputil.DumpRequest() in the Golang function for the route produces:
GET /chatclientws/13c21679-45b0-424a-872f-aa012a9ee7a0 HTTP/1.0
Host: eg.example.com
# Connection says close.
Connection: close
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,en-GB;q=0.8
Cache-Control: no-cache
# Connection says close again.
Connection: close
Cookie: clientroom=13c21679-45b0-424a-872f-aa012a9ee7a0
Origin: eg.example.com
Pragma: no-cache
# But websocket request does come through.
Sec-Websocket-Extensions: permessage-deflate; client_max_window_bits
Sec-Websocket-Key: ykQiDfJ2Tr2Z88WtnBQkAw==
Sec-Websocket-Version: 13
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36
X-Forwarded-For: 92.54.215.31
X-Forwarded-Proto: http
X-Nginx-Proxy: true
X-Real-Ip: 92.54.215.31
Somehow, Nginx is passing down all the information necessary except for the right Connection header.
Or so it seems. As seen above, I added a dummy header, proxy_set_header Dummy "Test";, to see if Nginx is really passing the headers down. The dummy header never makes it through.
On another page with the same Nginx config but without dynamically generated pathnames, dummy header and websocket connection work well. And, if I hardcode the pathname instead of using regex, like this:
location /chatclientws/1a904868-608d-42b2-9e02-4d7d4f8cef19 {
...
proxy_pass "http://localhost:8000/chatclientws/1a904868-608d-42b2-9e02-4d7d4f8cef19";
}
It works.
So, I believe I'm using regex wrongly here. But all the examples I've seen online seem to say my use is ok.
I'm puzzled as well as to how the websocket upgrade request comes through. Why is Nginx selectively passing down information?
How should I proceed from here?
After scouring the net and coming up short, I solved this by trial and error. So, this might not be the most professional solution. Anyway, it looks like we can't do regex with the location stanza in Nginx like this:
location ~* /chatclientws/[\w\-]+ {
...
proxy_pass "http://localhost:8000/chatclientws/$1";
}
}
Instead, do this:
# Name your regex variable.
location ~* /chatclientws/(?<Your_Variable_Name>[\w\-]+) {
...
# Then reference it in your proxy_pass.
proxy_pass "http://localhost:8000/chatclientws/$Your_Variable_Name";
}
Essentially, make your regex into named variables. I guess.

Sinatra does nothing with requests from a phonegap application

I have a simple sinatra server with a post block. If I send a $.post from a browser the server receives the post, but when sent from my phonegap application it does nothing, no error code or any output whatsoever.
I previously wrote a simple TCPServer#accept process, and since I was successful with that I proceeded to sinatra, but found the following:
This post works well in sinatra and with TCPServer.accept
POST /api/v/1 HTTP/1.1
Host: localho.st:8015
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://api.jquery.com
Cookie: _fitter_session=[deleted]
Content-Length: 7
Connection: keep-alive
Accept: */*
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/601.5.17 (KHTML, like Gecko) Version/9.1 Safari/601.5.17
Referer: http://api.jquery.com/jquery.post/
Accept-Language: en-us
Accept-Encoding: gzip, deflate
The next one doesn't work in sinatra though it still does in TCPServer
POST /api/v/1 HTTP/1.1
Host: localho.st:8015
Connection: keep-alive
Content-Length: 362
Accept: application/json, text/javascript, */*; q=0.01
Origin: file://
User-Agent: Mozilla/5.0 (Linux; Android 4.4.2; SM-G900F Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept-Encoding: gzip,deflate
Accept-Language: en-US
Cookie: _fitter_session=[deleted]
X-Requested-With: com.myapp.myphonegapp
I think I am missing something obvious but can't find what it is, I'm searching in google but find no soluction or similar problem, any help is welcome
Thanks in advance.
Edit:
- I tried running a rails server and it receives the post correctly.
- This problem affects both get and post sent from the phonegap application.
Edit2:
Sinatra file:
require 'sinatra'
# require 'sinatra/cross_origin'
set :port, 8015
#set :server, 'thin'
post '/api/v/1' do
puts 'it worked!'
end
Phonegap ajax request:
$.post('http://localho.st:8015/api/v/1', {
test: 'foo'
})
.done(function(s) {
console.log(s);
})
.fail(function(e) {
console.log(e);
})
If I run a node server and serve the application the request runs succesfully (with cors enabled in the browser) but on an android device, it doesn't, again, if I replace the sinatra with a rails in the same port, rails gets the request
Try to put in your codeset :bind, '0.0.0.0'. I guess that your server is listening only on localhost.

Web API Batch requests failing in Postman

I recently added batch request support to my Web API project, and spent the better part of a day trying to debug why the batch request was failing using Postman: Unexpected end of MIME multipart stream. MIME multipart message is not complete.
After searching around for quite a while, and learning all about the trailing CRLF issue, I finally wrote a quick C# console app using System.Net.Http similar to the example given here. This worked great!
My question is: what is Postman doing differently that makes my batch requests fail?
Using fiddler to capture the requests, and then using winmerge to diff them, the only difference is the Postman request contains a few additional headers:
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36
Cache-Control: no-cache
Origin: chrome-extension://fdmmgilgnpjigdojojpjoooidkmcomcm
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
I tried adding those headers to my console app to make the requests exactly the same, and it still worked in my console app, but failed in Postman!
Anyone have any idea WHY?
Fiddler-captured requests below:
POSTMAN:
POST http://localhost:49402/api/sequentialBatch HTTP/1.1
Host: localhost:49402
Connection: keep-alive
Content-Length: 528
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36
Cache-Control: no-cache
Origin: chrome-extension://fdmmgilgnpjigdojojpjoooidkmcomcm
Session-ID: 03317cfa-c051-4813-a02a-a9fa955cc7f5
Authorization: Basic c2E6c2E=
Content-Type: multipart/mixed; boundary="c3581ff4-f6eb-4c41-ac02-0bb8b80b30ef"
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
--c3581ff4-f6eb-4c41-ac02-0bb8b80b30ef
Content-Type: application/http; msgtype=request
GET /api/currency?$filter=Currency_ID eq 'Z-US$' HTTP/1.1
Host: localhost.fiddler:49402
Authorization: Basic c2E6c2E=
Session-ID: 03317cfa-c051-4813-a02a-a9fa955cc7f5
--c3581ff4-f6eb-4c41-ac02-0bb8b80b30ef
Content-Type: application/http; msgtype=request
GET /api/countrycode/US HTTP/1.1
Host: localhost.fiddler:49402
Authorization: Basic c2E6c2E=
Session-ID: 03317cfa-c051-4813-a02a-a9fa955cc7f5
--c3581ff4-f6eb-4c41-ac02-0bb8b80b30ef--
CONSOLE APP: (with additional postman headers)
POST http://localhost:49402/api/sequentialBatch HTTP/1.1
Host: localhost:49402
Connection: Keep-Alive
Content-Length: 553
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36
Cache-Control: no-cache
Origin: chrome-extension://fdmmgilgnpjigdojojpjoooidkmcomcm
Session-ID: 03317cfa-c051-4813-a02a-a9fa955cc7f5
Authorization: Basic c2E6c2E=
Content-Type: multipart/mixed; boundary="cf2b18a3-5861-49d7-878b-142283cb4959"
Accept: */*
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US, en; q=0.8
--cf2b18a3-5861-49d7-878b-142283cb4959
Content-Type: application/http; msgtype=request
GET /api/currency?$filter=Currency_ID%20eq%20'Z-US$' HTTP/1.1
Host: localhost.fiddler:49402
Authorization: Basic c2E6c2E=
Session-ID: 03317cfa-c051-4813-a02a-a9fa955cc7f5
--cf2b18a3-5861-49d7-878b-142283cb4959
Content-Type: application/http; msgtype=request
GET /api/countrycode/US HTTP/1.1
Host: localhost.fiddler:49402
Authorization: Basic c2E6c2E=
Session-ID: 03317cfa-c051-4813-a02a-a9fa955cc7f5
--cf2b18a3-5861-49d7-878b-142283cb4959--
I did notice one difference: in Postman the Content-Length header changed from 553 (as posted) to 528 (when captured)... not sure if this is relevant to my issue or not...
Had a few problems with this, but I was using Fiddler. It seems like the empty return character makes a difference:
That also seems like the difference between your Postman request and your console app.

Apache and Headers presence in response for Ajax requests

I try to figure out a cross-domain API issue.
I have an application created with Sencha Touch 2.3.1 that is using Ajax to fetch data from remote server.
The issue that I am facing is that all Ajax requests against local server does not contain all headers in response.
On remote server, all works fine and headers are ok.
Here are two prints that show the headers sent and received for each server individualy
1 - headers sent and received from localhost (http://local.api - vhost)
Headers received:
Connection Keep-Alive
Content-Length 274
Content-Type text/html; charset=iso-8859-1
Date Mon, 07 Jul 2014 10:58:54 GMT
Keep-Alive timeout=5, max=100
Location http://local.api/fa/?ref.agent/lista-clienti&_dc=1404730734262
Server Apache/2.2.17 (Win32) PHP/5.3.3
Headers sent:
Accept text/html,application/xhtml+xml,
application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language ro-ro,ro;q=0.8,en-us;q=0.6,en-gb;q=0.4,en;q=0.2
Content-Length 33
Content-Type application/x-www-form-urlencoded; charset=UTF-8
Host local.api
Origin http://sencha.local
Referer http://sencha.local/fisa-agenti/index.html
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101
Firefox/30.0
2 - headers sent and received from remote server (http://adgarage.ro)
Headers received
Accept-Ranges bytes
Access-Control-Allow-Cred... true
Access-Control-Allow-Orig... *
Age 0
Connection keep-alive
Content-Length 375
Content-Type application/json
Date Mon, 07 Jul 2014 10:58:52 GMT
Server Apache/2.2.22 (Unix) mod_ssl/2.2.22
OpenSSL/0.9.8e-fips-rhel5
Via 1.1 varnish
X-Powered-By PHP/5.3.13
X-Varnish 562862498
Headers sent
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language ro-ro,ro;q=0.8,en-us;q=0.6,en-gb;q=0.4,en;q=0.2
Host adgarage.ro
Origin http://sencha.local
Referer http://sencha.local/fisa-agenti/index.html
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101
Firefox/30.0
Note the Access-Controll-Allow header.
It is missing from the header container received from localhost
And here is my .htaccess file:
Header set Access-Control-Allow-Origin *
Header set Access-Control-Allow-Credentials: true
this file is the same on both servers.
I have the headers_module acitive on local machine.
Another thing I noticed is that response status from local is 301 moved Permanently while the response status received from remote server is 200 Ok
What I am missing?
Thank you!
I've identified the problem.
As discussed in this this topic headers were not sent because of the 301 Moved Permanently status.
My local requests were made to http://local.api/fa?ref.agent/... instead of http://local.api/fa/?ref.agent/... - notice the trailing slash missing after /fa in the first link.
Everything it's ok now.

Resources