HttpParserState Enum

Represents the different states of the HTTP message parser.

This enumeration is used internally by the System.Net.Http.Headers library to track the progress and current position of parsing an HTTP message. Each state corresponds to a specific part of the HTTP protocol that the parser is expecting or currently processing.

Namespace

System.Net.Http.Headers

Summary

The HttpParserState enum is crucial for managing the complex process of breaking down raw HTTP data into structured header information. It helps the parser differentiate between request lines, status lines, headers, and message bodies, and to handle the nuances of HTTP syntax.

Members

The enum includes members that cover various stages of HTTP parsing:

Members

Usage Example (Conceptual)

While direct instantiation or manipulation of HttpParserState by end-users is uncommon, it's fundamental to how HTTP data is processed. Here's a simplified conceptual snippet showing how a parser might use such states:


enum HttpParserState {
    None,
    Start,
    Version,
    Method,
    RequestUri,
    StatusCode,
    ReasonPhrase,
    Headers,
    HeaderName,
    Colon,
    HeaderValue,
    Lf,
    Cr,
    StartOfBody,
    InBody,
    End
}

class HttpRequestParser {
    private HttpParserState currentState = HttpParserState.Start;
    private StringBuilder currentHeaderName = new StringBuilder();
    private StringBuilder currentHeaderValue = new StringBuilder();
    private int bodyBytesRead = 0;

    public void ParseBuffer(byte[] buffer, int offset, int count) {
        for (int i = offset; i < offset + count; i++) {
            char c = (char)buffer[i];

            switch (currentState) {
                case HttpParserState.Start:
                    if (char.IsLetter(c)) {
                        currentState = HttpParserState.Method;
                        currentHeaderName.Append(c);
                    } else if (c == 'H') { // Start of HTTP/1.1 200 OK status line
                        currentState = HttpParserState.ResponseVersion;
                    }
                    break;

                case HttpParserState.Method:
                    if (c == ' ') {
                        // Process Method
                        currentState = HttpParserState.RequestUri;
                        currentHeaderName.Clear();
                    } else {
                        currentHeaderName.Append(c);
                    }
                    break;

                case HttpParserState.RequestUri:
                    if (c == ' ') {
                        // Process RequestUri
                        currentState = HttpParserState.Version;
                    } else {
                        // Append to RequestUri
                    }
                    break;

                case HttpParserState.Version:
                    if (c == '\r') {
                        currentState = HttpParserState.Cr;
                    } else if (c == '\n') {
                         currentState = HttpParserState.Headers;
                    }
                    break;

                 case HttpParserState.Cr:
                    if (c == '\n') {
                        currentState = HttpParserState.Headers;
                    }
                    break;

                case HttpParserState.Headers:
                    if (c == '\r') {
                         currentState = HttpParserState.Lf;
                    } else {
                        currentState = HttpParserState.HeaderName;
                        currentHeaderName.Append(c);
                    }
                    break;

                case HttpParserState.HeaderName:
                     if (c == ':') {
                        currentState = HttpParserState.Colon;
                    } else {
                        currentHeaderName.Append(c);
                    }
                    break;

                case HttpParserState.Colon:
                    if (c == ' ') {
                        currentState = HttpParserState.HeaderValue;
                    }
                    break;

                case HttpParserState.HeaderValue:
                    if (c == '\r') {
                        // Process Header
                        currentState = HttpParserState.Lf;
                        currentHeaderName.Clear();
                        currentHeaderValue.Clear();
                    } else {
                        currentHeaderValue.Append(c);
                    }
                    break;

                case HttpParserState.Lf:
                    if (c == '\n') {
                        // Empty line signifies end of headers
                        currentState = HttpParserState.StartOfBody;
                    }
                    break;

                case HttpParserState.StartOfBody:
                     // Check Content-Length or Transfer-Encoding header to determine body size
                     currentState = HttpParserState.InBody;
                     // Fallthrough to InBody
                     goto case HttpParserState.InBody;

                case HttpParserState.InBody:
                    bodyBytesRead++;
                    // Process body data
                    if (bodyBytesRead == expectedBodyLength) {
                        currentState = HttpParserState.End;
                    }
                    break;

                default:
                    // Handle unknown states or errors
                    break;
            }
        }
    }
}