@@ -448,58 +448,62 @@ static HRESULT SaveRequestBodyToRequestRec(RequestStoredContext* rsc)
448448 APR_BRIGADE_INSERT_TAIL (brigade, bucket);
449449 }
450450
451- apr_bucket* e = apr_bucket_eos_create (conn->bucket_alloc );
452- if (e == nullptr )
453- {
454- return E_OUTOFMEMORY;
455- }
456- APR_BRIGADE_INSERT_TAIL (brigade, e);
451+ if (!APR_BRIGADE_EMPTY (brigade)) {
452+ apr_bucket* e = apr_bucket_eos_create (conn->bucket_alloc );
453+ if (e == nullptr )
454+ {
455+ return E_OUTOFMEMORY;
456+ }
457+ APR_BRIGADE_INSERT_TAIL (brigade, e);
457458
458- modsecSetBodyBrigade (aprRequest, brigade);
459+ modsecSetBodyBrigade (aprRequest, brigade);
459460
460- apr_off_t contentLength = 0 ;
461- apr_status_t status = apr_brigade_length (brigade, FALSE , &contentLength);
462- if (status != APR_SUCCESS)
463- {
464- return E_FAIL;
465- }
461+ apr_off_t contentLength = 0 ;
462+ apr_status_t status = apr_brigade_length (brigade, FALSE , &contentLength);
463+ if (status != APR_SUCCESS)
464+ {
465+ return E_FAIL;
466+ }
466467
467- // Remove/Modify Transfer-Encoding header if "chunked" Encoding is set in the request.
468- // This is to avoid sending both Content-Length and Chunked Transfer-Encoding in the request header.
469- static const std::string CHUNKED = " chunked" ;
470- USHORT encodingLength = 0 ;
471- const char * transferEncoding = iisRequest->GetHeader (HttpHeaderTransferEncoding, &encodingLength);
472- if (transferEncoding)
473- {
474- if (CHUNKED.size () == encodingLength &&
475- std::equal (CHUNKED.cbegin (), CHUNKED.cend (), transferEncoding,
476- [](char lhs, char rhs) { return std::tolower (lhs) == std::tolower (rhs); }))
468+ // Remove/Modify Transfer-Encoding header if "chunked" Encoding is set in the request.
469+ // This is to avoid sending both Content-Length and Chunked Transfer-Encoding in the request header.
470+ static const std::string CHUNKED = " chunked" ;
471+ USHORT encodingLength = 0 ;
472+ const char * transferEncoding = iisRequest->GetHeader (HttpHeaderTransferEncoding, &encodingLength);
473+ if (transferEncoding)
477474 {
478- iisRequest->DeleteHeader (HttpHeaderTransferEncoding);
475+ if (encodingLength == CHUNKED.size () &&
476+ std::equal (CHUNKED.cbegin (), CHUNKED.cend (), transferEncoding,
477+ [](char lhs, char rhs) { return std::tolower (lhs) == std::tolower (rhs); }))
478+ {
479+ iisRequest->DeleteHeader (HttpHeaderTransferEncoding);
480+ }
479481 }
480- }
481482
482- auto contentLengthStr = std::to_string (contentLength);
483- HRESULT hr = iisRequest->SetHeader (
484- HttpHeaderContentLength,
485- contentLengthStr.c_str (),
486- contentLengthStr.size (),
487- TRUE );
483+ auto contentLengthStr = std::to_string (contentLength);
484+ HRESULT hr = iisRequest->SetHeader (
485+ HttpHeaderContentLength,
486+ contentLengthStr.c_str (),
487+ contentLengthStr.size (),
488+ TRUE );
488489
489- if (FAILED (hr))
490- {
491- return hr;
492- }
490+ if (FAILED (hr))
491+ {
492+ return hr;
493+ }
493494
494- // since we clean the APR pool at the end of OnSendRequest, we must get IIS-managed memory chunk
495- //
496- char * requestBuffer = static_cast <char *>(rsc->httpContext ->AllocateRequestMemory (contentLength));
497- status = apr_brigade_flatten (brigade, requestBuffer, reinterpret_cast <apr_size_t *>(&contentLength));
498- if (status != APR_SUCCESS)
499- {
500- return E_FAIL;
495+ // since we clean the APR pool at the end of OnSendRequest, we must get IIS-managed memory chunk
496+ //
497+ char * requestBuffer = static_cast <char *>(rsc->httpContext ->AllocateRequestMemory (contentLength));
498+ status = apr_brigade_flatten (brigade, requestBuffer, reinterpret_cast <apr_size_t *>(&contentLength));
499+ if (status != APR_SUCCESS)
500+ {
501+ return E_FAIL;
502+ }
503+ return iisRequest->InsertEntityBody (requestBuffer, contentLength);
501504 }
502- return iisRequest->InsertEntityBody (requestBuffer, contentLength);
505+
506+ return S_OK;
503507}
504508
505509
@@ -953,17 +957,6 @@ CMyHttpModule::OnBeginRequest(IHttpContext* httpContext, IHttpEventProvider* pro
953957
954958 delete apppath;
955959 delete path;
956-
957- if (config->config ->is_enabled == MODSEC_DETECTION_ONLY)
958- {
959- modsecSetReadBody (nullptr );
960- modsecSetWriteBody (nullptr );
961- }
962- else
963- {
964- modsecSetReadBody (ReadBodyCallback);
965- modsecSetWriteBody (WriteBodyCallback);
966- }
967960 }
968961
969962 ConnRecPtr connRec = MakeConnReq ();
@@ -979,11 +972,6 @@ CMyHttpModule::OnBeginRequest(IHttpContext* httpContext, IHttpEventProvider* pro
979972 rsc->responseProcessingEnabled = (config->config ->resbody_access == 1 );
980973 RequestStoredContext* context = rsc.get ();
981974
982- // on IIS we force input stream inspection flag, because its absence does not add any performance gain
983- // it's because on IIS request body must be restored each time it was read
984- //
985- modsecSetConfigForIISRequestBody (r);
986-
987975 StoreIISContext (r, rsc.get ());
988976
989977 httpContext->GetModuleContextContainer ()->SetModuleContext (rsc.release (), g_pModuleContext);
@@ -1214,13 +1202,14 @@ CMyHttpModule::OnBeginRequest(IHttpContext* httpContext, IHttpEventProvider* pro
12141202#endif
12151203 c->remote_host = NULL ;
12161204
1205+ hr = SaveRequestBodyToRequestRec (context);
1206+ if (FAILED (hr)) {
1207+ context->provider ->SetErrorStatus (hr);
1208+ return RQ_NOTIFICATION_FINISH_REQUEST;
1209+ }
1210+
12171211 if (config->config ->is_enabled == MODSEC_DETECTION_ONLY)
12181212 {
1219- hr = SaveRequestBodyToRequestRec (context);
1220- if (FAILED (hr)) {
1221- context->provider ->SetErrorStatus (hr);
1222- return RQ_NOTIFICATION_FINISH_REQUEST;
1223- }
12241213 // We post the processing task to the thread pool to happen in the background.
12251214 // We store the future to track and wait for this processing in case if we also
12261215 // need to process the response because we need request processing to finish
0 commit comments