]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/http/Http1Parser.h
Merge from trunk
[thirdparty/squid.git] / src / http / Http1Parser.h
index b217edfdc71215153522b0bf545eb46adf46b7ba..86439e440a4a7acc914b39222489a4887e0087f9 100644 (file)
@@ -1,12 +1,15 @@
-#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.
@@ -18,85 +21,115 @@ namespace Http {
 /** 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.
@@ -107,22 +140,22 @@ private:
     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 */