開発したモジュールでの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 ;

- .



.











All Articles