}
/* We know the whole request is in hp.buf now */
- size_t req_sz = hp.messageHeaderSize();
- assert(req_sz <= (size_t) hp.bufsiz);
-
- /* Will the following be true with HTTP/0.9 requests? probably not .. */
- /* So the rest of the code will need to deal with '0'-byte headers (ie, none, so don't try parsing em) */
- assert(req_sz > 0);
/* deny CONNECT via accelerated ports */
if (hp.method() == Http::METHOD_CONNECT && csd->port && csd->port->flags.accelSurrogate) {
{
ClientHttpRequest *http = context->http;
HttpRequest::Pointer request;
- bool notedUseOfBuffer = false;
bool chunked = false;
bool mustReplyToOptions = false;
bool unsupportedTe = false;
request->body_pipe = conn->expectRequestBody(
chunked ? -1 : request->content_length);
- // consume header early so that body pipe gets just the body
- connNoteUseOfBuffer(conn, http->req_sz);
- notedUseOfBuffer = true;
-
/* Is it too large? */
if (!chunked && // if chunked, we will check as we accumulate
clientIsRequestBodyTooLargeForPolicy(request->content_length)) {
http->doCallouts();
finish:
- if (!notedUseOfBuffer)
- connNoteUseOfBuffer(conn, http->req_sz);
-
/*
* DPW 2007-05-18
* Moved the TCP_RESET feature from clientReplyContext::sendMoreData
/* Process request */
ClientSocketContext *context = parseHttpRequest(this, *parser_);
+ if (parser_->messageOffset()) {
+ // nothing but prefix garbage in the buffer. consume it.
+ connNoteUseOfBuffer(this, parser_->messageOffset());
+ parser_->noteBufferShift(parser_->messageOffset());
+ }
PROF_stop(parseHttpRequest);
/* status -1 or 1 */
CommTimeoutCbPtrFun(clientLifetimeTimeout, context->http));
commSetConnTimeout(clientConnection, Config.Timeout.lifetime, timeoutCall);
+ // Request has now been shifted out of the buffer.
+ // Consume header early so that next action starts with just the next bytes.
+ connNoteUseOfBuffer(this, parser_->messageHeaderSize() + parser_->messageOffset());
clientProcessRequest(this, *parser_, context);
parsed_req = true; // XXX: do we really need to parse everything right NOW ?
debugs(74, DBG_DATA, "Parse " << Raw("buf", buf, bufsiz));
}
+void
+Http1::RequestParser::noteBufferShift(int64_t n)
+{
+ bufsiz -= n;
+
+ // if parsing done, ignore buffer changes.
+ if (completedState_ == HTTP_PARSE_DONE)
+ return;
+
+ // shift the parser resume point to match buffer content
+ parseOffset_ -= n;
+
+#if WHEN_INCREMENTAL_PARSING
+
+ // if have not yet finished request-line
+ if (completedState_ == HTTP_PARSE_NEW) {
+ // check for and adjust the known request-line offsets.
+
+ /* TODO: when the first-line is parsed incrementally we
+ * will need to recalculate the offsets for req.*
+ * For now, they are all re-calculated based on parserOffset_
+ * with each parse attempt.
+ */
+ }
+
+ // if finished request-line but not mime header
+ // adjust the mime header states
+ if (completedState_ == HTTP_PARSE_FIRST) {
+ /* TODO: when the mime-header is parsed incrementally we
+ * will need to store the initial offset of mime-header block
+ * instead of locatign it from req.end or parseOffset_.
+ * Since req.end may no longer be valid, and parseOffset_ may
+ * have moved into the mime-block interior.
+ */
+ }
+#endif
+}
+
/**
* Attempt to parse the first line of a new request message.
*
// stage 1: locate the request-line
if (completedState_ == HTTP_PARSE_NEW) {
if (skipGarbageLines() && (size_t)bufsiz < parseOffset_)
- return 0;
+ return false;
}
// stage 2: parse the request-line
/// 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
- /// including CRLF terminator
+ /// 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)
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();