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

more support for request streaming #1601

Open
3 tasks
kazuho opened this issue Jan 11, 2018 · 15 comments
Open
3 tasks

more support for request streaming #1601

kazuho opened this issue Jan 11, 2018 · 15 comments

Comments

@kazuho
Copy link
Member

kazuho commented Jan 11, 2018

With the merger of #1357 it has become possible to stream request body to the application without buffering entire content in H2O. However, the feature has so far been only implemented by the http2 protocol handler and the proxy handler.

We need to implement the feature in the following modules as well.

  • http1
  • fastcgi
  • mruby

relates to: #1585

@proyb6
Copy link
Contributor

proyb6 commented Feb 5, 2018

Is anyone working or interested in this feature request? How can we help to find interested parties to implement?

@chenbd
Copy link
Contributor

chenbd commented Mar 4, 2018

I'm interested in http1 part, but not clearly understand how to implement this feature.

@tomas
Copy link

tomas commented Feb 15, 2019

@kazuho I'm interested in the mruby part, although I wouldn't know where to begin. :)

I'm also assuming that it makes more sense to start working on this once #1966 gets merged, right?

@tomas
Copy link

tomas commented Feb 19, 2019

@kazuho any pointers as to where to begin?

@deweerdt
Copy link
Member

#1357 would be a good start, since that implemented request streaming for http2 and the proxy handler.

The key part is that it makes handlers (mruby, fastcgi, proxy, ...) declare whether they support streaming via h2o_handler_t::has_body_stream. If they do, requests that are received via http2 (since there's no streaming for http1 yet), can be streamed via the following struct members of h2o_req_t:

    struct {
        h2o_write_req_chunk cb;
        void *priv;
    } _write_req_chunk;
    h2o_write_req_chunk_done _write_req_chunk_done;

@tomas
Copy link

tomas commented Feb 20, 2019

I see, thanks @deweerdt. And how would this translate on the Mruby side? (ie. how would you trigger the callback or notification to get new chunks from the data stream)

@deweerdt
Copy link
Member

For mruby this would translate in to setting up the write chunk callback so that the frontend protocol (http2 only currently) can write body chunks as they become available. Here's where proxy does it: https://github.com/h2o/h2o/blob/master/lib/core/proxy.c#L632

@i110
Copy link
Contributor

i110 commented Feb 22, 2019

Sorry guys.. actually I've had an implementation of mruby request streaming that's nearly completed, but haven't pushed for a long time. I filed a work-in-progress PR as #1980.

@tomas if you're interested in implementing it, it'd be appreciated if you work based on that branch, and feel free to ask me anything. If instead you just want to use it, please wait just a little longer.

@tomas
Copy link

tomas commented Feb 22, 2019

Great news @i110! I can help with the testing, if it helps. I'm working on a streaming multipart parser and would love to try it with your branch.

From what I see on your PR, it should work as it is, right? (At least for receiving and not sending data)

@kishorenc
Copy link

I see some work for http 1 request streaming has landed in #2007 -- Can somebody clarify whether it is now expected to work on HTTP 1.1?

I modified the POST example to use the streaming API but it's working only for HTTP 2 requests.

When I force CURL to use HTTP 1.1, the req->write_req.cb is not getting called at all even though req->proceed_req is not NULL, partial response is available in req->entity and I initialise the callbacks properly:

https://gist.github.com/kishorenc/9aa7073fd31e10b5bcc4ceec9682cd0e#file-h2o_streaming-cpp-L61-L77

A quick clarification would be much appreciated.

@kishorenc
Copy link

@kazuho @deweerdt Sorry to bump this thread again. I tried building against master and still face the same issue -- request streaming is not working on HTTP 1.1 but works for HTTP 2 -- can you please confirm the status of request streaming support for HTTP 1.1? Thank you.

@chenbd
Copy link
Contributor

chenbd commented May 31, 2020

@kishorenc does call req->proceed_req manually help?

@kishorenc
Copy link

That worked @chenbd -- the trick was to call req->process_req manually. I've verified that request body streaming now works for both http 1.1 and http 2.

Very grateful for your help here. Thank you.

@kishorenc
Copy link

@chenbd or others, I've a follow up question here: The desired behavior is for the next chunk of request body to be sent to the callback only when req->process_req is called. However on HTTP 2, the async request callbacks are getting fired consecutively even before req->process_req is called -- this is not desirable because my application is not done processing the previous chunk before the next chunk arrives.

Why there is a difference in behavior between HTTP 1.1 and HTTP 2? Is the HTTP 2 behavior a bug?

@kishorenc
Copy link

Found the issue: http2.active_stream_window_size was higher than the size of the request body. On HTTP2, the request body callback is invoked multiple times with chunks of 16384 bytes until the active_stream_window_size size is reached. On HTTP 1, though, the handler is called only once with a small chunk size and requires process_req() to be called for fetching further chunks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants