Request forwarding with large files #350
-
I am working on a reverse-proxy-like thing where a user uploads a file to a central endpoint, which in turn forwards the file to an appropriate micro-service in the backend. The reverse-proxy works pretty well in its current state, however I have concerns related to handling large files, especially related to handling multiple simultaneous requests that may include large files. How do I ensure that the reverse-proxy is able to process multiple simultaneous requests without blowing up the memory-footprint of the app? |
Beta Was this translation helpful? Give feedback.
Replies: 8 comments 18 replies
-
Hi @thomafred
This way, files are never read whole in memory at once. I do NOT recommend using multipart/form-data for this kind of scenario, although it is the default used by HTML having To read the input in chunks in blacksheep (server part), you can do: from blacksheep import Application, Request, Response
app = Application()
post = app.router.post
@post("/upload")
async def save_big_file(request: Request):
async for chunk in request.stream():
# TODO: do something with the chunk, in this case forward the chunk to a back-end
...
# TODO: send a request to the back-end, return the desired response
return Response(200)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, port=44555) This is documented here. Are you using the BlackSheep HTTP client or another client? If you are using the client in BlackSheep, I can prepare an example for uploading files in chunks, too. Processing the files in chunks ensures that things are done efficiently. Then I would test with the expected workload - if things work, fine, otherwise I would consider two options:
As a side note, this depends on how your micro-service is implemented. For example, the Azure Storage Blob API offers two operations: one to upload a single chunk, one to communicate the end of the upload process. That approach is straightforward, and it forces clients to sends files in exact chunks, with multiple web requests. |
Beta Was this translation helpful? Give feedback.
-
Hi @RobertoPrevato. Hope you are doing well :) I have had a second look at this, and I have been unable to resolve the Do you have any ideas on how we might work around this? |
Beta Was this translation helpful? Give feedback.
-
Hi @thomafred I can reproduce the error you reported about the content-length. I did not find the root cause of the problem, yet, but I think to be on a good track. PS. lately I might have seemed inactive on GitHub. I had less time (I was busier than usual), and I am working on something privately, still (a CLI to bootstrap BlackSheep projects). |
Beta Was this translation helpful? Give feedback.
-
Hi @thomafred The BlackSheep server in my example handles files of any size properly (lazily, in chunks) - it is the proxy part. The example is not 100% complete, as it should handle better some cases, but it describes what you asked in this discussion. |
Beta Was this translation helpful? Give feedback.
-
Hi @RobertoPrevato, This is awesome, thank you so much! Based on your example, I can see the request coming in the backend service and I can see the backend service response being returned (A Are there any special considerations we need to do in the backend service too? |
Beta Was this translation helpful? Give feedback.
-
Hi @thomafred |
Beta Was this translation helpful? Give feedback.
-
Sorry to be pulling at this thread. I am seeing some issues related to small bodies with the
Setting a breakpoint at This does not appear to be supported by Should the body be populated when dealing small requests? |
Beta Was this translation helpful? Give feedback.
-
I think the invalid http request message came from an issue with my own
implementation, and that I may have been generating more data than the
content length I provided to the StreamedContent constructor.
The fix alone seems to be enough :)
…On Thu, 13 Jul 2023 at 18:38, Roberto Prevato ***@***.***> wrote:
I tried uploading a 5.2 GB file using an HTML form with Firefox, to my
proxy server in
https://github.com/Neoteroi/BlackSheep-Examples/tree/main/proxy-2, with
the fix applied locally (to use long long for Content.length) and could
not reproduce the error Invalid HTTP request received. with uvicorn, even
using httptools for it.
I will investigate more.
—
Reply to this email directly, view it on GitHub
<#350 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AB3NZPG7VSPTSI775MG6U7DXQAQABANCNFSM6AAAAAAXUXOXOA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
Hi @thomafred
I prepared a working example, and published it here: https://github.com/Neoteroi/BlackSheep-Examples/tree/main/proxy
The BlackSheep server in my example handles files of any size properly (lazily, in chunks) - it is the proxy part.
Please take a look at how I implemented it, and the notes I left there.
The example is not 100% complete, as it should handle better some cases, but it describes what you asked in this discussion.