RestSharp Timeout - timeout

I have an issue with RestClient response is coming back as
"StatusCode: 0, Content-Type: , Content-Length: )"
with the ErrorMessage of
"The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing."
Is this a timeout on the url's end or my httpclient? Is request.timeout correct? It might take 5+ minutes for this request even though it's only 170KB of data due to their end being poorly optimized.
var client = new RestClient(url);
RestRequest request = new RestRequest() { Method = Method.Get };
request.Timeout = 300000;
request.AddParameter("access_token", AccessToken);
request.AddParameter("start_date", StartDate.ToString("yyyy-MM-dd"));
request.AddParameter("end_date", EndDate.ToString("yyyy-MM-dd"));
request.AddParameter("offset", offset.ToString());
var response = await client.ExecuteAsync(request);
var responseWorkLoads = JObject.Parse(response.Content).SelectToken("worklogs");

There are two timeouts that RestSharp allows you to set.
When you create a new instance of RestClient, you can specify the HttpClient timeout that will override the default 100 ms using RestOptions:
var client = new RestClient(new RestClientOptions { Timeout = 300000 });
As the wrapped HttpClient is instantiated and configured once per RestClient instance, setting the request timeout doesn't override that setting, otherwise the client won't be thread-safe.
The request timeout, on the other hand, overrides the client timeout if it is less than the client timeout. RestSharp creates a cancellation token source using the request timeout, so the request will be cancelled when the linked cancellation token cancels.
I believe that currently RestClient also doesn't set the failure reason properly when the client times out, only if the token gets cancelled. I will create an issue for that.

Related

Flickering HttpClient sometimes throwing IOException

I'm using java.net.http.HttpClient.newHttpClient() under Java 19 (Temurin) and perform sendAsync(...) requests from different treads on the same instance. I assume this is ok, as the javadoc states:
Once built, an HttpClient is immutable...
However, some requests fail with:
java.io.IOException: HTTP/1.1 header parser received no bytes
The weird thing is, it depends on the speed of my requests:
Requests every 5 seconds: 30% failure
Requests every 3 seconds: 0% failure
I've written a test for it:
private final HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://..."))
.setHeader("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofByteArray("[]".getBytes()))
.build();
#ParameterizedTest
#ValueSource(ints = {3, 5})
void httpClientTest(int intervalSeconds) throws Exception {
HttpClient httpClient = HttpClient.newHttpClient();
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
Thread.sleep(Duration.ofSeconds(intervalSeconds));
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
Thread.sleep(Duration.ofSeconds(intervalSeconds));
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
Thread.sleep(Duration.ofSeconds(intervalSeconds));
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
Thread.sleep(Duration.ofSeconds(intervalSeconds));
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
}
I've already tried the following:
Doing the same with curl on the command line. No requests fail whatever interval I try. So it's probably not a problem with the server.
Running the tests multiple times in parallel. Still the 5-second-intervals fail (then multiple times in parallel). So it's probably not a problem with the server.
Creating an HttpClient.newHttpClient() for every request. No requests fail whatever interval. So it's probably not a problem with the server but with an internal state of the HttpClient (although it claims to be immutable?).
Do you have an idea what I could do, without needing to create a new HttpClient for every request?
Here is the answer for the record: the java.net.HttpClient has a long default HTTP/1.1 keepAlive time, which is longer than what usual servers are configured with. This often results in the server closing idle HTTP/1.1 connections before the client does. If the server closes the connection at about the same time than the client tries to reuse it, some IOException might get raised.
If such exceptions are observed too frequently applications should consider adapting the default keepAlive time in the client to some value shorter than what the servers it connects to are using.
A default value for the HttpClient HTTP/1.1 keepAlive time can be specified on the command line with: -Djdk.httpclient.keepalive.timeout=duration-in-seconds
So for instance - if a server is configured with a keepAlive time of 5s, you could consider supplying -Djdk.httpclient.keepalive.timeout=3 or -Djdk.httpclient.keepalive.timeout=4 on the client's java command line.

Keep HttpRequest stream open while I issue a Client.post

My dart server has a function which receives a POST request from a client. I want to use information from that request to issue a POST to another server, then use the response from this other server to send a response back to the original client request. When I issue my POST to the other server, it closes the stream on the inbound client request and I can no longer respond. Is there a way to keep the request stream 'alive' while I do a POST? Or, is there another way to do this? I did try to issue the POST on a different Isolate, but that didn't help, the http request stream is still getting closed.
void postRequest(HttpRequest request) async {
final endPoint = 'https://www.anotherserver.com/information';
final client = Client();
final data = request.headers.value('data'); // Get data from client
final response = client.post(endPoint, body: data); // Send data to other server
// Do stuff with the response from endPoint server
// For simplicity of this example, just send back the response body back to the client
// This write call to the request causes an "Stream Sink Closed" exception
// It appears the POST call to the endPoint server, caused the client request stream
// to get closed.
request.response.write(response.body);
await request.response.flush();
await request.response.close();
}
I was not awaiting the client.post.... I need to do a better job of watching out for that.

Error 401 Unauthorized MVC .NET WEB APP

I am working with an API that wants me to send the token along with Header, specifically Content Header.
Here is my code block.
string path_current_user = "me";
var cookie = HttpContext.Request.Cookies.Get("cookietoken");
string cookie_with_token = "ACCESS_TOKEN="+cookie.Value+";";
client.DefaultRequestHeaders.Add("Cookie", cookie_with_token);
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
HttpResponseMessage response = await client.GetAsync(path_current_user);
I always get a 410 Unauthorized response. However, during debugging I can collect the values from the client object, and copy paste them into https://www.hurl.it, and I get the expected 200 OK response. So, I know the values that are being stored in the above code are correct. Its not a credentials issue for sure.
I have looked at almost 50 different threads on stack overflow, but none of them talk about this specification situation. Doing a GET with the Header Content set. Here is a screenshot of the HURL that works just fine.
Update 1 - Here is the API documentation for what I am trying to achieve.
Endpoint
GET me
Request Route
GET me
Headers
Content-Type: application/json Cookie: ACCESS_TOKEN="token characters
come here and remove the quotes"; Host: x.x
Update 2 - One of my mentors, recommended the following.
using (var httpClient = new HttpClient())
{
var request = new HttpRequestMessage(HttpMethod.Get, "https://small-project-api.herokuapp.com/me");
request.Headers.Add.("Content-Type", "application/json");
request.Headers.Add.("Cookie", cookie_with_token);
var response2 = await httpClient.SendAsync(request);
var responsestring = await response2.Content.ReadAsStringAsync();
}
He is of the opinion that may be such a request, as mentioned below, simply won't work in dot net. I am all but ready to give up here.

Sending OAuth token works in Postman but does not work in RestSharp

I tried to send a bearer token to an Auth0 API using Postman and it works perfectly.
I then tried the same using RestSharp (in c#) but it doesn't work at all.
Below is my code. I've tried many different formats but none of them work.. Is there any other way I can try to make it work?
var client = new RestClient("http://domain.auth0.com/api/v2/users");
RestRequest request = new RestRequest(Method.GET);
//request.AddHeader("authorization", "Bearer eyJhbGcJ9.eyJhdWQiOiJ6VU4hVWUE2.token");
//request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
//request.AddHeader("Accept", "application/json");
//RestClient client = new RestClient("http://domain.auth0.com");
//RestRequest request = new RestRequest("api/v2/users", Method.GET);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddHeader("Accept", "application/json");
request.AddParameter("Authorization",
string.Format("Bearer " + "eyJhbGciOI1NiIsI9.eyJhdWQiOiWmVhTWpD2VycyI6eyJhY.token"),
ParameterType.HttpHeader);
//request.AddParameter("Authorization",
// String.Format("Bearer {0}", token),
//ParameterType.HttpHeader);
var response = client.Execute(request);
PS: the token was changed.
The problem is that you're using an HTTP URL. When you issue the first request the token is included, but you receive a redirect response informing that you should be calling the HTTPS endpoint.
Since RestSharp will not include the token in the second request performed automatically due to the first redirect response you get an unauthorized response.
You need to update the URL to be HTTPS which will prevent the redirect and as a consequence solve your problem. If you want to make multiple authenticated request using the same client you also change your code to be:
using RestSharp;
using RestSharp.Authenticators;
class Program
{
static void Main(string[] args)
{
// Use the HTTPS scheme
var client = new RestClient("https://[domain].auth0.com/api/v2/users");
client.Authenticator = new OAuth2AuthorizationRequestHeaderAuthenticator(
"eyJhbGciJIUz.eyJhdWQi4QW5OXhCNTNlNDdjIn0.vnzGPiWA", // Update the token
"Bearer");
var request = new RestRequest(Method.GET);
IRestResponse response = client.Execute(request);
Console.WriteLine("{0}", response.StatusCode);
}
}
If you really need to handle redirects and still send the token, check: https://github.com/restsharp/RestSharp/issues/414

FSharp.Data HTTP request - unable to set request timeout

We have a simple F# console app that sends a HTTP POST request to a WebAPI endpoint via FSharp.Data Http.Request. We are using the customizeHttpRequest parameter in order to try to set the request timeout property. Our usage is as follows:
let response = Http.Request(
serviceEndpoint,
headers = requestHeaders,
body = requestBody,
silentHttpErrors = true,
customizeHttpRequest = (fun request -> request.Timeout <- 1000; request))
We are observing that our custom timeout is ignored (i.e. the request does not timeout after 1 second as in this example). We have also observed that the request will not timeout after the default System.Net.HttpWebRequest timeout of 100,000ms.
Is there an issue here, or are we not using the customizeHttpRequest parameter correctly?
FSharp.Data uses the asynchronous GetResponse method. According to MSDN, in that case the timeout set on the HttpWebRequest object isn't considered and handling the timeout is left for the client code to implement.
Unfortunately FSharp.Data doesn't do it. There's an open issue for implementing it here.

Resources