HttpClient object Timeout property vs DefaultRequestHeaders Keep-alive - asp.net-web-api

Could you please let me know the difference between HttpClient object Timeout property vs the DefaultRequestHeaders "Keep-Alive".
httpClient.Timeout = TimeSpan.FromMinutes(10);
vs
httpClient.DefaultRequestHeaders.Add("Connection", "Keep-Alive");
httpClient.DefaultRequestHeaders.Add("Keep-Alive", "600");

The timeout is the time the client will wait for a response. Keep-alive is for reusing an already opened TCP connection for subsequent HTTP requests.

Related

Jetty upgrade (9.2.24 -> 9.4.10) fails with websocket (UpgradeException)

I am in the process of upgrading our jetty from 9.2.24 to 9.4.10, for an app that works extensively with websockets.
I have an existing test (junit) that sets embedded jetty, registers to it rest resource and websocket servlet and then tests to see if they can be accessed.
The test works perfectly well when jetty is at version 9.2.24. An attempt to move to version 9.4.10 with the very same code fails with
java.io.IOException: Connect failure
at org.eclipse.jetty.websocket.jsr356.ClientContainer.connect(ClientContainer.java:232)
at org.eclipse.jetty.websocket.jsr356.ClientContainer.connectToServer(ClientContainer.java:255)
...
Caused by: org.eclipse.jetty.websocket.api.UpgradeException: 400 Bad Request
at org.eclipse.jetty.websocket.client.WebSocketUpgradeRequest.onComplete(WebSocketUpgradeRequest.java:522)
at org.eclipse.jetty.client.ResponseNotifier.notifyComplete(ResponseNotifier.java:193)
The websocket definition on server side is based o JSR356 spec (i.e. extends EndPoint). The websocket client used to access the websocket is also based on the javax.websocket (i.e. ContainerProvider.getWebSocketContainer().connectToServer(Endpoint instance...)) - where the websocket container is effectively a jetty one...
The server sets up perfectly. The problem is only when trying to access the websocket. I have debugged and could not find any difference in the way the client initiates and sends the websocket request. In particular the request has a the 'upgrade' header set to 'websocket' as expected.
So I could only assume that the problem is in the way the websocket resource is registered in the embedded jetty. I have debugged the working flow (with 9.2.24) and found the most early place where the connection is accepted in jetty (one of the selector threads at AbstractConnection). but from some reason I am not getting to that point for the websocket when working with 9.4.10
I have read several resources and SO question (e.g. this question) and could not found anything that will help me with this problem.
I am in a dead end.
Here is the key elements in the relevant code of the server registration (I also have another rest resource along with the websocket one):
// web socket
ServletContextHandler wsContext = new ServletContextHandler(ServletContextHandler.SESSIONS);
wsContext.setContextPath("/ws_api");
ServerContainer container = WebSocketServerContainerInitializer.configureContext(servletContextHandler);
container.addEndpoint(new BasicServerEndpointConfig(container.getClient(), endpointClassObject, path)
// rest handler
ServletContextHandler restContext = new ServletContextHandler(ServletContextHandler.SESSIONS);
restContext.setContextPath("/rest_api");
...
ServletHolder sh = new ServletHolder(...);
restContext.addServlet(sh, "/*");
final HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]{wsContext, restContext, new DefaultHandler()});
server.setHandler(handlers);
Help...
Update (additional information per Joakim Erdfelt request):
I am at class HTTPConnection class, in BP at onComplete() method, fetching the request headers from the _channel._fields object I get:
The response object's status is 200 (and not 101 as expected):
My endpoint object is part of a large inheritance chain. It is full of boilerplate business logic code that I need to remove before I can upload it, but in the root stands the javax.websocket.Endpont class, where we implemented only the onOpen(Session session, EndpointConfig config) method. I am not getting to that method when debugging, seems to fail long before...
Your request headers looks like this ...
Accept: application/json, application/*+json
Accept-Encoding: gzip
Cache-Control: no-cache
Connection: keep-alive
Content-Type: application/json
Host: 127.0.0.1:8080
Pragma: no-cache
Sec-WebSocket-Key: sMQPm6Cf00itLII3QBb4w==
Sec-WebSocket-Version: 13
Upgrade: websocket
User-Agent: Java/1.8.0_144
That is an invalid WebSocket Upgrade Request.
The most glaring omission is
Connection: upgrade
But there's also other fields that a compliant WebSocket Client would never set.
Content-Type: application/json
Accept: application/json, application/*+json
Accept-Encoding: gzip

Ruby: Persistent HTTP client not receiving response on second request

I am trying to create an HTTP client that uses persistent connections. My Code works when I send my first request and get my first response. However, when I send a second request, I am unable to get a second response. I am not sure why? I got the same error when I was coding in C.
Here is the code
require 'socket'
include Socket::Constants
socket = Socket.new( AF_INET, SOCK_STREAM, 0 )
sockaddr = Socket.pack_sockaddr_in( 80, 'www.google.com' )
socket.connect( sockaddr )
# This Works
socket.write( "GET / HTTP/1.0\r\n\r\n" )
results = socket.read
# This Works
socket.write( "GET / HTTP/1.0\r\n\r\n" )
# THIS DOESN'T WORK
results = socket.read
I do not want to use built libraries like Net::HTTP. What do I need to do to make this work?
You cannot make 2 HTTP requests on the same connection, unless you've told the server that you're expecting to do so. This is how HTTP persistent connection works. At a minimum, you have to make sure to add this to your request header:
Connection: keep-alive
Servers have differing support for persistent connections, although it's become common for servers to support basic persistent connections. Here's an SO question that asks What exactly does a “persistent connection” mean?
Start there, and you'll find what you need to know to make persistent connections work correctly. You may have to check the HTTP response headers for an indication that the server will honor your request, or you may have to check that the server didn't simply close the connection when it was finished writing the first response. On your final request through a persistent connection, you should also specify the header:
Connection: close
Also check out these resources:
IETF HTTP 1.1 specification
W3 HTTP 1.1 section 8: Persistent Connections
Safari Books Online HTTP: The Definitive Guide - Persistent Connections

How to prevent establishment of SSL connection on each request

I use jersey 1.7. My client communicates with server over HTTPS. I figured out that HTTPS connection is established for each different request (URL). I would like to keep the same connection for multiple requests during specific period of time. I configure the client as it is describe in https://blogs.oracle.com/enterprisetechtips/entry/consuming_restful_web_services_with and send request via WebResource.Builder
public Response post(String actionName, Request request) {
WebResource webResource = rwsClient.resource( serverURL + actionName);
WebResource.Builder requestBuilder = webResource.accept(MediaType.APPLICATION_XML_TYPE);
Response response = requestBuilder.post(Request.class, request);
return response;
}
Connections from HTTP 1.1 requests are considered persistent unless declared otherwise.
If your client is making HTTP 1.0 request, they can pass the header "Connection: Keep-Alive"
Then you have to look at the connection timeout settings of your web servers. For Apache 2.2 for example, it is very low at only 5 seconds by default. Check your web server documentation.

How to make Symfony2 return HTTP Response with Connection: Keep-Alive?

I'm using Symfony2 to create a REST API server for my application in the backend, and was thinking of reusing the same HTTP connection for subsequent queries using Http Keep-Alive, but after every query, I see a Connection: close in the response header.
Is there a way to tell Symfony2 to don't close the connection after each response and wait for more Request headers?
In your case it seems that the best solution is to write kernel.response event listener. And modify your request like $response->headers->set('Connection', 'Keep-alive')

Problem with webclient: Expectation failed?

I have a custom Http Handler which manipulates HTTP POST and GET. I got the project working on a seperate isolated server now need to put it in production...
using (var client = new WebClient())
{
client.Credentials = CredentialCache.DefaultCredentials;
client.UploadFile("serverlocation:port", fileToUpload);
}
For some reason now when using client.UploadFile("", file); i.e. forcing the HTTP POST
System.Net.WebException: The remote server returned an error: (417) Expectation failed.
at System.Net.WebClient.UploadFile(Uri address, String method, String fileName)
What could this be? I know the code works, so what else? Maybe the server blocks HTTP POST requests?
I have tried adding:
ServicePointManager.Expect100Continue = false;
But have had no success though i'm not 100% sure where this code should before, I assume before i'm using the WebClient
Edit 0 :
I have just read the following:
Because of the presence of older implementations, the protocol allows
ambiguous situations in which a client may send "Expect: 100-
continue" without receiving either a 417 (Expectation Failed) status
or a 100 (Continue) status. Therefore, when a client sends this
header field to an origin server (possibly via a proxy) from which it
has never seen a 100 (Continue) status, the client SHOULD NOT wait
for an indefinite period before sending the request body.
I believe this request is going through a proxy, which may have something to do with the issue.
Edit 1:
Believe this problem has to be with 100-continue because, using fiddler to see exactly what my application is sending with WebClient.UploadFile shows this:
POST http://XXX.XXX.XXX.XXX:8091/file.myhandledextension HTTP/1.1
Content-Type: multipart/form-data; boundary=---------------------8ccd1eb03f78bc2
Host: XXX.XXX.XXX.XXX:8091
Content-Length: 4492
Expect: 100-continue
Despite having put that line: ServicePointManager.Expect100Continue = false; before the using statement. I don't think this line actually works.
I ended up solving this by putting the ServicePointManager.Expect100Continue = false; in the constructor for the calling WebClient class.
Then I used Fiddler to examine the POST request to ensure Expect: 100-continue was not in the request anymore.

Resources