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