Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File upload & streamed response not working through NGINX #4600

Closed
9 tasks done
xxcodianxx opened this issue Feb 20, 2022 · 2 comments
Closed
9 tasks done

File upload & streamed response not working through NGINX #4600

xxcodianxx opened this issue Feb 20, 2022 · 2 comments
Labels
question Question or problem question-migrate

Comments

@xxcodianxx
Copy link

First Check

  • I added a very descriptive title to this issue.
  • I used the GitHub search to find a similar issue and didn't find it.
  • I searched the FastAPI documentation, with the integrated search.
  • I already searched in Google "How to X in FastAPI" and didn't find any information.
  • I already read and followed all the tutorial in the docs and didn't find an answer.
  • I already checked if it is not related to FastAPI but to Pydantic.
  • I already checked if it is not related to FastAPI but to Swagger UI.
  • I already checked if it is not related to FastAPI but to ReDoc.

Commit to Help

  • I commit to help with one of those options 👆

Example Code

@app.post("/uploadfile")
async def upload_something(file: UploadFile = File(...)):
    return {'filename': file.filename}

Description

Streamed file requests, like the example above do not work when passing through nginx.

For some reason, whenever the above example is tried with the server before a NGINX proxy, with the proxy_pass directive, streamed requests do not get received by FastAPI.

eg.

location /api/ {
    proxy_pass http://127.0.0.1:8000/;
}

Contacting the server with a file upload directly works:

$ curl -F 'file=@somefile.txt' http://directly_to_fastapi/uploadfile

but this does not:

$ curl -F 'file=@somefile.txt' http://through_nginx/api/uploadfile

Exiting with error:

WARNING:  Invalid HTTP request received.
Traceback (most recent call last):
  File "/home/user/.local/lib/python3.10/site-packages/uvicorn/protocols/http/httptools_impl.py", line 132, in data_received
    self.parser.feed_data(data)
  File "httptools/parser/parser.pyx", line 212, in httptools.parser.parser.HttpParser.feed_data
httptools.parser.errors.HttpParserInvalidMethodError: Invalid method encountered

I have searched far and wide for a solution to this, however it seems that no one has come up with any sane solution.

Furthermore, streamed requests also break when passing through NGINX, eg.

@app.post("/stream")
async def stream_something(request: Request):
    chunks = 0 
    print("starting to stream")
    async for _ in request.stream():
        chunks += 1
        print(f"got chunk {chunks}")

does not work with the same error returned, unless the FastAPI server is contacted directly (not through NGINX).

Operating System

Linux

Operating System Details

No response

FastAPI Version

0.74.0

Python Version

Python 3.10.1

Additional Context

$ nginx -V
nginx version: nginx/1.21.6
built by gcc 10.2.1 20210110 (Debian 10.2.1-6) 
built with OpenSSL 1.1.1k  25 Mar 2021
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -ffile-prefix-map=/data/builder/debuild/nginx-1.21.6/debian/debuild-base/nginx-1.21.6=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'

I am running NGINX with the following Docker command line (for development):

$ docker run -it --rm --network host -v /somewhere/nginx.conf:/etc/nginx/nginx.conf:ro nginx

My Docker version is:

$ docker --version
Docker version 20.10.12, build e91ed5707e

And my full NGINX conf I am using to test this:

http {
    server_tokens off;

    client_max_body_size 128M;

    server {
        listen 80;
        root /mnt;

        location / {
            # where my hot reload frontend is (irrelevant to this)
            proxy_pass http://127.0.0.1:8080/;
        }

        location /api/ {
            # where my server is
            proxy_pass http://127.0.0.1:8000/;
        }
    }
}

events {}

Logs from NGINX whenever request attempts to reach FastAPI server:

2022/02/20 11:09:42 [error] 31#31: *3 writev() failed (104: Connection reset by peer) while sending request to upstream, client: 127.0.0.1, server: , request: "POST /api/uploadfile HTTP/1.1", upstream: "http://127.0.0.1:8000/uploadfile", host: "localhost"
127.0.0.1 - - [20/Feb/2022:11:09:42 +0000] "POST /api/uploadfile HTTP/1.1" 502 175 "-" "curl/7.81.0"
@xxcodianxx xxcodianxx added the question Question or problem label Feb 20, 2022
@frankie567
Copy link
Contributor

Are you serving your application with uvicorn? I had a similar issue some days ago; it seems it was related to a bug in uvicorn. Upgrade to uvicorn==0.17.5 fixed the issue for me.

@xxcodianxx
Copy link
Author

Yep! This indeed fixes it! Thanks for the help! 👍

@tiangolo tiangolo reopened this Feb 27, 2023
Repository owner locked and limited conversation to collaborators Feb 27, 2023
@tiangolo tiangolo converted this issue into discussion #6332 Feb 27, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
question Question or problem question-migrate
Projects
None yet
Development

No branches or pull requests

3 participants