Use http-parser instead of htparse

This commit is contained in:
Tatsuhiro Tsujikawa 2012-07-11 18:32:04 +09:00
parent 9fd49121ee
commit 12ab6863c4
6 changed files with 173 additions and 125 deletions

View File

@ -88,7 +88,7 @@ shrpx_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} \
shrpx_ssl.cc shrpx_ssl.h \ shrpx_ssl.cc shrpx_ssl.h \
shrpx_thread_event_receiver.cc shrpx_thread_event_receiver.h \ shrpx_thread_event_receiver.cc shrpx_thread_event_receiver.h \
shrpx_worker.cc shrpx_worker.h \ shrpx_worker.cc shrpx_worker.h \
htparse/htparse.c htparse/htparse.h http-parser/http_parser.c http-parser/http_parser.h
endif # HAVE_LIBEVENT_OPENSSL endif # HAVE_LIBEVENT_OPENSSL
noinst_PROGRAMS = spdycli noinst_PROGRAMS = spdycli

View File

@ -50,18 +50,20 @@ Downstream::Downstream(Upstream *upstream, int stream_id, int priority)
chunked_request_(false), chunked_request_(false),
request_connection_close_(false), request_connection_close_(false),
request_expect_100_continue_(false), request_expect_100_continue_(false),
request_header_key_prev_(false),
response_state_(INITIAL), response_state_(INITIAL),
response_http_status_(0), response_http_status_(0),
response_major_(1), response_major_(1),
response_minor_(1), response_minor_(1),
chunked_response_(false), chunked_response_(false),
response_connection_close_(false), response_connection_close_(false),
response_htp_(htparser_new()), response_header_key_prev_(false),
response_htp_(new http_parser()),
response_body_buf_(0), response_body_buf_(0),
recv_window_size_(0) recv_window_size_(0)
{ {
htparser_init(response_htp_, htp_type_response); http_parser_init(response_htp_, HTTP_RESPONSE);
htparser_set_userdata(response_htp_, this); response_htp_->data = this;
} }
Downstream::~Downstream() Downstream::~Downstream()
@ -157,11 +159,13 @@ void check_connection_close(bool *connection_close,
void Downstream::add_request_header(const std::string& name, void Downstream::add_request_header(const std::string& name,
const std::string& value) const std::string& value)
{ {
request_header_key_prev_ = true;
request_headers_.push_back(std::make_pair(name, value)); request_headers_.push_back(std::make_pair(name, value));
} }
void Downstream::set_last_request_header_value(const std::string& value) void Downstream::set_last_request_header_value(const std::string& value)
{ {
request_header_key_prev_ = false;
Headers::value_type &item = request_headers_.back(); Headers::value_type &item = request_headers_.back();
item.second = value; item.second = value;
check_transfer_encoding_chunked(&chunked_request_, item); check_transfer_encoding_chunked(&chunked_request_, item);
@ -169,6 +173,25 @@ void Downstream::set_last_request_header_value(const std::string& value)
//check_connection_close(&request_connection_close_, item); //check_connection_close(&request_connection_close_, item);
} }
bool Downstream::get_request_header_key_prev() const
{
return request_header_key_prev_;
}
void Downstream::append_last_request_header_key(const char *data, size_t len)
{
assert(request_header_key_prev_);
Headers::value_type &item = request_headers_.back();
item.first.append(data, len);
}
void Downstream::append_last_request_header_value(const char *data, size_t len)
{
assert(!request_header_key_prev_);
Headers::value_type &item = request_headers_.back();
item.second.append(data, len);
}
void Downstream::set_request_method(const std::string& method) void Downstream::set_request_method(const std::string& method)
{ {
request_method_ = method; request_method_ = method;
@ -184,6 +207,11 @@ void Downstream::set_request_path(const std::string& path)
request_path_ = path; request_path_ = path;
} }
void Downstream::append_request_path(const char *data, size_t len)
{
request_path_.append(data, len);
}
const std::string& Downstream::get_request_path() const const std::string& Downstream::get_request_path() const
{ {
return request_path_; return request_path_;
@ -393,17 +421,39 @@ const Headers& Downstream::get_response_headers() const
void Downstream::add_response_header(const std::string& name, void Downstream::add_response_header(const std::string& name,
const std::string& value) const std::string& value)
{ {
response_header_key_prev_ = true;
response_headers_.push_back(std::make_pair(name, value)); response_headers_.push_back(std::make_pair(name, value));
} }
void Downstream::set_last_response_header_value(const std::string& value) void Downstream::set_last_response_header_value(const std::string& value)
{ {
response_header_key_prev_ = false;
Headers::value_type &item = response_headers_.back(); Headers::value_type &item = response_headers_.back();
item.second = value; item.second = value;
check_transfer_encoding_chunked(&chunked_response_, item); check_transfer_encoding_chunked(&chunked_response_, item);
//check_connection_close(&response_connection_close_, item); //check_connection_close(&response_connection_close_, item);
} }
bool Downstream::get_response_header_key_prev() const
{
return response_header_key_prev_;
}
void Downstream::append_last_response_header_key(const char *data, size_t len)
{
assert(response_header_key_prev_);
Headers::value_type &item = response_headers_.back();
item.first.append(data, len);
}
void Downstream::append_last_response_header_value(const char *data,
size_t len)
{
assert(!response_header_key_prev_);
Headers::value_type &item = response_headers_.back();
item.second.append(data, len);
}
unsigned int Downstream::get_response_http_status() const unsigned int Downstream::get_response_http_status() const
{ {
return response_http_status_; return response_http_status_;
@ -455,14 +505,14 @@ void Downstream::set_response_connection_close(bool f)
} }
namespace { namespace {
int htp_hdrs_completecb(htparser *htp) int htp_hdrs_completecb(http_parser *htp)
{ {
Downstream *downstream; Downstream *downstream;
downstream = reinterpret_cast<Downstream*>(htparser_get_userdata(htp)); downstream = reinterpret_cast<Downstream*>(htp->data);
downstream->set_response_http_status(htparser_get_status(htp)); downstream->set_response_http_status(htp->status_code);
downstream->set_response_major(htparser_get_major(htp)); downstream->set_response_major(htp->http_major);
downstream->set_response_minor(htparser_get_minor(htp)); downstream->set_response_minor(htp->http_minor);
downstream->set_response_connection_close(!htparser_should_keep_alive(htp)); downstream->set_response_connection_close(!http_should_keep_alive(htp));
downstream->set_response_state(Downstream::HEADER_COMPLETE); downstream->set_response_state(Downstream::HEADER_COMPLETE);
downstream->get_upstream()->on_downstream_header_complete(downstream); downstream->get_upstream()->on_downstream_header_complete(downstream);
return 0; return 0;
@ -470,30 +520,38 @@ int htp_hdrs_completecb(htparser *htp)
} // namespace } // namespace
namespace { namespace {
int htp_hdr_keycb(htparser *htp, const char *data, size_t len) int htp_hdr_keycb(http_parser *htp, const char *data, size_t len)
{ {
Downstream *downstream; Downstream *downstream;
downstream = reinterpret_cast<Downstream*>(htparser_get_userdata(htp)); downstream = reinterpret_cast<Downstream*>(htp->data);
downstream->add_response_header(std::string(data, len), ""); if(downstream->get_response_header_key_prev()) {
downstream->append_last_response_header_key(data, len);
} else {
downstream->add_response_header(std::string(data, len), "");
}
return 0; return 0;
} }
} // namespace } // namespace
namespace { namespace {
int htp_hdr_valcb(htparser *htp, const char *data, size_t len) int htp_hdr_valcb(http_parser *htp, const char *data, size_t len)
{ {
Downstream *downstream; Downstream *downstream;
downstream = reinterpret_cast<Downstream*>(htparser_get_userdata(htp)); downstream = reinterpret_cast<Downstream*>(htp->data);
downstream->set_last_response_header_value(std::string(data, len)); if(downstream->get_response_header_key_prev()) {
downstream->set_last_response_header_value(std::string(data, len));
} else {
downstream->append_last_response_header_value(data, len);
}
return 0; return 0;
} }
} // namespace } // namespace
namespace { namespace {
int htp_bodycb(htparser *htp, const char *data, size_t len) int htp_bodycb(http_parser *htp, const char *data, size_t len)
{ {
Downstream *downstream; Downstream *downstream;
downstream = reinterpret_cast<Downstream*>(htparser_get_userdata(htp)); downstream = reinterpret_cast<Downstream*>(htp->data);
downstream->get_upstream()->on_downstream_body downstream->get_upstream()->on_downstream_body
(downstream, reinterpret_cast<const uint8_t*>(data), len); (downstream, reinterpret_cast<const uint8_t*>(data), len);
@ -502,10 +560,10 @@ int htp_bodycb(htparser *htp, const char *data, size_t len)
} // namespace } // namespace
namespace { namespace {
int htp_body_completecb(htparser *htp) int htp_msg_completecb(http_parser *htp)
{ {
Downstream *downstream; Downstream *downstream;
downstream = reinterpret_cast<Downstream*>(htparser_get_userdata(htp)); downstream = reinterpret_cast<Downstream*>(htp->data);
if(downstream->tunnel_established()) { if(downstream->tunnel_established()) {
// For tunneling, we remove timeouts. // For tunneling, we remove timeouts.
@ -514,30 +572,26 @@ int htp_body_completecb(htparser *htp)
downstream->set_response_state(Downstream::MSG_COMPLETE); downstream->set_response_state(Downstream::MSG_COMPLETE);
downstream->get_upstream()->on_downstream_body_complete(downstream); downstream->get_upstream()->on_downstream_body_complete(downstream);
return 0;
if(downstream->get_request_method() == "HEAD") {
// Ignore the response body. HEAD response may contain
// Content-Length or Transfer-Encoding: chunked.
return 1;
} else {
return 0;
}
} }
} // namespace } // namespace
namespace { namespace {
htparse_hooks htp_hooks = { http_parser_settings htp_hooks = {
0, /*htparse_hook on_msg_begin;*/ 0, /*http_cb on_message_begin;*/
0, /*htparse_data_hook method;*/ 0, /*http_data_cb on_url;*/
0, /* htparse_data_hook scheme;*/ htp_hdr_keycb, /*http_data_cb on_header_field;*/
0, /* htparse_data_hook host; */ htp_hdr_valcb, /*http_data_cb on_header_value;*/
0, /* htparse_data_hook port; */ htp_hdrs_completecb, /*http_cb on_headers_complete;*/
0, /* htparse_data_hook path; */ htp_bodycb, /*http_data_cb on_body;*/
0, /* htparse_data_hook args; */ htp_msg_completecb /*http_cb on_message_complete;*/
0, /* htparse_data_hook uri; */
0, /* htparse_hook on_hdrs_begin; */
htp_hdr_keycb, /* htparse_data_hook hdr_key; */
htp_hdr_valcb, /* htparse_data_hook hdr_val; */
0, /* htparse_data_hook hostname; */
htp_hdrs_completecb, /* htparse_hook on_hdrs_complete; */
0, /*htparse_hook on_new_chunk;*/
0, /*htparse_hook on_chunk_complete;*/
0, /*htparse_hook on_chunks_complete;*/
htp_bodycb, /* htparse_data_hook body; */
htp_body_completecb /* htparse_hook on_msg_complete;*/
}; };
} // namespace } // namespace
@ -547,17 +601,19 @@ int Downstream::parse_http_response()
evbuffer *input = bufferevent_get_input(bev); evbuffer *input = bufferevent_get_input(bev);
unsigned char *mem = evbuffer_pullup(input, -1); unsigned char *mem = evbuffer_pullup(input, -1);
size_t nread = htparser_run(response_htp_, &htp_hooks, size_t nread = http_parser_execute(response_htp_, &htp_hooks,
reinterpret_cast<const char*>(mem), reinterpret_cast<const char*>(mem),
evbuffer_get_length(input)); evbuffer_get_length(input));
evbuffer_drain(input, nread); evbuffer_drain(input, nread);
if(htparser_get_error(response_htp_) == htparse_error_none) { http_errno htperr = HTTP_PARSER_ERRNO(response_htp_);
if(htperr == HPE_OK) {
return 0; return 0;
} else { } else {
if(ENABLE_LOG) { if(ENABLE_LOG) {
LOG(INFO) << "Downstream HTTP parser failure: " LOG(INFO) << "Downstream HTTP parser failure: "
<< htparser_get_strerror(response_htp_); << "(" << http_errno_name(htperr) << ") "
<< http_errno_description(htperr);
} }
return SHRPX_ERR_HTTP_PARSE; return SHRPX_ERR_HTTP_PARSE;
} }

View File

@ -36,7 +36,7 @@
#include <event2/bufferevent.h> #include <event2/bufferevent.h>
extern "C" { extern "C" {
#include "htparse/htparse.h" #include "http-parser/http_parser.h"
} }
#include "shrpx_io_control.h" #include "shrpx_io_control.h"
@ -72,9 +72,15 @@ public:
const Headers& get_request_headers() const; const Headers& get_request_headers() const;
void add_request_header(const std::string& name, const std::string& value); void add_request_header(const std::string& name, const std::string& value);
void set_last_request_header_value(const std::string& value); void set_last_request_header_value(const std::string& value);
bool get_request_header_key_prev() const;
void append_last_request_header_key(const char *data, size_t len);
void append_last_request_header_value(const char *data, size_t len);
void set_request_method(const std::string& method); void set_request_method(const std::string& method);
const std::string& get_request_method() const; const std::string& get_request_method() const;
void set_request_path(const std::string& path); void set_request_path(const std::string& path);
void append_request_path(const char *data, size_t len);
const std::string& get_request_path() const; const std::string& get_request_path() const;
void set_request_major(int major); void set_request_major(int major);
void set_request_minor(int minor); void set_request_minor(int minor);
@ -101,6 +107,11 @@ public:
const Headers& get_response_headers() const; const Headers& get_response_headers() const;
void add_response_header(const std::string& name, const std::string& value); void add_response_header(const std::string& name, const std::string& value);
void set_last_response_header_value(const std::string& value); void set_last_response_header_value(const std::string& value);
bool get_response_header_key_prev() const;
void append_last_response_header_key(const char *data, size_t len);
void append_last_response_header_value(const char *data, size_t len);
unsigned int get_response_http_status() const; unsigned int get_response_http_status() const;
void set_response_http_status(unsigned int status); void set_response_http_status(unsigned int status);
void set_response_major(int major); void set_response_major(int major);
@ -131,6 +142,7 @@ private:
bool request_connection_close_; bool request_connection_close_;
bool request_expect_100_continue_; bool request_expect_100_continue_;
Headers request_headers_; Headers request_headers_;
bool request_header_key_prev_;
int response_state_; int response_state_;
unsigned int response_http_status_; unsigned int response_http_status_;
@ -139,7 +151,8 @@ private:
bool chunked_response_; bool chunked_response_;
bool response_connection_close_; bool response_connection_close_;
Headers response_headers_; Headers response_headers_;
htparser *response_htp_; bool response_header_key_prev_;
http_parser *response_htp_;
// This buffer is used to temporarily store downstream response // This buffer is used to temporarily store downstream response
// body. Spdylay reads data from this in the callback. // body. Spdylay reads data from this in the callback.
evbuffer *response_body_buf_; evbuffer *response_body_buf_;

View File

@ -46,12 +46,12 @@ const size_t SHRPX_HTTPS_MAX_HEADER_LENGTH = 64*1024;
HttpsUpstream::HttpsUpstream(ClientHandler *handler) HttpsUpstream::HttpsUpstream(ClientHandler *handler)
: handler_(handler), : handler_(handler),
htp_(htparser_new()), htp_(new http_parser()),
current_header_length_(0), current_header_length_(0),
ioctrl_(handler->get_bev()) ioctrl_(handler->get_bev())
{ {
htparser_init(htp_, htp_type_request); http_parser_init(htp_, HTTP_REQUEST);
htparser_set_userdata(htp_, this); htp_->data = this;
} }
HttpsUpstream::~HttpsUpstream() HttpsUpstream::~HttpsUpstream()
@ -69,10 +69,10 @@ void HttpsUpstream::reset_current_header_length()
} }
namespace { namespace {
int htp_msg_begin(htparser *htp) int htp_msg_begin(http_parser *htp)
{ {
HttpsUpstream *upstream; HttpsUpstream *upstream;
upstream = reinterpret_cast<HttpsUpstream*>(htparser_get_userdata(htp)); upstream = reinterpret_cast<HttpsUpstream*>(htp->data);
if(ENABLE_LOG) { if(ENABLE_LOG) {
LOG(INFO) << "Upstream https request start " << upstream; LOG(INFO) << "Upstream https request start " << upstream;
} }
@ -84,73 +84,61 @@ int htp_msg_begin(htparser *htp)
} // namespace } // namespace
namespace { namespace {
int htp_methodcb(htparser *htp, const char *data, size_t len) int htp_uricb(http_parser *htp, const char *data, size_t len)
{ {
HttpsUpstream *upstream; HttpsUpstream *upstream;
upstream = reinterpret_cast<HttpsUpstream*>(htparser_get_userdata(htp)); upstream = reinterpret_cast<HttpsUpstream*>(htp->data);
Downstream *downstream = upstream->get_last_downstream(); Downstream *downstream = upstream->get_last_downstream();
downstream->set_request_method(std::string(data, len)); downstream->append_request_path(data, len);
return 0; return 0;
} }
} // namespace } // namespace
namespace { namespace {
int htp_uricb(htparser *htp, const char *data, size_t len) int htp_hdr_keycb(http_parser *htp, const char *data, size_t len)
{ {
HttpsUpstream *upstream; HttpsUpstream *upstream;
upstream = reinterpret_cast<HttpsUpstream*>(htparser_get_userdata(htp)); upstream = reinterpret_cast<HttpsUpstream*>(htp->data);
Downstream *downstream = upstream->get_last_downstream(); Downstream *downstream = upstream->get_last_downstream();
downstream->set_request_path(std::string(data, len)); if(downstream->get_request_header_key_prev()) {
return 0; downstream->append_last_request_header_key(data, len);
} } else {
} // namespace downstream->add_request_header(std::string(data, len), "");
namespace {
int htp_hdrs_begincb(htparser *htp)
{
if(ENABLE_LOG) {
LOG(INFO) << "Upstream https request headers start";
} }
return 0; return 0;
} }
} // namespace } // namespace
namespace { namespace {
int htp_hdr_keycb(htparser *htp, const char *data, size_t len) int htp_hdr_valcb(http_parser *htp, const char *data, size_t len)
{ {
HttpsUpstream *upstream; HttpsUpstream *upstream;
upstream = reinterpret_cast<HttpsUpstream*>(htparser_get_userdata(htp)); upstream = reinterpret_cast<HttpsUpstream*>(htp->data);
Downstream *downstream = upstream->get_last_downstream(); Downstream *downstream = upstream->get_last_downstream();
downstream->add_request_header(std::string(data, len), ""); if(downstream->get_request_header_key_prev()) {
downstream->set_last_request_header_value(std::string(data, len));
} else {
downstream->append_last_request_header_value(data, len);
}
return 0; return 0;
} }
} // namespace } // namespace
namespace { namespace {
int htp_hdr_valcb(htparser *htp, const char *data, size_t len) int htp_hdrs_completecb(http_parser *htp)
{ {
HttpsUpstream *upstream; HttpsUpstream *upstream;
upstream = reinterpret_cast<HttpsUpstream*>(htparser_get_userdata(htp)); upstream = reinterpret_cast<HttpsUpstream*>(htp->data);
Downstream *downstream = upstream->get_last_downstream();
downstream->set_last_request_header_value(std::string(data, len));
return 0;
}
} // namespace
namespace {
int htp_hdrs_completecb(htparser *htp)
{
HttpsUpstream *upstream;
upstream = reinterpret_cast<HttpsUpstream*>(htparser_get_userdata(htp));
if(ENABLE_LOG) { if(ENABLE_LOG) {
LOG(INFO) << "Upstream https request headers complete " << upstream; LOG(INFO) << "Upstream https request headers complete " << upstream;
} }
Downstream *downstream = upstream->get_last_downstream(); Downstream *downstream = upstream->get_last_downstream();
downstream->set_request_major(htparser_get_major(htp)); downstream->set_request_method(http_method_str((enum http_method)htp->method));
downstream->set_request_minor(htparser_get_minor(htp)); downstream->set_request_major(htp->http_major);
downstream->set_request_minor(htp->http_minor);
downstream->set_request_connection_close(!htparser_should_keep_alive(htp)); downstream->set_request_connection_close(!http_should_keep_alive(htp));
DownstreamConnection *dconn; DownstreamConnection *dconn;
dconn = upstream->get_client_handler()->get_downstream_connection(); dconn = upstream->get_client_handler()->get_downstream_connection();
@ -176,10 +164,10 @@ int htp_hdrs_completecb(htparser *htp)
} // namespace } // namespace
namespace { namespace {
int htp_bodycb(htparser *htp, const char *data, size_t len) int htp_bodycb(http_parser *htp, const char *data, size_t len)
{ {
HttpsUpstream *upstream; HttpsUpstream *upstream;
upstream = reinterpret_cast<HttpsUpstream*>(htparser_get_userdata(htp)); upstream = reinterpret_cast<HttpsUpstream*>(htp->data);
Downstream *downstream = upstream->get_last_downstream(); Downstream *downstream = upstream->get_last_downstream();
downstream->push_upload_data_chunk(reinterpret_cast<const uint8_t*>(data), downstream->push_upload_data_chunk(reinterpret_cast<const uint8_t*>(data),
len); len);
@ -188,44 +176,35 @@ int htp_bodycb(htparser *htp, const char *data, size_t len)
} // namespace } // namespace
namespace { namespace {
int htp_msg_completecb(htparser *htp) int htp_msg_completecb(http_parser *htp)
{ {
if(ENABLE_LOG) { if(ENABLE_LOG) {
LOG(INFO) << "Upstream https request complete"; LOG(INFO) << "Upstream https request complete";
} }
HttpsUpstream *upstream; HttpsUpstream *upstream;
upstream = reinterpret_cast<HttpsUpstream*>(htparser_get_userdata(htp)); upstream = reinterpret_cast<HttpsUpstream*>(htp->data);
Downstream *downstream = upstream->get_last_downstream(); Downstream *downstream = upstream->get_last_downstream();
downstream->end_upload_data(); downstream->end_upload_data();
downstream->set_request_state(Downstream::MSG_COMPLETE); downstream->set_request_state(Downstream::MSG_COMPLETE);
// Stop further processing to complete this request // Stop further processing to complete this request
return 1; http_parser_pause(htp, 1);
return 0;
} }
} // namespace } // namespace
namespace { namespace {
htparse_hooks htp_hooks = { http_parser_settings htp_hooks = {
htp_msg_begin, /*htparse_hook on_msg_begin;*/ htp_msg_begin, /*http_cb on_message_begin;*/
htp_methodcb, /*htparse_data_hook method;*/ htp_uricb, /*http_data_cb on_url;*/
0, /* htparse_data_hook scheme;*/ htp_hdr_keycb, /*http_data_cb on_header_field;*/
0, /* htparse_data_hook host; */ htp_hdr_valcb, /*http_data_cb on_header_value;*/
0, /* htparse_data_hook port; */ htp_hdrs_completecb, /*http_cb on_headers_complete;*/
0, /* htparse_data_hook path; */ htp_bodycb, /*http_data_cb on_body;*/
0, /* htparse_data_hook args; */ htp_msg_completecb /*http_cb on_message_complete;*/
htp_uricb, /* htparse_data_hook uri; */
htp_hdrs_begincb, /* htparse_hook on_hdrs_begin; */
htp_hdr_keycb, /* htparse_data_hook hdr_key; */
htp_hdr_valcb, /* htparse_data_hook hdr_val; */
0, /* htparse_data_hook hostname; */
htp_hdrs_completecb, /* htparse_hook on_hdrs_complete; */
0, /*htparse_hook on_new_chunk;*/
0, /*htparse_hook on_chunk_complete;*/
0, /*htparse_hook on_chunks_complete;*/
htp_bodycb, /* htparse_data_hook body; */
htp_msg_completecb /* htparse_hook on_msg_complete;*/
}; };
} // namespace } // namespace
// on_read() does not consume all available data in input buffer if // on_read() does not consume all available data in input buffer if
// one http request is fully received. // one http request is fully received.
int HttpsUpstream::on_read() int HttpsUpstream::on_read()
@ -235,15 +214,19 @@ int HttpsUpstream::on_read()
unsigned char *mem = evbuffer_pullup(input, -1); unsigned char *mem = evbuffer_pullup(input, -1);
int nread = htparser_run(htp_, &htp_hooks, if(evbuffer_get_length(input) == 0) {
reinterpret_cast<const char*>(mem), return 0;
evbuffer_get_length(input)); }
size_t nread = http_parser_execute(htp_, &htp_hooks,
reinterpret_cast<const char*>(mem),
evbuffer_get_length(input));
evbuffer_drain(input, nread); evbuffer_drain(input, nread);
// Well, actually header length + some body bytes // Well, actually header length + some body bytes
current_header_length_ += nread; current_header_length_ += nread;
htpparse_error htperr = htparser_get_error(htp_);
Downstream *downstream = get_top_downstream(); Downstream *downstream = get_top_downstream();
if(htperr == htparse_error_user) { http_errno htperr = HTTP_PARSER_ERRNO(htp_);
if(htperr == HPE_PAUSED) {
if(downstream->get_request_state() == Downstream::CONNECT_FAIL) { if(downstream->get_request_state() == Downstream::CONNECT_FAIL) {
get_client_handler()->set_should_close_after_write(true); get_client_handler()->set_should_close_after_write(true);
error_reply(503); error_reply(503);
@ -259,7 +242,7 @@ int HttpsUpstream::on_read()
pause_read(SHRPX_MSG_BLOCK); pause_read(SHRPX_MSG_BLOCK);
} }
} }
} else if(htperr == htparse_error_none) { } else if(htperr == HPE_OK) {
// downstream can be NULL here. // downstream can be NULL here.
if(downstream) { if(downstream) {
if(downstream->get_request_state() == Downstream::INITIAL && if(downstream->get_request_state() == Downstream::INITIAL &&
@ -278,7 +261,8 @@ int HttpsUpstream::on_read()
} else { } else {
if(ENABLE_LOG) { if(ENABLE_LOG) {
LOG(INFO) << "Upstream http parse failure: " LOG(INFO) << "Upstream http parse failure: "
<< htparser_get_strerror(htp_); << "(" << http_errno_name(htperr) << ") "
<< http_errno_description(htperr);
} }
get_client_handler()->set_should_close_after_write(true); get_client_handler()->set_should_close_after_write(true);
error_reply(400); error_reply(400);
@ -319,6 +303,7 @@ void HttpsUpstream::resume_read(IOCtrlReason reason)
if(ioctrl_.resume_read(reason)) { if(ioctrl_.resume_read(reason)) {
// Process remaining data in input buffer here because these bytes // Process remaining data in input buffer here because these bytes
// are not notified by readcb until new data arrive. // are not notified by readcb until new data arrive.
http_parser_pause(htp_, 0);
on_read(); on_read();
} }
} }

View File

@ -32,7 +32,7 @@
#include <deque> #include <deque>
extern "C" { extern "C" {
#include "htparse/htparse.h" #include "http-parser/http_parser.h"
} }
#include "shrpx_upstream.h" #include "shrpx_upstream.h"
@ -71,7 +71,7 @@ public:
void reset_current_header_length(); void reset_current_header_length();
private: private:
ClientHandler *handler_; ClientHandler *handler_;
htparser *htp_; http_parser *htp_;
size_t current_header_length_; size_t current_header_length_;
std::deque<Downstream*> downstream_queue_; std::deque<Downstream*> downstream_queue_;
IOControl ioctrl_; IOControl ioctrl_;

View File

@ -351,9 +351,6 @@ ClientHandler* SpdyUpstream::get_client_handler() const
namespace { namespace {
void spdy_downstream_readcb(bufferevent *bev, void *ptr) void spdy_downstream_readcb(bufferevent *bev, void *ptr)
{ {
if(ENABLE_LOG) {
LOG(INFO) << "spdy_downstream_readcb";
}
DownstreamConnection *dconn = reinterpret_cast<DownstreamConnection*>(ptr); DownstreamConnection *dconn = reinterpret_cast<DownstreamConnection*>(ptr);
Downstream *downstream = dconn->get_downstream(); Downstream *downstream = dconn->get_downstream();
SpdyUpstream *upstream; SpdyUpstream *upstream;
@ -674,9 +671,6 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream)
int SpdyUpstream::on_downstream_body(Downstream *downstream, int SpdyUpstream::on_downstream_body(Downstream *downstream,
const uint8_t *data, size_t len) const uint8_t *data, size_t len)
{ {
if(ENABLE_LOG) {
LOG(INFO) << "Downstream on_downstream_body";
}
evbuffer *body = downstream->get_response_body_buf(); evbuffer *body = downstream->get_response_body_buf();
evbuffer_add(body, data, len); evbuffer_add(body, data, len);
spdylay_session_resume_data(session_, downstream->get_stream_id()); spdylay_session_resume_data(session_, downstream->get_stream_id());