Django Channels code is working on Chrome but not Firefox - django

I am writing a chat application using Django and Channels (new websocket implementation for Django). Users first enter a wait room, until at least 3 other people have joined, then they are directed to a chat room. The code works fine for Chrome, but is not working correctly for Firefox. Here is how it works:
On a new connect to the channel/websocket the server checks to see if at least three people are in the wait room (in consumers.py).
If at least three people are present it broadcasts a message to the channel/websocket using the Group function telling them to redirect.
The message is received by the clients and it executes a redirection in javascript.
Here are the steps I’ve taken to debug the problem:
The code works in browsers other than Firefox (e.g. Chrome).
The code works if the first two clients arriving to the wait room are Firefox and the last one (that triggers the server) is Chrome. It redirects all three clients.
If the first two clients are Chrome and the last client (that triggers the server) is Firefox it redirects the Chrome clients but not the Firefox client.
The problem is unlikely to be with the javascript running the redirection because replacing the code with a simple alert message (upon the client receiving the Group statement) is also not working in Firefox (but does work in Chrome). It is as if the Firefox client never receives the Group message when it is the client that triggers the server.
The chat uses channels and works on all browsers including Firefox. It successfully connects, sends messages, receives messages, and disconnects.
Based on these debugging steps I think something is going wrong when Firefox instigates the server code that executes the Group redirect. Do you have any suggestions for what might be going wrong? Do you have any suggestions that would help identify the problem?
Here is the code in consumers.py that I think is causing the problem:
#channel_session_user_from_http
#channel_session
def wait_connect(message):
try:
wait_room, created = WaitRoom.objects.get_or_create(title=title)
except WaitRoom.DoesNotExist:
log.debug('ws room does not exist title=%s', title)
return
Group('wait-'+title, channel_layer=message.channel_layer).add(message.reply_channel)
wait_user,created = wait_room.users.get_or_create(user=message.user)
userlist = WaitUser.objects.filter(wait_room=wait_room,is_active=1)
if len(userlist)>=3:
t = {t['url']='redirecturl'}
Group('wait-'+title, channel_layer=message.channel_layer).send({'text': json.dumps(t)})
Here is the javascript code that is executing the redirect:
$(function() {
var ws_scheme = window.location.protocol == "https:" ? "wss" : "ws";
var chatsock = new ReconnectingWebSocket(ws_scheme + '://' + window.location.host + window.location.pathname);
chatsock.onmessage = function(message) {
var data = JSON.parse(message.data);
window.location.replace(data.url);
};});

Related

Flask API, browser requests stopped working, no log the request was received

I have a very simple flask app that has been working for years, but last week requests from the built app return a 500, and from the Flask side, I can't even see the request. I am not seeing an OPTIONS request.
The below lines worked previously to keep CORS happy.
#app.after_request
def after_request(response):
response.headers.add('Access-Control-Allow-Origin', '*')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization,Auth-Token')
response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE')
return response
I have tried in a few browsers and all of them fail to successfully make any requests. Since the server doesn't even acknowledge the request has been made, I am not sure where to trouble shoot. I did confirm the app returns data as expected when I use Postman to make the request, as well as confirming that if I use the app locally (gulp serve on my computer) that the requests are successful. I have to believe its CORS, but what might I have to add / do to get the browser to be happy? Thanks.
The solution to my problem was that chrome started to "restrict the ability of websites to communicate with devices on the local network"
Communicating from Chrome 94+ with LAN devices that do not support HTTPS from a web app

phantomjs - Cookie is not being sent for any XHR/POST/GET AJAX requests

I found an interesting issue when attempting to login using PhantomJS. I'm at a loss as to why it's actually occurring.
Basically you start up a remote debugger like so:
/usr/local/bin/phantomjs --web-security=no --remote-debugger-port=13379 --remote-debugger-autorun=yes /tmp/test.js
Within the remote debugger:
> location.href = "https://www.mysite.com/login"
> $('input[name="username_or_email"]').val('blah#email.com')
> $('input[name="password"]').val('wrongpassword')
> $('button[type="submit"]').submit()
Doing this in Chrome will give me the correct "wrong password" message after the XHR request, whereas using phantomjs gives me a generic error as no cookie is sent with phantomjs (I examined the headers).
I'm quite confused on why phantomjs doesn't send the cookie with the POST request. Does anyone know how we can get phantomjs to send the cookie with ALL requests as it should? Setting a cookie-file doesn't make any difference either.
Ok, this seems to be something related with session cookies and not regular cookies.
Heres a huge thread on the developer in charge of the cookies feature of phantomjs and some guys with the same issue as yours.
https://groups.google.com/forum/#!msg/phantomjs/2UbPkIibnDg/JLV9jBKxhIQJ
If you dont want to skirm through the entire file, basically:
Phantomjs behaves like a regular browser, and it deletes all session cookies when browser closes, in your case, when your script execution ends.
So, even if you set the --cookies-file=/path/to/cookies.txt option you will only store regular cookies on it, for subsecuent executions.
There are two possible approaches for you. One, is to make all requests within the same script, or the other is to store and restore the cookies manually.
On the thread there are a couple of functions that you can use to do this.
function saveCookies(sessionCookieFile, page) {
var fs = require("fs");
fs.write(sessionCookieFile, JSON.stringify(page.cookies));
}
function restoreCookies(sessionCookieFile, page) {
var fs = require("fs");
var cookies = fs.read(sessionCookieFile);
page.cookies = JSON.parse(cookies);
}
var page = require('webpage').create();
And, if everything fails...
You could download source code and recopile phantomjs
You will need to edit src/cookiejar.cpp and remove or comment purgeSessionCookies();
Hope, this helps.

Asynchronous view with client update for long running processes / views

I have one view in my app that can take quite a long time to be served to the client when requested. In order to inform the user that the server is working I want to present the user some kind like a progress bar, but it is not really a progress bar, it s more like this:
a) client is requesting /myapp/longrunningview/
b) server returns part of the html side, including someting animated that looks like the server is working. At the same time server is calculating the rest of the response, the process which takes very long
c) server finished and returns the response to the client
d) at client side the response is presented
It is not really a progress bar, since the user may request this page from a page outside my app, and I want to return instantly something to the user, without the need to wait for the entire process to be finished. The progress bar implementations that I have found are all based upon some form which is send to the server, while the client showing a progress bar, while waiting for the response.
I would use a celery task for this sort of thing. When the user makes the request, start the task and then send back a page with a progress spinner or whatever, then either have a piece of AJAX hit the server every few seconds asking if it's done, or utilize socketio and django-socketio or a similar package to push a "finished" notification to the client, which can then redirect you to wherever you need to go.
Resources:
Django-SocketIO https://github.com/stephenmcd/django-socketio
SocketIO http://socket.io/
Celery http://celeryproject.org/
Django-Celery http://docs.celeryproject.org/en/latest/django/index.html

making WebResponse GetResponse WebBot wait for redirect

I am making a bot that simulates a human user using a specific website.
When the user uses the site here is what happens
the user uploads a file by using the site's Browse button and then clicks Upload
the server responds immediately and the user sees a Please Wait gif
in the meantime the server is evaluating the file for errors. When it is done it redirects, and the user is take to a new .aspx page where they can correct the errors.
What I am not able to do w the bot is make it wait to get the redirect info.
The bot hits the website with this line of code (VB.NET)
Dim Response As HttpWebResponse = CType(Request.GetResponse(), HttpWebResponse)
The Response has the Please Wait gif in it, not the Errors.aspx page. Somehow I need to make the bot, execute that line of code above then, sorta listen to the same port(?) and wait for the web server to send another response.
Ideas?
I ended up just sleeping the thread, then hitting the url again, repeatedly till I got the response I wanted.

Connecting a desktop application with a website

I made an application using Qt/C++ that reads some values every 5-7 seconds and sends them to a website.
My approach is very simple. I am just reading the values i want to send and then i make an HTTP POST to the website. I also send the username and password to the website.
The problem is that i cannot find out if the request is successful. I mean that if i send the request and server gets it, i will get an HTTP:200 always. For example if the password is not correct, there is no way to know it. It is the way HTTP works.
Now i think i will need some kind of a protocol to take care the communication between the application and the website.
The question is what protocol to use?
If the action performed completes before the response header is sent you have the option of adding a custom status to it. If your website is built on PHP you can call header() to add the custom status of the operation.
header('XAppRequest-Status: complete');
if you can modify the server side script you could do the following
on one end :
You can make the HTTP post request via ajax
and evaluate the result of the ajax request.
On the serve side
On the HTTP request you do your process and if everything goes accordingly you can send data back to the ajax script that called it.
solves your problem .. ?