ASP.NET Web APIを使用して一部のHTTP要求をプロキシするアプリケーションを作成していますが、断続的なエラーの原因を特定するのに苦労しています。競合状態のようです...しかし、完全にはわかりません。
ここで詳しく説明する前に、アプリケーションの一般的な通信フローを示します。
- クライアントはプロキシ1にHTTPリクエストを送信します。
- プロキシ1はHTTPリクエストの内容をプロキシ2に中継します
- プロキシ2は、HTTPリクエストの内容をターゲットWebアプリケーションに中継します
- ターゲットWebアプリはHTTP要求に応答し、応答はプロキシ2にストリーミング(チャンク転送)されます
- プロキシ2は、プロキシ1に応答を返します。プロキシ1は、元の呼び出し元のクライアントに応答します。
プロキシアプリケーションは、.NET4.5を使用してASP.NETWebAPIRTMで記述されています。リレーを実行するコードは次のようになります。
//Controller entry point.
public HttpResponseMessage Post()
{
using (var client = new HttpClient())
{
var request = BuildRelayHttpRequest(this.Request);
//HttpCompletionOption.ResponseHeadersRead - so that I can start streaming the response as soon
//As it begins to filter in.
var relayResult = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).Result;
var returnMessage = BuildResponse(relayResult);
return returnMessage;
}
}
private static HttpRequestMessage BuildRelayHttpRequest(HttpRequestMessage incomingRequest)
{
var requestUri = BuildRequestUri();
var relayRequest = new HttpRequestMessage(incomingRequest.Method, requestUri);
if (incomingRequest.Method != HttpMethod.Get && incomingRequest.Content != null)
{
relayRequest.Content = incomingRequest.Content;
}
//Copies all safe HTTP headers (mainly content) to the relay request
CopyHeaders(relayRequest, incomingRequest);
return relayRequest;
}
private static HttpRequestMessage BuildResponse(HttpResponseMessage responseMessage)
{
var returnMessage = Request.CreateResponse(responseMessage.StatusCode);
returnMessage.ReasonPhrase = responseMessage.ReasonPhrase;
returnMessage.Content = CopyContentStream(responseMessage);
//Copies all safe HTTP headers (mainly content) to the response
CopyHeaders(returnMessage, responseMessage);
}
private static PushStreamContent CopyContentStream(HttpResponseMessage sourceContent)
{
var content = new PushStreamContent(async (stream, context, transport) =>
await sourceContent.Content.ReadAsStreamAsync()
.ContinueWith(t1 => t1.Result.CopyToAsync(stream)
.ContinueWith(t2 => stream.Dispose())));
return content;
}
断続的に発生するエラーは次のとおりです。
非同期操作がまだ保留中に、非同期モジュールまたはハンドラーが完了しました。
このエラーは通常、プロキシアプリケーションへの最初の数回のリクエストで発生し、その後はエラーは再発しません。
Visual Studioは、スローされたときに例外をキャッチすることはありません。ただし、エラーはGlobal.asaxApplication_Errorイベントでキャッチできます。残念ながら、例外にはスタックトレースがありません。
プロキシアプリケーションは、AzureWebロールでホストされます。
犯人を特定する助けをいただければ幸いです。