summaryrefslogtreecommitdiff
path: root/src/http1.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/http1.cc')
-rw-r--r--src/http1.cc95
1 files changed, 69 insertions, 26 deletions
diff --git a/src/http1.cc b/src/http1.cc
index 868d367..6a06d15 100644
--- a/src/http1.cc
+++ b/src/http1.cc
@@ -545,7 +545,9 @@ public:
void Body(std::vector<body_content_ptr_t> body) override
{
+ assert(body_contents_.empty());
body_contents_.clear();
+
for (auto & body_content_iter : body)
{
body_contents_.emplace_back(std::move(body_content_iter), true);
@@ -557,7 +559,6 @@ private:
short resp_version_major_{1};
short resp_version_minor_{1};
- bool parse_complete_{false};
bool forward_{true};
bool readonly_{false};
@@ -831,9 +832,29 @@ void Http1Response::Construct()
/* 结尾行 */
evbuffer_add_printf(evbuf_ptr, "\r\n");
- /* TODO: 消息体的构建 */
+ for(auto & body_segment : body_contents_)
+ {
+ if (body_segment.ptr == nullptr || !body_segment.is_complete) continue;
+ auto * body_segment_ptr = body_segment.ptr.get();
+
+ if (body_is_chunk)
+ {
+ evbuffer_add_printf(evbuf_ptr, "%lx\r\n", body_segment_ptr->size());
+ evbuffer_add(evbuf_ptr, body_segment_ptr->data(), body_segment.ptr->size());
+ evbuffer_add_printf(evbuf_ptr, "\r\n");
+ }
+ else
+ {
+ evbuffer_add(evbuf_ptr, body_segment.ptr->data(), body_segment.ptr->size());
+ }
+ }
+
evbuf_content_raw_ = std::move(evbuf_construct);
- parse_complete_ = true;
+ section_state[kSectionHeader] = kStateComplete;
+ section_state[kSectionBody] = kStateComplete;
+ section_state[kSectionMessage] = kStateComplete;
+
+ return;
}
evbuffer_unique_ptr_t Http1Response::StolenEvBuf()
@@ -865,14 +886,14 @@ int Http1Connection::on_connection_read_request(pxy_conn_ctx_t * conn_ctx, pxy_c
pxy_conn_desc_t * conn_other)
{
/* Get the last session */
- auto & http_session = last_uncomplete_session();
- auto & request = dynamic_cast<Http1Request &>(http_session.request());
+ auto * http_session = last_uncomplete_session(kDirectionRequest);
+ assert(http_session != nullptr);
+ auto & request = dynamic_cast<Http1Request &>(http_session->request());
auto * downstream_evbuf = bufferevent_get_input(conn_this->bev);
auto * upstream_evbuf = bufferevent_get_output(conn_other->bev);
ssize_t forward_len = request.ConstructFromEvBuf(downstream_evbuf);
-
if (forward_len < 0)
{
LOG(DEBUG) << "ctx = " << conn_ctx << " "
@@ -884,15 +905,17 @@ int Http1Connection::on_connection_read_request(pxy_conn_ctx_t * conn_ctx, pxy_c
if (request.Complete(HttpRequest::kSectionHeader))
{
- http_session.CallRequestHeaderCallback();
+ LOG(DEBUG) << std::addressof(http_session) << "CallRequestHeaderCallback";
+ http_session->CallRequestHeaderCallback();
}
if (request.Complete(HttpRequest::kSectionBody) && request.Body() != nullptr)
{
- http_session.CallRequestBodyCallback();
+ LOG(DEBUG) << std::addressof(http_session) << "CallRequestBodyCallback";
+ http_session->CallRequestBodyCallback();
}
- if (http_session.NeedToDrop())
+ if (http_session->NeedToDrop())
{
drop_last_session();
return 0;
@@ -910,14 +933,14 @@ int Http1Connection::on_connection_read_request(pxy_conn_ctx_t * conn_ctx, pxy_c
int Http1Connection::on_connection_read_response(pxy_conn_ctx_t * conn_ctx, pxy_conn_desc_t * conn_this,
pxy_conn_desc_t * conn_other)
{
- auto & http_session = last_uncomplete_session();
- auto & response = dynamic_cast<Http1Response &>(http_session.response());
+ auto * http_session = last_uncomplete_session(kDirectionResponse);
+ assert(http_session != nullptr);
+ auto & response = dynamic_cast<Http1Response &>(http_session->response());
auto * downstream_evbuf = bufferevent_get_input(conn_this->bev);
auto * upstream_evbuf = bufferevent_get_output(conn_other->bev);
ssize_t forward_len = response.ConstructFromEvBuf(downstream_evbuf);
-
if (forward_len < 0)
{
LOG(DEBUG) << conn_ctx << "ResponseConstructFromEvBuf Failed, connection turns to passthrough";
@@ -931,12 +954,14 @@ int Http1Connection::on_connection_read_response(pxy_conn_ctx_t * conn_ctx, pxy_
if (response.SectionState(response.kSectionHeader) == response.kStateComplete)
{
- http_session.CallRequestHeaderCallback();
+ LOG(DEBUG) << std::addressof(http_session) << "CallResponseHeaderCallback";
+ http_session->CallResponseHeaderCallback();
}
if (response.SectionState(response.kSectionBody) == response.kStateComplete)
{
- http_session.CallResponseBodyCallback();
+ LOG(DEBUG) << std::addressof(http_session) << "CallResponseBodyCallback";
+ http_session->CallResponseBodyCallback();
}
/* 如果有任何一部分为Reading,说明该部分数据还为到来,暂时不转发 */
@@ -952,13 +977,13 @@ int Http1Connection::on_connection_read_response(pxy_conn_ctx_t * conn_ctx, pxy_
if (response.SectionState(response.kSectionMessage) == response.kStateComplete)
{
- drop_last_session();
+ drop_first_session();
}
return 0;
}
-HttpSession & Http1Connection::create_new_session()
+HttpSession * Http1Connection::create_new_session()
{
/* Create new session, set a new request */
auto __http_session = std::unique_ptr<HttpSession>(new HttpSession(*this));
@@ -970,22 +995,40 @@ HttpSession & Http1Connection::create_new_session()
/* Add to the last record */
http_sessions_.push_back(std::move(__http_session));
- return *http_sessions_.back();
+ return http_sessions_.back().get();
}
-HttpSession & Http1Connection::last_uncomplete_session()
+HttpSession * Http1Connection::last_uncomplete_session(enum direction dir)
{
- if (http_sessions_.cbegin() == http_sessions_.cend())
- return create_new_session();
+ if (dir == kDirectionRequest)
+ {
+ if (http_sessions_.empty())
+ {
+ return create_new_session();
+ }
- /* 最后一个Session已经处理结束了,新建一个Session */
- auto & __session = http_sessions_.back();
+ /* 看一下请求侧的状态,如果已经处理完了,说明使用了HttpPipeLine,新建一个Session */
+ auto * __session = http_sessions_.back().get();
+ if (__session->request().Complete(HttpRequest::kSecionMessage))
+ return create_new_session();
- if (__session->request().Complete(HttpRequest::kSecionMessage))
- return create_new_session();
+ /* 否则,返回最后一个没有完全处理结束的Session */
+ return __session;
+ }
+ else if (dir == kDirectionResponse)
+ {
+ if (http_sessions_.empty())
+ {
+ LOG(DEBUG) << "session queue is empty, no corresponding session for response.";
+ return nullptr;
+ }
+
+ auto * __session = http_sessions_.front().get();
+ return __session;
+ }
- /* 否则,返回最后一个没有完全处理结束的Session */
- return *__session;
+ assert(0);
+ return nullptr;
}
void Http1Connection::drop_last_session()