From 1cc49f3be4e5245fc660b510b0accf8bfb7dc2d4 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 25 May 2016 22:21:24 -0700 Subject: [PATCH] http: Allow retrieving other headers. Such as range request headers, accept headers, cookies, etc. --- ext/native/net/http_headers.cpp | 16 +++++++++++++++- ext/native/net/http_headers.h | 4 ++++ ext/native/net/http_server.cpp | 11 +++++++---- ext/native/net/http_server.h | 6 +++++- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/ext/native/net/http_headers.cpp b/ext/native/net/http_headers.cpp index de05f2f978..fdfaa2c1ea 100644 --- a/ext/native/net/http_headers.cpp +++ b/ext/native/net/http_headers.cpp @@ -1,5 +1,6 @@ #include "net/http_headers.h" +#include #include #include @@ -40,6 +41,15 @@ bool RequestHeader::GetParamValue(const char *param_name, std::string *value) co return false; } +bool RequestHeader::GetOther(const char *name, std::string *value) const { + auto it = other.find(name); + if (it != other.end()) { + *value = it->second; + return true; + } + return false; +} + // Intended to be a mad fast parser. It's not THAT fast currently, there's still // things to optimize, but meh. int RequestHeader::ParseHttpHeader(const char *buffer) { @@ -57,7 +67,7 @@ int RequestHeader::ParseHttpHeader(const char *buffer) { buffer += 5; } else { method = UNSUPPORTED; - status = 501; + status = 405; return -1; } SkipSpace(&buffer); @@ -117,6 +127,10 @@ int RequestHeader::ParseHttpHeader(const char *buffer) { } else if (!strncasecmp(key, "Content-Length", key_len)) { content_length = atoi(buffer); ILOG("Content-Length: %i", (int)content_length); + } else { + std::string key_str(key, key_len); + std::transform(key_str.begin(), key_str.end(), key_str.begin(), tolower); + other[key_str] = buffer; } return 0; diff --git a/ext/native/net/http_headers.h b/ext/native/net/http_headers.h index ccc3a09a2e..470f589972 100644 --- a/ext/native/net/http_headers.h +++ b/ext/native/net/http_headers.h @@ -1,6 +1,8 @@ #ifndef _NET_HTTP_HTTP_HEADERS #define _NET_HTTP_HTTP_HEADERS +#include +#include #include "base/buffer.h" namespace net { @@ -22,6 +24,7 @@ class RequestHeader { char *resource; char *params; int content_length; + std::unordered_map other; enum RequestType { SIMPLE, FULL, }; @@ -36,6 +39,7 @@ class RequestHeader { bool ok; void ParseHeaders(net::InputSink *sink); bool GetParamValue(const char *param_name, std::string *value) const; + bool GetOther(const char *name, std::string *value) const; private: int ParseHttpHeader(const char *buffer); bool first_header_; diff --git a/ext/native/net/http_server.cpp b/ext/native/net/http_server.cpp index 16c9aec70f..5b7dfac8d2 100644 --- a/ext/native/net/http_server.cpp +++ b/ext/native/net/http_server.cpp @@ -34,6 +34,9 @@ namespace http { +// Note: charset here helps prevent XSS. +const char *const DEFAULT_MIME_TYPE = "text/html; charset=utf-8"; + Request::Request(int fd) : fd_(fd) { in_ = new net::InputSink(fd); @@ -56,14 +59,14 @@ Request::~Request() { delete out_; } -void Request::WriteHttpResponseHeader(int status, int size) const { +void Request::WriteHttpResponseHeader(int status, int size, const char *mimeType) const { net::OutputSink *buffer = Out(); - buffer->Printf("HTTP/1.0 %d OK\r\n", status); + buffer->Printf("HTTP/1.0 %03d OK\r\n", status); buffer->Push("Server: SuperDuperServer v0.1\r\n"); - buffer->Push("Content-Type: text/html\r\n"); + buffer->Printf("Content-Type: %s\r\n", mimeType ? mimeType : DEFAULT_MIME_TYPE); buffer->Push("Connection: close\r\n"); if (size >= 0) { - buffer->Printf("Content-Length: %i\r\n", size); + buffer->Printf("Content-Length: %u\r\n", size); } buffer->Push("\r\n"); } diff --git a/ext/native/net/http_server.h b/ext/native/net/http_server.h index ab8abd95cc..870ed9f6a1 100644 --- a/ext/native/net/http_server.h +++ b/ext/native/net/http_server.h @@ -27,6 +27,10 @@ class Request { bool GetParamValue(const char *param_name, std::string *value) const { return header_.GetParamValue(param_name, value); } + // Use lowercase. + bool GetHeader(const char *name, std::string *value) const { + return header_.GetOther(name, value); + } net::InputSink *In() const { return in_; } net::OutputSink *Out() const { return out_; } @@ -41,7 +45,7 @@ class Request { bool IsOK() const { return fd_ > 0; } // If size is negative, no Content-Length: line is written. - void WriteHttpResponseHeader(int status, int size = -1) const; + void WriteHttpResponseHeader(int status, int size = -1, const char *mimeType = nullptr) const; private: net::InputSink *in_;