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
Feature request: Provide a way to read _all_ values of a cookie by name #813
Comments
We have an api called const cookies = Cookies.get();
Object.keys(cookies).filter(byname('cookieName')).map(key => ({ name: key, value: cookies[key] })); About this: Cookies.list('foo')
// => ['a', 'b', 'c']
Cookies.list()
// => { foo: ['a', 'b', 'c'] }
Cookies.list('bar')
// => [] It returns a different return type (Array Literal -> Object Literal -> Array Literal) based on the arguments, which is a bad API design. Return types should be predictable and stable in a method call regardless of the number of arguments. (.get() is an exception to this rule due to historical reasons and byte-size optimizations by not having too many API tokens that have to be supported for a long time) |
Cookies with the same name but from different scopes do all appear in |
That makes sense, For
Certainly a v3 feature, just need to make sure it passes Browserstack as I'm afraid we may get issues with shadowing. So in summary: This issue is to add the ability to return more than one cookie with the same name which is impossible today by |
I thinking of changing the api in a future version, with both
The arrays might rather be a
|
Alternatively, in a future version, there could be the |
That solves the For example, - const cookies = Cookie.get(); // Code gets all cookies, first implementation
+ const cookies = Cookie.get('authId'); // Author changes the code to get only auth-related cookies in the future without changing the processing. The assumption here is that the type is consistent.
processAuthCookies(cookies);
[...]
const processAuthCookies = (cookies) => {
// This breaks simply from a change of a parameter of a code the user does not control.
// The cause/effect is so far from it that it's almost impossible to debug and takes hours depending on the complexity of the app
console.log(cookies.map(cookie => processAuthId(cookie.authId)));
}; Of course, we can justify any API decision with "you should read the docs". It's just that the Principle of Least Surprise is violated in that case. |
I see the why hands in the eyes :D The only concern I guess is that if we start changing return types based on input it will create a lot of confusion for the reasons above. |
I'm confused.. could you explain which return type we plan to change based on input? I understand that we are currently changing the return type in |
Elsewhere I try to convince everyone that these days, especially with some IE peculiarities out of the way, you don't need a library any longer to work with cookies, haha: const s = 'foo=bar; foo=baz'
Array.from(s.matchAll(/(?![ ;])([^=]+)=([^;]+)/g)) // all the cookies (sure would need to map the iterator/array to cleanup the result) :) |
That's what I mean: We're talking about the same thing. Input = argument. My mental model is Changing the return type of the function/method by not providing an argument is as much a surprise. I believe that to be one of the worst decisions we've ever made in regards to js-cookie API design, not worse than the old --
Same here, tough you still need js-cookie to encode characters disallowed by the spec, just because browsers allow certain chars doesn't mean servers always will. That's IMHO the only value proposition of this project in modern days, and that's why this has been relevant for decades -> we design once, works forever. Not many projects have had this mindset, and that's why you have what you have in the frontend tooling/community. |
Big ➕ to this - was just trying to match existing behavior of It sounds like there are three options:
If we're OK defining a new pattern for a new function, my vote would go to all(): Array<{name: string, value: string}> and then letting filtering by name occur in userland. const fooCookies = Cookie.all().filter(c => c.name === 'foo') function all () {
var cookies = document.cookie ? document.cookie.split('; ') : []
var jar = []
for (var i = 0; i < cookies.length; i++) {
var parts = cookies[i].split('=')
var value = parts.slice(1).join('=')
try {
var name = decodeURIComponent(parts[0])
jar.push({ name, value: converter.read(value, name) })
} catch (e) {}
}
return jar
} |
That would mean we‘d leave I think first of all I would want to figure out whether all relevant browsers behave the same. |
Apart from that, I‘m also in favor of |
Though I‘m asking myself, — thinking out loud here — what kind of use-case this really is. You‘d have two (or more) cookies with the same name and there was no way to distinguish between them (by age or some other attribute). Returning the first seems as good/useful as returning a list.. (and you could always resort to |
That's a great question. If you're reading this, please comment with a real-life scenario of returning multiple cookies with the same name. We can always abide by technical implementations but js-cookie is known by its simple API and going an extra mile to develop 20% of the work that gives 95% - not 80% - of the value. Also, we optimize for byte size. Unless the use case is real and relevant and there's no other way of doing it in userland, we historically always favour bytes over features. One of the features we don't wanna break if possible is "< 800 bytes gzipped!" |
What prompted myself opening this ticket was a migration we ran to move a cookie from being shared with subdomains ( A comparable issue could be the treatment of headers in serverside Node.js - in the original release headers were treated as a
I bet we can make that happen ;) |
I did a relatively superficial experiment, three mayor browsers behave the same: https://github.com/js-cookie/js-cookie/wiki/Cookies-with-duplicated-name |
What's interesting to note as well is that the nested cookie consistently comes first.. probably a side-effect of adhering to
|
In the case of two (or more) cookies with the same name visible to the current scope, so far we've been retrieving the first one we find for `get('name')` and the last one for `get()` (because in the latter case we continued the loop and eventually overwrote a duplicate cookie name in the returned result/object). This change makes the behavior at least consistent, so there aren't different cookies in the result for both calls. We should be returning all visible cookies though, but the API change for this is still being discussed.. see: #813 Also see: https://github.com/js-cookie/js-cookie/wiki/Cookies-with-duplicated-name
In the case of two (or more) cookies with the same name visible to the current scope, so far we've been retrieving the first one we find for `getCookie()`, but the last one for `getCookies()` (because in the latter case we continued the loop and eventually overwrote a duplicate cookie name in the returned result/object). This change makes the behavior at least consistent, so there aren't different cookies in the result for both calls. Changing the api to include both cookies in the result seems reasonable. For context: js-cookie#813
what happened for me was in testing for the issue in #828, that the |
Any reason |
|
@carhartl Not sure what you mean? I can read the cookie in Application panel of Chrome DevTools, not with |
@carhartl A visual of what I'm talking about |
If you can‘t read it with |
Thanks. Never really experimented with cookies before. Am just trying to figure out a way to programmatically determine when I am logged in to GitHub. |
Hi I wanted to ask for the state of this, add our real world problem and report some browser specific behavior that I found:
Scenario A: We have two major versions so far and also versioned the cookies IN the cookie (default cookie name is the same). When user comes to sub.domain.com, with an old cookie from domain.com consent banner shows up, as it's not a "v2 cookie". Component stores users decision in new cookie (v2) for sub.domain.com. Scenario B: User previously visited domain.com and accepted (gave cookie consent). Then user comes to sub.domain.com (consent banner does not show up, as it's a valid "v2 cookie"). User goes to settings and changes consent (declines). However, in both cases I would expect js-cookie/the browser to return the more specific cookie (which would be sub.domain.com). But I realize this is not possible for you due to technical limitations.
I'm happy to provide additional info or support otherwise if needed! |
@chmerk Hi, thanks for your comment. As stated in the contributing guidelines, in order to take any further action we need a Short, Self Contained, Correct (Compilable), Example that shows a problem with js-cookie. As I see this seems to be an issue with browsers and your business domain model so it should be reported to them, js-cookie is only a Façade on browser cookies and we don't implement any subdomain-specific logic or browser-compatible workarounds as there's only so much we can do with JavaScript. For support, you can create a question in StackOverflow under the tag Don't let this stop you from keep contributing to js-cookie 👍 Thank you! |
thanks for the quick reaction. This was not meant as a support question but to provide additional real-life examples in support of the OP. For clarity, I'll phrase the problem to be more js-cookie-specific: So, I would be happy to see something like .list() or .all() (or an adaption of get()) in js-cookie to deal with this sort of situations. Just interested: Why didn't this land in v3? Again: Thanks a lot! :) |
This thread is mostly about returning an array of cookies whenever you do Cookies.get(name) so that we can account for cookies with the same name, then it morphed into which browsers support showing many cookies and the attributes limitations of it. The use case here is a cookie that has the exact same attributes, only set in a different subdomain or domain where it's still accessible in @carhartl made some research before but AFAIK it hasn't been extensive. I don't think we do get them for all browsers, and we may hook into an implementation detail and bring more questions/support issues our way, but happy to be proven wrong. The work required here is an extensive research on the duplicated cookies in different subdomains so that browser-specific limitations don't make it impossible for us to implement that on js-cookie side. @chmerk That's probably why we haven't done this in V3 since there hasn't been enough cross-browser research in this area at the time. The questions the research need to answer:
If anyone wanna help with "1" I can help with "2" and "3" after that. |
Is your feature request related to a problem? Please describe.
Whenever the same cookie name is set with differing domain or path semantics, multiple instances of that cookie are added to
document.cookie
. For example, try running the following code at https://example.com/somepathThe current API of
js-cookie
will only return the first value that matches the cookie name (Cookies.get('foo') === 'c'
).As an application developer, this means it is impossible to access certain cookie values, or even realize that you've gotten yourself into this situation, without looking at
document.cookie
yourself directly.I recognize that this is not the default case for most situations, but it is still a scenario that developers can find themselves in. For example, suppose an application migrates its cookies from being stored on a root domain, to being shared across all subdomains (or vice versa!) - being able to read two instances of the cookie name is a useful feature. Developers can use that information to attempt to unset cookies,
console.log
out debug info, etc.Describe the solution you'd like
I'd love a new method -
Cookies.list()
- with similar semantics toCookies.get()
. Pass in the name of the cookie to retrieve and it will return all values stored for that name. Pass in nothing and it will return an object containing all lists of cookies.Given a
document.cookie
offoo=a; foo=b; foo=c
, I'd expect the following output:a rough implementation might look very similar to the existing implementation for
get
:Describe alternatives you've considered
Obviously, a developer can access
document.cookie
directly, but they'll also need to reimplement the logic inconverter.read
to ensure that they're getting the same values. At that point, they've reimplemented half of this library themselves.Unlike issues like #800, it is impossible to build this functionality from the existing API.
The text was updated successfully, but these errors were encountered: