ervu-sign-module/src/fcgisrv/fcgi_utils.c

243 lines
6.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "fcgi_server_internal.h"
#include "utils/response_builder.h"
#include <assert.h>
int
fcgi_get_content_length(const FCGX_Request* request)
{
int content_length = 0;
char* p = FCGX_GetParam(FCGI_PARAM_NAME_CONTENT_LENGTH, request->envp);
if (p != NULL) {
content_length = atoi(p);
}
return content_length;
}
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;
}
/* (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;
}
fcgi_handler_status_t
check_content_type(const FCGX_Request* request, const str_t* acceptable_content_type, const char** actual_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 (actual_content_type) {
*actual_content_type = content_type;
}
/*
* Проверяем, начинается ли заголовок Content-Type с допустимого префикса
* Сравнение производится только для начальной части строки
* (игнорируя дополнительные параметры после точки с запятой)
* Пример: "multipart/form-data;boundary=--123" является допустимым для "multipart/form-data"
*/
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' (!= '%.*s')",
content_type, (int) acceptable_content_type->len, acceptable_content_type->data);
return HANDLER_HTTP_NOT_ACCEPTABLE;
}
char*
fcgi_request_get_param(const FCGX_Request* request, const char* name, /*out*/ bool* err)
{
assert(request != NULL);
assert(name != NULL);
char* param_value = FCGX_GetParam(name, request->envp);
if (param_value == NULL) {
LOG_ERROR("Could not get fcgi parameter '%s'", name);
goto error;
}
LOG_DEBUG("fcgi_request_get_param. name: %s, value: %s", name, param_value);
if (err) {
*err = false;
}
return param_value;
error:
LOG_ERROR("fcgi_request_get_param exit with error");
if (err) {
*err = true;
}
return NULL;
}
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)
{
assert(request != NULL);
assert(response != NULL);
//int n = FCGX_FPrintF(request->out, response);
int n = FCGX_PutStr(response, response_len, request->out);
if (n < 0) {
LOG_ERROR("FCGX_PutStr failed");
return HANDLER_ERROR;
}
if (n != response_len) {
LOG_ERROR("response_len (%d) differs from the number of characters written (%d)",
response_len, n);
return HANDLER_ERROR;
}
return HANDLER_SUCCESS;
}
fcgi_handler_status_t
fcgi_printf_header(const FCGX_Request* request, const char* name, const char* value, int value_len)
{
if (FCGX_FPrintF(request->out, "%s: %.*s"CRLF, name, value_len, value) == -1) {
LOG_ERROR("FCGX_FPrintF failed");
return HANDLER_ERROR;
}
return HANDLER_SUCCESS;
}
fcgi_handler_status_t
fcgi_200_ok_handler(const FCGX_Request* request, const char* response)
{
LOG_TRACE("fcgi_200_ok_handler");
const char *format = response ? FCGI_200_JSON_RESPONSE_FORMAT : FCGI_200_EMPTY_RESPONSE_FORMAT;
if (response) {
LOG_DEBUG("response:\n" FCGI_200_JSON_RESPONSE_FORMAT, response);
} else {
LOG_DEBUG("response:\n" FCGI_200_EMPTY_RESPONSE_FORMAT);
}
if (FCGX_FPrintF(request->out, format, response) < 0) {
LOG_ERROR("FCGX_FPrintF() failed");
LOG_ERROR("fcgi_200_ok_handler exit with error");
return HANDLER_ERROR;
}
return HANDLER_SUCCESS;
}
fcgi_handler_status_t
fcgi_401_bad_signature_handler(const FCGX_Request* request, const char* verify_error)
{
LOG_TRACE("fcgi_401_bad_signature_handler");
assert(verify_error != NULL);
LOG_DEBUG("response status: " FCGI_401_RESPONSE_FORMAT, verify_error);
if (FCGX_FPrintF(request->out, FCGI_401_RESPONSE_FORMAT, verify_error) < 0) {
LOG_ERROR("FCGX_FPrintF() failed");
return HANDLER_ERROR;
}
fcgi_print_log(request, "401 Unauthorized");
return HANDLER_SUCCESS;
}
fcgi_handler_status_t
fcgi_500_internal_server_error_handler(const FCGX_Request* request, const char *error_code)
{
LOG_TRACE("fcgi_500_internal_server_error_handler");
char *response = build_response_from_error_code(error_code);
if (response == NULL) {
goto error;
}
LOG_DEBUG("response status: " FCGI_500_RESPONSE_FORMAT, response);
if (FCGX_FPrintF(request->out, FCGI_500_RESPONSE_FORMAT, response) < 0) {
LOG_ERROR("FCGX_FPrintF() failed");
goto error;
}
fcgi_print_log(request, "500 Internal Server Error");
free(response);
return HANDLER_SUCCESS;
error:
free(response);
LOG_ERROR("fcgi_500_internal_server_error_handler exit with error");
return HANDLER_ERROR;
}