Skip to content
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

New HTTPHeaderDict class for response headers with multiple header value support #4282

Closed
wants to merge 5 commits into from

Conversation

the-allanc
Copy link

I personally wanted something like this while writing my own Requests-related library, but I can see other people also have wanted something like this - #3957 and #4214 both mention it in terms of handling Set-Cookie headers.

I've written an subclass implementation of CaseInsensitiveDict which is compatible with all the current usage (according to the tests), but adds new methods for clients that want to deal directly with unjoined headers. I've also added quite a number of tests and made slight changes to the documentation in relation to it.

@codecov-io
Copy link

codecov-io commented Sep 10, 2017

Codecov Report

Merging #4282 into master will increase coverage by 0.26%.
The diff coverage is 98.36%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #4282      +/-   ##
==========================================
+ Coverage   88.66%   88.93%   +0.26%     
==========================================
  Files          18       18              
  Lines        2021     2079      +58     
==========================================
+ Hits         1792     1849      +57     
- Misses        229      230       +1
Impacted Files Coverage Δ
requests/adapters.py 92.99% <100%> (ø) ⬆️
requests/structures.py 98.97% <98.3%> (-1.03%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update fdb9b75...5cbd6dd. Read the comment docs.

@kennethreitz
Copy link
Contributor

kennethreitz commented Sep 11, 2017

I generally like this.

This should be a PR against the proposed/3.0.0 branch, though, not master.

@kennethreitz
Copy link
Contributor

I also wouldn't be opposed to the name CaseInsensitiveMultiDict

@kennethreitz
Copy link
Contributor

kennethreitz commented Sep 11, 2017

I haven't checked, but I'd like this API to be compatible with Flask/Werkzeug's MultiDict, if possible.

Copy link
Contributor

@kennethreitz kennethreitz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So yeah, requested changes:

  • Make this against the proposed/3.0.0 branch, instead of master:
  • Rename to CaseInsensitiveMultiDict
  • Use same API as Flask/Werkzeug's MultiDict.

@kennethreitz
Copy link
Contributor

In general though, this looks real solid! ✨🍰✨

@kennethreitz
Copy link
Contributor

Good job with the tests too 🍪

@kennethreitz
Copy link
Contributor

You get a cookie.

@kennethreitz
Copy link
Contributor

I also really like that this is a subclass of CaseInsensitiveDict.

@the-allanc
Copy link
Author

With regards to MultiDict in werkzeug, it uses getlist and setlist. HTTPHeaderDict in urllib3 also uses getlist (it has no setlist equivalent). I was going to use the same naming convention, except that I'm storing and returning tuples.

I did have concerns about the lists being modified outside of HTTPHeaderDict (which tries to enforce that only string types are present). So it's either a case of::

  • Leaving the names as they are.
  • Using "list" names even though we're returning tuples.
  • Rename the methods and return lists (either copies or the underlying sequence).

@the-allanc
Copy link
Author

Renaming HTTPHeaderDict to MultiCaseInsensitiveDict is a bit more contentious - because it's not a generalised class (it's intended for string values only).

The main intent was to keep the exact same behaviour that we had in requests for response header processing, but to handle the concatenation of values ourselves (rather than letting urllib3 to do it for us). The concatenation of values is specific to HTTP headers (comma separation).

I could refactor part of the code and extract the Multi... part of the class into a separate class, and then inherit from that. We would need to decide what happens for general item access (I note that MultiDict returns just the first item).

@kennethreitz
Copy link
Contributor

I think what you have is good, then, unless we cast to lists.

@kennethreitz
Copy link
Contributor

Which seems silly to me.

@kennethreitz
Copy link
Contributor

I just wanted to provide a very familiar API to those who have used similar APIs before.

@kennethreitz
Copy link
Contributor

I've just always liked the name CaseInsensitiveMultiDict, and wish we had it. This is good though.

@the-allanc
Copy link
Author

OK, I've renamed the methods to getlist and setlist, and they now return lists, so that's more consistent with other implementations. Both urllib3 and werkzeug provide copies of the sequences, so we also do the same (we still use tuples under the hood, which makes me happy).

I was going to try and extract some of the code into a CaseInsensitiveMultiDict class, but there's too much nuance in trying to determine the best behaviour for such a generalised class (especially for the extend method, which tries to distinguish between items and sequences - how should it behave if you're using the dictionary to store sequences of sequences?)

I've made sure that this class is entirely backwards compatible with what we were using before - I wrote some of the tests using CaseInsensitiveDict and they still worked when I switched to HTTPHeaderDict for responses. Are you sure that you still want it against the proposed/3.0.0 branch?

@kennethreitz
Copy link
Contributor

@the-allanc definitely :)

P.S. good work!

@the-allanc
Copy link
Author

In that case, I'm closing this pull request in favour of #4290.

@the-allanc the-allanc closed this Sep 12, 2017
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 4, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants