-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
feat(headers): use a Vec + a map for Cookie #1153
Conversation
Use a Vec and a map for the Cookie header in order to satisfy the need for both duplicate names (keys) from a client perspective and single value for a given key from a server perspective . BREAKING CHANGE: This change the format of the cookie header, any previous implementation will have to be changed.
As part of the larger discussion in #1145 This is a first stab to make sure that's going in the right direction.
|
Thanks for contributing! Unfortunately, I'm here to tell you there were the following style issues with your Pull Request:
Guidelines are available at https://github.com/hyperium/hyper/blob/master/CONTRIBUTING.md This message was auto-generated by https://gitcop.com |
Use MapVec instead of HashMap for the Cookie header as per sugestion from @seanmonstar for performance purpose.
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.
Thanks for exploring this with me. I believe the code in #1152 may be in a slightly better place, but we wouldn't have gotten there without your efforts to bring up the question and discuss how to solve it!
|
||
|
||
/// Clear the current Cookie, and add one with specified name and value. | ||
pub fn set<T: Into<String>>(&mut self, name_tref: T, value_tref: T) { |
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.
My understanding of the suggestion for this method was to clear the values of only this key. This would seem confusing:
let mut cookie = Cookie::new();
cookie.set("foo", "bar");
cookie.set("baz", "quux");
// where did my foo=bar go!
assert_eq!(cookie.to_string(), "baz=quux");
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 understood the suggestion as push()/append() to add an extra cookie name/value to the header, and set() to for the entire header to this one value.
try!(f.write_str("; ")); | ||
let mut first = true; | ||
for pair in self.cookies.clone() { | ||
let cookie = format!("{}={}", pair.0, pair.1); |
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 would allocate a brand new String
, before then writing it to the formatter. It can be done without the temporary allocated, such as write!(f, "{}={}", key, val)
.
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.
Great point. Thanks.
#[derive(Clone)] | ||
pub struct Cookie { | ||
cookies: Vec<(String, String)>, | ||
index: VecMap<String, String>, |
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.
The VecMap
is sufficient on it's own. There no need to double the strings here. The VecMap
has insert
and append
, and iter
gets all the key-value pairs, with duplicates.
Also, a Cow<'static, str>
can be used, which allows someone who wants to set the same key and value on all cookies to do so without allocating and copying memory for it:
let mut cookie = Cookie::new();
// no allocation or copy required
cookie.set("foo", "bar");
// dynamic string, use a String
cookie.set(nonce_key.to_string(), nonce_val.to_string());
@@ -27,10 +28,15 @@ use std::str::from_utf8; | |||
/// ]) | |||
/// ); | |||
/// ``` | |||
#[derive(Clone, PartialEq, Debug)] | |||
pub struct Cookie(pub Vec<String>); | |||
#[allow(missing_debug_implementations)] |
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.
We'd still want a Debug
implementation. It can use formatter.debug_map()
.
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.
Agreed, but with my implementation, I would have had to add a Debug trait to VecMap. I wanted to get the code out fast for sake of discussion, rather than spend too many hours on an implementation that wasn't going to be used.
Thanks for taking the time to go through my code and the comments, this is really helpful. |
Use a Vec and a map for the Cookie header in order to satisfy the need
for both duplicate names (keys) from a client perspective and single
value for a given key from a server perspective .
BREAKING CHANGE: This change the format of the cookie header, any
previous implementation will have to be changed.