Summary
In the IIS connector (iis/mymodule.cpp), the audit log's F part (response status line) renders as HTTP/1.1 500 Internal Server Error for every transaction, even for normal requests that actually return e.g. 200 OK or 404.
Root cause
The IIS connector never copies the real HTTP response status into the request_rec. In CMyHttpModule::OnSendResponse, r->status is left at its initial value 0 (the request_rec is apr_pcalloc'd). When hookfn_log_transaction later builds the F part it calls ap_get_status_line(r->status); for r->status == 0 the standalone ap_index_of_response() maps anything < 100 to the LEVEL_500 bucket, producing 500 Internal Server Error.
Affected output
--A--
[13/Aug/2026:16:16:40.333548] ...
--F--
HTTP/1.1 500 Internal Server Error <- should be the real status (e.g. 200 OK)
Proposed fix
In CMyHttpModule::OnSendResponse (iis/mymodule.cpp), transfer pRawHttpResponse->StatusCode into r->status (and build r->status_line from the reason phrase) before the rest of the response handling:
if(pRawHttpResponse->StatusCode > 0)
{
r->status = pRawHttpResponse->StatusCode;
if(pRawHttpResponse->pReason != NULL && pRawHttpResponse->ReasonLength > 0)
{
r->status_line = apr_psprintf(r->pool, "%d %s", r->status,
ZeroTerminate(pRawHttpResponse->pReason, pRawHttpResponse->ReasonLength, r->pool));
}
}
This makes the audit log F part and relevant-status checks use the real response code. Verified against a local IIS (default site + OWASP CRS): a normal GET / now logs HTTP/1.1 200 OK, blocked requests log HTTP/1.1 403 ModSecurity Action.
Summary
In the IIS connector (
iis/mymodule.cpp), the audit log's F part (response status line) renders asHTTP/1.1 500 Internal Server Errorfor every transaction, even for normal requests that actually return e.g.200 OKor404.Root cause
The IIS connector never copies the real HTTP response status into the
request_rec. InCMyHttpModule::OnSendResponse,r->statusis left at its initial value0(the request_rec isapr_pcalloc'd). Whenhookfn_log_transactionlater builds the F part it callsap_get_status_line(r->status); forr->status == 0the standaloneap_index_of_response()maps anything< 100to theLEVEL_500bucket, producing500 Internal Server Error.Affected output
Proposed fix
In
CMyHttpModule::OnSendResponse(iis/mymodule.cpp), transferpRawHttpResponse->StatusCodeintor->status(and buildr->status_linefrom the reason phrase) before the rest of the response handling:This makes the audit log F part and relevant-status checks use the real response code. Verified against a local IIS (default site + OWASP CRS): a normal
GET /now logsHTTP/1.1 200 OK, blocked requests logHTTP/1.1 403 ModSecurity Action.