5

Problem: Trying to translate instructor's python 2 code to python 3
Specific Problem: Cannot access message field from the form in python 3

Instructor's Code Snippet From Udacity Full-Stack Foundations Course

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.getheader('content-type'))
                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]
                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)
                print output
            except:
                pass

After looking up documentation, github repositories, stackoverflow posts, and spending countless hours... I could not figure out how to pull the messages field in python 3 like fields.get('message').

My attempt

def do_POST(self):
            try:
                length = int(self.headers['Content-Length'])
                print(self.headers['Content-Type'])
                self.send_response(301)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                post_data = parse_qs(self.rfile.read(length).decode('utf-8'))
                self.wfile.write("Lorem Ipsum".encode("utf-8"))
                ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
                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]
                # You now have a dictionary of the post data
    
    
                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 += '</html></body>'
                self.wfile.write(output.encode('utf-8'))
    
            except:
                print('Error!')

My post_data variable is a dictionary but I cannot find a way to pull out the 'hi' message that I typed into the form. I am also not sure if this is the right way to go about pulling the data from the form.

>>> post_data
{' name': ['"message"\r\n\r\nhi\r\n------WebKitFormBoundarygm0MsepKJXVrBubX--\r\n']}

2 Answers 2

3

My solution

def do_POST(self):
            try:
                length = int(self.headers['Content-Length'])
                self.send_response(301)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                post_data = parse_qs(self.rfile.read(length).decode('utf-8'))
                messagecontent = post_data.get(' name')[0].split('\n')[2]
                output = ''
                output += '<html><body>'
                output += '<h2> Okay, how about this: </h2>'
                output += '<h1> %s </h1>' % messagecontent
                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 += '</html></body>'
                self.wfile.write(output.encode('utf-8'))
            except:
                pass

If there is a better way, I would like to know it! Not sure why I have to add a space before 'name' in post_data.get(' name'). But, hey! It works!

UPDATE: FINALLY FIGURED IT OUT

def do_POST(self):
        self.send_response(301)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        ctype, pdict = cgi.parse_header(self.headers['Content-Type'])
        if ctype == 'multipart/form-data':
            pdict['boundary'] = bytes(pdict['boundary'], 'utf-8')
            fields = cgi.parse_multipart(self.rfile, pdict)
            messagecontent = fields.get('message')[0].decode('utf-8')
        output = ''
        output += '<html><body>'
        output += '<h2> Okay, how about this: </h2>'
        output += '<h1> %s </h1>' % messagecontent
        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 += '</html></body>'
        self.wfile.write(output.encode('utf-8'))

Use this to be unstuck on the Udacity Full Stack Foundations Course!!

Sign up to request clarification or add additional context in comments.

1 Comment

Can you explain why you created a pdict['boundary'] and explain the other changes regarding the Python3 changes please?
3

I wasn't able to make your code work @ the time of posting (2019). Inspecting cgi module, parse_multipart tried to access pdict['CONTENT-LENGHT'].

My solution, working @ post time:

   def do_POST(self):
    try:
        self.send_response(301)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        # HEADERS are now in dict/json style container
        ctype, pdict = cgi.parse_header(
            self.headers.get('content-type'))
        # boundary data needs to be encoded in a binary format


        if ctype == 'multipart/form-data':
            pdict['boundary'] = bytes(pdict['boundary'], "utf-8")
            pdict['CONTENT-LENGTH'] = self.headers.get('content-length')
            fields = cgi.parse_multipart(self.rfile, pdict)
            messagecontent = fields.get('message')

        output = ""
        output += "<html><body>"
        output += " <h2> Okay, how about this: </h2>"
        # decode it back into a string rather than byte string(b'stuff')
        output += "<h1> {} </h1>".format(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>"
        self.wfile.write(output.encode())
        print(output)

    except:
        raise

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.