-#ifndef _SQUID_SRC_HTTP_HTTP1PARSER_H
-#define _SQUID_SRC_HTTP_HTTP1PARSER_H
+#ifndef _SQUID_SRC_HTTP_ONEREQUESTPARSER_H
+#define _SQUID_SRC_HTTP_ONEREQUESTPARSER_H
#include "base/RefCount.h"
#include "http/forward.h"
#include "http/ProtocolVersion.h"
+#include "http/RequestMethod.h"
#include "http/StatusCode.h"
+#include "SBuf.h"
namespace Http {
+namespace One {
// Parser states
#define HTTP_PARSE_NONE 0 // nothing. completely unset state.
/** HTTP protocol parser.
*
* Works on a raw character I/O buffer and tokenizes the content into
- * either an error state or, an HTTP procotol request major segments:
+ * either an error state or HTTP procotol major sections:
*
- * \item Request Line (method, URL, protocol, version)
- * \item Mime header block
+ * \item first-line (request-line / simple-request / status-line)
+ * \item mime-header block
*/
-class Http1Parser : public RefCountable
+class Parser : public RefCountable
{
public:
- typedef RefCount<Http1Parser> Pointer;
-
- Http1Parser() { clear(); }
+ Parser() { clear(); }
/** Initialize a new parser.
- * Presenting it a buffer to work on and the current length of available
- * data.
+ * Presenting it a buffer to work on and the current length of available data.
* NOTE: This is *not* the buffer size, just the parse-able data length.
* The parse routines may be called again later with more data.
*/
- Http1Parser(const char *aBuf, int len) { reset(aBuf,len); };
+ Parser(const char *aBuf, int len) { reset(aBuf,len); }
/// Set this parser back to a default state.
/// Will DROP any reference to a buffer (does not free).
- void clear();
+ virtual void clear();
/// Reset the parser for use on a new buffer.
void reset(const char *aBuf, int len);
+ /** Adjust parser state to account for a buffer shift of n bytes.
+ *
+ * The leftmost n bytes bytes have been dropped and all other
+ * bytes shifted left n positions.
+ */
+ virtual void noteBufferShift(int64_t n) = 0;
+
/** Whether the parser is already done processing the buffer.
* Use to determine between incomplete data and errors results
- * from the parse methods.
+ * from the parse.
*/
bool isDone() const {return completedState_==HTTP_PARSE_DONE;}
- /// size in bytes of the first line (request-line)
- /// including CRLF terminator
- int64_t firstLineSize() const {return req.end - req.start + 1;}
+ /// number of bytes in buffer before the message
+ virtual int64_t messageOffset() const = 0;
+
+ /// size in bytes of the first line including CRLF terminator
+ virtual int64_t firstLineSize() const = 0;
/// size in bytes of the message headers including CRLF terminator(s)
- /// but excluding request-line bytes
- int64_t headerBlockSize() const {return mimeHeaderBytes_;}
+ /// but excluding first-line bytes
+ int64_t headerBlockSize() const {return mimeHeaderBlock_.length();}
- /// size in bytes of HTTP message block, includes request-line and mime headers
+ /// size in bytes of HTTP message block, includes first-line and mime headers
/// excludes any body/entity/payload bytes
- /// excludes any garbage prefix before the request-line
+ /// excludes any garbage prefix before the first-line
int64_t messageHeaderSize() const {return firstLineSize() + headerBlockSize();}
- /// buffer containing HTTP mime headers
- // TODO: convert to SBuf
- const char *rawHeaderBuf() {return buf + hdr_start;}
+ /// buffer containing HTTP mime headers, excluding message first-line.
+ const char *rawHeaderBuf() {return mimeHeaderBlock_.c_str();}
- /** Attempt to parse a request.
- * \return true if a valid request was parsed.
- * \note Use isDone() method to determine between incomplete parse and errors.
+ /// attempt to parse a message from the buffer
+ virtual bool parse() = 0;
+
+ /// the protocol label for this message
+ const AnyP::ProtocolVersion & messageProtocol() const {return msgProtocol_;}
+
+ /**
+ * \return A pointer to a field-value of the first matching field-name, or NULL.
*/
- bool parseRequest();
+ char *getHeaderField(const char *name);
public:
const char *buf;
int bufsiz;
- /// Offsets for pieces of the (HTTP request) Request-Line as per RFC 2616
- struct request_offsets {
- int start, end;
- int m_start, m_end; // method
- int u_start, u_end; // url
- int v_start, v_end; // version (full text)
- } req;
+protected:
+ /// what stage the parser is currently up to
+ uint8_t completedState_;
- /// the protocol label for this message
- const AnyP::ProtocolVersion & messageProtocol() const {return msgProtocol_;}
+ /// what protocol label has been found in the first line
+ AnyP::ProtocolVersion msgProtocol_;
- /// the HTTP method if this is a request method
- const HttpRequestMethodPointer & method() const {return method_;}
+ /// byte offset for non-parsed region of the buffer
+ size_t parseOffset_;
- // Offsets for pieces of the MiME Header segment
- // \deprecated use rawHeaderBuf() and headerBlockSize() instead
- int hdr_start, hdr_end;
+ /// buffer holding the mime headers
+ SBuf mimeHeaderBlock_;
+};
- // TODO: Offsets for pieces of the (HTTP reply) Status-Line as per RFC 2616
+/** HTTP protocol request parser.
+ *
+ * Works on a raw character I/O buffer and tokenizes the content into
+ * either an error state or, an HTTP procotol request major segments:
+ *
+ * \item Request Line (method, URL, protocol, version)
+ * \item Mime header block
+ */
+class RequestParser : public Http1::Parser
+{
+public:
+ /* Http::One::Parser API */
+ RequestParser() : Parser() {}
+ RequestParser(const char *aBuf, int len) : Parser(aBuf, len) {}
+ virtual void clear();
+ virtual void noteBufferShift(int64_t n);
+ virtual int64_t messageOffset() const {return req.start;}
+ virtual int64_t firstLineSize() const {return req.end - req.start + 1;}
+ virtual bool parse();
+
+ /// the HTTP method if this is a request message
+ const HttpRequestMethod & method() const {return method_;}
+
+ /// the request-line URI if this is a request message, or an empty string.
+ const SBuf &requestUri() const {return uri_;}
/** HTTP status code to be used on the invalid-request error page
* Http::scNone indicates incomplete parse, Http::scOkay indicates no error.
bool skipGarbageLines();
int parseRequestFirstLine();
- /// byte offset for non-parsed region of the buffer
- size_t parseOffset_;
-
- /// what stage the parser is currently up to
- uint8_t completedState_;
-
- /// what protocol label has been found in the first line
- AnyP::ProtocolVersion msgProtocol_;
+ /// Offsets for pieces of the (HTTP request) Request-Line as per RFC 2616
+ struct request_offsets {
+ int start, end;
+ int m_start, m_end; // method
+ int u_start, u_end; // url
+ int v_start, v_end; // version (full text)
+ } req;
/// what request method has been found on the first line
- HttpRequestMethodPointer method_;
+ HttpRequestMethod method_;
- /// number of bytes in the mime header block
- int64_t mimeHeaderBytes_;
+ /// raw copy of the origina client reqeust-line URI field
+ SBuf uri_;
};
+} // namespace One
} // namespace Http
#endif /* _SQUID_SRC_HTTP_HTTP1PARSER_H */