Skip to content

Commit

Permalink
Add new API function cgi_redirect_status() and deprecate old one
Browse files Browse the repository at this point in the history
Sending a HTTP Location header only makes sense with certain HTTP status
responses [1]. For letting a CGI return a certain status code, you have
to send the pseudo header 'Status:' with the right code, the webserver
will remove that and send the corresponding HTTP status instead. See RFC
3875 section 6.3.3 [2] for details.

The new API function allows to send a 'redirect' header 'Location:'
together with an arbitrary status code. The old API function is marked
deprecated, because it makes no sense sending 'Location' without
'Status' or the standard response code 200.

[1] https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location
[2] https://tools.ietf.org/html/rfc3875#section-6.3.3

Signed-off-by: Alexander Dahl <[email protected]>
  • Loading branch information
LeSpocky committed Jul 20, 2018
1 parent 6ba2fe2 commit 1532dd5
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 1 deletion.
68 changes: 67 additions & 1 deletion include/libcgi/cgi.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,58 @@
#define CGI_DEPRECATED
#endif

/**
* HTTP status codes.
*
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
*/
enum cgi_http_status_code {
HTTP_STATUS_CONTINUE = 100,
HTTP_STATUS_SWITCHING_PROTOCOLS = 101,

HTTP_STATUS_OK = 200,
HTTP_STATUS_CREATED = 201,
HTTP_STATUS_ACCEPTED = 202,
HTTP_STATUS_NON_AUTH_INFO = 203,
HTTP_STATUS_NO_CONTENT = 204,
HTTP_STATUS_RESET_CONTENT = 205,
HTTP_STATUS_PARTIAL_CONTENT = 206,

HTTP_STATUS_MULTIPLE_CHOICES = 300,
HTTP_STATUS_MOVED_PERMANENTLY = 301,
HTTP_STATUS_FOUND = 302,
HTTP_STATUS_SEE_OTHER = 303,
HTTP_STATUS_NOT_MODIFIED = 304,
HTTP_STATUS_USE_PROXY = 305,
HTTP_STATUS_TEMPORARY_REDIRECT = 307,

HTTP_STATUS_BAD_REQUEST = 400,
HTTP_STATUS_UNAUTHORIZED = 401,
HTTP_STATUS_PAYMENT_REQUIRED = 402,
HTTP_STATUS_FORBIDDEN = 403,
HTTP_STATUS_NOT_FOUND = 404,
HTTP_STATUS_METHOD_NOT_ALLOWED = 405,
HTTP_STATUS_NOT_ACCEPTABLE = 406,
HTTP_STATUS_PROXY_AUTH_REQUIRED = 407,
HTTP_STATUS_REQUEST_TIMEOUT = 408,
HTTP_STATUS_CONFLICT = 409,
HTTP_STATUS_GONE = 410,
HTTP_STATUS_LENGTH_REQUIRED = 411,
HTTP_STATUS_PRECONDITION_FAILED = 412,
HTTP_STATUS_REQ_ENT_TOO_LARGE = 413,
HTTP_STATUS_REQ_URI_TOO_LONG = 414,
HTTP_STATUS_UNSUPP_MEDIA_TYPE = 415,
HTTP_STATUS_REQ_RANGE_NOT_SATIS = 416,
HTTP_STATUS_EXPECTATION_FAILED = 417,

HTTP_STATUS_INTERNAL_SERVER_ERR = 500,
HTTP_STATUS_NOT_IMPLEMENTED = 501,
HTTP_STATUS_BAD_GATEWAY = 502,
HTTP_STATUS_SERVICE_UNAVAILABLE = 503,
HTTP_STATUS_GATEWAY_TIMEOUT = 504,
HTTP_STATUS_HTTP_VER_NOT_SUPP = 505,
};

#ifdef __cplusplus
extern "C" {
#endif
Expand All @@ -57,7 +109,7 @@ extern int cgi_display_errors;

// General purpose cgi functions
extern void cgi_init_headers(void);
extern void cgi_redirect(char *url);
CGI_DEPRECATED void cgi_redirect(char *url);
extern void cgi_fatal(const char *error);
extern char *cgi_unescape_special_chars(const char *str);
extern char *cgi_escape_special_chars(const char *str);
Expand Down Expand Up @@ -143,6 +195,20 @@ void cgi_session_free( void );
*/
const char *cgi_version( void );

/**
* Send a HTTP header 'Location:' with the uri provided together with a
* pseudo header 'Status:' with some HTTP status code. See RFC 3875,
* section 6.3 (Response Header Fields) for details on how this is
* supposed to work.
*
* @see https://tools.ietf.org/html/rfc3875#section-6.3
*
* @param[in] status_code HTTP status code number, pick it from our enum type
* @param[in] uri URI to be sent with the Location: header
*/
void cgi_redirect_status( enum cgi_http_status_code status_code,
const char *uri );

#ifdef __cplusplus
}
#endif
Expand Down
16 changes: 16 additions & 0 deletions src/cgi.c
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,22 @@ const char *cgi_version( void )
return CGI_VERSION;
}

void cgi_redirect_status( enum cgi_http_status_code status_code,
const char *uri )
{
if ( headers_initialized )
{
libcgi_error( E_WARNING,
"<br><b>Cannot redirect. Headers already sent</b><br>" );
return;
}

printf( "Status: %i\r\n"
"Location: %s\r\n"
"\r\n",
status_code, uri );
}

/**
* @}
*/

0 comments on commit 1532dd5

Please sign in to comment.