226 lines
7.6 KiB
C
226 lines
7.6 KiB
C
#ifndef FCGI_UTILS_H_INCLUDED
|
|
#define FCGI_UTILS_H_INCLUDED
|
|
|
|
|
|
#include "fcgi_server.h"
|
|
#include "utils/logger.h"
|
|
#include "utils/str_t.h"
|
|
|
|
#include "stdbool.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
|
|
/************************** fastCGI parameters: *******************************/
|
|
|
|
|
|
#define FCGI_PARAM_NAME_REMOTE_ADDR "REMOTE_ADDR"
|
|
#define FCGI_PARAM_NAME_HTTP_COOKIE "HTTP_COOKIE"
|
|
#define FCGI_PARAM_NAME_REQUEST_URI "REQUEST_URI"
|
|
#define FCGI_PARAM_NAME_CONTENT_LENGTH "CONTENT_LENGTH"
|
|
#define FCGI_PARAM_NAME_CONTENT_TYPE "CONTENT_TYPE"
|
|
#define FCGI_PARAM_NAME_REQUEST_METHOD "REQUEST_METHOD"
|
|
#define FCGI_PARAM_NAME_SERVER_ADDR "SERVER_ADDR"
|
|
#define FCGI_PARAM_NAME_SERVER_PORT "SERVER_PORT"
|
|
#define FCGI_PARAM_NAME_SERVER_NAME "SERVER_NAME"
|
|
#define FCGI_PARAM_NAME_DOCUMENT_URI "DOCUMENT_URI"
|
|
#define FCGI_PARAM_NAME_QUERY_STRING "QUERY_STRING"
|
|
#define FCGI_PARAM_NAME_REQUEST_SCHEME "REQUEST_SCHEME"
|
|
#define FCGI_PARAM_NAME_HOST "HTTP_HOST"
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
static inline void
|
|
fcgi_request_print_envp(const FCGX_Request* request)
|
|
{
|
|
if (request == NULL) return;
|
|
|
|
char **envp = request->envp;
|
|
if (envp == NULL) return;
|
|
|
|
int i = 0;
|
|
for (; envp[i] != NULL; i++) {
|
|
LOG_DEBUG("%d: %s", i, envp[i]);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @note just pointer is copied
|
|
*/
|
|
char* fcgi_request_get_param(const FCGX_Request* request, const char* name, bool* err);
|
|
|
|
|
|
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 str_t* acceptable_content_type, const char** actual_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);
|
|
|
|
|
|
fcgi_handler_status_t
|
|
fcgi_printf_header(const FCGX_Request* request, const char* name, const char* value, int value_len);
|
|
|
|
|
|
/************************** fastCGI handlers: *********************************/
|
|
|
|
|
|
#define CRLF "\r\n"
|
|
|
|
#define FCGI_200_EMPTY_RESPONSE_FORMAT \
|
|
"Status: 200 OK" CRLF\
|
|
CRLF
|
|
|
|
#define FCGI_200_JSON_RESPONSE_FORMAT \
|
|
"Status: 200 OK" CRLF\
|
|
"Content-type: application/json" CRLF\
|
|
CRLF\
|
|
"%s" CRLF
|
|
|
|
#define FCGI_400_RESPONSE_FORMAT \
|
|
"Status: 400 Bad Request" CRLF\
|
|
"Content-type: text/plain" CRLF\
|
|
CRLF\
|
|
"400 Bad Request" CRLF
|
|
|
|
#define FCGI_401_RESPONSE_FORMAT \
|
|
"Status: 401 Unauthorized" CRLF\
|
|
"Content-type: text/plain" CRLF\
|
|
CRLF\
|
|
"%s" CRLF
|
|
|
|
#define FCGI_404_RESPONSE_FORMAT \
|
|
"Status: 404 Not Found" CRLF\
|
|
"Content-type: text/plain" CRLF\
|
|
CRLF\
|
|
"404 Not Found" CRLF
|
|
|
|
#define FCGI_405_RESPONSE_FORMAT \
|
|
"Status: 405 Method Not Allowed" CRLF\
|
|
"Content-type: text/plain" CRLF\
|
|
CRLF\
|
|
"405 Method Not Allowed" CRLF
|
|
|
|
#define FCGI_406_RESPONSE_FORMAT \
|
|
"Status: 406 Not Acceptable" CRLF\
|
|
"Content-type: text/plain" CRLF\
|
|
CRLF\
|
|
"406 Not Acceptable" CRLF
|
|
|
|
#define FCGI_413_RESPONSE_FORMAT \
|
|
"Status: 413 Request Entity Too Large " CRLF\
|
|
"Content-type: text/plain" CRLF\
|
|
CRLF\
|
|
"413 Request Entity Too Large " CRLF
|
|
|
|
#define FCGI_500_RESPONSE_FORMAT \
|
|
"Status: 500 Internal Server Error" CRLF\
|
|
"Content-type: application/json" CRLF\
|
|
CRLF\
|
|
"%s" CRLF
|
|
|
|
|
|
|
|
#define FCGI_CHECK_PRINTF_STATUS(request, format, code) \
|
|
(HANDLER_ERROR != fcgi_printf_str(request, format, sizeof(format) - 1)) ? \
|
|
code : HANDLER_ERROR
|
|
|
|
|
|
typedef fcgi_handler_status_t (*fcgi_request_handler_pt)(const FCGX_Request* request, void* ctx);
|
|
typedef fcgi_request_handler_pt (*FCGI_REQUEST_FINALIZE_HANDLER)(int rc);
|
|
|
|
|
|
static inline void
|
|
fcgi_print_log(const FCGX_Request* request, const char* status)
|
|
{
|
|
const char* uri = fcgi_request_get_param(request, FCGI_PARAM_NAME_REQUEST_URI, NULL);
|
|
uri = uri != NULL ? uri : "nil";
|
|
|
|
const char* method = fcgi_request_get_param(request, FCGI_PARAM_NAME_REQUEST_METHOD, NULL);
|
|
method = method != NULL ? method : "nil";
|
|
|
|
LOG_INFO("%s %s, '%s'", method, uri, status);
|
|
}
|
|
|
|
fcgi_handler_status_t
|
|
fcgi_200_ok_handler(const FCGX_Request* request, const char* response);
|
|
|
|
static inline fcgi_handler_status_t
|
|
fcgi_400_bad_request_handler(const FCGX_Request* request, void* ctx __attribute__((unused)))
|
|
{
|
|
fcgi_print_log(request, "400 Bad Request");
|
|
return FCGI_CHECK_PRINTF_STATUS(request, FCGI_400_RESPONSE_FORMAT, 400);
|
|
}
|
|
|
|
|
|
fcgi_handler_status_t
|
|
fcgi_401_bad_signature_handler(const FCGX_Request* request, const char* verify_error);
|
|
|
|
|
|
static inline fcgi_handler_status_t
|
|
fcgi_404_not_found_handler(const FCGX_Request* request, void* ctx __attribute__((unused)))
|
|
{
|
|
fcgi_print_log(request, "404 Not Found");
|
|
return FCGI_CHECK_PRINTF_STATUS(request, FCGI_404_RESPONSE_FORMAT, 404);
|
|
}
|
|
|
|
|
|
static inline fcgi_handler_status_t
|
|
fcgi_405_method_not_allowed_handler(const FCGX_Request* request, void* ctx __attribute__((unused)))
|
|
{
|
|
fcgi_print_log(request, "405 Method Not Allowed");
|
|
return FCGI_CHECK_PRINTF_STATUS(request, FCGI_405_RESPONSE_FORMAT, 405);
|
|
}
|
|
|
|
|
|
static inline fcgi_handler_status_t
|
|
fcgi_406_not_acceptable_handler(const FCGX_Request* request, void* ctx __attribute__((unused)))
|
|
{
|
|
fcgi_print_log(request, "406 Not Acceptable");
|
|
return FCGI_CHECK_PRINTF_STATUS(request, FCGI_406_RESPONSE_FORMAT, 406);
|
|
}
|
|
|
|
|
|
static inline fcgi_handler_status_t
|
|
fcgi_413_request_entity_too_large_handler(const FCGX_Request* request, void* ctx __attribute__((unused)))
|
|
{
|
|
fcgi_print_log(request, "413 Request Entity Too Large'");
|
|
return FCGI_CHECK_PRINTF_STATUS(request, FCGI_413_RESPONSE_FORMAT, 413);
|
|
}
|
|
|
|
|
|
fcgi_handler_status_t
|
|
fcgi_500_internal_server_error_handler(const FCGX_Request* request, const char *error_code);
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* FCGI_UTILS_H_INCLUDED */
|