Search code examples
pythonpython-3.xmultipartform-datapython-3.6

do_POST method failing in Python 3.6


I have been trying to make a basic multi-part form in Python 3.6. The do_GET method is working perfectly, but the do_POST method keeps failing.

When I submit the form in Chrome, it says that localhost didn’t send any data. ERR_EMPTY_RESPONSE, but when I check the Network tab in the Developer Console, I can see the form values.

The code seems to be working perfectly with Python 2.7. I am not sure with where I went wrong in the code.

Here's the code I wrote:

from http.server import BaseHTTPRequestHandler, HTTPServer
import cgi


class WebServerHandle(BaseHTTPRequestHandler):
    def do_GET(self):
        try:
            if self.path.endswith("/new"):
                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                output = ""
                output += "<html><head><style>body {font-family: Helvetica, Arial; color: #333}</style></head>"
                output += "<body><h2>Add new Restaurant</h2>"
                output += "<form method='POST' enctype='multipart/form-data' action='/new'>"
                output += "<input name='newRestaurantName' type='text' placeholder='New Restaurant Name'> "
                output += "<input type='submit' value='Add Restaurant'>"
                output += "</form></html></body>"
                self.wfile.write(bytes(output, "utf-8"))
                return
            if self.path.endswith("/restaurant"):
                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                output = ""
                output += "<html><head><style>body {font-family: Helvetica, Arial; color: #333}</style></head>"
                output += "<body><h3>Restaurant name added successfully!</h3>"
                output += "</html></body>"
                self.wfile.write(bytes(output, "utf-8"))
                return
        except IOError:
            self.send_error(404, 'File Not Found: %s' % self.path)

    def do_POST(self):
        try:
            if self.path.endswith("/new"):
                ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
                if ctype == 'multipart/form-data':
                    fields = cgi.parse_multipart(self.rfile, pdict)
                    restaurant_name = fields.get('newRestaurantName')
                    print("Restaurant name is ", restaurant_name)
                    self.send_response(301)
                    self.send_header('Content-type', 'text/html')
                    self.send_header('Location', '/restaurant')
                    self.end_headers()
        except:
            print("Something went wrong, inside exception..")


def main():
    try:
        server = HTTPServer(('', 8080), WebServerHandle)
        print("Starting web server on the port 8080..")
        server.serve_forever()
    except KeyboardInterrupt:
        print('^C entered. Shutting down the server..')
        server.socket.close()

if __name__ == '__main__':
    main()

Solution

  • Made a change to decode to the field values from the form.

    Changed the self.headers.getheader('content-type') method to

    self.headers.('content-type').

    Then added the following line after that, to decode the pdict value:

    pdict['boundary'] = bytes(pdict['boundary'], "utf-8"),

    and then to print the field values by converting from bytes to string, I changed the print line to

    print("Restaurant name is ", restaurant_name[0].decode("utf-8")).

    So the final code looks like:

        def do_POST(self):
            try:
                if self.path.endswith("/new"):
                    ctype, pdict = cgi.parse_header(self.headers['content-type'])
                    pdict['boundary'] = bytes(pdict['boundary'], "utf-8")
                    if ctype == 'multipart/form-data':
                        fields = cgi.parse_multipart(self.rfile, pdict)
                        print("Fields value is", fields)
                        restaurant_name = fields.get('newRestaurantName')
                        print("Restaurant name is ", restaurant_name[0].decode("utf-8"))
                        self.send_response(301)
                        self.send_header('Content-type', 'text/html')
                        self.send_header('Location', '/restaurant')
                        self.end_headers()
            except:
                print("Inside the exception block")