#include "Debug.h"
#include "http/one/Parser.h"
+/// RFC 7230 section 2.6 - 7 magic octets
+const SBuf Http::One::Parser::Http1magic("HTTP/1.");
+
void
Http::One::Parser::clear()
{
char *getHeaderField(const char *name);
public:
+ /// RFC 7230 section 2.6 - 7 magic octets
+ static const SBuf Http1magic;
+
SBuf buf;
protected:
* Governed by:
* RFC 1945 section 5.1
* RFC 2616 section 5.1
+ * RFC 7230
*
* Parsing state is stored between calls. However the current implementation
* begins parsing from scratch on every call.
req.v_start = last_whitespace + 1;
req.v_end = line_end;
- // We only accept HTTP protocol requests right now.
- // TODO: accept other protocols; RFC 2326 (RTSP protocol) etc
- if ((req.v_end - req.v_start +1) < 5 || buf.substr(req.v_start, 5).caseCmp(SBuf("HTTP/")) != 0) {
-#if USE_HTTP_VIOLATIONS
- // being lax; old parser accepted strange versions
- // there is a LOT of cases which are ambiguous, therefore we cannot use relaxed_header_parser here.
- msgProtocol_ = Http::ProtocolVersion(0,9);
- req.u_end = line_end;
- request_parse_status = Http::scOkay; // treat as HTTP/0.9
- return 1;
-#else
- // protocol not supported / implemented.
+ /* RFC 2616 section 10.5.6 : handle unsupported HTTP major versions cleanly. */
+ if ((req.v_end - req.v_start +1) < (int)Http1magic.length() || !buf.substr(req.v_start, SBuf::npos).startsWith(Http1magic)) {
+ // non-HTTP/1 protocols not supported / implemented.
request_parse_status = Http::scHttpVersionNotSupported;
return -1;
-#endif
}
+ // NP: magic octets include the protocol name and major version DIGIT.
msgProtocol_.protocol = AnyP::PROTO_HTTP;
+ msgProtocol_.major = 1;
- int i = req.v_start + sizeof("HTTP/") -1;
+ int i = req.v_start + Http1magic.length() -1;
- /* next should be 1 or more digits */
- if (!isdigit(buf[i])) {
- request_parse_status = Http::scHttpVersionNotSupported;
- return -1;
- }
- int maj = 0;
- for (; i <= line_end && (isdigit(buf[i])) && maj < 65536; ++i) {
- maj = maj * 10;
- maj = maj + (buf[i]) - '0';
- }
- // catch too-big values or missing remainders
- if (maj >= 65536 || i > line_end) {
- request_parse_status = Http::scHttpVersionNotSupported;
- return -1;
- }
- msgProtocol_.major = maj;
-
- /* next should be .; we -have- to have this as we have a whole line.. */
- if (buf[i] != '.') {
- request_parse_status = Http::scHttpVersionNotSupported;
- return -1;
- }
// catch missing minor part
if (++i > line_end) {
request_parse_status = Http::scHttpVersionNotSupported;
}
msgProtocol_.minor = min;
- /* RFC 2616 section 10.5.6 : handle unsupported HTTP major versions cleanly. */
- /* We currently only support 0.9, 1.0, 1.1 properly in this parser */
- if ((maj == 0 && min != 9) || (maj > 1)) {
- request_parse_status = Http::scHttpVersionNotSupported;
- return -1;
- }
-
/*
* Rightio - we have all the schtuff. Return true; we've got enough.
*/
input.clear();
}
- // RFC 2616 : future version full-request
+ // RFC 7230 : future versions do not use request-line syntax
{
- // IETF HTTPbis WG has made this two-digits format invalid.
- // it gets treated same as HTTP/0.9 for now
input.append("GET / HTTP/10.12\r\n", 18);
struct resultSet expect = {
.parsed = false,
.uri = "/",
.versionStart = 6,
.versionEnd = 15,
- .version = AnyP::ProtocolVersion(AnyP::PROTO_HTTP,10,12)
+ .version = AnyP::ProtocolVersion()
};
output.clear();
testResults(__LINE__, input, output, expect);
// unknown non-HTTP protocol names
{
- // XXX: violations mode treats them as HTTP/0.9 requests! which is wrong.
-#if !USE_HTTP_VIOLATIONS
input.append("GET / FOO/1.0\n", 14);
struct resultSet expect = {
.parsed = false,
output.clear();
testResults(__LINE__, input, output, expect);
input.clear();
-#endif
}
// no version
.uri = "/",
.versionStart = 6,
.versionEnd = 10,
- .version = AnyP::ProtocolVersion(AnyP::PROTO_HTTP,0,0)
+ .version = AnyP::ProtocolVersion()
};
output.clear();
testResults(__LINE__, input, output, expect);
.uri = "/",
.versionStart = 6,
.versionEnd = 12,
- .version = AnyP::ProtocolVersion(AnyP::PROTO_HTTP,0,0)
+ .version = AnyP::ProtocolVersion()
};
output.clear();
testResults(__LINE__, input, output, expect);
.uri = "/",
.versionStart = 6,
.versionEnd = 12,
- .version = AnyP::ProtocolVersion(AnyP::PROTO_HTTP,0,0)
+ .version = AnyP::ProtocolVersion()
};
output.clear();
testResults(__LINE__, input, output, expect);
.uri = "/",
.versionStart = 6,
.versionEnd = 19,
- .version = AnyP::ProtocolVersion(AnyP::PROTO_HTTP,0,0)
+ .version = AnyP::ProtocolVersion()
};
output.clear();
testResults(__LINE__, input, output, expect);