cyberbemon
cyberbemon

Reputation: 3200

Python HTTP Post fails

After searching for how to POST large files using python, I came across this and I wrote a program based on that, but when I run it I get the following error message:

  Traceback (most recent call last):
  File "Test3.py", line 187, in <module>
    main()
  File "Test3.py", line 184, in main
    do_upload(options, args)
  File "Test3.py", line 48, in do_upload
    response = urllib2.urlopen(request)
  File "C:\Python27\lib\urllib2.py", line 126, in urlopen
    return _opener.open(url, data, timeout)
  File "C:\Python27\lib\urllib2.py", line 400, in open
    response = meth(req, response)
  File "C:\Python27\lib\urllib2.py", line 513, in http_response
    'http', request, response, code, msg, hdrs)
  File "C:\Python27\lib\urllib2.py", line 438, in error
    return self._call_chain(*args)
  File "C:\Python27\lib\urllib2.py", line 372, in _call_chain
    result = func(*args)
  File "C:\Python27\lib\urllib2.py", line 521, in http_error_default
    raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 500: Internal Server Error

and here is my code, to run the program I use --upload "path_to_file" [space] "filename". I'm new to python programming so most of this still confuses me.

def do_upload(options, args):
    url = 'http://127.0.0.1/test_server/upload'

    path = args[0]
   # print path
    filename = args[1]
    if not os.access(args[0], os.F_OK):
                print "Directory/file Doesn't exist"
                exit(1)

    os.chdir(path)
    f = open(filename, 'rb')
    mmapped_file_as_string = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)


    request = urllib2.Request(url, mmapped_file_as_string)
    contenttype = mimetypes.guess_type(filename)[0] 
    request.add_header(contenttype, 'application/octet-stream')
    response = urllib2.urlopen(request)


    #close everything
    mmapped_file_as_string.close()
    f.close()

UPDATE

I have changed the code from above and now I'm getting some socket error.

Updated code

def do_upload(options, args):

    host = 'http://localhost:80'
    selector = '/test_server/upload'
    url = 'http://localhost:80/test_server/upload'

    if len(args) == 2:
        print "len of args = 2"
        files = "File is " + str(args[1])
        print files
        path = args[0]
        print "Path is " + str(args[0])



    content_type, body = encode_multipart_formdata(files)
    h = httplib.HTTP(host)
    h.putrequest('POST', selector)
    h.putheader('content-type', content_type)
    h.putheader('content-length', str(len(body)))
    h.endheaders()
    h.send(body)
    errcode, errmsg, headers = h.getreply()
    return h.file.read()

    f = open(files, 'rb')
    mmapped_file_as_string = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
    request = urllib2.Request(url, mmapped_file_as_string)
    request.add_header('Content-Type', content_type)
    response = urllib2.urlopen(request)

    mmapped_file_as_string.close()
    f.close()


def encode_multipart_formdata(files):

    BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$'
    CRLF = '\r\n'
    L = []

    for (filename) in files:
        L.append('--' + BOUNDARY)
        L.append('Content-Disposition: form-data;  filename="%s"' % (filename))
        L.append('Content-Type: %s' % get_content_type(filename))
        L.append('')
        #L.append(value)
    L.append('--' + BOUNDARY + '--')
    L.append('')
    body = CRLF.join(L)
    content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
    return content_type, body

def get_content_type(filename):
    return mimetypes.guess_type(filename)[0] or 'application/octet-stream'

Error message

Traceback (most recent call last):
  File "Test3.py", line 208, in <module>
    main()
  File "Test3.py", line 205, in main
    do_upload(options, args)
  File "Test3.py", line 41, in do_upload
    h.endheaders()
  File "C:\Python27\lib\httplib.py", line 951, in endheaders
    self._send_output(message_body)
  File "C:\Python27\lib\httplib.py", line 811, in _send_output
    self.send(msg)
  File "C:\Python27\lib\httplib.py", line 773, in send
    self.connect()
  File "C:\Python27\lib\httplib.py", line 754, in connect
    self.timeout, self.source_address)
  File "C:\Python27\lib\socket.py", line 553, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
socket.gaierror: [Errno 11004] getaddrinfo failed

Upvotes: 0

Views: 2489

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1124228

You are setting a non-existing header instead of the Content-Type header:

request.add_header(contenttype, 'application/octet-stream')

Change that to:

request.add_header('Content-Type', contenttype)

instead.

Your biggest problem however is that you are not uploading a multipart POST, but rather just the file itself as the POST body, while your server is expecting only a multipart upload.

Take a look at this SO answer for a very simple way to generate a proper multipart POST body: https://stackoverflow.com/a/681182/100297. Note that you'll have to adjust your Content-Type header accordingly.

Upvotes: 4

Related Questions