]>
Commit | Line | Data |
---|---|---|
1b51ee7b AJ |
1 | #ifndef _SQUID_SRC_HTTP_ONEREQUESTPARSER_H |
2 | #define _SQUID_SRC_HTTP_ONEREQUESTPARSER_H | |
4c14658e | 3 | |
25f0d354 | 4 | #include "base/RefCount.h" |
274bd5ad | 5 | #include "http/forward.h" |
5aedd08d | 6 | #include "http/ProtocolVersion.h" |
9ff1b8ca | 7 | #include "http/RequestMethod.h" |
955394ce | 8 | #include "http/StatusCode.h" |
eb1bd364 | 9 | #include "SBuf.h" |
4c14658e | 10 | |
bb86dcd4 | 11 | namespace Http { |
1b51ee7b | 12 | namespace One { |
bb86dcd4 | 13 | |
4c14658e | 14 | // Parser states |
678451c0 AJ |
15 | enum ParseState { |
16 | HTTP_PARSE_NONE =0, ///< nothing. completely unset state. | |
17 | HTTP_PARSE_NEW =1, ///< initialized, but nothing usefully parsed yet | |
18 | HTTP_PARSE_FIRST, ///< HTTP/1 message first line | |
19 | HTTP_PARSE_MIME, ///< mime header block | |
20 | HTTP_PARSE_DONE ///< completed with parsing a full request header | |
21 | }; | |
4c14658e AJ |
22 | |
23 | /** HTTP protocol parser. | |
24 | * | |
00589b8e | 25 | * Works on a raw character I/O buffer and tokenizes the content into |
7322c9dd | 26 | * either an error state or HTTP procotol major sections: |
4c14658e | 27 | * |
7322c9dd AJ |
28 | * \item first-line (request-line / simple-request / status-line) |
29 | * \item mime-header block | |
4c14658e | 30 | */ |
7322c9dd | 31 | class Parser : public RefCountable |
4c14658e AJ |
32 | { |
33 | public: | |
7322c9dd | 34 | Parser() { clear(); } |
4c14658e AJ |
35 | |
36 | /** Initialize a new parser. | |
7322c9dd | 37 | * Presenting it a buffer to work on and the current length of available data. |
4c14658e AJ |
38 | * NOTE: This is *not* the buffer size, just the parse-able data length. |
39 | * The parse routines may be called again later with more data. | |
40 | */ | |
bfe8bc51 | 41 | Parser(const char *aBuf, int len) { reset(aBuf,len); } |
4c14658e AJ |
42 | |
43 | /// Set this parser back to a default state. | |
44 | /// Will DROP any reference to a buffer (does not free). | |
7322c9dd | 45 | virtual void clear(); |
4c14658e AJ |
46 | |
47 | /// Reset the parser for use on a new buffer. | |
48 | void reset(const char *aBuf, int len); | |
49 | ||
f9daf571 AJ |
50 | /** Adjust parser state to account for a buffer shift of n bytes. |
51 | * | |
52 | * The leftmost n bytes bytes have been dropped and all other | |
53 | * bytes shifted left n positions. | |
54 | */ | |
678451c0 | 55 | virtual void noteBufferShift(const int64_t n) = 0; |
f9daf571 | 56 | |
87abd755 AJ |
57 | /** Whether the parser is already done processing the buffer. |
58 | * Use to determine between incomplete data and errors results | |
f9daf571 | 59 | * from the parse. |
87abd755 AJ |
60 | */ |
61 | bool isDone() const {return completedState_==HTTP_PARSE_DONE;} | |
b6a7fc85 | 62 | |
f9daf571 AJ |
63 | /// number of bytes in buffer before the message |
64 | virtual int64_t messageOffset() const = 0; | |
65 | ||
66 | /// size in bytes of the first line including CRLF terminator | |
7322c9dd | 67 | virtual int64_t firstLineSize() const = 0; |
7e1d6c48 | 68 | |
f4880526 | 69 | /// size in bytes of the message headers including CRLF terminator(s) |
7322c9dd | 70 | /// but excluding first-line bytes |
eb1bd364 | 71 | int64_t headerBlockSize() const {return mimeHeaderBlock_.length();} |
7e1d6c48 | 72 | |
7322c9dd | 73 | /// size in bytes of HTTP message block, includes first-line and mime headers |
7e1d6c48 | 74 | /// excludes any body/entity/payload bytes |
7322c9dd | 75 | /// excludes any garbage prefix before the first-line |
f4880526 | 76 | int64_t messageHeaderSize() const {return firstLineSize() + headerBlockSize();} |
7e1d6c48 | 77 | |
7322c9dd | 78 | /// buffer containing HTTP mime headers, excluding message first-line. |
eb1bd364 | 79 | const char *rawHeaderBuf() {return mimeHeaderBlock_.c_str();} |
7e1d6c48 | 80 | |
7322c9dd | 81 | /// attempt to parse a message from the buffer |
678451c0 AJ |
82 | /// \retval true if a full message was found and parsed |
83 | /// \retval false if incomplete, invalid or no message was found | |
7322c9dd AJ |
84 | virtual bool parse() = 0; |
85 | ||
86 | /// the protocol label for this message | |
87 | const AnyP::ProtocolVersion & messageProtocol() const {return msgProtocol_;} | |
afff15b2 | 88 | |
a4181565 AJ |
89 | /** |
90 | * \return A pointer to a field-value of the first matching field-name, or NULL. | |
91 | */ | |
92 | char *getHeaderField(const char *name); | |
93 | ||
4c14658e | 94 | public: |
4c14658e AJ |
95 | const char *buf; |
96 | int bufsiz; | |
74f478f8 | 97 | |
7322c9dd AJ |
98 | protected: |
99 | /// what stage the parser is currently up to | |
678451c0 | 100 | ParseState completedState_; |
7322c9dd AJ |
101 | |
102 | /// what protocol label has been found in the first line | |
103 | AnyP::ProtocolVersion msgProtocol_; | |
104 | ||
105 | /// byte offset for non-parsed region of the buffer | |
106 | size_t parseOffset_; | |
107 | ||
108 | /// buffer holding the mime headers | |
109 | SBuf mimeHeaderBlock_; | |
110 | }; | |
111 | ||
112 | /** HTTP protocol request parser. | |
113 | * | |
114 | * Works on a raw character I/O buffer and tokenizes the content into | |
115 | * either an error state or, an HTTP procotol request major segments: | |
116 | * | |
117 | * \item Request Line (method, URL, protocol, version) | |
118 | * \item Mime header block | |
119 | */ | |
120 | class RequestParser : public Http1::Parser | |
121 | { | |
122 | public: | |
123 | /* Http::One::Parser API */ | |
124 | RequestParser() : Parser() {} | |
125 | RequestParser(const char *aBuf, int len) : Parser(aBuf, len) {} | |
126 | virtual void clear(); | |
678451c0 | 127 | virtual void noteBufferShift(const int64_t n); |
bfe8bc51 | 128 | virtual int64_t messageOffset() const {return req.start;} |
7322c9dd AJ |
129 | virtual int64_t firstLineSize() const {return req.end - req.start + 1;} |
130 | virtual bool parse(); | |
5aedd08d | 131 | |
9ff1b8ca AJ |
132 | /// the HTTP method if this is a request message |
133 | const HttpRequestMethod & method() const {return method_;} | |
274bd5ad | 134 | |
9ff1b8ca AJ |
135 | /// the request-line URI if this is a request message, or an empty string. |
136 | const SBuf &requestUri() const {return uri_;} | |
5f3cc9a2 | 137 | |
4c14658e | 138 | /** HTTP status code to be used on the invalid-request error page |
955394ce | 139 | * Http::scNone indicates incomplete parse, Http::scOkay indicates no error. |
4c14658e | 140 | */ |
955394ce | 141 | Http::StatusCode request_parse_status; |
b6a7fc85 AJ |
142 | |
143 | private: | |
c11191e0 AJ |
144 | bool skipGarbageLines(); |
145 | int parseRequestFirstLine(); | |
146 | ||
5ff9a17a AJ |
147 | /// Offsets for pieces of the (HTTP request) Request-Line as per RFC 2616 |
148 | struct request_offsets { | |
149 | int start, end; | |
150 | int m_start, m_end; // method | |
151 | int u_start, u_end; // url | |
152 | int v_start, v_end; // version (full text) | |
153 | } req; | |
154 | ||
274bd5ad | 155 | /// what request method has been found on the first line |
9ff1b8ca | 156 | HttpRequestMethod method_; |
f4880526 | 157 | |
5f3cc9a2 AJ |
158 | /// raw copy of the origina client reqeust-line URI field |
159 | SBuf uri_; | |
4c14658e AJ |
160 | }; |
161 | ||
1b51ee7b | 162 | } // namespace One |
bb86dcd4 AJ |
163 | } // namespace Http |
164 | ||
e02d9044 | 165 | #endif /* _SQUID_SRC_HTTP_HTTP1PARSER_H */ |