示例#1
0
        /// <summary>
        /// Handle the HTTP connection
        ///
        /// This implementation doesn't support keep alive so each HTTP session
        /// consists of parsing the request, dispatching to a handler and then
        /// sending the response before closing the connection.
        /// </summary>
        /// <param name="server"></param>
        /// <param name="input"></param>
        /// <param name="output"></param>
        public void ProcessHttpRequest(Stream input, Stream output)
        {
            // Set up state
            HttpRequest    request        = null;
            HttpResponse   response       = null;
            HttpException  parseError     = null;
            HttpContext    context        = null;
            SessionHandler sessionHandler = null;

            // Process the request
            try
            {
                request = ParseRequest(input);
                if ((request == null) || !m_connected)
                {
                    return; // Nothing we can do, just drop the connection
                }
                // Do we have any content in the body ?
                if (request.Headers.ContainsKey(HttpHeaders.ContentType))
                {
                    if (!request.Headers.ContainsKey(HttpHeaders.ContentLength))
                    {
                        throw new HttpLengthRequiredException();
                    }
                    int length;
                    if (!int.TryParse(request.Headers[HttpHeaders.ContentLength], out length))
                    {
                        throw new HttpLengthRequiredException();
                    }
                    request.ContentLength = length;
                    if (length > MaxRequestBody)
                    {
                        throw new HttpRequestEntityTooLargeException();
                    }
                    // Read the data in
                    MemoryStream content = new MemoryStream();
                    //23.08.2016 - Changes for supporting POST Method
                    int contentCopyCounter = 0;
                    int bodyReadCount      = 0;
                    while (m_connected && (content.Length != length))
                    {
                        if (contentCopyCounter > 0)
                        {
                            int bytesToRead = ((length - bodyReadCount) > InputBufferSize) ? InputBufferSize : (length - bodyReadCount);
                            ReadData(input, bytesToRead);
                        }

                        bodyReadCount += m_index;

                        content.Write(m_buffer, 0, m_index);
                        ExtractBytes(m_index);
                        contentCopyCounter++;
                    }
                    //23.08.2016 - End of Changes for supporting POST Method

                    // Did the connection drop while reading?
                    if (!m_connected)
                    {
                        return;
                    }
                    // Reset the stream location and attach it to the request
                    content.Seek(0, SeekOrigin.Begin);
                    request.Content = content;
                }
                // Process the cookies
                if (request.Headers.ContainsKey(HttpHeaders.Cookie))
                {
                    string[] cookies = request.Headers[HttpHeaders.Cookie].Split(CookieSeparator);
                    foreach (string cookie in cookies)
                    {
                        string[] parts = cookie.Split(CookieValueSeparator);
                        Cookie   c     = new Cookie();
                        c.Name = parts[0].Trim();
                        if (parts.Length > 1)
                        {
                            c.Value = parts[1].Trim();
                        }
                        request.Cookies.Add(c);
                    }
                }
                // We have at least a partial request, create the matching response
                context  = new HttpContext();
                response = new HttpResponse();

                //Get session id from cookies
                var sessionId    = GetSessionIdentifier(request.Cookies);
                var isNewRequest = string.IsNullOrEmpty(sessionId);

                if (isNewRequest)
                {
                    sessionId = Utilities.GetNewSessionIdentifier();
                }

                sessionHandler         = new SessionHandler(sessionId, m_server.SessionStorageHandler);
                context.SessionHandler = sessionHandler;

                sessionHandler.DestroyExpiredSessions();

                //Update session data
                if (isNewRequest)
                {
                    sessionHandler.SaveSessionData();
                    response.Cookies.Add(new Cookie(SessionName, sessionHandler.SessionId));
                }
                else
                {
                    sessionHandler.UpdateSessionTimeOut();

                    var isRetrieved = sessionHandler.GetSessionData();
                    if (!isRetrieved)
                    {
                        sessionId              = Utilities.GetNewSessionIdentifier();
                        sessionHandler         = new SessionHandler(sessionId, m_server.SessionStorageHandler);
                        context.SessionHandler = sessionHandler;
                        sessionHandler.SaveSessionData();
                        response.Cookies.Add(new Cookie(SessionName, sessionHandler.SessionId));
                    }
                }

                // Apply filters
                if (m_server.ApplyBeforeFilters(request, response, context))
                {
                    // Check for WebSocket upgrade
                    IWebSocketRequestHandler wsHandler = UpgradeToWebsocket(request, response);
                    if (wsHandler != null)
                    {
                        // Apply the after filters here
                        m_server.ApplyAfterFilters(request, response, context);
                        // Write the response back to accept the connection
                        /////////////////////////////////Changes done locally to fix HTTP 1.1 on Safari 10 websocket error on 22.11.2016/////////////////////
                        response.Send(output, HttpVersion.Ver1_1);
                        output.Flush();
                        // Now we can process the websocket
                        WebSocket ws = new WebSocket(input, output);
                        wsHandler.Connected(ws);
                        ws.Run();
                        // Once the websocket connection is finished we don't need to do anything else
                        return;
                    }
                    // Dispatch to the handler
                    string partialUri;
                    IHttpRequestHandler handler = m_server.GetHandlerForUri(request.URI, out partialUri);
                    if (handler == null)
                    {
                        throw new HttpNotFoundException();
                    }
                    handler.HandleRequest(partialUri, request, response, context);
                }
            }
            catch (HttpException ex)
            {
                parseError = ex;
            }
            catch (Exception)
            {
                parseError = new HttpInternalServerErrorException();
            }
            // Do we need to send back an error response ?
            if (parseError != null)
            {
                // TODO: Clear any content that might already be added
                response.ResponseCode    = parseError.ResponseCode;
                response.ResponseMessage = parseError.Message;
            }
            // Apply the after filters here
            m_server.ApplyAfterFilters(request, response, context);

            //Update the session before sending the response
            if (sessionHandler != null)
            {
                if (sessionHandler.IsChanged)
                {
                    sessionHandler.SaveSessionData();
                }

                if (sessionHandler.IsSessionDestroyed)
                {
                    sessionHandler.IsSessionDestroyed = false;
                    response.Cookies.Add(new Cookie(SessionName, sessionHandler.SessionId));
                }
            }

            // Write the response
            response.Send(output);
            output.Flush();
        }