mirror of
				https://git.haproxy.org/git/haproxy.git/
				synced 2025-10-31 08:30:59 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			336 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			336 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| --- Relevant portions of RFC2616 ---
 | ||
| 
 | ||
| OCTET               = <any 8-bit sequence of data>
 | ||
| CHAR                = <any US-ASCII character (octets 0 - 127)>
 | ||
| UPALPHA             = <any US-ASCII uppercase letter "A".."Z">
 | ||
| LOALPHA             = <any US-ASCII lowercase letter "a".."z">
 | ||
| ALPHA               = UPALPHA | LOALPHA
 | ||
| DIGIT               = <any US-ASCII digit "0".."9">
 | ||
| CTL                 = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
 | ||
| CR                  = <US-ASCII CR, carriage return (13)>
 | ||
| LF                  = <US-ASCII LF, linefeed (10)>
 | ||
| SP                  = <US-ASCII SP, space (32)>
 | ||
| HT                  = <US-ASCII HT, horizontal-tab (9)>
 | ||
| <">                 = <US-ASCII double-quote mark (34)>
 | ||
| CRLF                = CR LF
 | ||
| LWS                 = [CRLF] 1*( SP | HT )
 | ||
| TEXT                = <any OCTET except CTLs, but including LWS>
 | ||
| HEX                 = "A" | "B" | "C" | "D" | "E" | "F"
 | ||
|                       | "a" | "b" | "c" | "d" | "e" | "f" | DIGIT
 | ||
| separators          = "(" | ")" | "<" | ">" | "@"
 | ||
|                     | "," | ";" | ":" | "\" | <">
 | ||
|                     | "/" | "[" | "]" | "?" | "="
 | ||
|                     | "{" | "}" | SP | HT
 | ||
| token               = 1*<any CHAR except CTLs or separators>
 | ||
| 
 | ||
| quoted-pair         = "\" CHAR
 | ||
| ctext               = <any TEXT excluding "(" and ")">
 | ||
| qdtext              = <any TEXT except <">>
 | ||
| quoted-string       = ( <"> *(qdtext | quoted-pair ) <"> )
 | ||
| comment             = "(" *( ctext | quoted-pair | comment ) ")"
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 4 HTTP Message
 | ||
| 4.1 Message Types
 | ||
| 
 | ||
| HTTP messages consist of requests from client to server and responses from
 | ||
| server to client. Request (section 5) and Response (section 6) messages use the
 | ||
| generic message format of RFC 822 [9] for transferring entities (the payload of
 | ||
| the message). Both types of message consist of :
 | ||
| 
 | ||
|   - a start-line
 | ||
|   - zero or more header fields (also known as "headers")
 | ||
|   - an empty line (i.e., a line with nothing preceding the CRLF) indicating the
 | ||
|     end of the header fields
 | ||
|   - and possibly a message-body.
 | ||
| 
 | ||
| 
 | ||
| HTTP-message        = Request | Response
 | ||
| 
 | ||
| start-line          = Request-Line | Status-Line
 | ||
| generic-message     = start-line
 | ||
|                       *(message-header CRLF)
 | ||
|                       CRLF
 | ||
|                       [ message-body ]
 | ||
| 
 | ||
| In the interest of robustness, servers SHOULD ignore any empty line(s) received
 | ||
| where a Request-Line is expected. In other words, if the server is reading the
 | ||
| protocol stream at the beginning of a message and receives a CRLF first, it
 | ||
| should ignore the CRLF.
 | ||
| 
 | ||
| 
 | ||
| 4.2 Message headers
 | ||
| 
 | ||
| - Each header field consists of a name followed by a colon (":") and the field
 | ||
|   value.
 | ||
| - Field names are case-insensitive.
 | ||
| - The field value MAY be preceded by any amount of LWS, though a single SP is
 | ||
|   preferred.
 | ||
| - Header fields can be extended over multiple lines by preceding each extra
 | ||
|   line with at least one SP or HT.
 | ||
| 
 | ||
| 
 | ||
| message-header      = field-name ":" [ field-value ]
 | ||
| field-name          = token
 | ||
| field-value         = *( field-content | LWS )
 | ||
| field-content       = <the OCTETs making up the field-value and consisting of
 | ||
|                        either *TEXT or combinations of token, separators, and
 | ||
|                        quoted-string>
 | ||
| 
 | ||
| 
 | ||
| The field-content does not include any leading or trailing LWS occurring before
 | ||
| the first non-whitespace character of the field-value or after the last
 | ||
| non-whitespace character of the field-value. Such leading or trailing LWS MAY
 | ||
| be removed without changing the semantics of the field value. Any LWS that
 | ||
| occurs between field-content MAY be replaced with a single SP before
 | ||
| interpreting the field value or forwarding the message downstream.
 | ||
| 
 | ||
| 
 | ||
| => format des headers = 1*(CHAR & !ctl & !sep) ":" *(OCTET & (!ctl | LWS))
 | ||
| => les regex de matching de headers s'appliquent sur field-content, et peuvent
 | ||
|    utiliser field-value comme espace de travail (mais de pr<70>f<EFBFBD>rence apr<70>s le
 | ||
|    premier SP).
 | ||
| 
 | ||
| (19.3) The line terminator for message-header fields is the sequence CRLF.
 | ||
| However, we recommend that applications, when parsing such headers, recognize
 | ||
| a single LF as a line terminator and ignore the leading CR.
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| message-body    = entity-body
 | ||
|                 | <entity-body encoded as per Transfer-Encoding>
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 5 Request
 | ||
| 
 | ||
| Request         = Request-Line
 | ||
|                   *(( general-header
 | ||
|                     | request-header
 | ||
|                     | entity-header ) CRLF)
 | ||
|                   CRLF
 | ||
|                   [ message-body ]
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 5.1 Request line
 | ||
| 
 | ||
| The elements are separated by SP characters. No CR or LF is allowed except in
 | ||
| the final CRLF sequence.
 | ||
| 
 | ||
| Request-Line = Method SP Request-URI SP HTTP-Version CRLF
 | ||
| 
 | ||
| (19.3) Clients SHOULD be tolerant in parsing the Status-Line and servers
 | ||
| tolerant when parsing the Request-Line. In particular, they SHOULD accept any
 | ||
| amount of SP or HT characters between fields, even though only a single SP is
 | ||
| required.
 | ||
| 
 | ||
| 4.5 General headers
 | ||
| Apply to MESSAGE.
 | ||
| 
 | ||
| general-header  = Cache-Control
 | ||
|                 | Connection
 | ||
|                 | Date
 | ||
|                 | Pragma
 | ||
|                 | Trailer
 | ||
|                 | Transfer-Encoding
 | ||
|                 | Upgrade
 | ||
|                 | Via
 | ||
|                 | Warning
 | ||
| 
 | ||
| General-header field names can be extended reliably only in combination with a
 | ||
| change in the protocol version. However, new or experimental header fields may
 | ||
| be given the semantics of general header fields if all parties in the
 | ||
| communication recognize them to be general-header fields. Unrecognized header
 | ||
| fields are treated as entity-header fields.
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 5.3 Request Header Fields
 | ||
| 
 | ||
| The request-header fields allow the client to pass additional information about
 | ||
| the request, and about the client itself, to the server. These fields act as
 | ||
| request modifiers, with semantics equivalent to the parameters on a programming
 | ||
| language method invocation.
 | ||
| 
 | ||
| request-header  = Accept
 | ||
|                 | Accept-Charset
 | ||
|                 | Accept-Encoding
 | ||
|                 | Accept-Language
 | ||
|                 | Authorization
 | ||
|                 | Expect
 | ||
|                 | From
 | ||
|                 | Host
 | ||
|                 | If-Match
 | ||
|                 | If-Modified-Since
 | ||
|                 | If-None-Match
 | ||
|                 | If-Range
 | ||
|                 | If-Unmodified-Since
 | ||
|                 | Max-Forwards
 | ||
|                 | Proxy-Authorization
 | ||
|                 | Range
 | ||
|                 | Referer
 | ||
|                 | TE
 | ||
|                 | User-Agent
 | ||
| 
 | ||
| Request-header field names can be extended reliably only in combination with a
 | ||
| change in the protocol version. However, new or experimental header fields MAY
 | ||
| be given the semantics of request-header fields if all parties in the
 | ||
| communication recognize them to be request-header fields. Unrecognized header
 | ||
| fields are treated as entity-header fields.
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 7.1 Entity header fields
 | ||
| 
 | ||
| Entity-header fields define metainformation about the entity-body or, if no
 | ||
| body is present, about the resource identified by the request. Some of this
 | ||
| metainformation is OPTIONAL; some might be REQUIRED by portions of this
 | ||
| specification.
 | ||
| 
 | ||
| entity-header   = Allow
 | ||
|                 | Content-Encoding
 | ||
|                 | Content-Language
 | ||
|                 | Content-Length
 | ||
|                 | Content-Location
 | ||
|                 | Content-MD5
 | ||
|                 | Content-Range
 | ||
|                 | Content-Type
 | ||
|                 | Expires
 | ||
|                 | Last-Modified
 | ||
|                 | extension-header
 | ||
| extension-header = message-header
 | ||
| 
 | ||
| The extension-header mechanism allows additional entity-header fields to be
 | ||
| defined without changing the protocol, but these fields cannot be assumed to be
 | ||
| recognizable by the recipient. Unrecognized header fields SHOULD be ignored by
 | ||
| the recipient and MUST be forwarded by transparent proxies.
 | ||
| 
 | ||
| ----------------------------------
 | ||
| 
 | ||
| The format of Request-URI is defined by RFC3986 :
 | ||
| 
 | ||
|    URI           = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
 | ||
| 
 | ||
|    hier-part     = "//" authority path-abempty
 | ||
|                  / path-absolute
 | ||
|                  / path-rootless
 | ||
|                  / path-empty
 | ||
| 
 | ||
|    URI-reference = URI / relative-ref
 | ||
| 
 | ||
|    absolute-URI  = scheme ":" hier-part [ "?" query ]
 | ||
| 
 | ||
|    relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
 | ||
| 
 | ||
|    relative-part = "//" authority path-abempty
 | ||
|                  / path-absolute
 | ||
|                  / path-noscheme
 | ||
|                  / path-empty
 | ||
| 
 | ||
|    scheme        = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
 | ||
| 
 | ||
|    authority     = [ userinfo "@" ] host [ ":" port ]
 | ||
|    userinfo      = *( unreserved / pct-encoded / sub-delims / ":" )
 | ||
|    host          = IP-literal / IPv4address / reg-name
 | ||
|    port          = *DIGIT
 | ||
| 
 | ||
|    IP-literal    = "[" ( IPv6address / IPvFuture  ) "]"
 | ||
| 
 | ||
|    IPvFuture     = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
 | ||
| 
 | ||
|    IPv6address   =                            6( h16 ":" ) ls32
 | ||
|                  /                       "::" 5( h16 ":" ) ls32
 | ||
|                  / [               h16 ] "::" 4( h16 ":" ) ls32
 | ||
|                  / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
 | ||
|                  / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
 | ||
|                  / [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
 | ||
|                  / [ *4( h16 ":" ) h16 ] "::"              ls32
 | ||
|                  / [ *5( h16 ":" ) h16 ] "::"              h16
 | ||
|                  / [ *6( h16 ":" ) h16 ] "::"
 | ||
| 
 | ||
|    h16           = 1*4HEXDIG
 | ||
|    ls32          = ( h16 ":" h16 ) / IPv4address
 | ||
|    IPv4address   = dec-octet "." dec-octet "." dec-octet "." dec-octet
 | ||
|    dec-octet     = DIGIT                 ; 0-9
 | ||
|                  / %x31-39 DIGIT         ; 10-99
 | ||
|                  / "1" 2DIGIT            ; 100-199
 | ||
|                  / "2" %x30-34 DIGIT     ; 200-249
 | ||
|                  / "25" %x30-35          ; 250-255
 | ||
| 
 | ||
|    reg-name      = *( unreserved / pct-encoded / sub-delims )
 | ||
| 
 | ||
|    path          = path-abempty    ; begins with "/" or is empty
 | ||
|                  / path-absolute   ; begins with "/" but not "//"
 | ||
|                  / path-noscheme   ; begins with a non-colon segment
 | ||
|                  / path-rootless   ; begins with a segment
 | ||
|                  / path-empty      ; zero characters
 | ||
| 
 | ||
|    path-abempty  = *( "/" segment )
 | ||
|    path-absolute = "/" [ segment-nz *( "/" segment ) ]
 | ||
|    path-noscheme = segment-nz-nc *( "/" segment )
 | ||
|    path-rootless = segment-nz *( "/" segment )
 | ||
|    path-empty    = 0<pchar>
 | ||
| 
 | ||
|    segment       = *pchar
 | ||
|    segment-nz    = 1*pchar
 | ||
|    segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
 | ||
|                  ; non-zero-length segment without any colon ":"
 | ||
| 
 | ||
|    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
 | ||
| 
 | ||
|    query         = *( pchar / "/" / "?" )
 | ||
| 
 | ||
|    fragment      = *( pchar / "/" / "?" )
 | ||
| 
 | ||
|    pct-encoded   = "%" HEXDIG HEXDIG
 | ||
| 
 | ||
|    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
 | ||
|    reserved      = gen-delims / sub-delims
 | ||
|    gen-delims    = ":" / "/" / "?" / "#" / "[" / "]" / "@"
 | ||
|    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
 | ||
|                  / "*" / "+" / "," / ";" / "="
 | ||
| 
 | ||
| => so the list of allowed characters in a URI is :
 | ||
| 
 | ||
|    uri-char      = unreserved / gen-delims / sub-delims / "%"
 | ||
|                  = ALPHA / DIGIT / "-" / "." / "_" / "~"
 | ||
|                  / ":" / "/" / "?" / "#" / "[" / "]" / "@"
 | ||
|                  / "!" / "$" / "&" / "'" / "(" / ")" /
 | ||
|                  / "*" / "+" / "," / ";" / "=" / "%"
 | ||
| 
 | ||
| Note that non-ascii characters are forbidden ! Spaces and CTL are forbidden.
 | ||
| Unfortunately, some products such as Apache allow such characters :-/
 | ||
| 
 | ||
| ---- The correct way to do it ----
 | ||
| 
 | ||
| - one http_session
 | ||
|   It is basically any transport session on which we talk HTTP. It may be TCP,
 | ||
|   SSL over TCP, etc... It knows a way to talk to the client, either the socket
 | ||
|   file descriptor or a direct access to the client-side buffer. It should hold
 | ||
|   information about the last accessed server so that we can guarantee that the
 | ||
|   same server can be used during a whole session if needed. A first version
 | ||
|   without optimal support for HTTP pipelining will have the client buffers tied
 | ||
|   to the http_session. It may be possible that it is not sufficient for full
 | ||
|   pipelining, but this will need further study. The link from the buffers to
 | ||
|   the backend should be managed by the http transaction (http_txn), provided
 | ||
|   that they are serialized. Each http_session, has 0 to N http_txn. Each
 | ||
|   http_txn belongs to one and only one http_session.
 | ||
| 
 | ||
| - each http_txn has 1 request message (http_req), and 0 or 1 response message
 | ||
|   (http_rtr). Each of them has 1 and only one http_txn. An http_txn holds
 | ||
|   informations such as the HTTP method, the URI, the HTTP version, the
 | ||
|   transfer-encoding, the HTTP status, the authorization, the req and rtr
 | ||
|   content-length, the timers, logs, etc... The backend and server which process
 | ||
|   the request are also known from the http_txn.
 | ||
| 
 | ||
| - both request and response messages hold header and parsing informations, such
 | ||
|   as the parsing state, start of headers, start of message, captures, etc...
 | ||
| 
 |