summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLu <[email protected]>2018-07-27 16:10:50 +0800
committerLu <[email protected]>2018-07-27 16:10:50 +0800
commit2bcf031a15cb0565483273a5ade570d5c922ecdc (patch)
tree8ae737311fb968a229b9e7210315ec4ac14527c2
parent3f3bd23e54538897ada98a255280a7e8ebf8f8a0 (diff)
修正发送伪造HTTP 451重定向报文格式构建错误的问题。
增加发送重定向报文后关闭TCP连接的功能。
-rw-r--r--src/http.h14
-rw-r--r--src/http1.cc58
-rw-r--r--src/httpaction.cc10
3 files changed, 61 insertions, 21 deletions
diff --git a/src/http.h b/src/http.h
index 88432b4..5a18e43 100644
--- a/src/http.h
+++ b/src/http.h
@@ -202,7 +202,9 @@ public:
virtual const struct sockaddr * SockAddrDest() const = 0;
virtual void Write(std::unique_ptr<HttpSession> http_session) = 0;
- virtual void Close() = 0;
+
+ virtual void CloseImmediately() = 0;
+ virtual void ClosePeacefully(bool eof_upstream, bool eof_downstream) = 0;
protected:
http_connection_cb_t session_new_cb_{nullptr};
@@ -367,7 +369,7 @@ private:
}
};
-std::unique_ptr<HttpRequest> HttpRequestFactory(int primary_version, int second_version);
+std::unique_ptr<HttpRequest> HttpRequestFactory(short major_version, short minor_version);
std::unique_ptr<HttpResponse> HttpResponseFactory(short major_version, short minor_version);
#include "pxyconn.h"
@@ -382,9 +384,15 @@ public:
~Http1Connection() = default;
- void Close() override
+ void CloseImmediately() override
{ need_to_close_ = true; };
+ void ClosePeacefully(bool eof_upstream, bool eof_downstream) override
+ {
+ if (eof_upstream) bufferevent_trigger_event(bev_upstream_, BEV_EVENT_EOF, 0);
+ if (eof_downstream) bufferevent_trigger_event(bev_downstream_, BEV_EVENT_EOF, 0);
+ }
+
bool NeedToClose()
{ return need_to_close_; }
diff --git a/src/http1.cc b/src/http1.cc
index b9a3401..4bd89aa 100644
--- a/src/http1.cc
+++ b/src/http1.cc
@@ -88,7 +88,7 @@ public:
const auto & __header_field = __iterate.first;
const auto & __header_value = __iterate.second;
- evbuffer_add_printf(__evbuffer_ptr.get(), "%s:%s\r\n",
+ evbuffer_add_printf(__evbuffer_ptr.get(), "%s: %s\r\n",
__header_field.c_str(), __header_value.c_str());
}
@@ -155,7 +155,7 @@ private:
class Http1Request : public HttpRequest
{
public:
- Http1Request();
+ explicit Http1Request(short major_version, short minor_version);
virtual ~Http1Request() = default;
virtual ssize_t ConstructFromMemory(const char * buf, size_t buflen);
@@ -344,7 +344,8 @@ int Http1RequestParserCallbacks::CallbackOnMessageComplete(http_parser * parser)
return 0;
}
-Http1Request::Http1Request()
+Http1Request::Http1Request(short major_version, short minor_version) :
+ major_version_(major_version), minor_version_(minor_version)
{
http_parser_init(parser_.get(), HTTP_REQUEST);
}
@@ -474,7 +475,29 @@ static const char * client_error_phrases[] = {
/* 414 */ "Request-URI Too Large",
/* 415 */ "Unsupported Media Type",
/* 416 */ "Requested range not satisfiable",
- /* 417 */ "Expectation Failed"
+ /* 417 */ "Expectation Failed",
+ /* 418 */ nullptr,
+ /* 419 */ nullptr,
+ /* 420 */ nullptr,
+ /* 421 */ "Misdirected Request",
+ /* 422 */ "Unprocessable Entity",
+ /* 423 */ "Locked",
+ /* 424 */ "Failed Dependency",
+ /* 425 */ nullptr,
+ /* 426 */ "Upgrade Required",
+ /* 427 */ nullptr,
+ /* 428 */ "Precondition Required",
+ /* 429 */ "Too Many Requests"
+};
+
+static const char * client_error_phrases_43x[] = {
+ /* 430 */ nullptr,
+ /* 431 */ "Request Header Fields Too Large"
+};
+
+static const char * client_error_phrases_45x[] = {
+ /* 450 */ nullptr,
+ /* 451 */ "Unavailable For Legal Reasons"
};
static const char * server_error_phrases[] = {
@@ -491,7 +514,9 @@ const char * __resp_code_to_str(int resp_code)
if (resp_code >= 101 && resp_code <= 102) return informational_phrases[resp_code - 101];
if (resp_code >= 200 && resp_code <= 206) return success_phrases[resp_code - 200];
if (resp_code >= 300 && resp_code <= 307) return redirection_phrases[resp_code - 300];
- if (resp_code >= 400 && resp_code <= 417) return client_error_phrases[resp_code - 400];
+ if (resp_code >= 400 && resp_code <= 429) return client_error_phrases[resp_code - 400];
+ if (resp_code >= 430 && resp_code <= 431) return client_error_phrases_43x[resp_code - 430];
+ if (resp_code >= 450 && resp_code <= 451) return client_error_phrases_45x[resp_code - 450];
if (resp_code >= 500 && resp_code <= 505) return server_error_phrases[resp_code - 500];
return nullptr;
@@ -874,7 +899,7 @@ void Http1Response::Construct()
/* 应答头部 */
headers_.ForEachHeader([this, evbuf_ptr](const std::string & str_field, const std::string & str_value)
{
- evbuffer_add_printf(evbuf_ptr, "%s:%s\r\n", str_field.c_str(), str_value.c_str());
+ evbuffer_add_printf(evbuf_ptr, "%s: %s\r\n", str_field.c_str(), str_value.c_str());
return true;
});
@@ -1158,27 +1183,27 @@ void Http1Connection::Write(std::unique_ptr<HttpSession> http_session)
if (request.Complete(HttpRequest::kSecionMessage))
{
auto stolen_buffer = request.StolenEvbuf();
- bufferevent_write_buffer(bev_upstream_, stolen_buffer.release());
+ bufferevent_write_buffer(bev_upstream_, stolen_buffer.get());
}
if (response.SectionState(response.kSectionMessage) == response.kStateComplete)
{
auto stolen_buffer = response.StolenEvBuf();
- bufferevent_write_buffer(bev_downstream_, stolen_buffer.release());
+ bufferevent_write_buffer(bev_downstream_, stolen_buffer.get());
}
return;
}
-std::unique_ptr<HttpRequest> HttpRequestFactory(int primary_version, int second_version)
+std::unique_ptr<HttpRequest> HttpRequestFactory(short major_version, short minor_version)
{
- if (primary_version == 1 && second_version == 0)
- return std::move(std::make_unique<Http1Request>());
- if (primary_version == 1 && second_version == 1)
- return std::move(std::make_unique<Http1Request>());
+ if (major_version == 1 && minor_version == 0)
+ return std::move(std::make_unique<Http1Request>(major_version, minor_version));
+ if (major_version == 1 && minor_version == 1)
+ return std::move(std::make_unique<Http1Request>(major_version, minor_version));
- assert(0);
- return nullptr;
+ throw std::invalid_argument(string_format("Invalid HTTP Version: %d, %d",
+ major_version, minor_version));
}
std::unique_ptr<HttpResponse> HttpResponseFactory(short major_version, short minor_version)
@@ -1188,6 +1213,7 @@ std::unique_ptr<HttpResponse> HttpResponseFactory(short major_version, short min
if (major_version == 1 && minor_version == 1)
return std::move(std::make_unique<Http1Response>(major_version, minor_version));
- return nullptr;
+ throw std::invalid_argument(string_format("Invalid HTTP Version: %d, %d",
+ major_version, minor_version));
}
diff --git a/src/httpaction.cc b/src/httpaction.cc
index 0d3fde4..b244879 100644
--- a/src/httpaction.cc
+++ b/src/httpaction.cc
@@ -368,6 +368,9 @@ void HttpActionRedirect::do_redirect_action(HttpSession * session)
http_response.Headers().Add("Location", resp_location_);
}
+ http_response.Headers().Add("Content-Type", "text/html; charset=utf-8");
+ http_response.Headers().Add("Content-Length", std::to_string(resp_content_.length()));
+
/* 应答内容 */
if (is_resp_content_set)
{
@@ -380,11 +383,14 @@ void HttpActionRedirect::do_redirect_action(HttpSession * session)
http_response.Body(std::move(body_segment_vec));
}
+
+
/* 调试记录 */
- str_dump_ = string_format("%d %s", resp_code_, resp_location_.c_str());
+ str_dump_ += string_format("%d %s", resp_code_, resp_location_.c_str());
http_response.Construct();
http_connection.Write(std::move(http_session));
+ http_connection.ClosePeacefully(true, false);
/* 丢弃当前的HTTP Session */
session->Drop();
@@ -420,7 +426,7 @@ private:
void HttpActionBlock::do_block_action(HttpSession * session)
{
- session->connection().Close();
+ session->connection().CloseImmediately();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////