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

How does one know when headers are finished? #125

Closed
ioquatix opened this issue Apr 6, 2018 · 13 comments
Closed

How does one know when headers are finished? #125

ioquatix opened this issue Apr 6, 2018 · 13 comments

Comments

@ioquatix
Copy link
Collaborator

ioquatix commented Apr 6, 2018

It's possible to have end_headers flag set, but how does one receive that information via

emit(:headers, frame[:payload]) unless frame[:ignore]
?

@HoneyryderChuck
Copy link
Collaborator

I didn't understand the question. The lib emits the headers callback when all headers have been received and decoded.

@ioquatix
Copy link
Collaborator Author

ioquatix commented Apr 8, 2018

How do you know when you've finished emitting headers? i.e. end_headers.

@ioquatix
Copy link
Collaborator Author

ioquatix commented Apr 8, 2018

i.e. if there are multiple headers frames.

@HoneyryderChuck
Copy link
Collaborator

When you're sending, or when you're receiving?

When it's receiving, the parser receives all the headers/continuation frames, decodes them and emits a single headers callback (haven't tested with trailers though).

When sending, you send all headers at once, or you send them separately, and all calls to #headers before last one will have to set :end_headers to false (as it's done with the #data method).

Does that answer the question?

@ioquatix
Copy link
Collaborator Author

ioquatix commented Apr 8, 2018

Yes, thanks that's a helpful answer.

It wasn't clear to me that there would only be one headers callback.

Once the stream is open, I assume it's not possible to send arbitrary headers frames?

@ioquatix
Copy link
Collaborator Author

ioquatix commented Apr 8, 2018

Okay so I checked the code and it looks like you and send multiple frames of headers down the wire.

http-2/lib/http/2/stream.rb

Lines 151 to 157 in 2c127ae

def headers(headers, end_headers: true, end_stream: false)
flags = []
flags << :end_headers if end_headers
flags << :end_stream if end_stream
send(type: :headers, flags: flags, payload: headers)
end

Where is it reassembled?

@HoneyryderChuck
Copy link
Collaborator

You definitely can send. And they'll be reassembled at the server, according to protocol.

@ioquatix
Copy link
Collaborator Author

ioquatix commented Apr 8, 2018

Okay, I may investigate this further, because it looks like there is a potential issue here.

@ioquatix
Copy link
Collaborator Author

ioquatix commented Apr 8, 2018

So, if one wants to send multiple frames of headers, do you need to manually use a HEADERS followed by a CONTINUATION frame?

@ioquatix
Copy link
Collaborator Author

ioquatix commented Apr 8, 2018

Is it actually valid to send multiple HEADERS frames?

@HoneyryderChuck
Copy link
Collaborator

You don't need to manually send frames, the lib handles that for you. You can however call #headers multiple times, provided that you'll set :end_headers as false in all the before-last calls. Internally, it will create all the necessary frames.

@ioquatix
Copy link
Collaborator Author

Okay, so there will only ever be one :headers event emitted and it will be complete. After that, we can expect 0 or more data frames. Let me know if this is wrong.

@ioquatix
Copy link
Collaborator Author

ioquatix commented Jun 24, 2018

I did a bit more digging into this after experiencing issues with Cloudflare and a few other situations.

I found it's feasible to send multiple header frames, but end_headers is not preserved correctly on the receiver end in the case of this code base.

It's logical to only have one headers frame followed by continuation frames if required.

That being said, this library doesn't enforce any of those invariants and can break if you try to do so (e.g. send multiple header frames). I don't think it's in violation of the spec but it's a little bit confusing at first given the discussion above.

You don't need to manually send frames, the lib handles that for you. You can however call #headers multiple times, provided that you'll set :end_headers as false in all the before-last calls. Internally, it will create all the necessary frames.

I don't think this is correct because I made a spec for it and it didn't coalesce headers, they were received in multiple discrete events.

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

No branches or pull requests

2 participants