Keep alive header and Web API - http

I am not able to set the keep-alive in the response header with the web Api. I am running in the IIS Express(Development server). I am using the message handler which sets the same
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
if (request.Headers.Authorization == null)
{
var NonAuthenicateresponse = new HttpResponseMessage(HttpStatusCode.Unauthorized);
NonAuthenicateresponse.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue("NTLM"));
return NonAuthenicateresponse;
}
var response=await base.SendAsync(request,cancellationToken);
response.Headers.ConnectionClose = false;
return response;
}
Am i missing anything extra parameter for the same.
To add more details , I am trying to implement NTLM authentication for the application. Once the request is made from the browser we issue a 401 unauthorized and the negotiation happening but it is able to send the Authorization header back in the subsequent request.
We need to explicitly say to the browser about the Keep-alive the connection.

Related

POST with transfer-enconding: chunked fails in IIS 8.5 web API

I have ASP.NET Web API running on IIS 8.5, and my POST method takes in a body of json document. Now a client app is using apache httpclient, which apparently automatically adds the Transfer-Encoding: chunked header into the request. My API method throws an exception because of non-existent body - it can't deserialize the json in the body, even though it looks good in the client logs.
How should I handle the request to ensure I get the whole body? I guess IIS should support transfer-encoding on the request as well, as it is part the HTTP/1.1 spec, right?
There's a similar question unanswered: Reading Body on chunked transfer encoded http requests in ASP.NET
You have to basically check the ContentLength header and set it to null if it is 0.
public class ChunkJsonMediaTypeFormatter : JsonMediaTypeFormatter
{
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
content.Headers.ContentLength = (content.Headers.ContentLength == 0) ? null : content.Headers.ContentLength;
return base.ReadFromStreamAsync(type, readStream, content, formatterLogger);
}
}
Wire up this formatter
GlobalConfiguration.Configure(config =>
{
var jsonFormatter = new ChunkJsonMediaTypeFormatter() { SerializerSettings = config.Formatters.JsonFormatter.SerializerSettings };
config.Formatters.Remove(config.Formatters.JsonFormatter);
config.Formatters.Insert(0, jsonFormatter);
}
https://gist.github.com/jayoungers/0b39b66c49bf974ba73d83943c4b218b

Best way to have one Web API forward request to other

I have a few web services running on different servers, and I want to have one web service running "in front" of the rest to decide which web service (server) the request should be forwarded to based on header values.
The idea is that a client will send a request, say:
http://api.mysite.com/cars
The API at mysite.com will inspect the request, extract information from the API key (which is supplied in the headers) and redirect to the appropriate server, e.g.
http://server4.mysite.com/api/cars
Is this going to work? I'm concerned about how I will return the response (w/data) from "server4" to the client. Will the response only be returned back to the first server or will the client achieve that response?
Just run into the same task and have to add some more lines in addition to Yazan Ati answer.
[HttpPost]
[HttpGet]
[Route("api/TestBot/{*remaining}")]
public Task<HttpResponseMessage> SendMessage()
{
const string host = "facebook.botframework.com";
string forwardUri = $"https://{host}/api/v1/bots/billycom{Request.RequestUri.Query}";
Request.Headers.Remove("Host");
Request.RequestUri = new Uri(forwardUri);
if (Request.Method == HttpMethod.Get)
{
Request.Content = null;
}
var client = new HttpClient();
return client.SendAsync(Request, HttpCompletionOption.ResponseHeadersRead);
}
All you need to do is build a Web API DelegatingHandler like this:
public class ProxyHandler : DelegatingHandler
{
protected override async System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
UriBuilder forwardUri = new UriBuilder(request.RequestUri);
//strip off the proxy port and replace with an Http port
forwardUri.Port = 80;
//send it on to the requested URL
request.RequestUri = forwardUri.Uri;
HttpClient client = new HttpClient();
var response = await client.SendAsync(request,HttpCompletionOption.ResponseHeadersRead);
return response;
}
}

HttpClient client-side message handlers

The HttpClient custom Client Message Handlers insert themselves in the client-side pipeline when making web api calls. This info is from this article
The author says that these message handlers go into action as the request is being sent out and also when the response is received back from the server.
I understand these client message handler's role as request is being sent out from client to the Server because the sendAsync method provides the request object. One can add custom request headers, etc.
I do not understand the usefulness of these message handlers AFTER the response is received from the server because the sendAsync method does not provide access to the response object. So, I am not sure how these client side message handlers are useful on the return journey of the request.
I am obviously missing something here.
Actually you do get access to the response message inside the message handler. For example, in the following handler, I am logging outgoing request and incoming response. Now as long as I use this instance of HttpClient, all calls made through it write traces of requests and response.
HttpClient client = new HttpClient(new LoggingHandler(new HttpClientHandler()));
public class LoggingHandler : DelegatingHandler
{
public LoggingHandler(HttpMessageHandler innerHandler)
: base(innerHandler)
{
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
Console.WriteLine("Request:");
Console.WriteLine(request.ToString());
if (request.Content != null)
{
Console.WriteLine(await request.Content.ReadAsStringAsync());
}
Console.WriteLine();
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
Console.WriteLine("Response:");
Console.WriteLine(response.ToString());
if (response.Content != null)
{
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
Console.WriteLine();
return response;
}
}

ASP.NET Web API CORS not working when method not exist

I have enabled CORS in web api and i am able to catch error in jquery ajax call with correct status code when unauthorized request are made. But i find that if method with some name is not exist in controller than i am not able to catch 404 error in ajax call. Following errors are returned
OPTIONS "{url}" 404 (Not Found) jquery.js:9666
XMLHttpRequest cannot load {url}. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
I think its problem with cors which is not adding headers when method is not exist. Is there any way to resolve this issue?
finally got solution after searching on net and get solution form following question on stackoverflow:
How to catch forms authorization error in Web API in ASP.NET MVC4
I have added one delegating handler which add headers if they are not exist to response. for example case when method is not exist or any of the required parameter is missing in request at that time Web API CORS support is not adding headers so Access-Control-Allow-Origin error received on client:
public class ResponseHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
if (!response.Headers.Contains("Access-Control-Allow-Headers") && !response.Headers.Contains("Access-Control-Allow-Origin"))
{
response.Headers.Add("Access-Control-Allow-Headers", "x-requested-with,authorization,content-type");
response.Headers.Add("Access-Control-Allow-Origin", "*");
}
return response;
}
}

Executing Code on Every Request

I need to run a validation routine looking for some header information on every request to the server. I would use OnActionExecuting in ASP.NET MVC, or an ActionInvoker, to run on every request, but I've been looking in Web API, and haven't found something specific.
If something could be implemented for both synchronous and asynchronous, that would be the best.
For Web API you should resort to MessageHandlers
Message handlers always run first, before anything else in the pipeline, and they are also able to run last (after Web API returns response, just prior to the response reaching the client).
More about message handlers can be found here - http://www.asp.net/web-api/overview/working-with-http/http-message-handlers.
And here is a simple example, validating an API key:
public class WebApiKeyHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
string apikey = HttpUtility.ParseQueryString(request.RequestUri.Query).Get("apikey");
if (apikey != "something")
{
HttpResponseMessage response = request.CreateErrorResponse(HttpStatusCode.Forbidden, "You can't use the API without the key.");
throw new HttpResponseException(response);
}
else
{
return base.SendAsync(request, cancellationToken);
}
}
}
In this example only request with the key "something": i.e./api/values/?apikey=something will be allowed, all other will be rejected.
In your case, you can simply access the request.Headers and validate whatever you need.

Resources