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

Spring HTTP clients do not enforce RFC 6265 (cookies in a single header) [SPR-12196] #16810

Closed
spring-projects-issues opened this issue Sep 15, 2014 · 4 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: backported An issue that has been backported to maintenance branches type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Sep 15, 2014

Cédrik LIME opened SPR-12196 and commented

RFC 6265 mandates that all cookies be placed in a single Cookie HTTP header:
When the user agent generates an HTTP request, the user agent MUST NOT attach more than one Cookie header field.

Spring HTTP Client (using SimpleHttpClient) does not follow this requirement, which can break application using multiple cookies.
In my own tests, Apache https tends to be quite lenient, whereas IIS strictly follows RFC 6265.

Affected classes are:

  • org.springframework.http.client. SimpleBufferingAsyncClientHttpRequest#executeInternal()
  • org.springframework.http.client.SimpleBufferingClientHttpRequest#executeInternal()
  • org.springframework.http.client. SimpleStreamingAsyncClientHttpRequest#writeHeaders()
  • org.springframework.http.client. SimpleStreamingClientHttpRequest#writeHeaders()

All those classes should read when copying HTTP headers to the underlying connection:

for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
     String headerName = entry.getKey();
     if ("Cookie".equalsIgnoreCase(headerName)) { // RFC 6265
          String headerValue = StringUtils.collectionToDelimitedString(entry.getValue(), "; ");
          this.connection.setRequestProperty(headerName, headerValue);
     } else {
          for (String headerValue : entry.getValue()) {
                   this.connection.addRequestProperty(headerName, headerValue);
          }
     }
}

Fixing this bug in client (application) code is quite difficult, since those classes are package-private, final, and their state is private.
Hence this should really be taken care of in Spring Framework.


Affects: 3.2.11, 4.1 GA

Issue Links:

Backported to: 4.0.8, 3.2.12

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

Fixed for both Simple*ClientHttpRequest and HttpComponents*ClientHttpRequest on master; this will be available in the next 4.1.1 snapshot. To be backported to 4.0.8 and 3.2.12 as well.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

Actually, since Spring doesn't seem to set the Cookie header itself anywhere, I suppose you are programmatically adding several Cookie headers yourself? Could you - as a workaround - manually merge those header values into the same line and set it as such?

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

This is available in the latest 4.1.1 and 4.0.8 snapshots now. It would be great if you could it a try... We intend to backport this to 3.2.12 as well but we'd like to verify the fix first.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Cédrik LIME commented

Hi Juergen,

Thanks for integrating this fix.
I have tested my application with the current Spring master, and it works beautifully.

Regards,
Cédrik

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: backported An issue that has been backported to maintenance branches type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants