HTTPS: Keep-Alive connection to downstream servers.
Reset status = 0 when entering s_status state in htparse_run
This commit is contained in:
parent
9303cca430
commit
695dd50612
|
@ -1118,6 +1118,7 @@ htparser_run(htparser * p, htparse_hooks * hooks, const char * data, size_t len)
|
|||
if (p->type == htp_type_request) {
|
||||
p->state = s_spaces_after_digit;
|
||||
} else if (p->type == htp_type_response) {
|
||||
p->status = 0;
|
||||
p->state = s_status;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ Downstream::Downstream(Upstream *upstream, int stream_id, int priority)
|
|||
bev_(0),
|
||||
stream_id_(stream_id),
|
||||
priority_(priority),
|
||||
counter_(1),
|
||||
ioctrl_(0),
|
||||
request_state_(INITIAL),
|
||||
request_major_(1),
|
||||
|
@ -53,6 +54,7 @@ Downstream::Downstream(Upstream *upstream, int stream_id, int priority)
|
|||
response_major_(1),
|
||||
response_minor_(1),
|
||||
chunked_response_(false),
|
||||
response_connection_close_(false),
|
||||
response_htp_(htparser_new()),
|
||||
response_body_buf_(0)
|
||||
{
|
||||
|
@ -82,6 +84,41 @@ Downstream::~Downstream()
|
|||
}
|
||||
}
|
||||
|
||||
int Downstream::get_counter() const
|
||||
{
|
||||
return counter_;
|
||||
}
|
||||
|
||||
void Downstream::reuse(int stream_id)
|
||||
{
|
||||
stream_id_ = stream_id;
|
||||
++counter_;
|
||||
request_state_ = INITIAL;
|
||||
}
|
||||
|
||||
void Downstream::idle()
|
||||
{
|
||||
stream_id_ = -1;
|
||||
priority_ = 0;
|
||||
ioctrl_.force_resume_read();
|
||||
request_state_ = IDLE;
|
||||
request_method_.clear();
|
||||
request_path_.clear();
|
||||
request_major_ = 1;
|
||||
request_minor_ = 1;
|
||||
chunked_request_ = false;
|
||||
request_connection_close_ = false;
|
||||
request_headers_.clear();
|
||||
|
||||
response_state_ = INITIAL;
|
||||
response_http_status_ = 0;
|
||||
response_major_ = 1;
|
||||
response_minor_ = 1;
|
||||
chunked_response_ = false;
|
||||
response_connection_close_ = false;
|
||||
response_headers_.clear();
|
||||
}
|
||||
|
||||
void Downstream::pause_read(IOCtrlReason reason)
|
||||
{
|
||||
ioctrl_.pause_read(reason);
|
||||
|
@ -110,8 +147,8 @@ void check_transfer_encoding_chunked(bool *chunked,
|
|||
} // namespace
|
||||
|
||||
namespace {
|
||||
void check_request_connection(bool *connection_close,
|
||||
const Headers::value_type &item)
|
||||
void check_connection_close(bool *connection_close,
|
||||
const Headers::value_type &item)
|
||||
{
|
||||
if(util::strieq(item.first.c_str(), "connection")) {
|
||||
if(util::strifind(item.second.c_str(), "close")) {
|
||||
|
@ -134,7 +171,7 @@ void Downstream::set_last_request_header_value(const std::string& value)
|
|||
Headers::value_type &item = request_headers_.back();
|
||||
item.second = value;
|
||||
check_transfer_encoding_chunked(&chunked_request_, item);
|
||||
check_request_connection(&request_connection_close_, item);
|
||||
check_connection_close(&request_connection_close_, item);
|
||||
}
|
||||
|
||||
void Downstream::set_request_method(const std::string& method)
|
||||
|
@ -255,7 +292,9 @@ int Downstream::push_request_headers()
|
|||
}
|
||||
hdrs += "\r\n";
|
||||
}
|
||||
hdrs += "Connection: close\r\n";
|
||||
if(request_connection_close_) {
|
||||
hdrs += "Connection: close\r\n";
|
||||
}
|
||||
if(!xff_found) {
|
||||
hdrs += "X-Forwarded-For: ";
|
||||
hdrs += upstream_->get_client_handler()->get_ipaddr();
|
||||
|
@ -327,6 +366,7 @@ void Downstream::set_last_response_header_value(const std::string& value)
|
|||
Headers::value_type &item = response_headers_.back();
|
||||
item.second = value;
|
||||
check_transfer_encoding_chunked(&chunked_response_, item);
|
||||
check_connection_close(&response_connection_close_, item);
|
||||
}
|
||||
|
||||
unsigned int Downstream::get_response_http_status() const
|
||||
|
@ -364,6 +404,11 @@ bool Downstream::get_chunked_response() const
|
|||
return chunked_response_;
|
||||
}
|
||||
|
||||
bool Downstream::get_response_connection_close() const
|
||||
{
|
||||
return response_connection_close_;
|
||||
}
|
||||
|
||||
namespace {
|
||||
int htp_hdrs_completecb(htparser *htp)
|
||||
{
|
||||
|
|
|
@ -57,6 +57,9 @@ public:
|
|||
void pause_read(IOCtrlReason reason);
|
||||
bool resume_read(IOCtrlReason reason);
|
||||
void force_resume_read();
|
||||
void idle();
|
||||
void reuse(int stream_id);
|
||||
int get_counter() const;
|
||||
// downstream request API
|
||||
const Headers& get_request_headers() const;
|
||||
void add_request_header(const std::string& name, const std::string& value);
|
||||
|
@ -78,7 +81,8 @@ public:
|
|||
HEADER_COMPLETE,
|
||||
MSG_COMPLETE,
|
||||
STREAM_CLOSED,
|
||||
CONNECT_FAIL
|
||||
CONNECT_FAIL,
|
||||
IDLE
|
||||
};
|
||||
void set_request_state(int state);
|
||||
int get_request_state() const;
|
||||
|
@ -93,6 +97,7 @@ public:
|
|||
int get_response_major() const;
|
||||
int get_response_minor() const;
|
||||
bool get_chunked_response() const;
|
||||
bool get_response_connection_close() const;
|
||||
int parse_http_response();
|
||||
void set_response_state(int state);
|
||||
int get_response_state() const;
|
||||
|
@ -103,6 +108,7 @@ private:
|
|||
bufferevent *bev_;
|
||||
int32_t stream_id_;
|
||||
int priority_;
|
||||
int counter_;
|
||||
IOControl ioctrl_;
|
||||
int request_state_;
|
||||
std::string request_method_;
|
||||
|
@ -118,6 +124,7 @@ private:
|
|||
int response_major_;
|
||||
int response_minor_;
|
||||
bool chunked_response_;
|
||||
bool response_connection_close_;
|
||||
Headers response_headers_;
|
||||
htparser *response_htp_;
|
||||
// This buffer is used to temporarily store downstream response
|
||||
|
|
|
@ -76,8 +76,14 @@ int htp_msg_begin(htparser *htp)
|
|||
HttpsUpstream *upstream;
|
||||
upstream = reinterpret_cast<HttpsUpstream*>(htparser_get_userdata(htp));
|
||||
upstream->reset_current_header_length();
|
||||
Downstream *downstream = new Downstream(upstream, 0, 0);
|
||||
upstream->add_downstream(downstream);
|
||||
Downstream *downstream = upstream->get_top_downstream();
|
||||
if(downstream) {
|
||||
// Keep-Alived connection
|
||||
downstream->reuse(0);
|
||||
} else {
|
||||
downstream = new Downstream(upstream, 0, 0);
|
||||
upstream->add_downstream(downstream);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
@ -160,11 +166,13 @@ int htp_hdrs_completecb(htparser *htp)
|
|||
downstream->push_request_headers();
|
||||
downstream->set_request_state(Downstream::HEADER_COMPLETE);
|
||||
|
||||
int rv = downstream->start_connection();
|
||||
if(rv != 0) {
|
||||
LOG(ERROR) << "Upstream connection failed";
|
||||
downstream->set_request_state(Downstream::CONNECT_FAIL);
|
||||
return 1;
|
||||
if(downstream->get_counter() == 1) {
|
||||
int rv = downstream->start_connection();
|
||||
if(rv != 0) {
|
||||
LOG(ERROR) << "Upstream connection failed";
|
||||
downstream->set_request_state(Downstream::CONNECT_FAIL);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -298,12 +306,21 @@ void https_downstream_readcb(bufferevent *bev, void *ptr)
|
|||
Downstream *downstream = reinterpret_cast<Downstream*>(ptr);
|
||||
HttpsUpstream *upstream;
|
||||
upstream = static_cast<HttpsUpstream*>(downstream->get_upstream());
|
||||
if(downstream->get_request_state() == Downstream::IDLE) {
|
||||
upstream->pop_downstream();
|
||||
delete downstream;
|
||||
return;
|
||||
}
|
||||
int rv = downstream->parse_http_response();
|
||||
if(rv == 0) {
|
||||
if(downstream->get_response_state() == Downstream::MSG_COMPLETE) {
|
||||
assert(downstream == upstream->get_top_downstream());
|
||||
upstream->pop_downstream();
|
||||
delete downstream;
|
||||
if(downstream->get_response_connection_close()) {
|
||||
upstream->pop_downstream();
|
||||
delete downstream;
|
||||
} else {
|
||||
downstream->idle();
|
||||
}
|
||||
upstream->resume_read(SHRPX_MSG_BLOCK);
|
||||
} else {
|
||||
ClientHandler *handler = upstream->get_client_handler();
|
||||
|
@ -344,27 +361,28 @@ void https_downstream_eventcb(bufferevent *bev, short events, void *ptr)
|
|||
LOG(INFO) << "Downstream connection established. downstream "
|
||||
<< downstream;
|
||||
}
|
||||
}
|
||||
if(events & BEV_EVENT_EOF) {
|
||||
} else if(events & BEV_EVENT_EOF) {
|
||||
if(ENABLE_LOG) {
|
||||
LOG(INFO) << "Downstream EOF. stream_id="
|
||||
<< downstream->get_stream_id();
|
||||
}
|
||||
if(downstream->get_response_state() == Downstream::HEADER_COMPLETE) {
|
||||
// Server may indicate the end of the request by EOF
|
||||
if(ENABLE_LOG) {
|
||||
LOG(INFO) << "Assuming downstream content-length is 0 byte";
|
||||
if(downstream->get_request_state() != Downstream::IDLE) {
|
||||
if(downstream->get_response_state() == Downstream::HEADER_COMPLETE) {
|
||||
// Server may indicate the end of the request by EOF
|
||||
if(ENABLE_LOG) {
|
||||
LOG(INFO) << "Assuming downstream content-length is 0 byte";
|
||||
}
|
||||
upstream->on_downstream_body_complete(downstream);
|
||||
//downstream->set_response_state(Downstream::MSG_COMPLETE);
|
||||
} else if(downstream->get_response_state() == Downstream::MSG_COMPLETE) {
|
||||
// Nothing to do
|
||||
} else {
|
||||
// error
|
||||
if(ENABLE_LOG) {
|
||||
LOG(INFO) << "Treated as downstream error";
|
||||
}
|
||||
upstream->error_reply(502);
|
||||
}
|
||||
upstream->on_downstream_body_complete(downstream);
|
||||
//downstream->set_response_state(Downstream::MSG_COMPLETE);
|
||||
} else if(downstream->get_response_state() == Downstream::MSG_COMPLETE) {
|
||||
// Nothing to do
|
||||
} else {
|
||||
// error
|
||||
if(ENABLE_LOG) {
|
||||
LOG(INFO) << "Treated as downstream error";
|
||||
}
|
||||
upstream->error_reply(502);
|
||||
}
|
||||
upstream->pop_downstream();
|
||||
delete downstream;
|
||||
|
|
Loading…
Reference in New Issue