You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This basic implementation of the Cookie concept is relatively similar to the existing cookie-rs crate, although it follows the pattern of the url crate in that it maintains a single underlying string representation and provides getter/setter methods slicing into the serialization. The current design eagerly sets/modifies the underlying serialization as various fields are set.
However, as @seanmonstar mentions in reqwest issue #14, there may be utility in having a "more opinionated" Cookie. To that end, some thoughts follow.
In terms of usage scenarios, I would typically envision the various handlers of cookies as: Server: The component producing Set-Cookie headers. This server may have a set of commonly generated cookies; that is, cookies with the same name, Domain, etc., but with changing values and possibly expiry information.
It may also receive Requests from clients which contain Cookie headers which are strictly of the form <name>=<value> (e.g. should not contain any attributes such as Domain, etc.).
Client: The component consuming Set-Cookie headers, possibly storing the results in a local store ("CookieJar"), and making Requests of a server containing Cookie headers as described previously.
CookieJar/Store: The client component actually concerned with the various attributes (Domain, Expiry, etc.) of a Cookie; the client itself will only be interested in the name/value pair (CookiePair).
As such, rather than a single, universal Cookie type, we could introduce this conceptual split in the API. For the server, following a builder-style pattern, avoiding creating/modifying the final string until actually need for placement into a Set-Cookie header:
// ``cooky`` libstructRecipe{name:String,max_age:u64,// 0 is not a valid max_age value, and as such can be used to signify "no MaxAge"expires:Option<Tm>,domain:Option<CookieDomain>,path:Option<CookiePath>,secure:bool,http_only:bool,}implRecipe{pubfnnew(name:String) -> Recipe{ ...}pubfnexpires_in(self,max_age:u64) -> Recipe{ ...}pubfnexpires_at(self,at:Tm) -> Recipe{ ...}// validation of domain & path handled elsewhere, so builder API doesn't need to return Result<..>pubfnset_domain(self,domain:CookieDomain) -> Recipe{ ...}pubfnset_path(self,path:CookiePath) -> Recipe{ ...}pubfnset_secure(self,secure:bool) -> Recipe{ ...}pubfnset_http_only(self,http_only:bool) -> Recipe{ ...}// instead of returning String, could return ``SetCookiePayload`` or somesuch specific typepubfnbake() -> String{// creates a cookie String with no value ("<name>=; Domain=...")}pubfnbake_value(value:&str) -> String{// creates a cookie String with the given value}pubfnstale() -> String{// creates an expired version of the cookie ("<name>=; Expires=<time in past>")}}// inside hyper / some http serverlet recipe1 = cooky::Recipe::new("foo").set_secure(true).set_domain("www.example.com".into());let recipe2 = cooky::Recipe::new("bus").set_http_only(true).expires_in(10);let response:ResponseBuilder = ...;response.headers_mut().set(SetCookie(recipe1.bake_value("bar")));// Set-Cookie: foo=bar; Secure; Domain=www.example.com
response.headers_mut().set(SetCookie(recipe2.bake());// Set-Cookie: bus=; HttpOnly; Max-Age: 10// .. responding to some other kind of request elsewhere
response.headers_mut().set(SetCookie(recipe1.stale());// Set-Cookie: foo=; Secure; Domain=www.example.com; Expires=1900-01-01T00:00:00Z
For the client receiving such a response:
// ``cooky`` libstructCookiePair{raw_cookie_pair:String,name_end:usize,value_end:usize,}implCookiePair{pubfnname() -> &str{ ...}pubfnvalue() -> &str{ ...}// possibly the empty stringpubfnpair() -> (&str,&str){ ...}}enumExpiry{SessionEnd,AtUtc(Tm),}structCookieStoreEntry{cookie_pair:CookiePair,expiry:Expiry,domain:Option<CookieDomain>,// "HostOnly" case encoded herepath:Option<CookiePath>,secure:bool,http_only:bool,created:Tm,last_accessed:Tm,}structCookieStore{ ... }implCookieStore{pubfnstore(raw_set_cookie:String,request_url:&Url){ .. }// or SetCookiePayload instead of String?pubfnget<U:IntoUrl>(url:U) -> Vec<&CookiePair>{ ...}}// Client code...// jar storing/retrieval in the below could be handled by the ``Session`` concept in the ``user_agent`` crate.// ... client processing some response from www.example.comifletSome(cs) = response.get::<SetCookie>(){// Set-Cookie: foo=bar; Secure; Domain=www.example.com// Set-Cookie: bus=; HttpOnly; Max-Age=10for c in cs {
jar.store(c,&request_url);}}// .. get some other url for www.not-example.comifletSome(cs) = response.get::<SetCookie>(){// Set-Cookie: baz=bang; Domain=www.not-example.comfor c in cs {
jar.store(c,&other_url);}}// ... client making a subsequent requestlet url = Url::parse("https://www.example.com/api/foo");let cookies:Vec<&CookiePair> = jar.get(&url);// get relevant cookies, only the www.example.com onesfor c in cookies {
request.headers_mut().Set(Cookie(c));}
(please excuse the naming, I can't help myself).
The text was updated successfully, but these errors were encountered:
This basic implementation of the Cookie concept is relatively similar to the existing
cookie-rs
crate, although it follows the pattern of theurl
crate in that it maintains a single underlying string representation and provides getter/setter methods slicing into the serialization. The current design eagerly sets/modifies the underlying serialization as various fields are set.However, as @seanmonstar mentions in reqwest issue #14, there may be utility in having a "more opinionated" Cookie. To that end, some thoughts follow.
In terms of usage scenarios, I would typically envision the various handlers of cookies as:
Server: The component producing
Set-Cookie
headers. This server may have a set of commonly generated cookies; that is, cookies with the samename
,Domain
, etc., but with changingvalue
s and possibly expiry information.It may also receive
Request
s from clients which containCookie
headers which are strictly of the form<name>=<value>
(e.g. should not contain any attributes such as Domain, etc.).Client: The component consuming
Set-Cookie
headers, possibly storing the results in a local store ("CookieJar"), and makingRequest
s of a server containingCookie
headers as described previously.CookieJar/Store: The client component actually concerned with the various attributes (Domain, Expiry, etc.) of a Cookie; the client itself will only be interested in the name/value pair (CookiePair).
As such, rather than a single, universal
Cookie
type, we could introduce this conceptual split in the API. For the server, following a builder-style pattern, avoiding creating/modifying the final string until actually need for placement into aSet-Cookie
header:For the client receiving such a response:
(please excuse the naming, I can't help myself).
The text was updated successfully, but these errors were encountered: