Skip to content
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

Support chunked transfers (file upload) #3658

Open
MaximeDetne opened this issue Oct 6, 2024 · 3 comments
Open

Support chunked transfers (file upload) #3658

MaximeDetne opened this issue Oct 6, 2024 · 3 comments
Labels
bug Something isn't working

Comments

@MaximeDetne
Copy link

MaximeDetne commented Oct 6, 2024

Describe the Bug

Strawberry-django does not seem to support chunked transfers when using multipart uploads.

Thanks to @enisdanjo (ardatan/graphql-mesh#7701) :

You can reproduce the issue by appending Transfer-Encoding: chunked to the upload request.

curl localhost:8000 \ -H 'Transfer-Encoding: chunked' \ -F operations='{ "query": "mutation ($file: Upload!) { uploadFile(file: $file) { id } }", "variables": { "file": null } }' \ -F map='{ "0": ["variables.file"] }' \ -F [email protected]

This is problematic when using Strawberry after a proxy or a gateway that cannot calculate the content-length.

Upvote & Fund

  • We're using Polar.sh so you can upvote and help fund this issue.
  • We receive the funding once the issue is completed & confirmed by you.
  • Thank you in advance for helping prioritize & fund our backlog.
Fund with Polar
@MaximeDetne MaximeDetne added the bug Something isn't working label Oct 6, 2024
@MaximeDetne
Copy link
Author

MaximeDetne commented Oct 9, 2024

Just FYI, I found an hacky workaround thanks to : https://code.djangoproject.com/ticket/35289

I read that WSGI servers does not support chunked transfers very well, I don't know if that's true but now I run django with Daphne (I need subscriptions anyway).

So it works by creating a middleware that intercepts the request and sets content-length like so:

def force_content_length(get_response):

    def middleware(request):

        if "Transfer-Encoding" in request.headers:
          if request.headers["Transfer-Encoding"] == "chunked" and "CONTENT_LENGTH" not in request.META:
              request.META["CONTENT_LENGTH"] = "1"

        response = get_response(request)

        return response

    return middleware

I'm not experienced enough to tell if doing this affects performance or introduces bugs, but at least it unstuck me.

@erikwrede
Copy link
Member

Hey @MaximeDetne,
glad you found a workaround. To me, this looks like an upstream issue with Daphne about which we cannot do much 😢 . Tagging @bellini666 as he's our Django expert 😊
django/daphne#371

@bellini666
Copy link
Member

Tagging @bellini666 as he's our Django expert 😊

hahaha for this at least I don't have much knowledge, but indeed seems to be an issue with Daphne or Django itself. I can try to replicate this issue later.

Having said that, have you tried using uvicorn instead?

Also, regarding performance for your custom middleware, the only tip is to make sure it can run both sync and async, so django doesn't have to switch contexts for it. This explains how: https://docs.djangoproject.com/en/5.1/topics/http/middleware/#asynchronous-support

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants