SUPPORT-8592. Рефакторинг. Вынесены из service_sign в fcgi_utils: check_content_length(), check_content_type() и fcgi_request_load_data()

This commit is contained in:
alashkova 2024-10-11 13:17:47 +03:00
parent 473a009905
commit bf197c89cd
3 changed files with 121 additions and 94 deletions

View file

@ -17,6 +17,60 @@ fcgi_get_content_length(const FCGX_Request* request)
}
fcgi_handler_status_t
check_content_length(int content_length, int client_max_body_size)
{
LOG_TRACE("check_content_length");
if (content_length > 0 && content_length <= client_max_body_size) {
LOG_DEBUG("Content-Length is ok");
return HANDLER_SUCCESS;
}
if (content_length == 0) {
LOG_DEBUG("Content-Length == 0, so there is no body");
return HANDLER_HTTP_OK;
}
if (content_length < 0) {
LOG_WARN("Content-Length < 0 (%d)", content_length);
return HANDLER_HTTP_BAD_REQUEST;
}
if (content_length > client_max_body_size) {
LOG_WARN("Content-Length (%d) is too large (> %d)",
content_length,
client_max_body_size);
return HANDLER_HTTP_REQUEST_ENTITY_TOO_LARGE;
}
return HANDLER_ERROR;
}
fcgi_handler_status_t
check_content_type(const FCGX_Request* request, const char* acceptable_content_type)
{
LOG_TRACE("check_content_type");
const char* content_type = FCGX_GetParam(FCGI_PARAM_NAME_CONTENT_TYPE, request->envp);
if (content_type == NULL) {
LOG_ERROR("Could not get FCGI param: "FCGI_PARAM_NAME_CONTENT_TYPE);
return HANDLER_HTTP_BAD_REQUEST;
}
if (strcmp(content_type, acceptable_content_type) == 0) {
LOG_DEBUG("Content-Type is ok");
return HANDLER_SUCCESS;
}
LOG_WARN("Content-Type is not acceptable, '%s' (!= '%s')",
content_type, acceptable_content_type);
return HANDLER_HTTP_NOT_ACCEPTABLE;
}
char*
fcgi_request_get_param(const FCGX_Request* request, const char* name, /*out*/ bool* err)
{
@ -45,6 +99,40 @@ error:
}
fcgi_handler_status_t
fcgi_request_load_data(const FCGX_Request* request, int content_length, char** content)
{
LOG_TRACE("fcgi_request_load_data enter");
char* data = malloc(content_length + 1);
if (data == NULL) {
LOG_ERROR("Could not allocate memory for request body (%d bytes)", content_length + 1);
return HANDLER_ERROR;
}
int actual_content_length = FCGX_GetStr(data, content_length, request->in);
if (actual_content_length != content_length) {
LOG_ERROR("fcgi_request_load_data: "
"actual_content_length(%d) != content_length(%d); content: '%.*s'",
actual_content_length, content_length,
actual_content_length, data);
free(data);
return HANDLER_HTTP_BAD_REQUEST;
}
data[content_length] = '\0';
*content = data;
LOG_DEBUG("content_length: %d", content_length);
LOG_DEBUG("content: '%s'", *content);
LOG_TRACE("fcgi_request_load_data exit");
return HANDLER_SUCCESS;
}
fcgi_handler_status_t
fcgi_printf_str(const FCGX_Request* request, const char* response, int response_len)
{

View file

@ -56,6 +56,25 @@ char* fcgi_request_get_param(const FCGX_Request* request, const char* name, bool
int
fcgi_get_content_length(const FCGX_Request* request);
/**
* Returns: HANDLER_SUCCESS, HANDLER_HTTP_OK (no body), HANDLER_HTTP_BAD_REQUEST,
* HANDLER_HTTP_REQUEST_ENTITY_TOO_LARGE, HANDLER_ERROR
*/
fcgi_handler_status_t
check_content_length(int content_length, int client_max_body_size);
/**
* Returns: HANDLER_SUCCESS, HANDLER_HTTP_BAD_REQUEST, HANDLER_HTTP_NOT_ACCEPTABLE
*/
fcgi_handler_status_t
check_content_type(const FCGX_Request* request, const char* acceptable_content_type);
/**
* Returns: HANDLER_SUCCESS, HANDLER_HTTP_BAD_REQUEST, HANDLER_ERROR
*/
fcgi_handler_status_t
fcgi_request_load_data(const FCGX_Request* request, int content_length, char** content);
fcgi_handler_status_t
fcgi_printf_str(const FCGX_Request* request, const char* response, int response_len);
@ -70,6 +89,10 @@ fcgi_printf_header(const FCGX_Request* request, const char* name, const char* va
#define CRLF "\r\n"
#define FCGI_200_RESPONSE_FORMAT \
"Status: 200 OK" CRLF\
CRLF
#define FCGI_400_RESPONSE_FORMAT \
"Status: 400 Bad Request" CRLF\
"Content-type: text/plain" CRLF\
@ -123,6 +146,13 @@ typedef fcgi_handler_status_t (*fcgi_request_handler_pt)(const FCGX_Request* req
typedef fcgi_request_handler_pt (*FCGI_REQUEST_FINALIZE_HANDLER)(int rc);
static inline fcgi_handler_status_t
fcgi_200_ok_handler(const FCGX_Request* request, void* ctx __attribute__((unused)))
{
LOG_INFO("response status: '200 OK'");
return FCGI_CHECK_PRINTF_STATUS(request, FCGI_200_RESPONSE_FORMAT, 200);
}
static inline fcgi_handler_status_t
fcgi_400_bad_request_handler(const FCGX_Request* request, void* ctx __attribute__((unused)))
{

View file

@ -17,7 +17,7 @@
static const str_t SIGN_CONF_DEFAULT_LOCATION = str_t_const("/sign");
static const int CLIENT_MAX_BODY_SIZE = 4096;
static const str_t ACCEPTABLE_CONTENT_TYPE = str_t_const("text/plain");
static const char* ACCEPTABLE_CONTENT_TYPE = "text/plain";
typedef struct sign_service_s {
const sign_conf_t *conf;
@ -38,13 +38,6 @@ static void fcgi_sign_request_clear(fcgi_sign_request_t *req_info);
static fcgi_request_handler_pt fcgi_request_finalize_handler(fcgi_handler_status_t status);
static fcgi_handler_status_t check_content_length(int content_length);
static fcgi_handler_status_t check_content_type(const FCGX_Request* request);
static fcgi_handler_status_t fcgi_request_load_data(const FCGX_Request* request,
int content_length, char** content);
static int sign_content(const sign_service_t *hsign, fcgi_sign_request_t *req_info);
int
@ -162,12 +155,12 @@ fcgi_sign_handler(FCGX_Request* request, void* ctx)
req_info.content_length = fcgi_get_content_length(request);
status = check_content_length(req_info.content_length);
status = check_content_length(req_info.content_length, CLIENT_MAX_BODY_SIZE);
if (status != HANDLER_SUCCESS) {
goto exit;
}
status = check_content_type(request);
status = check_content_type(request, ACCEPTABLE_CONTENT_TYPE);
if (status != HANDLER_SUCCESS) {
goto exit;
}
@ -253,90 +246,6 @@ fcgi_request_finalize_handler(fcgi_handler_status_t status)
return handler;
}
static fcgi_handler_status_t
check_content_length(int content_length)
{
LOG_TRACE("check_content_length");
if (content_length > 0 && content_length <= CLIENT_MAX_BODY_SIZE) {
LOG_DEBUG("Content-Length is ok");
return HANDLER_SUCCESS;
}
if (content_length == 0) {
LOG_DEBUG("Content-Length == 0, so there is nothing to sign");
return HANDLER_HTTP_OK;
}
if (content_length < 0) {
LOG_WARN("Content-Length < 0 (%d)", content_length);
return HANDLER_HTTP_BAD_REQUEST;
}
if (content_length > CLIENT_MAX_BODY_SIZE) {
LOG_WARN("Content-Length (%d) is too large (> %d)",
content_length,
CLIENT_MAX_BODY_SIZE);
return HANDLER_HTTP_REQUEST_ENTITY_TOO_LARGE;
}
return HANDLER_ERROR;
}
static fcgi_handler_status_t
check_content_type(const FCGX_Request* request)
{
LOG_TRACE("check_content_type");
const char* content_type = FCGX_GetParam(FCGI_PARAM_NAME_CONTENT_TYPE, request->envp);
if (content_type == NULL) {
LOG_ERROR("Could not get FCGI param: "FCGI_PARAM_NAME_CONTENT_TYPE);
return HANDLER_HTTP_BAD_REQUEST;
}
if (strncmp(content_type, ACCEPTABLE_CONTENT_TYPE.data, ACCEPTABLE_CONTENT_TYPE.len) == 0) {
LOG_DEBUG("Content-Type is ok");
return HANDLER_SUCCESS;
}
LOG_WARN("Content-Type is not acceptable, '%s'", content_type);
return HANDLER_HTTP_NOT_ACCEPTABLE;
}
static fcgi_handler_status_t
fcgi_request_load_data(const FCGX_Request* request, int content_length, char** content)
{
LOG_TRACE("fcgi_request_load_data enter");
char* data = malloc(content_length + 1);
if (data == NULL) {
LOG_ERROR("Could not allocate memory for request body (%d bytes)", content_length + 1);
return HANDLER_ERROR;
}
int actual_content_length = FCGX_GetStr(data, content_length, request->in);
if (actual_content_length != content_length) {
LOG_ERROR("fcgi_request_load_data: "
"actual_content_length(%d) != content_length(%d); content: '%.*s'",
actual_content_length, content_length,
actual_content_length, data);
free(data);
return HANDLER_HTTP_BAD_REQUEST;
}
data[content_length] = '\0';
*content = data;
LOG_DEBUG("content_length: %d", content_length);
LOG_DEBUG("content: '%s'", *content);
LOG_TRACE("fcgi_request_load_data exit");
return HANDLER_SUCCESS;
}
static int
sign_content(const sign_service_t *hsign, fcgi_sign_request_t *req_info)
{