Suppose I have a client that continually requests streams from a service, and I want automate testing it. So, as part of the test, I create a service that returns a stream. The following code snippet constructs the response and returns it:
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StreamContent(fstream);
response.Content.Headers.ContentType = mediaType;
return response;
This works for the success case where the client calls the API and gets a response in a timely manner. But I also want to simulate some timeout failures.
If I want to simulate timeouts before any part of the response is returned, i can simply add a Thread.Sleep() before return response.
My question is: how can I simulate the timeout case where the service has already started return response? I would like to simulate the service timing out after the response headers have been sent, but before the entirety of fstream is sent.
Maybe try something like this?
var response = HttpContext.Current.Response;
response.Buffer = false;
response.AddHeader("SomeHeader","SomeValue");
response.Write("Some body text.");
System.Threading.Thread.Sleep(WEB_SERVER_TIMEOUT_VALUE + 1);
Related
We are sending JsonConvert.SerializeObject(lstobject); to the URL here. lstobject is a large list sent to the url.error also returned after 3 minutes to log error how to make webrequest to wait 5 minutes.
var httpWebRequest = (HttpWebRequest)WebRequest
.Create(ConfigurationManager.AppSettings["JsonPayloadPostUrl"]
.ToString());
httpWebRequest.Timeout = 1000000;
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(jsonPayload);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseText = streamReader.ReadToEnd();
}
Ee have used httpWebRequest.Timeout = 1000000; but the server is unable to send request back in less than 5 minutes. How to make request to wait for server for response ?
I might be missing something reading your question, but HTTP 500 server error means that the server has provided a response, saying it encountered some internal issue. So you cannot prevent it by setting a bigger timeout on the Request side.
Following https://www.w3.org/Protocols/HTTP/HTRESP.html
Internal Error 500
The server encountered an unexpected condition which prevented it from
fulfilling the request.
I would say either your request is not properly built, or the server has some application-side issue.
Coming back to the timeout setting way, I think it looks properly. Please note that this time might be taking into account topics like DNS name resolution etc. which in turn might require a bit more time than it seems in the first place. This shouldn't be a problem in your case though, looking at the value you are trying to set.
I donwnload a stream with RestSharp by using the ResponseWriter.
var client = new RestClient
var request = new RestRequest();
// ...
request.ResponseWriter = (ms) => {
// how to detect the status code
};
var response = client.Execute(request);
How can I found out the HTTP Status Code in the ResponseWriter?
Is there a better way to download a Stream?
You can check response.StatusCode and response.StatusDescription after executing the request.
Interestingly, if you use the DownloadData method as described here https://github.com/restsharp/RestSharp/wiki/Other-Usage-Examples there is no way to access this information as far as I can tell.
Currently You can use property AdvancedResponseWriter instead ResponseWriter.
The main difference is that AdvancedResponseWriter in addition to Response Stream gets IHttpResponse and You can check Response Status.
It should be working properly from version 106.6.
https://github.com/restsharp/RestSharp/issues/1207
I got simple JAX-RS resource and I'm using Apache CXF WebClient as a client. I'm using HTTP basic authentication. When it fails on server, typical 401 UNAUTHORIZED response is sent along with WWW-Authenticate header.
The strange behavior happens with WebClient when this (WWW-Auhenticate) header is received. The WebClient (internally) repeats the same request multiple times (20 times) and than fails.
WebClient webClient = WebClientFactory.newClient("http://myserver/auth");
try {
webClient.get(SimpleResponse.class);
// inside GET, 20 HTTP GET requests are invoked
} catch (ServerWebApplicationException ex) {
// data are present when WWW-authenticate header is not sent from server
// if header is present, unmarshalling fails
AuthError err = ex.toErrorObject(webClient, AuthError.class);
}
I found the same problem in CXF 3.1.
In my case for all async http rest request if response came 401/407, then thread is going in infinite loop and printing WWW-Authenticate is not set in response.
What I analysed the code I found that :
In case of Asynchronous call Control flow from HttpConduit.handleRetransmits-> processRetransmit-> AsyncHTTPConduit.authorizationRetransmit
which return true and in HttpConduit the code is
int maxRetransmits = getMaxRetransmits();
updateCookiesBeforeRetransmit();
int nretransmits = 0;
while ((maxRetransmits < 0 || nretransmits < maxRetransmits) && processRetransmit()) {
nretransmits++;
}
If maxRetransmits = -1 and processRetransmit() return true then thread going in infinite loop.
So to overcome this issue we pass maxRetransmitValue as 0 in HttpConduit.getClient().
Hope it will others.
This has been fixed in the latest versions of CXF:
https://issues.apache.org/jira/browse/CXF-4815
I'm in the process of creating a REST API using HttpListener in .NET (C#). This all works out great, except for one slight issue.
I'm trying to return responses with Status Codes other than OK (200), for instance ResourceNotFound (404).
When I set the StatusCode of the HttpListenerResponse to something other than 200, and create a response body (using HttpListenerResponse.OutputStream), it seems to be resetting the status code to 200. I'm not able to send a response with StatusCode 404 and a message body. However, this should be possible according to the HTTP specs. I'm checking the requests and responses with Fiddler, but I'm not able to get what I'm looking for.
I've had the same problem and found the source of the problem :
If you write the body in the OutputStream before set the StatusCode (or any other property), the response will be sent before the modification is applied !
So, you have to proceed in this order :
public void Send(HttpListenerContext context, byte[] body)
{
// First, set a random status code and other stuffs
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
context.Response.ContentType = "text/plain";
// Write to the stream IN LAST (will send request)
context.Response.OutputStream.Write(body, 0, body.Length);
}
I am having to re-write an existing REST API using .NET (originally written with Ruby). From the client's perspective, it has to work exactly the same way as the old API - i.e. the client code mustn't need to change. The current API requires Basic Authentication. So to call the old API, the following works perfectly:-
var wc = new System.Net.WebClient();
var myCache = new CredentialCache();
myCache.Add(new Uri(url), "Basic", new NetworkCredential("XXX", "XXX"));
wc.Credentials = myCache;
var returnBytes = wc.DownloadData("http://xxxx");
(I have had to ommit the real URL / username / password etc for security reasons).
Now I am writing the new API using ASP.Net Web API with MVC4. I have a weird problem and cannot find anybody else with exactly the same problem. In order to support Basic Authentication, I have followed the guidelines here:
http://sixgun.wordpress.com/2012/02/29/asp-net-web-api-basic-authentication/
One thing, I put the code to "hook in the handler" in the Global.asax.cs file in the Application_Start() event (that wasn't explained so I guessed).
Anyway, if I call my API (which I have deployed in IIS) using the above code, the Authorization header is always null, and the above fails with 401 Unauthorized. However, if I manually set the header using this code, it works fine - i.e. the Authorization header now exists and I am able to Authenticate the user.
private void SetBasicAuthHeader(WebClient request, String userName, String userPassword)
{
string authInfo = userName + ":" + userPassword;
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
request.Headers["Authorization"] = "Basic " + authInfo;
}
.......
var wc = new System.Net.WebClient();
SetBasicAuthHeader(request, "XXXX", "XXXX");
var returnBytes = wc.DownloadData("http://xxxx");
Although that works, it's no good to me because existing users of the existing API are not going to be manually setting the header.
Reading up on how Basic Authentication works, the initial request is meant to be anonymous, then the client is returned 401, then the client is meant to try again. However if I put a break point in my code, it will never hit the code again in Antony's example. I was expecting my breakpoint to be hit twice.
Any ideas how I can get this to work?
You're expecting the right behavior. System.Net.WebClient does not automatically include the Authorization headers upon initial request. It only sends them when properly challenged by a response, which to my knowledge is a 401 status code and a proper WWW-Authenticate header. See here and here for further info.
I'm assuming your basic authentication handler is not returning the WWW-Authenticate header and as such WebClient never even attempts to send the credentials on a second request. You should be able to watch this in Fiddler or a similar tool.
If your handler did something like this, you should witness the WebClient approach working:
//if is not authenticated or Authorization header is null
return base.SendAsync(request, cancellationToken).ContinueWith(task =>
{
var response = task.Result;
response.StatusCode = HttpStatusCode.Unauthorized;
response.Headers.Add("WWW-Authenticate", "Basic realm=\"www.whatever.com\"");
return response;
});
//else (is authenticated)
return base.SendAsync(request, cancellationToken);
As you noticed, if you include the Authorization headers on every request (like you did in your alternative approach) then your handler already works as is. So it may be sufficient - it just isn't for WebClient and other clients that operate in the same way.