private void SetResponseData( HttpListenerRequest request, Stream responseDataStream, out long dataSize, out string mimeType, out int statusCode) { try { // レスポンスデータを取得するためのデリゲート情報を取得する HttpResponseData responseData = GetTargetResponseData(request); dataSize = responseData.SetStream(responseDataStream, request); mimeType = responseData.MimeType; statusCode = 200; } catch (Exception ex) { // レスポンスデータ取得処理でエラーが発生した場合 // スタックトレース付きのエラーメッセージを取得 string errorMessage = ExceptionHandling.GetErrorMessageWithStackTrace(ex); // エラー用のHTMLレスポンスデータを生成 string errorResponse = string.Format( CultureInfo.InvariantCulture, ErrorMessage.LocalHttpServerErrorResponseHtmlFormat, errorMessage); byte[] responseData = System.Text.Encoding.UTF8.GetBytes(errorResponse); // 500:Internal Server Errorレスポンスを返却 LocalHttpServerCommon.SetDataToStream(responseDataStream, responseData); dataSize = responseData.LongLength; mimeType = "text/html"; statusCode = 500; } }
/// <summary> /// <see cref="HttpListener"/> の受信返信処理を非同期で行う /// </summary> /// <param name="listener">ローカルHTTPサーバのリスナーオブジェクト</param> /// <returns>非同期処理のタスクオブジェクト</returns> private async Task ReceiveResponseProcess(HttpListener listener) { try { // ローカルHTTPサーバが起動しているかどうかのフラグがOFFになるまで無限ループ while (IsRunning) { // 受信が完了するまで待ち、要求オブジェクトを取得する HttpListenerContext context = await listener.GetContextAsync().ConfigureAwait(false); HttpListenerRequest request = context.Request; // レスポンスデータ用のStreamオブジェクトを生成 using (Stream responseDataStream = new MemoryStream()) { // レスポンスデータをStreamに設定する SetResponseData( request: request, responseDataStream: responseDataStream, dataSize: out long dataSize, mimeType: out string mimeType, statusCode: out int statusCode); // レスポンスオブジェクトを取得する using (HttpListenerResponse response = context.Response) { // ステータスコードの設定 response.StatusCode = statusCode; // コンテンツタイプの設定 response.ContentType = mimeType; // データサイズの設定 response.ContentLength64 = dataSize; // レスポンス処理 LocalHttpServerCommon.SetDataToStream( response.OutputStream, responseDataStream); } } } } catch (Exception ex) when(ex is HttpListenerException || ex is ArgumentException || ex is RegexMatchTimeoutException || ex is InvalidOperationException || ex is NotSupportedException || ex is IOException) { // 下記の例外が発生する可能性がある // [HttpListenerException] // ・Win32 関数の呼び出しが失敗しました。 // エラーの詳細は HttpListenerException.ErrorCode プロパティを参照 // // [ArgumentException] // ・レスポンスで設定するContentTypeの値がNULL又は空文字の場合に発生 // (HttpResponseDelegateの生成時に値のチェックを行っているので // 基本的に発生しない発生しないはず、発生したらバグ) // [ArgumentNullException] // [ArgumentException] // ・レスポンスで設定するContentLength64の値が0未満の場合に発生 // (基本的に発生しない発生しないはず、 // コマンドラインユーザーインターフェース発生した場合は // レスポンスデータ取得用のデリゲートにバグがあり不正な値を返却している) // [ArgumentOutOfRangeException] // // [RegexMatchTimeoutException] // ・対象のレスポンス処理を取得する際に、 // 正規表現のマッチング処理にてタイムアウトが発生した場合に発生 // // [InvalidOperationException] // 1.下記の場合に発生 // [ObjectDisposedException] // ・処理中にHttpListenerオブジェクトがDisposedされていた場合 // ・処理中にHttpListenerResponseオブジェクトがDisposedされていた場合 // ・処理中にレスポンスデータを読み込むStreamオブジェクトがDisposedされていた場合 // ・処理中にレスポンスを出力するStreamオブジェクトがDisposedされていた場合 // 2.下記の場合に発生 // [InvalidOperationException] // ・HttpListenerオブジェクトが開始されていないか、停止中の場合 // ・レスポンスで設定するContentLength64の処理中に既にレスポンスが返却済みの場合 // // [NotSupportedException] // ・レスポンスデータ読み込み用のStreamが読み込みをサポートしていない場合に発生 // ・レスポンスデータ書き込み用のStreamが書き込みをサポートしていない場合に発生 // // [IO.IOException] // ・レスポンスデータの読み書きでI/O エラーが発生した場合に発生 // エラーに対する処理を行う ErrorHandling(ex); } finally { // HttpListenerを強制終了する HttpListenerAbort(); } }