-
Notifications
You must be signed in to change notification settings - Fork 25
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
Expose zero-copy-ish headers on ClientRequest #35
Conversation
loop { | ||
crate::read(&mut self.socket, &mut self.buffer, BLOCK_SIZE).await?; | ||
if let Parsing::Done { value, offset } = self.decode_request()? { | ||
self.buffer.advance(offset); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This mutable borrow of self.buffer
prevented us from borrowing stuff in return value. The advance
was not necessary since the buffer is never read after the headers (not just that, it should not contain any bytes after the request AFAIU).
loop { | ||
crate::read(&mut self.socket, &mut self.buffer, BLOCK_SIZE).await?; | ||
if let Parsing::Done { value, offset } = self.decode_request()? { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attempting decode after each read also made lifetimes convoluted since there is a mutable borrow to self.buffer
made on every iteration. Opted to do a single parse after we are sure headers are complete in the new code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should work, nice job. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have a lot to nit-pick, but I won't bother you more
Return copied `RequestHeaders`. Co-authored-by: Pierre Krieger <[email protected]>
|
||
// Give up if we've reached the limit. We could emit a specific error here, | ||
// but httparse will produce meaningful error for us regardless. | ||
if limit == MAX_HEADERS_SIZE { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, this will also emit an error if self.buffer.len() > MAX_HEADER_SIZE
?
it's truncated below by std::cmp::min
a couple lines above
Alternative to #34.
I hope @tomaka can appreciate the number of hoops I had to jump through to get this to work properly. The way headers were previously parsed totally screwed with lifetimes here and prevented zero-copy header exposure (also the reason why
path
was previously an ownedString
).What made this possible is realization that WebSocket handshake request does not contain body, thus we can safely borrow stuff from the buffer until a response needs to be sent (at which point buffer is cleared regardless).
Side effect: removed two allocations from request handling, not that it was a bottleneck, but hey.
BREAKING CHANGES:
ClientRequest::path()
will default to"\"
if omitted in request (was empty string).ClientRequest::key()
now returnsWebSocketKey
(alias of[u8; 24]
), was&[u8]
.ClientRequest::into_key()
is gone.Response::Accept
'skey
field is nowWebSocketKey
(alias of[u8; 24]
), was&[u8]
.handshake::Error
has new variants.Server::receive_request()
will only attempt to read headers up to 8KiB.ADDED
ClientRequest::headers()
returns a newRequestHeaders
struct withhost
andorigin
fields, exposing theHost
andOrigin
header values (&[u8]
andOption<&[u8]>
respectively).