首先请求体的读取已经进入了HTTP请求的11个阶段,针对有些模块需要对请求体做一些处理,那么这个模块就需要在这个阶段注册函数,其中读取请求体的函数ngx_http_read_client_request_body()是存在的,只不过不同的模块可能对请求体做不同的处理,读取请全体的函数是在某个模块的conent_handler函数中包含的,比如比如proxy模块,fastcgi模块,uwsgi模块等这些模块对请求体感兴趣,那么读取请求体的函数在这些模块的content_handler中注册。
上节说到nginx核心本身不会主动读取请求体,这个工作是交给请求处理阶段的模块来做,但是nginx核心提供了ngx_http_read_client_request_body()接口来读取请求体,另外还提供了一个丢弃请求体的接口-ngx_http_discard_request_body(),在请求执行的各个阶段中,任何一个阶段的模块如果对请求体感兴趣或者希望丢掉客户端发过来的请求体,可以分别调用这两个接口来完成。这两个接口是nginx核心提供的处理请求体的标准接口,如果希望配置文件中一些请求体相关的指令(比如client_body_in_file_only,client_body_buffer_size等)能够预期工作,
以及能够正常使用nginx内置的一些和请求体相关的变量(比如$request_body和$request_body_file),一般来说所有模块都必须调用这些接口来完成相应操作,如果需要自定义接口来处理请求体,也应尽量兼容nginx默认的行为。
1,读取请求体
请求体的读取一般发生在nginx的content handler中,一些nginx内置的模块,比如proxy模块,fastcgi模块,uwsgi模块等,这些模块的行为必须将客户端过来的请求体(如果有的话)以相应协议完整的转发到后端服务进程,所有的这些模块都是调用了ngx_http_read_client_request_body()接口来完成请求体读取。值得注意的是这些模块会把客户端的请求体完整的读取后才开始往后端转发数据。
由于内存的限制,ngx_http_read_client_request_body()接口读取的请求体会部分或者全部写入一个临时文件中,根据请求体的大小以及相关的指令配置,请求体可能完整放置在一块连续内存中,也可能分别放置在两块不同内存中,还可能全部存在一个临时文件中,最后还可能一部分在内存,剩余部分在临时文件中。下面先介绍一下和这些不同存储行为相关的指令:
client_body_buffer_size:设置缓存请求体的buffer大小,默认为系统页大小的2倍,当请求体的大小超过此大小时,nginx会把请求体写入到临时文件中。可以根据业务需求设置合适的大小,尽量避免磁盘io操作;
client_body_in_single_buffer:指示是否将请求体完整的存储在一块连续的内存中,默认为off,如果此指令被设置为on,则nginx会保证请求体在不大