1

I'm making posts requests with curl using this, and even more simple than this:

curl -u usr:pwd -H "Content-Type: multipart/form-data" -i --form "file=@/path/to/myfile/myfile.zip"  -X POST http://midominio.co/api/mypostrequest/

but I'm always getting an empty body, this what I'm getting:

{
'session': <django.contrib.sessions.backends.db.SessionStore object at 0x7f118e502b90>, 
'_post': <QueryDict: {}>, 
'content_params': {'boundary': '------------------------axxxxxxxxx'}, 
'_post_parse_error': False, 
'_messages': <django.contrib.messages.storage.fallback.FallbackStorage object at 0x7f118e502d90>, 
'resolver_match': ResolverMatch(func=piston.resource.Resource, args=(), kwargs={}, url_name=None, app_names=[], namespaces=[]), 
'GET': <QueryDict: {}>, 
'_stream': <django.core.handlers.wsgi.LimitedStream object at 0x7f118e502b50>, 
'COOKIES': {}, 
'_files': <MultiValueDict: {}>, 
'_read_started': False, 
'META': {'HTTP_AUTHORIZATION': 'Basic Y2FpbjpjYWlu', 
'SERVER_SOFTWARE': 'gunicorn/19.7.1', 
'SCRIPT_NAME': u'', 
'REQUEST_METHOD': 'POST', 
'PATH_INFO': u'/api/mypostrequest/', 
'SERVER_PROTOCOL': 'HTTP/1.0', 
'QUERY_STRING': '', 
'CONTENT_LENGTH': '180', 
'HTTP_USER_AGENT': 'curl/7.51.0', 
'HTTP_CONNECTION': 'close', 
'SERVER_NAME': 'midominio.co', 
'REMOTE_ADDR': '', 
'wsgi.url_scheme': 'http', 
'SERVER_PORT': '80', 
'wsgi.input': <gunicorn.http.body.Body object at 0x7f118e5029d0>, 
'HTTP_HOST': 'midominio.co', 
'wsgi.multithread': False, 
'HTTP_ACCEPT': '*/*', 
'wsgi.version': (1, 0), 
'RAW_URI': '/api/mypostrequest/', 
'wsgi.run_once': False, 
'wsgi.errors': <gunicorn.http.wsgi.WSGIErrorsWrapper object at 0x7f118e502950>, 
'wsgi.multiprocess': True, 
'gunicorn.socket': <socket._socketobject object at 0x7f118e4f6de0>, 
'CONTENT_TYPE': 'multipart/form-data; boundary=------------------------axxxxxxxxx', 
'HTTP_X_FORWARDED_FOR': '186.00.00.000', 
'wsgi.file_wrapper': <class 'gunicorn.http.wsgi.FileWrapper'>}, 
'environ': {'HTTP_AUTHORIZATION': 'Basic Y2FpbjpjYWlu', 
'SERVER_SOFTWARE': 'gunicorn/19.7.1', 
'SCRIPT_NAME': u'', 
'REQUEST_METHOD': 'POST', 
'PATH_INFO': u'/api/mypostrequest/', 
'SERVER_PROTOCOL': 'HTTP/1.0', 
'QUERY_STRING': '', 
'CONTENT_LENGTH': '180', 
'HTTP_USER_AGENT': 'curl/7.51.0', 
'HTTP_CONNECTION': 'close', 
'SERVER_NAME': 'midominio.co', 
'REMOTE_ADDR': '', 
'wsgi.url_scheme': 'http', 
'SERVER_PORT': '80', 
'wsgi.input': <gunicorn.http.body.Body object at 0x7f118e5029d0>, 
'HTTP_HOST': 'midominio.co', 
'wsgi.multithread': False, 
'HTTP_ACCEPT': '*/*', 
'wsgi.version': (1, 0), 
'RAW_URI': '/api/mypostrequest/', 
'wsgi.run_once': False, 
'wsgi.errors': <gunicorn.http.wsgi.WSGIErrorsWrapper object at 0x7f118e502950>, 
'wsgi.multiprocess': True, 
'gunicorn.socket': <socket._socketobject object at 0x7f118e4f6de0>, 
'CONTENT_TYPE': 'multipart/form-data; boundary=------------------------axxxxxxxxx', 
'HTTP_X_FORWARDED_FOR': '186.00.00.000', 
'wsgi.file_wrapper': <class 'gunicorn.http.wsgi.FileWrapper'>}, 
'path_info': u'/api/mypostrequest/', 
'content_type': 'multipart/form-data; boundary=------------------------axxxxxxxxx', 
'path': u'/api/mypostrequest/', 
'data': <QueryDict: {}>, 
'method': 'POST', 
'user': <User: cain>

}

I'm using the default nginx configuration, I also have a web version of this part with an "upload button" and everything is working fine, there is not errors in the .log files of nginx or supervisor and the django installation is okay, any ideas? thanks

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
LaBE
  • 117
  • 1
  • 9

1 Answers1

1

I was a mistake trying to take this as a normal request, this is a WSGIRequest so that means it need to be processed different I solved using this, I hope this help to someone else:

    environ =  request.environ
    form = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ)
    f = form['file'].file
LaBE
  • 117
  • 1
  • 9
  • 1
    Just in case someone else comes along this path: In my case using `nginx+gunicorn+django + django-restframework + drf-writable-nested` I believed that this answer was the reason why my POST `multipart/form-data` requests would work in local development mode (without gunicorn and without nginx) but not in my docker environment with nginx+gunicorn. However: It was simply a difference in the request body: The fieldnames were not correctly formatted in my case in the gunicorn/docker environment because I used a `npx patch` command for a npm dependency which was not run as `postinstall` – ElectRocnic Sep 23 '21 at 21:02
  • See https://stackoverflow.com/questions/47748075/npm-postinstall-not-running-in-docker/47748545#47748545 "When running as root, npm won't run any scripts." And inside the Dockerfile where I ran `npm install` I am running this command as `root`. This is not the case when I run `npm install` in local development, so my npx patch was executed in local dev but not in the Docker image. – ElectRocnic Sep 23 '21 at 21:04
  • The patch simply corrected the format of nested list fields from `files[0][file]='bytes...'` to `files[0]file='bytes...'`, where the latter could be interpreted by the DRF MultiPartParser classes and the former not, leading to `This field is required` errors. – ElectRocnic Sep 23 '21 at 21:05
  • See also my answer here: https://stackoverflow.com/a/69307185/3433137 – ElectRocnic Sep 23 '21 at 21:39