開発したモジュールでのPOSTボディの処理

今日、nginx用の独自のモジュールを開発する方法についての十分なガイドと説明があります。 タンクにいる人の場合、リンク nginxのウェブサイトで見つけることができます
しかし、残念ながらPOSTデータの使用方法については、情報が叫びました。


まず、Igor Sysoev( nginxの作成者 )は、モジュールでのPOSTデータの使用を非常に注意深く調べます。 そして、これは原則として正当化されます:原則として、POSTでは、ヘッダーサイズに比べてデータが大量に使用されるため、処理メカニズムが異なります。 また、余分なデータを処理すると、常に間接的にパフォーマンスに影響する可能性があります。 nginxでのプロセスはできる限り簡単にして、女性が接続をできるだけ早く処理し、次の接続の処理を開始できるようにする必要があります。

処理サイクルを考慮してください。


通常、すべてのhttpモジュールは、応答生成フェーズ中にハングアップします。 もちろん、例外はアップストリームモジュールとフィルターです。 Emillerの詳細

POSTの場合、すべてが異なり、まったく処理されない場合があります。 リクエストngx_http_request_t * rの構造を見ると、これはすべてのhttpモジュールを赤いスレッドとして渡し、コンテンツハンドラーでフィールドの値を次のように渡します。
r-> request_body-> bufは現在のバッファーであり、
r-> request_body-> bufs-POST要求のデータバッファーのチェーンは空(NULL)になります。 これは、処理が開始されなかったためです。

POSTリクエスト処理は、ボディハンドラコールバックをngx_http_read_client_request_bodyに設定することで実行されます(関数はhttp_request_body.cで定義されています)。
次のようなものがあるはずです。
rc = ngx_http_read_client_request_body ( r, ngx_http_mymodule_body_handler ) ; // " " <br/>
// , , NGX_AGAIN, <br/>
<br/>
if ( rc >= NGX_HTTP_SPECIAL_RESPONSE ) { <br/>
return rc ; <br/>
} <br/>
<br/>
return NGX_DONE ;
rc = ngx_http_read_client_request_body ( r, ngx_http_mymodule_body_handler ) ; // " " <br/>
// , , NGX_AGAIN, <br/>
<br/>
if ( rc >= NGX_HTTP_SPECIAL_RESPONSE ) { <br/>
return rc ; <br/>
} <br/>
<br/>
return NGX_DONE ;

ngx_http_mymodule_body_handlerは、POST要求の本文を処理するためのハンドラーです。 ハンドラーの本体では、ハンドラーフェーズが呼び出されます。 ボディハンドラコードは次のようになります。
static void ngx_http_mymodule_body_handler ( request_body * r ) { <br/>
ngx_int_t rc = NGX_OK ; <br/>
<br/>
rc = ngx_http_mymodule_phase_handler ( r ) ; // <br/>
if ( rc >= NGX_HTTP_SPECIAL_RESPONSE ) { <br/>
ngx_http_finalize_request ( f, 0 ) ; // , , . <br/>
} <br/>
return ; <br/>
} <br/>

static void ngx_http_mymodule_body_handler ( request_body * r ) { <br/>
ngx_int_t rc = NGX_OK ; <br/>
<br/>
rc = ngx_http_mymodule_phase_handler ( r ) ; // <br/>
if ( rc >= NGX_HTTP_SPECIAL_RESPONSE ) { <br/>
ngx_http_finalize_request ( f, 0 ) ; // , , . <br/>
} <br/>
return ; <br/>
} <br/>



ハンドラーフェーズでは、POSTデータを含むチャンクが処理されます。 フェーズハンドラーはデータを処理し、コールバックをボディ処理に再度設定します。 ハンドラーフェーズコードは次のようになります。
<br/>
ngx_int_t ngx_http_mymodule_phase_handler ( request_body * r ) { <br/>
<br/>
ngx_int_t rc = NGX_OK ; <br/>
if ( r - > request_body == NULL ) { <br/>
// POST , <br/>
rc = ngx_http_read_client_request_body ( r, ngx_http_mymodule_body_handler ) ; <br/>
<br/>
if ( rc >= NGX_HTTP_SPECIAL_RESPONSE ) { <br/>
return rc ; <br/>
} <br/>
<br/>
return NGX_DONE ; <br/>
} <br/>
<br/>
// ? <br/>
if ( r - > request_body - > rest ) { <br/>
return NGX_DONE ; <br/>
} <br/>
return rc ; <br/>
} <br/>


<br/>
ngx_int_t ngx_http_mymodule_phase_handler ( request_body * r ) { <br/>
<br/>
ngx_int_t rc = NGX_OK ; <br/>
if ( r - > request_body == NULL ) { <br/>
// POST , <br/>
rc = ngx_http_read_client_request_body ( r, ngx_http_mymodule_body_handler ) ; <br/>
<br/>
if ( rc >= NGX_HTTP_SPECIAL_RESPONSE ) { <br/>
return rc ; <br/>
} <br/>
<br/>
return NGX_DONE ; <br/>
} <br/>
<br/>
// ? <br/>
if ( r - > request_body - > rest ) { <br/>
return NGX_DONE ; <br/>
} <br/>
return rc ; <br/>
} <br/>




リクエストPOStデータは、ngx_http_request.hで定義されたngx_http_request_body_t構造体にあります
typedef struct { <br/>
ngx_temp_file_t * temp_file ; // ( ) <br/>
ngx_chain_t * bufs ; // . <br/>
ngx_buf_t * buf ; // <br/>
off_t rest ; <br/>
ngx_chain_t * to_write ; <br/>
ngx_http_client_body_handler_pt post_handler ; <br/>
} ngx_http_request_body_t ; <br/>

typedef struct { <br/>
ngx_temp_file_t * temp_file ; // ( ) <br/>
ngx_chain_t * bufs ; // . <br/>
ngx_buf_t * buf ; // <br/>
off_t rest ; <br/>
ngx_chain_t * to_write ; <br/>
ngx_http_client_body_handler_pt post_handler ; <br/>
} ngx_http_request_body_t ; <br/>


この構造体へのポインタは、ngx_http_request_sリクエスト構造体で定義されています:
r-> request_body;

現在のウィンドウのデータは、バッファフレームによって決定されます。
r-> request_body-> buf-> start
r-> request_body-> buf-> end
または、POST要求サイズが大きい場合、データはバッファーチェーンr-> request_body-> bufs-> buf-> start ... endから抽出され、次のバッファーが取得されます。そのアドレスは次のフィールドにあります。 ngx_chain_s構造を参照してください:
// core/ngx_buf.h
struct ngx_chain_s {
ngx_buf_t * buf ;
ngx_chain_t * next ;
} ;

size -- ( start end) Content-Length r->headers_in->off_t ;
- .

.
// core/ngx_buf.h
struct ngx_chain_s {
ngx_buf_t * buf ;
ngx_chain_t * next ;
} ;

size -- ( start end) Content-Length r->headers_in->off_t ;
- .

.

Source: https://habr.com/ru/post/J76963/


All Articles