When an exception(example: OperationCanceledException) occurs in a message handler, we do not convert it to a safe http response message at the HttpServer level. By 'safe', I mean to HttpResponseMessage with 500 Internal Server Error.
Currently following is the behavior in different hosts:
1. SelfHost: HttpSelfHostServer does the conversion to safe responses.
2. WebHost: HttpControllerHandler does not.
3. KatanaHost: It currently does not.
So instead of each host taking care of this responsibility of converting them to safe http response messages, we need to do this in HttpServer level itself.
HttpServer's SendAsync code:
```
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request == null)
{
throw Error.ArgumentNull("request");
}
if (_disposed)
{
return TaskHelpers.FromResult(request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, SRResources.HttpServerDisposed));
}
// The first request initializes the server
EnsureInitialized();
// Capture current synchronization context and add it as a parameter to the request
SynchronizationContext context = SynchronizationContext.Current;
if (context != null)
{
request.Properties.Add(HttpPropertyKeys.SynchronizationContextKey, context);
}
// Add HttpConfiguration object as a parameter to the request
request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, _configuration);
// Ensure we have a principal, even if the host didn't give us one
IPrincipal originalPrincipal = Thread.CurrentPrincipal;
if (originalPrincipal == null)
{
Thread.CurrentPrincipal = _anonymousPrincipal.Value;
}
try
{
return base.SendAsync(request, cancellationToken);
}
finally
{
Thread.CurrentPrincipal = originalPrincipal;
}
}
```
Currently following is the behavior in different hosts:
1. SelfHost: HttpSelfHostServer does the conversion to safe responses.
2. WebHost: HttpControllerHandler does not.
3. KatanaHost: It currently does not.
So instead of each host taking care of this responsibility of converting them to safe http response messages, we need to do this in HttpServer level itself.
HttpServer's SendAsync code:
```
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request == null)
{
throw Error.ArgumentNull("request");
}
if (_disposed)
{
return TaskHelpers.FromResult(request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, SRResources.HttpServerDisposed));
}
// The first request initializes the server
EnsureInitialized();
// Capture current synchronization context and add it as a parameter to the request
SynchronizationContext context = SynchronizationContext.Current;
if (context != null)
{
request.Properties.Add(HttpPropertyKeys.SynchronizationContextKey, context);
}
// Add HttpConfiguration object as a parameter to the request
request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, _configuration);
// Ensure we have a principal, even if the host didn't give us one
IPrincipal originalPrincipal = Thread.CurrentPrincipal;
if (originalPrincipal == null)
{
Thread.CurrentPrincipal = _anonymousPrincipal.Value;
}
try
{
return base.SendAsync(request, cancellationToken);
}
finally
{
Thread.CurrentPrincipal = originalPrincipal;
}
}
```