Issue With Python Sockets: How To Get Reliably POSTed data whatever the browser?

I wrote small Python+Ajax programs (listed at the end) with socket module to study the COMET concept of asynchronous communications.

The idea is to allow browsers to send messages real time each others via my python program.

The trick is to let the "GET messages/..." connection opened waiting for a message to answer back.

My problem is mainly on the reliability of what I have via socket.recv...

When I POST from Firefox, it is working well.

When I POST from Chrome or IE, the "data" I get in Python is empty.

Does anybody know about this problem between browsers?

Are some browsers injecting some EOF or else characters killing the receiving of "recv"?

Is there any solution known to this problem?

The server.py in Python:

 import socket
connected={}
def inRequest(text):
   content=''
   if text[0:3]=='GET':
      method='GET'
   else:
      method='POST'
      k=len(text)-1
      while k>0 and text[k]!='\n' and text[k]!='\r':
         k=k-1
      content=text[k+1:]
   text=text[text.index(' ')+1:]
   url=text[:text.index(' ')]
   return {"method":method,"url":url,"content":content}

mySocket = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
mySocket.bind ( ( '', 80 ) )
mySocket.listen ( 10 )
while True:
   channel, details = mySocket.accept()
   data=channel.recv(4096)
   req=inRequest(data)
   url=req["url"]
   if url=="/client.html" or url=="/clientIE.html":
      f=open('C:\\async\\'+url)
      channel.send ('HTTP/1.1 200 OK\n\n'+f.read())
      f.close()
      channel.close()
   elif '/messages' in url:
      if req["method"]=='POST':
         target=url[10:]
         if target in connected:
            connected[target].send("HTTP/1.1 200 OK\n\n"+req["content"])
            print req["content"]+" sent to "+target
            connected[target].close()
            channel.close()
      elif req["method"]=='GET':
         user=url[10:]
         connected[user]=channel
         print user+' is connected'

The client.html in HTML+Javascript:

<html>
<head>
    <script>
        var user=''
        function post(el) {
            if (window.XMLHttpRequest) {
                var text=el.value;
                var req=new XMLHttpRequest();
                el.value='';
                var target=document.getElementById('to').value
            }
            else if (window.ActiveXObject) {
                var text=el.content;
                var req=new ActiveXObject("Microsoft.XMLHTTP");
                el.content='';
            }
            else 
                return;
            req.open('POST','messages/'+target,true)
            req.send(text);
        }
        function get(u) {
            if (user=='')
                user=u.value
            var req=new XMLHttpRequest()
            req.open('GET','messages/'+user,true)
            req.onload=function() {
                var message=document.createElement('p');
                message.innerHTML=req.responseText;
                document.getElementById('messages').appendChild(message);
                get(user);
            }
            req.send(null)
        }
    </script>
</head>
<body>
<span>From</span>
<input id="user"/>
<input type="button" value="sign in" onclick="get(document.getElementById('user'))"/>
<span>To</span>
<input id="to"/>
<span>:</span>
<input id="message"/>

<input type="button" value="post" onclick="post(document.getElementById('message'))"/>
<div id="messages">
</div>
</body>
</html>


Asked by: Charlie582 | Posted: 05-10-2021






Answer 1

The problem you have is that

  • your tcp socket handling isn't reading as much as it should
  • your http handling is not complete

I recommend the following lectures:

See the example below for a working http server that can process posts

index = '''
<html>
    <head>
    </head>
    <body>
        <form action="/" method="POST">
            <textarea name="foo"></textarea>
            <button type="submit">post</button>
        </form>
        <h3>data posted</h3>
        <div>
            %s
        </div>
    </body>
</html>
'''

bufsize = 4048
import socket
import re
from urlparse import urlparse

class Headers(object):
    def __init__(self, headers):
        self.__dict__.update(headers)

    def __getitem__(self, name):
        return getattr(self, name)

    def get(self, name, default=None):
        return getattr(self, name, default)

class Request(object):
    header_re = re.compile(r'([a-zA-Z-]+):? ([^\r]+)', re.M)

    def __init__(self, sock):
        header_off = -1
        data = ''
        while header_off == -1:
            data += sock.recv(bufsize)
            header_off = data.find('\r\n\r\n')
        header_string = data[:header_off]
        self.content = data[header_off+4:]

        lines = self.header_re.findall(header_string)
        self.method, path = lines.pop(0)
        path, protocol = path.split(' ')
        self.headers = Headers(
            (name.lower().replace('-', '_'), value)
            for name, value in lines
        )

        if self.method in ['POST', 'PUT']:
            content_length = int(self.headers.get('content_length', 0))
            while len(self.content) <  content_length:
                self.content += sock.recv(bufsize)

        self.query = urlparse(path)[4]

acceptor = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
acceptor.setsockopt(
    socket.SOL_SOCKET,
    socket.SO_REUSEADDR,
    1,
)
acceptor.bind(('', 2501 ))
acceptor.listen(10)

if __name__ == '__main__':
    while True:
        sock, info = acceptor.accept()
        request = Request(sock)
        sock.send('HTTP/1.1 200 OK\n\n' + (index % request.content) )
        sock.close()

Answered by: Daniel723 | Posted: 06-11-2021



Answer 2

I would recommend using a JS/Ajax library on the client-side just to eliminate the possibility of cross-browser issues with your code. For the same reason I would recommend using a python http server library like SimpleHTTPServer or something from Twisted if the former does not allow low-level control.

Another idea - use something like Wireshark to check what's been sent by the browsers.

Answered by: Melissa856 | Posted: 06-11-2021



Answer 3

Thank you very much Florian, your code is working!!!!
I reuse the template and complete the main with my COMET mecanism and it is working much better
Chrome and Firefox are working perfectly well
IE has still a problem with the "long GET" system
When it received the answer to the GET it does not stop to re executing the loop to print the messages.
Investigating right now the question

Here is my updated code for very basic JQuery+Python cross browser system.

The Python program, based on Florian's code:

bufsize = 4048
import socket
import re
from urlparse import urlparse
connected={}
class Headers(object):
    def __init__(self, headers):
        self.__dict__.update(headers)

    def __getitem__(self, name):
        return getattr(self, name)

    def get(self, name, default=None):
        return getattr(self, name, default)

class Request(object):
    header_re = re.compile(r'([a-zA-Z-]+):? ([^\r]+)', re.M)

    def __init__(self, sock):
        header_off = -1
        data = ''
        while header_off == -1:
            data += sock.recv(bufsize)
            header_off = data.find('\r\n\r\n')
        header_string = data[:header_off]
        self.content = data[header_off+4:]
        furl=header_string[header_string.index(' ')+1:]
        self.url=furl[:furl.index(' ')]
        lines = self.header_re.findall(header_string)
        self.method, path = lines.pop(0)
        path, protocol = path.split(' ')
        self.headers = Headers(
            (name.lower().replace('-', '_'), value)
            for name, value in lines
        )
        if self.method in ['POST', 'PUT']:
            content_length = int(self.headers.get('content_length', 0))
            while len(self.content) <  content_length:
                self.content += sock.recv(bufsize)
        self.query = urlparse(path)[4]

acceptor = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
acceptor.setsockopt(
    socket.SOL_SOCKET,
    socket.SO_REUSEADDR,
    1,
)
acceptor.bind(('', 8007 ))
acceptor.listen(10)

if __name__ == '__main__':
    while True:
        sock, info = acceptor.accept()
        request = Request(sock)
        m=request.method
        u=request.url[1:]
        if m=='GET' and (u=='client.html' or u=='jquery.js'):
            f=open('c:\\async\\'+u,'r')
            sock.send('HTTP/1.1 200 OK\n\n'+f.read())
            f.close()
            sock.close()
        elif 'messages' in u:
            if m=='POST':
                target=u[9:]
                if target in connected:
                    connected[target].send("HTTP/1.1 200 OK\n\n"+request.content)
                    connected[target].close()
                    sock.close()
            elif m=='GET':
                user=u[9:]
                connected[user]=sock
                print user+' is connected'

And the HTML with Jquery compacted:

   <html>
<head>
    <style>
        input {width:80px;}
        span {font-size:12px;}
        button {font-size:10px;}
    </style>
    <script type="text/javascript" src='jquery.js'></script>
    <script>
        var user='';
        function post(el) {$.post('messages/'+$('#to').val(),$('#message').val());}
        function get(u) {
            if (user=='') user=u.value
            $.get('messages/'+user,function(data) { $("<p>"+data+"</p>").appendTo($('#messages'));get(user);});
        }
    </script>
</head>
<body>
<span>From</span><input id="user"/><button onclick="get(document.getElementById('user'))">log</button>
<span>To</span><input id="to"/>
<span>:</span><input id="message"/><button onclick="post()">post</button>
<div id="messages"></div>
</body>
</html>

Answered by: Rafael289 | Posted: 06-11-2021



Similar questions

javascript - Why don't Django admin "Today" and "Now" buttons show up in Safari?

I'm developing a Django application that contains a model with a date/time field. On my local copy of the application, the admin page for that particular model shows this for the date/time field: alt text http://www.cs.wm.edu/~mpd/images/bugs/django-date-local.png This is as expected. However, when I deploy t...


javascript - Google Apps HTTP Streaming with Python question

I got a little question here: Some time ago I implemented HTTP Streaming using PHP code, something similar to what is on this page: http://my.opera.com/WebApplications/blog/show.dml/438711#comments And I get data with very similar solution. Now I tried to use second code from this page (in Pytho...


javascript - HTML Rich Textbox

I'm writing a web-app using Python and Pylons. I need a textbox that is rich (ie, provides the ability to bold/underline/add bullets..etc...). Does anyone know a library or widget I can use? It doesn't have to be Python/Pylons specific, as it can be a Javascript implementation as well. Thanks!


javascript - What's easiest way to get Python script output on the web?

I have a python script that runs continuously. It outputs 2 lines of info every 30 seconds. I'd like to be able to view this output on the web. In particular, I'd like the site to auto-update (add the new output at the top of the page/site every 30 seconds without having to refresh the page). I understand I can do this with javascript but is there a python only based solution? Even if there is, is javascript th...


Anyone use Pyjamas (pyjs) python to javascript compiler (like GWT..)


port python code to javascript

indices[i:] = indices[i+1:] + indices[i:i+1] Hope someone helps.


Best way to integrate Python and JavaScript?

Is it possible to integrate Python and JavaScript? For example, imagine you wanted to be able to define classes in JavaScript and use them from Python (or vice versa). If so, what's the best way? I'm interested not only if this is possible but if anyone has done it within a "serious" project or product. I'm guessing it would be possible using


javascript - How to limit choice field options based on another choice field in django admin

I have the following models: class Category(models.Model): name = models.CharField(max_length=40) class Item(models.Model): name = models.CharField(max_length=40) category = models.ForeignKey(Category) class Demo(models.Model): name = models.CharField(max_length=40) category = models.ForeignKey(Category) item = models.ForeignKey(Item) In the admin interface when c...


javascript - How to construct a web file browser?

Goal: simple browser app, for navigating files on a web server, in a tree view. Background: Building a web site as a learning experience, w/ Apache, mod_python, Python code. (No mod_wsgi yet.) What tools should I learn to write the browser tree? I see JavaScript, Ajax, neither of which I know. Learn them? Grab a JS example from the web and rework? Can such a thing be built in raw HTML? Python I'm ad...


javascript - Python HTML output (first attempt), several questions (code included)

While I have been playing with Python for a few months now (just a hobbyist), I know very little about Web programming (a little HTML, zero JavaScript, etc). That said, I have a current project that is making me look at web programming for the first time. This led me to ask: What&#39;s easiest way to get P...






Still can't find your answer? Check out these communities...



PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python



top