HttpClient does not send cookie when connecting via hostname - java

I'm using Apache HttpComponents HttpClient 4.4.1 to communicate with an ASP.Net SOAP service running on IIS (client and server are on the same host as it happens). The SOAP service returns a Set-Cookie header with a session token in response to its AuthenticateUser service. Example:
02 22:16:32.994 DEBUG <localhost-startStop-1> [org.apache.http.headers ] http-outgoing-1 << Set-Cookie: NTSSOCookie=50d2300d-31cf-4187-820f-83b29949f38b; expires=Sat, 02-Jul-2016 21:16:32 GMT; path=/
...
02 22:16:33.002 DEBUG <localhost-startStop-1> [rotocol.ResponseProcessCookies] Cookie accepted [NTSSOCookie="50d2300d-31cf-4187-820f-83b29949f38b", version:0, domain:palab46, path:/, expiry:Sat Jul 02 22:16:32 BST 2016]
Something peculiar I have observed is that if I connect to the server using just the hostname, the HttpClient library indicates that it has accepted the cookie returned from the server, but never attaches it to outgoing requests for the same connection. If however, I switch to using either the IP address or the FQDN of the server, the cookie is returned just fine.
I've verified the address, port and protocol are consistent across the authentication request and subsequent requests, and also that the cookie path and expiry date values are valid and consistent in all cases.
For kicks, I also checked the hostname and FQDN both resolve to the correct IP address.
What could be causing this odd behaviour?

Related

Java HttpClient doesn't keep TCP connection alive with HTTP/1.1 version

I configured java.net.http.HttpClient as shown below:
HttpClient client = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build();
Also, I have a simple Spring Boot (Tomcat) HTTP server, which is running on the 8080 port. For each request, I check incoming headers in a controller and the number of TCP connections using the next command: lsof -i -P | grep "TCP" | grep "8080".
When I make a GET request from client then exactly one TCP connection is created for each request. Incoming headers don't have any information about keep-alive
When I try to set keep-alive header directly I got the exception.
HttpRequest req = HttpRequest.newBuilder()
.setHeader("Connection", "Keep-Alive")
.uri(uri)
.build();
When I make a GET request from a browser (safari) then the browser adds keep-alive headers to each request and only one TCP connection is created for multiply requests (as expected).
When I set version HTTP/2 and make the request from the client then only one TCP connection creates for all requests (as expected):
HttpClient client = HttpClient.newBuilder().version(HttpClient.Version.HTTP_2).build();
As described here - both HTTP/1.1 and HTTP/2 have keep-alive property which is enabled by default, but as you can see from the examples above it doesn't work for HTTP/1.1 in my case.
Does anyone know how to configure HttpClient properly? Or maybe, I'm doing something wrong?

HTTPS redirects get lost through tunneling

I experience a problem while doing integration tests of our system, that usage of a JSF application via https always returns a 400 (forbidden) when coming back from a redirect after POST because of conversion to http. This only happens, if the request is done through a tunneled connection via jumphost.
So here's the setup:
Server has a WildFly running with an JSF application and an nginx which cares about incoming https requests from 443 and transfer them to the WildFly port
Server is in a closed network which is accessable via a jumphost which again can be accessed from my machine
An SSH connection establishes a tunnel between a local port on my machine and the 443 port on the server
The browser requests https://localhost:myport
Now, whenever I post something, e.g. the login, the redirected answer comes back with http scheme and thus gives me a 400. If I manually add https in the browser, the requests gets answered correctly.
A curl of the same URL gives me this:
curl -i -k https://localhost:8426
HTTP/1.1 302 Found
Server: nginx
Date: Fri, 23 Oct 2020 15:03:52 GMT
Content-Length: 0
Connection: keep-alive
Set-Cookie: INCENTCONTROL_JSESSIONID=[....]; path=/
Location: http://localhost:8426/login.xhtml
If I do the very same directly from a machine within the network of the server, everything is fine.
What has the tunneling to do with the problem and does anyone have an idea how to overcome it?

How to properly handle client "Connection: close" request on HTTP file server?

How do I handle properly a client Connection: close request field? As of now if I get this particular field I close the socket and wait for a following request from the client than reply again and start serving the data.
I don't know why my client/server communication is not working as the Apache Server I tested with.
Thanks for any clarifications...
Client/Server comunication:
CLIENT:
HEAD /stream.mpeg HTTP/1.0
Host: 127.0.0.1
User-Agent: SuperPlayer
Connection: Close
SERVER:
HTTP/1.0 200 OK
Date: Wed, 1 Jun 2011 20:05:13 GMT
Server: HTTP Server
Last-Modified: Mon, 06 Aug 2009 01:02:23 GMT
Accept-Ranges: bytes
Connection: Close
Content-Type: audio/mpeg
CLIENT:
HEAD /stream.mpeg HTTP/1.0
Host: 127.0.0.1
User-Agent: SuperPlayer
Connection: Close
SERVER:
HTTP/1.0 200 OK
Date: Wed, 1 Jun 2011 20:05:13 GMT
Server: HTTP Server
Last-Modified: Mon, 06 Aug 2009 01:02:23 GMT
Accept-Ranges: bytes
Connection: Close
Content-Type: audio/mpeg
231489172304981723409817234981234acvass123412323
21312hjdfaoi8w34yorhadl4hi8rali45mhalo3i,wmotw
345fqw354aoicu43yocq2i3hr
Client/ApacheServer Comunication:
CLIENT:
GET /test.mp3 HTTP/1.0
Host: 192.168.1.120
User-Agent: SuperPlayer
Connection: Close
SERVER:
HTTP/1.1 200 OK
Date: Wed, 01 Jun 2011 19:15:11 GMT
Server: Apache/2.2.16 (Win32)
Last-Modified: Thu, 29 Apr 2010 21:06:34 GMT
ETag: "14000000047049-4f75c8-4856680636a80"
Accept-Ranges: bytes
Content-Length: 5207496
Connection: close
Content-Type: audio/mpeg
...d.....<).0.. ..........<.#.. ( .h.$.J...1...i....A. ......c....a.9..!g.N...A. ........ ....>......|.......8....a......|..|N.............'>........?...C.....#..TJt.n .e...r.iL..#..IH...pR|.
Yes closing the socket is the right action to take. If the client is using this header properly, they are closing the socket on their end once they receive your response.
What I'm noticing here is that your server is not returning a Content-Length header. Even though the client is issuing a HEAD request, based on the W3C proposal (sec. 9.4):
The metainformation contained in the HTTP
headers in response to a HEAD request
SHOULD be identical to the information
sent in response to a GET request.
This method can be used for obtaining
metainformation about the entity
implied by the request without
transferring the entity-body itself.
This method is often used for testing
hypertext links for validity,
accessibility, and recent
modification.
The response to a HEAD request MAY be
cacheable in the sense that the
information contained in the response
MAY be used to update a previously
cached entity from that resource. If
the new field values indicate that the
cached entity differs from the current
entity (as would be indicated by a
change in Content-Length, Content-MD5,
ETag or Last-Modified), then the cache
MUST treat the cache entry as stale.
The key here is to make sure you're telling the client the size of the response without actually sending the data.
The Connection: close header just means that the client is expecting you to close the connection after sending the response. That also absolves you of having to send a Content-Length: header.
May I ask why are you using http 1.0 in the request?
There were no persistent connections in http 1.0, so the server is supposed to terminate the TCP connection after the response, whether you send Connection: close or not.
If you are using HTTP 1.0, there is no persistent connections as alexrs pointed, instead, Connection: keep-alive is being used with HTTP 1.0. On HTTP 1.1, you do not need that because HTTP connections are persistent by default on HTTP 1.1.
8.1.2 Overall Operation
A significant difference between HTTP/1.1 and earlier versions of HTTP
is that persistent connections are the default behavior of any HTTP
connection. That is, unless otherwise indicated, the client SHOULD
assume that the server will maintain a persistent connection, even
after error responses from the server.
Persistent connections provide a mechanism by which a client and a
server can signal the close of a TCP connection. This signaling takes
place using the Connection header field (section 14.10). Once a close
has been signaled, the client MUST NOT send any more requests on that
connection.
You can take a look at to the HTTP 1.1 RFC;
RFC for HTTP 1.1

cookie being set for www.example.com instead of example.com

I have java application running under tomcat which is fronted by apache webserver.
In my code I set cookie domain as
.example.com
but still my cookies shows up under www.example.com instead of under example.com in the client browser. What is so strange google analytics cookies shows up under example.com but my own code cannot store cookies under example.com?
Apache server is setup such that requests for example.com shows up as www.example.com in the client browser address bar if that is related to the issue ? I do need this otherwise different session id are generated for example.com and www.example.com which is bad for my applicaton.
Apache server is setup such that
requests for example.com shows up as
www.example.com in the client browser
address bar if that is related to the
issue ?
I am not 100% sure, but this looks like the root of the problem. How does Apache make the client browser to display www.example.com instead of example.com? Most probably, by redirecting each request for example.com to www.example.com. When the browser processes redirection, it sends a request for www.example.com and from that point on thinks that it is working with www.example.com.
Now, what happens when there is a Set-Cookie in the response header? It will obviously treat it as coming from www.example.com. There is no way a browser would allow such cookie to set its domain to .example.com because it would be a security problem. Imagine that mysite.somefreehosting.com sets a cookie for the domain .somefreehosting.com. Then someothersite.somefreehosting.com would receive this cookie which may lead to a lot of trouble. The standard specifies that such cookie should be rejected, but I wouldn't be surprised if some browsers are smart enough to handle such cases and to treat .example.com as www.example.com.
To be sure, I recommend that you check what exactly your site sends to the browser by sending a request with something like lwp-request script. You'll see what redirections are happening and what headers are actually set in the response, like this:
alqualos#ubuntu:~$ lwp-request -sSed http://google.com/
GET http://google.com/ --> 301 Moved Permanently
GET http://www.google.com/ --> 302 Found
GET http://www.google.co.il/ --> 200 OK
Cache-Control: private, max-age=0
Connection: close
Date: Sat, 18 Dec 2010 18:54:57 GMT
Server: gws
Content-Type: text/html; charset=windows-1255
Content-Type: text/html; charset=windows-1255
Expires: -1
Client-Date: Sat, 18 Dec 2010 18:54:57 GMT
Client-Peer: 173.194.37.104:80
Client-Response-Num: 1
Set-Cookie: PREF=ID=368e9cfd56643257:FF=0:TM=1292698497:LM=1292698497:S=s-Jur84NgaNH5Mzx;
expires=Mon, 17-Dec-2012 18:54:57 GMT; path=/; domain=.google.co.il
Set-Cookie: NID=42=bZ6goDV_b2MiWlTMONwiijaON5U_TBGB2_yNheonEwA1GVLU77EhyfUhk9Wvj70xTFrpvGy4s_aBp1UZtvRRnsnYjacjz_UVx0_iSr9R3nYXMyRtwkS5qV98_Egb16pZ;
expires=Sun, 19-Jun-2011 18:54:57 GMT; path=/; domain=.google.co.il; HttpOnly
Title: Google
X-XSS-Protection: 1; mode=block

Send http request from TCP client in java to Apache

I am trying to send a http request from a tcp client in java. I want to read the http request message from a text file and send the http request through my tcp client.
Http message
GET /index.html HTTP/1.1
Host:http://localhost/xampp/ (is this correct? I want to send request to my localhost)
From:xyz#something.com
Accept:text/html, text/plain
User-Agent:Mozilla/3.5.3
How can i do this?
Host:http://localhost/xampp/ (is this
correct? I want to send request to my
localhost)
I believe you should put at host only "localhost" instead of "http://localhost/xampp/".
I believe you should also modify "GET /index.html HTTP/1.1" to "GET /xampp/index.html HTTP/1.1"
Telnet
But I would first do some debugging via telnet, And if successful I would write code
telnet localhost 80
From wikipedia.com
Below is a sample conversation
between an HTTP client and an HTTP
server running on www.example.com,
port 80.
[edit] Client request
GET /index.html HTTP/1.1
Host: www.example.com
A client request (consisting in this case of the request line and only
one header) is followed by a blank
line, so that the request ends with a
double newline, each in the form of a
carriage return followed by a line
feed. The "Host" header distinguishes
between various DNS names sharing a
single IP address, allowing name-based
virtual hosting. While optional in
HTTP/1.0, it is mandatory in HTTP/1.1.
[edit] Server response
HTTP/1.1 200 OK
Date: Mon, 23 May 2005 22:38:34 GMT
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
Etag: "3f80f-1b6-3e1cb03b"
Accept-Ranges: bytes
Content-Length: 438
Connection: close
Content-Type: text/html; charset=UTF-8

Categories

Resources