Beispiel #1
0
            public void ProcessRequest()
            {
                try
                {
                    do
                    {
                        _clientStream = new HttpStream(_client);
                        _session      = new Session();
                        if (CheckServerTimeOut())
                        {
                            return;
                        }
                        ReceiveRequest();
                        if (_session.Request.Method == null)
                        {
                            return;
                        }
                        if (_session.Request.Method == "CONNECT")
                        {
                            HandleConnect();
                            return;
                        }
                        if (_session.Request.Host.StartsWith("localhost") ||
                            _session.Request.Host.StartsWith("127.0.0.1"))
                        {
                            LogServer.Process(_client, _session.Request.RequestLine);
                            return;
                        }
                        SendRequest();
                        ReceiveRequestBody();
                        SendRequestBody();
                        ReceiveResponse();
                        if (_session.Response.StatusCode == null)
                        {
                            return;
                        }
                        AfterSessionComplete?.Invoke(_session);
                        SendResponse();
                    } while (_client.Connected && _server.Connected &&
                             _session.Request.IsKeepAlive && _session.Response.IsKeepAlive);
                }
#if DEBUG
                catch (Exception e)
                {
                    lock (SyncObj)
                        File.AppendAllText("debug.log", $"[{DateTime.Now:g}] " + e + "\r\n");
                }
#else // ReSharper disable once EmptyGeneralCatchClause
                catch
                {
                }
#endif
                finally
                {
                    Close();
                }
            }
Beispiel #2
0
        /// <summary>
        /// OnReceiveResponseをoverrideし、レスポンスデータを読み取る。
        /// </summary>
        protected override void OnReceiveResponse()
        {
            AfterReadResponseHeaders?.Invoke(new HttpResponse(this.ResponseStatusLine, this.ResponseHeaders, null));

            //200だけ
            if (this.ResponseStatusLine.StatusCode != 200)
            {
                return;
            }

            // GetContentだけやるとサーバーからデータ全部読み込むけどクライアントに送らないってことになる。
            // のでTransferEncodingとContentLengthを書き換えてchunkedじゃないレスポンスとしてクライアントに送信してやる必要がある。
            //
            // RFC 7230 の 3.3.1 を見る限りだと、Transfer-Encoding はリクエスト/レスポンスチェーンにいるどの recipient も
            // デコードしておっけーみたいに書いてあるから、HTTP的には問題なさそう。
            // https://tools.ietf.org/html/rfc7230#section-3.3.1
            //
            // ただ4.1.3のロジックとTrotiNetのとを見比べると trailer フィールドへの対応が足りてるのかどうか疑問が残る。
            // https://tools.ietf.org/html/rfc7230#section-4.1.3
            var response = this.ResponseHeaders.IsUnknownLength()
                ? this.GetContentWhenUnknownLength()
                : this.GetContent();

            this.State.NextStep = null; //既定の後続動作(SendResponse)をキャンセル(自前で送信処理を行う)

            //Content-Encoding対応っぽい
            using (var ms = new MemoryStream())
            {
                var stream = this.GetResponseMessageStream(response);
                stream.CopyTo(ms);
                var content = ms.ToArray();
                this.currentSession.Response = new HttpResponse(this.ResponseStatusLine, this.ResponseHeaders, content);
            }

            // Transfer-Encoding: Chunked をやめて Content-Length を使うようヘッダ書き換え
            this.ResponseHeaders.TransferEncoding = null;
            this.ResponseHeaders.ContentLength    = (uint)response.Length;

            this.SendResponseStatusAndHeaders();                 //クライアントにHTTPステータスとヘッダ送信
            this.SocketBP.TunnelDataTo(this.TunnelBP, response); //クライアントにレスポンスボディ送信

            //keep-aliveとかじゃなかったら閉じる
            if (!this.State.bPersistConnectionPS)
            {
                this.SocketPS?.CloseSocket();
                this.SocketPS = null;
            }

            //AfterSessionCompleteイベント
            AfterSessionComplete?.Invoke(this.currentSession);
        }
Beispiel #3
0
        /// <summary>
        /// Override OnReceiveResponse to read response data
        /// </summary>
        protected override void OnReceiveResponse()
        {
            #region Nekoxy Code
            AfterReadResponseHeaders?.Invoke(new HttpResponse(this.ResponseStatusLine, this.ResponseHeaders, null));

            if (this.ResponseStatusLine.StatusCode != 200)
            {
                return;
            }

            var response = this.ResponseHeaders.IsUnknownLength()
                                ? this.GetContentWhenUnknownLength()
                                : this.GetContent();
            this.State.NextStep = null;

            using (var ms = new MemoryStream())
            {
                var stream = this.GetResponseMessageStream(response);
                stream.CopyTo(ms);
                var content = ms.ToArray();
                this.currentSession.Response = new HttpResponse(this.ResponseStatusLine, this.ResponseHeaders, content);
            }
            #endregion

            if (BeforeResponse != null)
            {
                response = BeforeResponse?.Invoke(this.currentSession, this.currentSession.Response.Body);
                this.ResponseHeaders.ContentEncoding = null;                 // remove gzip and chunked...
            }

            #region Nekoxy Code
            this.ResponseHeaders.TransferEncoding = null;
            this.ResponseHeaders.ContentLength    = (uint)response.Length;

            this.SendResponseStatusAndHeaders();                 // Send HTTP status & head to client
            this.SocketBP.TunnelDataTo(this.TunnelBP, response); // Send response body to client

            if (!this.State.bPersistConnectionPS)
            {
                this.SocketPS?.CloseSocket();
                this.SocketPS = null;
            }

            AfterSessionComplete?.Invoke(this.currentSession);
            #endregion
        }
Beispiel #4
0
 private static void InvokeAfterSessionComplete(Session session)
 => AfterSessionComplete?.Invoke(session);