-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Added cookie accessor/iterator to CookieContainer #44094
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
Tagging subscribers to this area: @dotnet/ncl |
CookieContainer tries to be thread-safe, although I don't see that in the documentation. If other threads add or remove cookies while you enumerate them, does that invalidate the enumerator? |
It could invalidate it and throw an exception on the next iteration, or it could iterate an older "snapshot" similar to how The only bad version would be one that doesn't make any guarantees and just silently corrupts itself to miss entries or return duplicate ones. |
Seems like just implementing |
Actually, we already did this. See dotnet/corefx#30080. I knew it sounded familiar. |
@geoffkizer That's weird, I just made a new project using .NET 5.0 and I still can't get it to work: Maybe it was changed after? I don't see it in master either https://github.com/dotnet/runtime/blob/master/src/libraries/System.Net.Primitives/src/System/Net/CookieContainer.cs#L94 |
Sorry, the linked issue is about CookieCollection, not CookieContainer. |
Ah that makes sense. Agree that implementing |
Could even implement Implementing Perhaps, instead of having |
Yeah, the more I think about this, the more I'm kinda concerned about enumerating a CookieContainer directly. Another suggestion would be to add a method that creates a snapshot as a CookieCollection, which you can then iterate as you want without worrying about someone else mutating it. Edit to add: We already have a GetCookies(uri) method which returns a CookieCollection for a specific uri: https://docs.microsoft.com/en-us/dotnet/api/system.net.cookiecontainer.getcookies?view=net-5.0#System_Net_CookieContainer_GetCookies_System_Uri_ So adding something like GetAllCookies() that returns a CookieCollection for all uris would fit nicely with this. |
Couldn't we do that (i.e. create a snapshot) internally and iterate over that one in |
Why is that better? |
I suppose it's a matter of opinion, and I hold mine lightly - Since it's a container object (like lists or sets), it should be iterable using a for-each loop or LINQ query. What are your thoughts on doing both i.e. |
I think that since we have Then the question is, should we also add an enumerator that calls GetAllCookies under the covers? It doesn't add any new capability, and it might not be obvious to users that it implicitly does a snapshot. So I think I'd lean toward not doing this.
I'm somewhat sympathetic to this, but I think this is a bit of an unusual case. CookieCollection is the collection class for Cookies and supports the methods you'd expect -- IEnumerable, ICollection, etc. CookieContainer is optimized for multithreaded access when you are adding/updating/etc cookies. As long as it's easy to go from one to another, I think that's sufficient. |
Sounds reasonable to me, let's go with |
Huh, CookieCollection has a System.Net.Cookie this[string name] indexer, but CookieCollection.Add allows multiple cookies with the same Name to be added to the collection, provided that the Domain or Path differs. I suppose CookieContainer.GetAllCookies() can return a CookieCollection, then. |
cc @antonfirsov -- you know this code better than I do, any thoughts? |
@KalleOlaviNiemitalo considering the first part of the sentence, I guess you rather wanted to say " I suppose CookieContainer.GetAllCookies() can return a CookieCollection, then." :)
@geoffkizer I agree. Adding a single enumerator method seems to be the safest thing to do here. I don't think we should return The only remaining open question before an actual API proposal is whether we should return an |
Of course |
@antonfirsov, isn't that exactly what I wrote already? To elaborate: The CookieCollection.Item[string name] indexer gives the impression that CookieCollection (source) has at most one cookie for each name. CookieCollection.Add(Cookie) however has no such restriction: it calls CookieCollection.IndexOf(Cookie), which uses CookieComparer (source), which compares Name, Domain, and Path. Thus, it would be technically possible to have CookieContainer.GetAllCookies() return a CookieCollection, even if that might look a bit odd. |
I have to bump this issue while a lot of developers still using either Reflection or As for me it's doesn't matter how accessing to all Cookies will be implemented. I prefer any way to get all Cookies because it's better than no way. Just need something better than this extension: public static CookieCollection GetAllCookies(this CookieContainer container)
{
CookieCollection allCookies = new CookieCollection();
Hashtable domainTable = (Hashtable)container.GetType()
.GetRuntimeFields()
.First(x => x.Name == "m_domainTable")
.GetValue(container);
FieldInfo pathListField = null;
foreach (object domain in domainTable.Values)
{
SortedList pathList = (SortedList)(pathListField ??= domain.GetType()
.GetRuntimeFields()
.First(x => x.Name == "m_list"))
.GetValue(domain);
foreach (CookieCollection cookies in pathList.GetValueList())
allCookies.Add(cookies);
}
return allCookies;
} The job is loading+saving all the Cookies for Also the most popular answers to this problem on StackOverflow have ~77k views in total: 1, 2. |
I don't think we have consensus about the API here. |
@shravan2x Upon thread-safe Suggestion1. Add method public CookieCollection GetAllCookies(); Suggestion2. Add overload for public CookieCollection GetCookies(); I think |
@geoffkizer to me the only open question was if public CookieCollection GetAllCookies(); If you agree, I recommend to push this into the API review queue, so we have a chance to get this into 6.0. It's a trivially small feature, and it's no fun that reflection+BinaryFormatter (🤯 ) workarounds keep spreading over stackoverflow as described in #44094 (comment). The number of upvotes on SO indicate that this is a visible API gap. |
@antonfirsov I agree that getting some API out for this functionality is more important than small differences in proposed APIs. At its core @aepot I prefer |
@shravan2x I guess you may edit the first post according to template linked in the API Review Process. |
Ok, I updated the initial post to reflect the consensus proposal and marked this as ready for review. Any feedback is welcome. |
@geoffkizer FYI: I updated top post to keep visible Original and Latest API proposals -- easier for following discussions ... |
I marked this as 6.0 so it will get reviewed in the near future. That doesn't mean this is committed for 6.0. |
Looks good as proposed namespace System.Net
{
partial class CookieContainer
{
public CookieCollection GetAllCookies();
}
} |
Background and Motivation
There's currently no way to access all cookies in a CookieContainer instance without known their domain names. CookieContainer also does not expose a list of domains it holds cookies for. I propose adding a
GetAllCookies()
method for this. It seems I'm not the only one with a use-case for it https://stackoverflow.com/questions/15983166/how-can-i-get-all-cookies-of-a-cookiecontainerLatest API proposal
Based on discussion below - #44094 (comment)
Original API proposal
or
The text was updated successfully, but these errors were encountered: