summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLu <[email protected]>2018-07-13 19:58:21 +0800
committerLu <[email protected]>2018-07-13 19:58:21 +0800
commit029c1140317f76229690b8aa89e10b78f9d6a19d (patch)
tree38222f2a33d81a640db94b20cfb9ce1e5b628078
parent660e3fbe82371b090a57f6ae1b30ebd5fb98947e (diff)
实现对Chunk类型的应答内容的解析 #2
-rw-r--r--src/http1.cc29
-rw-r--r--src/httpscan.cc97
-rw-r--r--src/httpscan.h10
3 files changed, 127 insertions, 9 deletions
diff --git a/src/http1.cc b/src/http1.cc
index ac02b58..2011bd6 100644
--- a/src/http1.cc
+++ b/src/http1.cc
@@ -670,17 +670,22 @@ int Http1ResponseParserCallbacks::CallbackOnMessageComplete(http_parser * parser
int Http1ResponseParserCallbacks::CallbackOnChunkHeader(http_parser * parser)
{
+ auto * resp_ptr = __response_this_ptr(parser);
+ resp_ptr->__set_section_state(resp_ptr->kSectionBody, resp_ptr->kStateReading);
+
/* On chunk begin, setup chunk tag */
- __response_this_ptr(parser)->body_is_chunk = true;
- __response_this_ptr(parser)->body_chunk_id++;
+ resp_ptr->body_is_chunk = true;
+ resp_ptr->body_chunk_id++;
/* Drop old body content */
- __response_this_ptr(parser)->body_content_ = nullptr;
+ resp_ptr->body_content_ = nullptr;
return 0;
}
int Http1ResponseParserCallbacks::CallbackOnChunkComplete(http_parser * parser)
{
+ auto * resp_ptr = __response_this_ptr(parser);
+ resp_ptr->__set_section_state(resp_ptr->kSectionBody, resp_ptr->kStateComplete);
return 0;
}
@@ -848,28 +853,36 @@ int Http1Connection::on_connection_read_response(pxy_conn_ctx_t * conn_ctx, pxy_
conn_ctx->passthrough = 1;
return 0;
}
+ else if (forward_len == 0)
+ {
+ return 0;
+ }
if (response.SectionState(response.kSectionHeader) == response.kStateComplete)
{
http_session.CallRequestHeaderCallback();
- goto __forward;
}
if (response.SectionState(response.kSectionBody) == response.kStateComplete)
{
http_session.CallResponseBodyCallback();
- goto __forward;
}
+ /* 如果有任何一部分为Reading,说明该部分数据还为到来,暂时不转发 */
+ if (response.SectionState(response.kSectionHeader) == response.kStateReading ||
+ response.SectionState(response.kSectionBody) == response.kStateReading)
+ {
+ return 0;
+ }
+
+ /* 转发缓存中的数据,如果该Response处理结束,本Session处理完毕,销毁Session */
+ evbuffer_add_buffer(upstream_evbuf, response.StolenEvBuf().release());
if (response.SectionState(response.kSectionMessage) == response.kStateComplete)
{
drop_last_session();
}
return 0;
-
-__forward:
- evbuffer_add_buffer(upstream_evbuf, response.StolenEvBuf().release());
}
HttpSession & Http1Connection::create_new_session()
diff --git a/src/httpscan.cc b/src/httpscan.cc
index 6366f85..29ee773 100644
--- a/src/httpscan.cc
+++ b/src/httpscan.cc
@@ -232,14 +232,109 @@ void HttpScanSession::ScanRequestBody(HttpSession * http_session_ctx)
void HttpScanSession::ScanResponseHeader(HttpSession * http_session_ctx)
{
+ auto & response = http_session_ctx->response();
+
+ /* 扫描应答头部 */
+ auto scan_result = scan_headers(response.cHeaders(), httpscan_module_ref_.table_id_ctrl_http_res_hdr);
+
+ /* Hit */
+ if (scan_result == scan_result_t::kScanResultHit)
+ {
+ http_session_ctx->SetResponseHeaderTag(http_session_ctx->kCallbackTagRepeat);
+ return hit_config_and_do_action(http_session_ctx);
+ }
+ /* Error */
+ else if (scan_result == scan_result_t::kScanResultError)
+ {
+ return hit_scan_error();
+ }
+
+ /* Not Hit */
return;
}
void HttpScanSession::ScanResponseBody(HttpSession * http_session_ctx)
{
+ auto & response = http_session_ctx->response();
+
+ /* Body Content and length, prepare for maat */
+ const char * body_content_raw = response.Body()->data();
+ size_t body_content_length = response.Body()->size();
+
+ auto scan_result = scan_body(body_content_raw, body_content_length,
+ httpscan_module_ref_.table_id_ctrl_http_res_body);
+
+ /* Hit */
+ if (scan_result == scan_result_t::kScanResultHit)
+ {
+ http_session_ctx->SetResponseBodyTag(http_session_ctx->kCallbackTagRepeat);
+ return hit_config_and_do_action(http_session_ctx);
+ }
+ /* Error */
+ else if (scan_result == scan_result_t::kScanResultError)
+ {
+ return hit_scan_error();
+ }
+
return;
}
+HttpScanSession::scan_result_t HttpScanSession::scan_headers(const HttpHeaders & c_headers, int table_id)
+{
+ scan_result_t scan_result = scan_result_t::kScanResultNotHit;
+
+ c_headers.ForEachHeader([this, &scan_result, table_id]
+ (const std::string & field, const std::string & value) -> bool
+ {
+ int ret = Maat_set_scan_status(httpscan_module_ref_.maat_feather_ref, &maat_scan_mid_,
+ MAAT_SET_SCAN_DISTRICT, field.c_str(), (int) field.length());
+
+ if (ret < 0)
+ {
+ scan_result = scan_result_t::kScanResultError;
+ return false;
+ }
+
+ int __dummy[MAAT_SCAN_RESULT_];
+
+ nr_maat_scan_result_ = Maat_full_scan_string(httpscan_module_ref_.maat_feather_ref,
+ table_id, MAAT_DEFAULT_CHARSET_, value.c_str(), (int) value.length(), maat_scan_result_, __dummy,
+ MAAT_SCAN_RESULT_, &maat_scan_mid_, 0);
+
+ if (nr_maat_scan_result_ > 0)
+ {
+ scan_result = scan_result_t::kScanResultHit;
+ return false;
+ }
+ else if (nr_maat_scan_result_ == -1)
+ {
+ scan_result = scan_result_t::kScanResultError;
+ return false;
+ }
+
+ return true;
+ });
+
+ return scan_result;
+}
+
+HttpScanSession::scan_result_t HttpScanSession::scan_body(const char * data, size_t len, int table_id)
+{
+ /* Dummy For maat */
+ int __dummy[MAAT_SCAN_RESULT_];
+
+ nr_maat_scan_result_ = Maat_full_scan_string(httpscan_module_ref_.maat_feather_ref,
+ table_id, CHARSET_UTF8, data, (int) len, maat_scan_result_, __dummy, MAAT_SCAN_RESULT_, &maat_scan_mid_, 0);
+
+ if (nr_maat_scan_result_ > 0)
+ return scan_result_t::kScanResultHit;
+
+ else if (nr_maat_scan_result_ == -1)
+ return scan_result_t::kScanResultError;
+
+ return scan_result_t::kScanResultNotHit;
+}
+
void HttpScanSession::hit_config_and_do_action(HttpSession * session)
{
/* 判断命中数量,若为多命中,选择优先级最高的动作执行 */
@@ -300,4 +395,4 @@ void HttpScanSession::hit_config_and_do_action(HttpSession * session)
void HttpScanSession::hit_scan_error()
{
return;
-} \ No newline at end of file
+}
diff --git a/src/httpscan.h b/src/httpscan.h
index 6b3fd1f..e3891ce 100644
--- a/src/httpscan.h
+++ b/src/httpscan.h
@@ -68,6 +68,16 @@ public:
void ScanResponseBody(HttpSession *http_session_ctx);
private:
+ enum class scan_result_t
+ {
+ kScanResultNotHit = 0,
+ kScanResultHit = 1,
+ kScanResultError = -1
+ };
+
+ scan_result_t scan_headers(const HttpHeaders & c_headers, int table_id);
+ scan_result_t scan_body(const char * data, size_t len, int table_id);
+
void hit_config_and_do_action(HttpSession *session);
void hit_scan_error();