NGINX status code based on *response* body

Roman Arutyunyan arut at nginx.com
Mon Sep 25 14:54:10 UTC 2023


Hi Muhammad,

On Mon, Sep 25, 2023 at 12:01:11AM +0800, Muhammad Nuzaihan wrote:
> Hi,
> 
> I would like to return an error message based on the *response* body.
> 
> I know i can do it easily with *request* body (with "return
> NGX_HTTP_BAD_REQUEST") but my case i want to do it with *response*
> body.
> 
> Also i have tried this code with response body filter but i got "*1
> header already sent, client: 127.0.0.1, server: localhost":

That's because you need to delay sending the response, both header and body,
before making the decision about the response code.  It's quite complicated.
If you send the header right away, there's no way to change it in the future.
You can look into ngx_http_xslt_filter_module and ngx_http_image_filter_module
for inspiration.

For the xslt module (src/http/modules/ngx_http_xslt_filter_module.c), its
header filter ngx_http_xslt_header_filter() does not call
ngx_http_next_header_filter() on first call (ctx == NULL).  Its body filter
ngx_http_xslt_body_filter() also does not call ngx_http_next_body_filter()
right away.  Instead, it buffers the entire response body.  Upon body
completion, ngx_http_xslt_send() is called, which sends both header
(ngx_http_next_header_filter()) and buffered body (ngx_http_next_body_filter()). 
If a decision is made to trigger an error, ngx_http_filter_finalize_request()
is called instead.

> Thank you for your guidance.
> 
> Code:
> 
> ```
>     return ngx_http_filter_finalize_request(request,
>                                          &ngx_m_module,
>                                           NGX_HTTP_BAD_REQUEST);
> ```
> RESPONSE BODY CODE:
> 
> ngx_int_t ResponseBodyFilter(ngx_http_request_t *request,
>                                      ngx_chain_t *chain_head) {
>   // Set the logging level to debug
>   // TODO: remove
>   request->connection->log->log_level = NGX_LOG_DEBUG;
> 
>   // Get our context so we can store the response body data
>   FilterContext *ctx = GetModuleFilterContext(request);
>   if (ctx == NULL) {
>     return NGX_ERROR;
>   }
> 
>     return ngx_http_filter_finalize_request(request,
>                                           &ngx_my_module,
>                                           NGX_HTTP_BAD_REQUEST);
> 
> }
> 
> ngx_int_t ModuleInit(ngx_conf_t *cf) {
>   kNextRequestBodyFilter = ngx_http_top_request_body_filter;
>   ngx_http_top_request_body_filter = RequestBodyFilter;
> 
>   kNextResponseBodyFilter = ngx_http_top_body_filter;
>   ngx_http_top_body_filter = ResponseBodyFilter;
> 
>   kNextHeaderFilter = ngx_http_top_header_filter;
>   ngx_http_top_header_filter = HeaderFilter;
> 
>   return NGX_OK;
> }
> _______________________________________________
> nginx-devel mailing list
> nginx-devel at nginx.org
> https://mailman.nginx.org/mailman/listinfo/nginx-devel

--
Roman Arutyunyan


More information about the nginx-devel mailing list