简体   繁体   中英

do_POST not working on http.server with python

I'm trying to create a simple http server with basic GET and POST functionality. The program is supposed to GET requests by printing out a simple webpage that greets a user and askes how he would rather be greeted. When the user enters a greeting of his choice, the webpage should now greet him as he had chosen.

While GET seems to be working fine, POST is not. I tried debugging by printing at every code execution and it seems to be getting stuck here:

ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))

I'll paste the code full code below, along with my terminal output.

Code:

    from http.server import BaseHTTPRequestHandler, HTTPServer
    import cgi


    class webServerHandler(BaseHTTPRequestHandler):

        def do_GET(self):
            try:
                if self.path.endswith("/hello"):
                    self.send_response(200)
                    self.send_header('Content-type', 'text/html')
                    self.end_headers()
                    output = ""
                    output += "<html><body>"
                    output += "<h1>Hello!</h1>"
                    output += '''<form method='POST' enctype='multipart/form-data' action='/hello'><h2>What would you like me to say?</h2><input name="message" type="text" ><input type="submit" value="Submit"> </form>'''
                    output += "</body></html>"
                    self.wfile.write(output.encode(encoding = 'utf_8'))
                    print (output)
                    return

                if self.path.endswith("/hola"):
                    self.send_response(200)
                    self.send_header('Content-type', 'text/html')
                    self.end_headers()
                    output = ""
                    output += "<html><body>"
                    output += "<h1>&#161 Hola !</h1>"
                    output += '''<form method='POST' enctype='multipart/form-data' action='/hello'><h2>What would you like me to say?</h2><input name="message" type="text" ><input type="submit" value="Submit"> </form>'''
                    output += "</body></html>"
                    self.wfile.write(output.encode(encoding = 'utf_8'))
                    print (output)
                    return

            except IOError:
                self.send_error(404, 'File Not Found: %s' % self.path)

        def do_POST(self):
            try:
                self.send_response(201)
                print("Sent response")
                self.send_header('Content-type', 'text/html')
                print("Sent headers")
                self.end_headers()
                print("Ended header")
                ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
                print("Parsed headers")
                if ctype == 'multipart/form-data':
                    fields = cgi.parse_multipart(self.rfile, pdict)
                    messagecontent = fields.get('message')
                print("Receiver message content")
                output = ""
                output += "<html><body>"
                output += " <h2> Okay, how about this: </h2>"
                output += "<h1> %s </h1>" % messagecontent[0]
                output += '''<form method='POST' enctype='multipart/form-data' action='/hello'><h2>What would you like me to say?</h2><input name="message" type="text" ><input type="submit" value="Submit"> </form>'''
                output += "</body></html>"
                print(output)
                self.wfile.write(output.encode(encoding = 'utf_8'))
                print ("Wrote through CGI")
            except:
                pass


    def main():
        try:
            port = 8080
            server = HTTPServer(('', port), webServerHandler)
            print ("Web Server running on port", port)
            server.serve_forever()
        except KeyboardInterrupt:
            print (" ^C entered, stopping web server....")
            server.socket.close()

    if __name__ == '__main__':
        main()

Terminal Output:

Web Server running on port 8080
127.0.0.1 - - [28/Apr/2016 13:28:59] "GET /hello HTTP/1.1" 200 -
<html><body><h1>Hello!</h1><form method='POST'      enctype='multipart/form-data' action='/hello'><h2>What would you like me to say?</h2><input name="message" type="text" ><input type="submit" value="Submit"> </form></body></html>
127.0.0.1 - - [28/Apr/2016 13:29:09] "POST /hello HTTP/1.1" 201 -
Sent response
Sent headers
Ended header

As you can see, the POST function does not seem to go beyong the parse_header command. I cannot figure this out, and any help would be usefu!

It's too late now. However, I will still post this answer, as I was facing the same issue while following an online tutorial. Hope, this will help someone if someone stumble upon the same issue.

In the tutorial, the instructor was using python 2 and I was using python 3.6.

Changelog compared to what instructor said:

  • used get method instead of getheader while parsing header, cause self.headers is an instance of class 'MessageClass'. And it provide get method.
  • Converted boundary to bytes before parsing the multipart message.

Here, is a copy of the working code

from http.server import BaseHTTPRequestHandler, HTTPServer
import cgi

class webserverHandler(BaseHTTPRequestHandler):
    """docstring for webserverHandler"""

def do_GET(self):
    try:
        if self.path.endswith("/hello"):
            self.send_response(200)
            self.send_header('Content-Type', 'text/html')
            self.end_headers()

            output = ""
            output += '<html><body>Hello!'
            output += '<form method="POST" enctype="multipart/form-data" action="/hello"><h2> What would you like me to say?</h2><input name="message" type="text" /><input type="submit" value="Submit" /></form>'
            output += '</body></html>'
            self.wfile.write(output.encode())
            print(output)
            return

        if self.path.endswith("/hola"):
            self.send_response(200)
            self.send_header('Content-Type', 'text/html')
            self.end_headers()

            output = ""
            output += '<html><body>&#161Hola <a href="/hello">Back to Hello</a>'
            output += '<form method="POST" enctype="multipart/form-data" action="/hello"><h2> What would you like me to say?</h2><input name="message" type="text" /><input type="submit" value="Submit" /></form>'
            output += '</body></html>'
            self.wfile.write(output.encode())
            print(output)
            return

    except IOError:
        self.send_error(404, "File not found %s" % self.path)

def do_POST(self):
    try:
        self.send_response(301)
        self.send_header('Content-Type', 'text/html')
        self.end_headers()
        ctype, pdict = cgi.parse_header(self.headers.get('Content-Type'))
        pdict['boundary'] = bytes(pdict['boundary'], "utf-8")
        if ctype == 'multipart/form-data':
            fields = cgi.parse_multipart(self.rfile, pdict)
            messagecontent = fields.get('message')
        output = ''
        output += '<html><body>'
        output += '<h2> Okay, how about this: </h2>'
        output += '<h1> %s </h1>' % messagecontent[0].decode("utf-8")
        output += '<form method="POST" enctype="multipart/form-data" action="/hello"><h2> What would you like me to say?</h2><input name="message" type="text" /><input type="submit" value="Submit" /></form>'
        output += '</body></html>'
        self.wfile.write(output.encode())
        print(output)
    except:
        self.send_error(404, "{}".format(sys.exc_info()[0]))
        print(sys.exc_info())


def main():
try:
    port = 8000
    server = HTTPServer(('', port), webserverHandler)
    print("Web server running on port %s" % port)
    server.serve_forever()

except KeyboardInterrupt:
    print(" ^C entered stopping web server...")
    server.socket.close()

    if __name__ == '__main__':
        main()

In addition to Arpit Jain's answer, I have to add content_len = int(self.headers.get('Content-length')) and pdict['CONTENT-LENGTH'] = content_len to make it work.

Below is the full code,

from http.server import BaseHTTPRequestHandler, HTTPServer
import cgi
import sys

class webserverHandler(BaseHTTPRequestHandler):
    """docstring for webserverHandler"""

    def do_GET(self):
        try:
            if self.path.endswith("/hello"):
                self.send_response(200)
                self.send_header('Content-Type', 'text/html')
                self.end_headers()

                output = ""
                output += '<html><body>Hello!'
                output += '<form method="POST" enctype="multipart/form-data" action="/hello"><h2> What would you like me to say?</h2><input name="message" type="text" /><input type="submit" value="Submit" /></form>'
                output += '</body></html>'
                self.wfile.write(output.encode())
                print(output)
                return

            if self.path.endswith("/hola"):
                self.send_response(200)
                self.send_header('Content-Type', 'text/html')
                self.end_headers()

                output = ""
                output += '<html><body>&#161Hola <a href="/hello">Back to Hello</a>'
                output += '<form method="POST" enctype="multipart/form-data" action="/hello"><h2> What would you like me to say?</h2><input name="message" type="text" /><input type="submit" value="Submit" /></form>'
                output += '</body></html>'
                self.wfile.write(output.encode())
                print(output)
                return

        except IOError:
            self.send_error(404, "File not found %s" % self.path)

    def do_POST(self):
        try:
            self.send_response(301)
            self.send_header('Content-Type', 'text/html')
            self.end_headers()
            ctype, pdict = cgi.parse_header(self.headers.get('Content-Type'))
            content_len = int(self.headers.get('Content-length'))
            pdict['boundary'] = bytes(pdict['boundary'], "utf-8")
            pdict['CONTENT-LENGTH'] = content_len
            if ctype == 'multipart/form-data':
                fields = cgi.parse_multipart(self.rfile, pdict)
                message_content = fields.get('message')
            output = ''
            output += '<html><body>'
            output += '<h2> Okay, How about this: </h2>'
            output += '<h1> %s </h1>' % message_content[0]
            output += '<form method="POST" enctype="multipart/form-data" action="/hello"><h2> What would you like me to say?</h2><input name="message" type="text" /><input type="submit" value="Submit" /></form>'
            output += '</body></html>'
            self.wfile.write(output.encode())
            print(output)
        except:
            self.send_error(404, "{}".format(sys.exc_info()[0]))
            print(sys.exc_info())


def main():
    try:
        port = 8080
        server = HTTPServer(('', port), webserverHandler)
        print("Web server running on port %s" % port)
        server.serve_forever()

    except KeyboardInterrupt:
        print(" ^C entered stopping web server...")
        server.socket.close()


if __name__ == '__main__':
    main()

I was able to run your code properly, and get POST to work, after making the following change:

You have:

from http.server

Change that to:

from BaseHTTPServer

And it should work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM