websocket disconnect just after opening handshake - websocket

I would like to keep the websocket connection alive.
I am using RFC 6455 protocol as websocket protocol.
I tested this via Firefox 13 and Chrome 20.
===WEB SOCKET CLIENT===
GET / HTTP/1.1
Host: #.#.#.#:#
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:13.0) Gecko/20100101 Firefox/13.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ko-kr,ko;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive, Upgrade
Sec-WebSocket-Version: 13
Origin: http://its.secret.com
Sec-WebSocket-Key: TbJqTlFtGocvRvk/9stMhg==
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
===WEB SOCKET SERVER===
HTTP/1.1 101 WebSocket Protocol Handshake
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: outIACgIETcILj0NjzA0MhwP7uc=
the newline in this websocket protocol is CR/LF.
the next is the part of websocket client source.
var host = "ws://#.#.#.#:#";
try {
Rsocket = new WebSocket(host);
Rsocket.onopen = function(msg) {
alert("Welcome - status " + this.readyState);
};
Rsocket.onmessage = function(msg) {...
};
Rsocket.onclose = function(msg) {
alert("Disconnected - status " + this.readyState);
};
}
catch (ex) {
log(ex);
}​
First, the success alert appears in the web browser.
Just after pressing OK, the disconnect alert appears.
Although pressing OK when the success alert appears, I would like the disconnect alert not to appear.

Related

esp32, esp32_https_server library, self-signed certificate, cors and 499 status code

i am working on an ESP32 project. one of my goals is to communicate with the ESP32 from a website using javascript fetch or XMLHttpRequest().
the ESP32 is connected to my local network and i am using the esp32_https_server library. it uses a self-signed certificate which the browser indicates as valid (but issues a warning, "Connection not protected" due to the self-signed certificate). the website has a CA certificate and is secure.
in testing, the esp32 is conected via USB to my computer, idealy i would like it to stand alone.
the problem i am experiencing is that i cannot seem to connect to the esp32. i keep getting status code 499 errors.
my questions are:
1) how do i successfully connect to the esp32 server from a secure website to get data frome the esp32?
2) how do i do this when the esp32 is not connected to my pc via the usb cable?
please see more info regarding the esp32 set up and responses below.
here's the esp32 code:
ResourceNode *nodeRoot = new ResourceNode("/", "GET", [](HTTPRequest *req, HTTPResponse *res) {
ResourceParameters *params = req->getParams();
std::string action = params->getRequestParameter("action");
String aksie = action.c_str();
Serial.println("Aksie: " + aksie);
if (aksie != "upload_data" && aksie != "upload_current_temp")
{
// this should be home page displayed
// Set the response status
res->setStatusCode(200);
res->setStatusText("success");
res->println("Secure Hello World!!!");
}
else
{
// either uploads..
processParams(aksie, res);
}
});
secureServer->registerNode(nodeRoot);
and here's the code that processes the "upload_current_temp" request:
if (action == "upload_current_temp")
{
// get random temperature
int currentTemp = random(0, 9);
String temp = String(currentTemp);
Serial.println("upload current temperature");
Serial.println("uploadCurrentTemp: " + temp);
std::string tem = temp.c_str();
// Set the response status
res->setStatusCode(200);
res->setStatusText("success current temperature");
StaticJsonDocument<200> doc;
doc["temperature"] = temp;
// Produce a minified JSON document
String output;
serializeJson(doc, output);
Serial.println("curent temp json output: " + output);
deserializeJson(doc, output);
// Set the content type of the response
res->setHeader("Content-Type", "application/json");
res->setHeader("Access-Control-Allow-Origin", "*");
res->setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS");
// As HTTPResponse implements the Print interface, this works fine. Just remember
// to use *, as we only have a pointer to the HTTPResponse here:
serializeJson(doc, *res);
}
and also in setUp() i have this line:
secureServer->setDefaultHeader("Access-Control-Allow-Origin", "*"); //replace * with actual address
when using:
const xhr = new XMLHttpRequest();
const url = 'https://192.168.0.102/?action=upload_current_temp';
xhr.open('GET', url);
xhr.responseType = 'text';
xhr.onload = function () {
const data = xhr.response;
console.log(data);
if (this.readyState == 4 && this.status == 200) {
var obj = JSON.parse(this.responseText);
console.log("getCurTemp(), responseText: " + JSON.stringify(this.responseText, null, 2));
currentTemperature = obj.temperature;
console.log("current temperature: " + currentTemperature);
document.getElementById('currentTemp').innerHTML = currentTemperature;
}
};
xhr.send();
i get these errors (in opera):
499 (Request has been forbidden by antivirus)
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
and in chrome:
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
with these headers (opera):
Request URL: https://192.168.0.102/?action=upload_current_temp
Request Method: GET
Status Code: 499 Request has been forbidden by antivirus
Remote Address: 192.168.0.102:443
Referrer Policy: no-referrer-when-downgrade
Cache-Control: no-store, no-cache, must-revalidate, max-age=0
Connection: close
Content-Length: 52266
Content-Type: text/html; charset=utf-8
Expires: Mon, 04 Dec 1999 21:29:02 GMT
Pragma: no-cache
Accept: /
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Host: 192.168.0.102
Origin: https://istimuli.co.uk
Referer: https://istimuli.co.uk/?code=66b72f8e-400c-4adb-ad42-f4efec391d06
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36 OPR/67.0.3575.79
action: upload_current_temp
and when using :
var url = "https://192.168.0.102/?action=upload_current_temp";
var request = new Request(url, {
method: 'GET',
mode: 'cors', // no-cors, *cors, same-origin
headers: {
'Content-Type': 'application/json'
}
});
fetch(request).then(function (response) {
// Convert to JSON
return response.json();
}).then(function (data) {
console.log("temp: " + JSON.stringify(data));
return data;
}).catch(function (error) {
console.log('Request failed', error)
return 000;
});
i get these errors in opera:
499 (Request has been forbidden by antivirus)
has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
and in chrome:
has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
and these are the headers (opera):
1 requests
51.3 KB transferred
51.0 KB resources
Request URL: https://192.168.0.102/?action=upload_current_temp
Request Method: OPTIONS
Status Code: 499 Request has been forbidden by antivirus
Remote Address: 192.168.0.102:443
Referrer Policy: no-referrer-when-downgrade
Cache-Control: no-store, no-cache, must-revalidate, max-age=0
Connection: close
Content-Length: 52266
Content-Type: text/html; charset=utf-8
Expires: Mon, 04 Dec 1999 21:29:02 GMT
Pragma: no-cache
Accept: /
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: GET
Connection: keep-alive
Host: 192.168.0.102
Origin: https://istimuli.co.uk
Referer: https://istimuli.co.uk/?code=66b72f8e-400c-4adb-ad42-f4efec391d06
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36 OPR/67.0.3575.79
action: upload_current_temp

Jersey Server-Sent Events not working with Firefox

Jersey 2.1.4, Java 8, Tomcat 8, Firefox 38.0.1
Server:
#GET
#Produces(SseFeature.SERVER_SENT_EVENTS)
public EventOutput listenToBroadcast() {
final EventOutput eventOutput = new EventOutput();
this.broadcaster.add(eventOutput);
return eventOutput;
}
Client:
var source = new EventSource('broadcast');
source.addEventListener('event', function(event) {
alert('event');
}, false);
source.onopen = function() {
alert('connection open');
};
Using Firefox, the connection open alert does not show up on page load.
Firefox shows the following error in the console: Firefox can't establish a connection to the server at http://localhost:8080/broadcast.
The onopen function DOES get called when the first event comes in. And in that case, only the onopen function is called, and not the event listener.
Chrome is working properly. Also, this demo is working with Firefox properly.
On page load, and before the server sends an event, The Network tab in Firefox shows that it received OK 200 for the /broadcast SSE endpoint, but no headers are present. Jersey log shows the following for the connection establishment:
o.glassfish.jersey.filter.LoggingFilter : 11 * Server has received a request on thread http-nio-8080-exec-3
11 > GET http://localhost:8080/broadcast
11 > accept: text/event-stream
11 > accept-encoding: gzip, deflate
11 > accept-language: en-US,en;q=0.5
11 > cache-control: no-cache
11 > connection: keep-alive
11 > host: localhost:8080
11 > pragma: no-cache
11 > referer: http://localhost:8080/test_sse.html
11 > user-agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0
11 * Server responded with a response on thread http-nio-8080-exec-3
11 < 200
11 < Content-Type: text/event-stream
My client was waiting on the EventSource.onOpen event after creating the EventSource connection (new EventSource()). Chrome invokes the onOpen callback right after the connection is open, but Firefox would only invoke it when the first event is sent from the server. To work around this, I am sending a comment event right after the server opens up the SSE connection. Firefox gets this event, which is meaningless, and calls the onOpen function.
Here is my server-side client subscription code:
#GET
#Produces(SseFeature.SERVER_SENT_EVENTS)
public EventOutput listenToBroadcast() {
final EventOutput eventOutput = new EventOutput();
this.broadcaster.add(eventOutput);
// firefox doesn't call the EventSource.onOpen callback when the connection is created, but it requires at least one event to be sent, so a
// meaningless comment event is used
OutboundEvent.Builder eventBuilder = new OutboundEvent.Builder();
OutboundEvent event = eventBuilder.name("event")
.comment("")
.build();
broadcaster.broadcast(event);
return eventOutput;
}
However, FF still show an error on the console: The connection to http://localhost:8080/broadcast was interrupted while the page was loading.
You can see the error showing up using this demo
Probably a known bug

OPTIONS request while adding Authorization header

Here's my problem, I'm trying to add the following Header to my GET ajax request :
Authorization: Basic XXXXXXX
So I wrote this :
function() {
var storage = window.localStorage;
var currentUsername = storage.getItem("username");
var currentPassword = storage.getItem("password");
var auth = makeBasicAuth(currentUsername, currentPassword);
$.ajaxSetup ({
beforeSend: function(request) {
request.setRequestHeader( "Authorization", auth );
}
});
I already have check the value of auth which is correct. And when I try to send my request, I get that :
OPTIONS <myurl> Error 401
Here are the headers of the request and of its answer :
Request :
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Access-Control-Request-He... authorization
Access-Control-Request-Me... GET
Connection keep-alive
Host <myhost>
Origin null
User-Agent Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:22.0) Gecko/20100101 Firefox/22.0
Answer :
Access-Control-Allow-Head... Authorization
Access-Control-Allow-Meth... *
Access-Control-Allow-Orig... *
Access-Control-Max-Age 3628800
Connection Keep-Alive
Content-Encoding gzip
Content-Length 440
Content-Type text/html;charset=utf-8
Date Tue, 23 Jul 2013 13:00:58 GMT
Keep-Alive timeout=15, max=100
Server Apache-Coyote/1.1
Set-Cookie JSESSIONID=03A48D00EA04DE16396824E804E914AC; Path=/...
Vary Accept-Encoding
WWW-Authenticate Basic realm="Name Of Your Realm"
Note : I get this result whatever is the header I try to add.
Where is the problem ?
Thanks ^^.

Only in Opera: JSON.parse: Unterminated string

In Opera only I receive "JSON.parse: Unterminated string" when going to http://www.underfashion.nl/babys
The string is indeed unterminated, does not end with "]}.
In the other browsers (IE, FF, Chrome) it works fine and receives the entire string.
The string is very long: 217529 chars. Is that possibly the problem? The other browsers receive 220374 chars ending with "]}
I have tried 3 AJAXways to get the data, all with the same strings as result:
The first:
var value = (function () {
var val = null;
$.ajax({'async': false, 'global': false, 'url': uf_urlsearch,
'success': function (data) { val = data;
alert("Data Loaded: " + data.slice(-100) + "<br/>Numofchars: " + data.length);
}
});
return val;
})();
The second:
$.get(uf_urlsearch, function(data){
alert("Data Loaded: " + data.slice(-100));
});
The third:
uf_XMLHttpProductlist.onreadystatechange=function(){
if (uf_XMLHttpProductlist.readyState==4 && uf_XMLHttpProductlist.status==200){
//Get the returned menu-items in Responsetext, expected to look like this:
...
};//if (uf_XMLHttp.readyState==4 && uf_XMLHttp.status==200){
};//uf_XMLHttp.onreadystatechange=function()
uf_urlsearch = "http://www.underfashion.nl/php/get_productlist.php?"+uf_PHPsearchstring;
uf_XMLHttpProductlist.open("GET",uf_urlsearch,true);
uf_XMLHttpProductlist.send();
};
Anyone see any solution?
Best regards,
To inspect the network activity, Go to Opera Menu -> Tools -> Advanced -> Opera Dragonfly. Then enter the URL in your addressbar.
In the Network Tab you can see the list of resources. Select the XHR button, and you will see the get_productlist.php resource. For what is worth, I didn't have any issue with your Web site. The HTTP Request was:
GET /php/get_productlist.php?afdeling=babys HTTP/1.1
User-Agent: Opera/9.80 (Macintosh; Intel Mac OS X 10.7.4; U; fr) Presto/2.10.289 Version/12.00
Host: www.underfashion.nl
Accept-Language: fr,en;q=0.9,en-US;q=0.8,ja;q=0.7,pt;q=0.6,de;q=0.5,zh-CN;q=0.4,es;q=0.3,it;q=0.2,nl;q=0.1,sv;q=0.1,nb;q=0.1,da;q=0.1,fi;q=0.1,zh-TW;q=0.1,ko;q=0.1,pl;q=0.1,pt-PT;q=0.1,ru;q=0.1,ar;q=0.1,cs;q=0.1,hu;q=0.1,tr;q=0.1,ca;q=0.1,el;q=0.1,he;q=0.1,hr;q=0.1,ro;q=0.1,sk;q=0.1,th;q=0.1,uk;q=0.1
Accept-Encoding: gzip, deflate
Referer: http://www.underfashion.nl/babys
Cookie: JSESSIONID=9ABC3B0357487E01298EBC7A02B5FDCD; __atuvc=1%7C25; __utma=137714676.906129982.1340200451.1340200451.1340200451.1; __utmb=137714676.1.10.1340200451; __utmc=137714676; __utmz=137714676.1340200451.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmv=
Connection: Keep-Alive
X-Requested-With: XMLHttpRequest
Accept: */*
Now the HTTP Response is interesting:
HTTP/1.1 200 OK
Date: Wed, 20 Jun 2012 13:54:11 GMT
Server: Apache/2.2.14 (Ubuntu)
X-Powered-By: PHP/5.3.2-1ubuntu4.15
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 11469
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/html
Then the json content. Do you see what is wrong in the HTTP response above? YUP.
Content-Type: text/html
The mime type for JSON is defined in RFC 4627. Please send with JSON content the following mime type.
Content-Type: application/json
That said You are saying that you still have the issue (I don't) on some specific URIs. Could you share which one?

How to make Flask/ keep Ajax HTTP connection alive?

I have a jQuery Ajax call, like so:
$("#tags").keyup(function(event) {
$.ajax({url: "/terms",
type: "POST",
contentType: "application/json",
data: JSON.stringify({"prefix": $("#tags").val() }),
dataType: "json",
success: function(response) { display_terms(response.terms); },
});
I have a Flask method like so:
#app.route("/terms", methods=["POST"])
def terms_by_prefix():
req = flask.request.json
tlist = terms.find_by_prefix(req["prefix"])
return flask.jsonify({'terms': tlist})
tcpdump shows the HTTP dialog:
POST /terms HTTP/1.1
Host: 127.0.0.1:5000
User-Agent: Mozilla/5.0 (X11; Linux i686; rv:12.0) Gecko/20100101 Firefox/12.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Type: application/json; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://127.0.0.1:5000/
Content-Length: 27
Pragma: no-cache
Cache-Control: no-cache
{"prefix":"foo"}
However, Flask replies without keep-alive.
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 445
Server: Werkzeug/0.8.3 Python/2.7.2+
Date: Wed, 09 May 2012 17:55:04 GMT
{"terms": [...]}
Is it really the case that keep-alive is not implemented?
The default request_handler is WSGIRequestHandler.
Before app.run(), Add one line,
WSGIRequestHandler.protocol_version = "HTTP/1.1"
Don't forget from werkzeug.serving import WSGIRequestHandler.
Werkzeug's integrated web server builds on BaseHTTPServer from Python's standard library. BaseHTTPServer seems to support Keep-Alives if you set its HTTP protocol version to 1.1.
Werkzeug doesn't do it but if you're ready to hack into the machinery that Flask uses to instantiate Werkzeug's BaseWSGIServer, you can do it yourself. See Flask.run() which calls werkzeug.serving.run_simple(). What you have to do boils down to BaseWSGIServer.protocol_version = "HTTP/1.1".
I haven't tested the solution. I suppose you do know that Flask's web server ought to be used for development only.

Resources