Skip to content

ElesiqArt/buffer_handle_http_header

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

47 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Handle HTTP header buffer

This C++ 11 header-only library under MIT license and based on the buffer handle library, eases the management of common HTTP response headers.

Dependencies

The library depends on buffer handle 1.5. Please refer to the documentation for concepts and examples.

Normative documents
  • RFC 2616 Hypertext Transfer Protocol -- HTTP/1.1
  • RFC 6265 HTTP State Management Mechanism
  • RFC 6585 Additional HTTP Status Codes
  • RFC 7231 Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
  • RFC 7232 Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests
  • W3C CORS Cross-Origin Resource Sharing

Reference

All code is scoped in namespace buffer_handle_http_header.

A layer on top of buffer handle functions and functors is provided in order to handle HTTP header fields.

Types

The four types defined by buffer handle are directly imported to avoid scoping.

//Declared in buffer_handle_http_header/type.hpp

typedef buffer_handle::action action;
typedef buffer_handle::align align;
typedef buffer_handle::case_ case_;
typedef buffer_handle::config config;

Status line (RFC 2616 §6.1)

//Defined in buffer_handle_http_header/status_line.hpp

template<config Config, class Code, action Action, typename Number, class Itoa>
char * status_line(char * buffer, Number major, Number minor, status_code_t value,
		   std::size_t & max_length, const Itoa & itoa = Itoa());

template<config Config, class Code, action Action, typename Number, class Itoa>
char * status_line(char * buffer, Number major, Number minor, status_code_t value,
		   std::size_t & max_length, std::size_t & previous_length, const Itoa & itoa = Itoa());

template<config Config, class Code, typename Number, class Itoa>
struct status_line_t
{
  template<action Action>
  char * handle(char * buffer, Number major, Number minor, status_code_t value,
		const Itoa & itoa = Itoa());
};

HTTP version (RFC 2616 §3.1)

//Defined in buffer_handle_http_header/version.hpp

template<config Config, action Action, typename Number, class Itoa>
char * version(char * buffer, Number major, Number minor, std::size_t & max_length,
	       const Itoa & itoa = Itoa());

template<config Config, typename Number>
struct version_t
{
  template<action Action, class Itoa>
  char * handle(char * buffer, Number major, Number minor, const Itoa & itoa = Itoa());
};

Status code and reason phrase (RFC 2616 §6.1.1)

//Declared in buffer_handle_http_header/status_code.hpp

typedef uint16_t status_code_t;

namespace status_code
{
  #define BUFFER_HANDLE_HTTP_HEADER_INSTALL_STATUS_CODE(NAME, VALUE, REASON)
  //To define
  struct NAME
  {
    static constexpr status_code_t value; // to hold VALUE
    static constexpr const char * reason; // to hold REASON
  };
};
//Defined in buffer_handle_http_header/status_code.hpp

template<config Config, action Action, class Itoa>
char * status_code_(char * buffer, status_code_t value, const Itoa & itoa = Itoa());

template<config Config, class Code, action Action>
char * reason_phrase(char * buffer, status_code_t value);

template<config Config, class Code, action Action>
char * reason_phrase(char * buffer, status_code_t value, std::size_t & previous_length);
//Declared in buffer_handle_http_header/status_code.hpp

namespace status_code
{
  namespace informational
  {
    struct continue_;
    struct switching_protocols;
  };

  namespace success
  {
    struct ok;
    struct created;
    struct accepted;
    struct non_authoritative_information;
    struct no_content;
    struct reset_content;
    struct partial_content;
  };

  namespace redirection
  {
    struct multiple_choice;
    struct moved_permanently;
    struct found;
    struct see_other;
    struct not_modified;
    struct use_proxy;
    struct temporary_redirect;
  };

  namespace client_error
  {
    struct bad_request;
    struct unauthorized;
    struct payment_required;
    struct forbidden;
    struct not_found;
    struct method_not_allowed;
    struct not_acceptable;
    struct proxy_authentication_required;
    struct request_time_out;
    struct conflict;
    struct gone;
    struct length_required;
    struct precondition_failed;
    struct request_entity_too_large;
    struct request_uri_too_large;
    struct unsupported_media_type;
    struct requested_range_not_satisfiable;
    struct expectation_failed;
  };

  namespace server_error
  {
    struct internal_server_error;
    struct not_implemented;
    struct bad_gateway;
    struct service_unavailable;
    struct gateway_timeout;
    struct http_version_not_supported;
  };
};
//Defined in buffer_handle_http_header/status_code.hpp

namespace status_code
{
  struct rfc2616_t
  {
    static const status_code_t any;
    static const std::size_t max_reason_length;
    static const char * reason(status_code_t code);
  };
};
//Declared in buffer_handle_http_header/status_code.hpp

namespace status_code
{
  namespace client_error
  {
    struct precondition_required;//§3
    struct too_many_requests;//§4
    struct request_header_fields_too_large;//§5
  };

  namespace server_error
  {
    struct network_authentication_required;//§6
  };
};
//Defined in buffer_handle_http_header/status_code.hpp

namespace status_code
{
  struct rfc6585_t
  {
    static const status_code_t any;
    static const std::size_t max_reason_length;
    static const char * reason(status_code_t code);
  };
};
  • reason() defaults to rfc2616_t::reason() for non RFC6585 status codes.

General headers (RFC 2616 §4.5)

//Defined in buffer_handle_http_header/date.hpp

template<config Config, action Action,
	     typename Weekday, typename Day, typename Month, typename Year,
	     typename Hours, typename Minutes, typename Seconds>
char * date(char * buffer, Weekday weekday, Day day, Month month, Year year,
	    Hours hours, Minutes minutes, Seconds seconds);

template<config Config, action Action>
char * date(char * buffer, std::tm value);

Upgrade (RFC2616 §14.42)

template<config Config, bool ListSetMaxLength, bool IsLong = false>
struct upgrade_t
{
  template<action Action, class Iterator, class Element, class Separator>
  char * handle(char * buffer, const Iterator & begin, const Iterator & end, Element & element, Separator & separator);
};

Response headers (RFC 2616 §6.2)

Accept-Ranges (RFC 2616 §14.5)

//Defined in buffer_handle_http_header/accept_ranges.hpp

template<config Config, class RangeUnit, bool IsLong = false>
struct accept_ranges_t
{
  template<action Action>
  char * handle(char * buffer, typename RangeUnit::value_type value);
};

The RangeUnit template parameter holds the range unit enumeration type and is used to convert a range unit to its string form.

//Defined in buffer_handle_http_header/age.hpp

template<config Config, typename I, typename MaxDigits = uint8_t, bool IsLong = false>
struct age_t
{
  template<action Action, class Itoa>
  char * handle(char * buffer, I value, const Itoa & itoa = Itoa());
};

Location (RFC7231 §7.1.2)

Obsoletes RFC 2616 §14.30.

//Defined in buffer_handle_http_header/location.hpp

template<config Config, bool IsLong = false>
struct location_t
{
  template<action Action>
  char * handle(char * buffer, const char * value, std::size_t length);
};

Set-Cookie (RFC 6265 §4.1)

//Defined in buffer_handle_http_header/cookie.hpp

namespace cookie
{
    template<config Config, action Action>
    char * name(char * buffer, const char * name, std::size_t name_length, std::size_t max_name_length);

    template<config Config, action Action>
    char * name(char * buffer, char ** name, std::size_t name_length, std::size_t max_name_length);

    template<config Config, bool IsQuoted, action Action>
    char * value(char * buffer, const char * value, std::size_t length, std::size_t max_length);

    template<config Config, bool IsQuoted, action Action>
    char * value(char * buffer, char ** value, std::size_t length, std::size_t max_length);

    template<config Config, action Action>
    char * expires(char * buffer, std::tm * at);

    template<config Config, action Action, class Itoa>
    char * max_age(char * buffer, time_t * max_age, uint8_t & max_digits, const Itoa & itoa = Itoa());

    template<action Action, class Itoa>
    char * max_age(char * buffer, time_t max_age, const Itoa & itoa = Itoa());

    template<config Config, action Action>
    char * domain(char * buffer, const char * value, std::size_t length, std::size_t max_length);

    template<config Config, action Action>
    char * domain(char * buffer, char ** value, std::size_t length, std::size_t max_length);

    template<config Config, action Action>
    char * path(char * buffer, const char * value, std::size_t length, std::size_t max_length);

    template<config Config, action Action>
    char * path(char * buffer, char ** value, std::size_t length, std::size_t max_length);

    template<config Config, action Action>
    char * is_secure(char * buffer, bool value);

    template<config Config, action Action>
    char * http_only(char * buffer, bool value);
};
  • The name function will take care of the header field, the name of the cookie and the equal.
  • For functions with a const char * argument, passing a nullptr for a write is equivalent to a reset.
  • For functions with a char ** argument, the content will be left-aligned except for name for which it will be right-aligned.
  • For functions taking either const char * or char **, there is an overload with std::nullptr_t to resolve a nullptr parameter.
//Defined in buffer_handle_http_header/cookie.hpp

namespace cookie
{
  template<config Config, bool IsExternal = false>
  struct name_t
  {
    template<action Action>
    char * handle(char * buffer);
  };

  template<config Config, bool IsQuoted = false, bool IsExternal = false>
  struct value_t
  {
    template<action Action>
    char * handle(char * buffer);
  };

  template<class Next, config Config>
  struct expires_t : Next
  {
    std::tm * expires;

    template<action Action>
    char * handle(char * buffer);
  };

  template<class Next, config Config, class Itoa>
  struct max_age_t : Next
  {
    time_t * max_age;//Not a pointer if Config == config::static_

    template<action Action>
    char * handle(char * buffer);
  };

  template<class Next, config Config, bool IsExternal = false>
  struct domain_t : Next
  {
    template<action Action>
    char * handle(char * buffer);
  };

  template<class Next, config Config, bool IsExternal = false>
  struct path_t : Next
  {
    template<action Action>
    char * handle(char * buffer);
  };

  template<class Next, config Config, bool Value = true>
  struct is_secure_t : Next
  {
    template<action Action>
    char * handle(char * buffer);
  };

  template<class Next, config Config, bool Value = true>
  struct http_only_t : Next
  {
    template<action Action>
    char * handle(char * buffer);
  };
};
  • The Next template parameter is used to combine functors.
  • The attributes name and type of name_t, value_t, domain_t and path_t functors depend on the Config and the IsExternal parameters such that:
template<config Config, bool IsExternal>
struct T
{
  std::conditional<IsExternal, char *, const char *>::type T;
  std::size_t T_length;//Except if Config == config::dynamic && IsExternal
  std::size_t max_T_length;//If Config == config::dynamic
};
  • The is_secure_t and http_only_t functors have a bool is_secure and bool http_only attribute respectively when dynamic; otherwise the Value parameters is used to set the content.
//Defined in buffer_handle_http_header/cookie.hpp

template<class Next, config NameConfig, config ValueConfig, bool IsQuoted,
	 bool IsNameExternal = false, bool IsValueExternal = false>
struct cookie_t
{
  template<action Action>
  char * handle(char * buffer);
};
  • This main class aggregates name_t and value_t to Next.

Entity headers (RFC 2616 §7.1)

//Defined in buffer_handle_http_header/allow.hpp

template<config Config, class Method, bool IsLong = false>
struct allow_t
{
  template<action Action>
  char * handle(char * buffer, typename Method::value_type value);
};

The Method template parameter holds the method enumeration type and is used to convert a method to its string form.

Content-Encoding (RFC 2616 §14.11)

//Defined in buffer_handle_http_header/content_encoding.hpp

template<config Config, class ContentCoding, bool IsLong = false>
struct content_encoding_t
{
  template<action Action>
  char * handle(char * buffer, typename ContentCoding::value_type value);
};

The ContentCoding template parameter holds the content coding enumeration type and is used to convert a content coding to its string form.

Content-Language (RFC 2616 §14.12)

template<config Config, bool ListSetMaxLength, bool IsLong = false>
struct content_language_t : public container_field_t<Config, ListSetMaxLength, IsLong>
{
  template<action Action, class Iterator, class Element, class Separator>
  char * handle(char * buffer, const Iterator & begin, const Iterator & end, Element & element);
};

Content-Length (RFC 2616 §14.13)

//Defined in buffer_handle_http_header/content_length.hpp

template<config Config, bool IsLong = false>
struct content_length_t
{
  template<action Action, class Itoa>
  char * handle(char * buffer, std::size_t value, const Itoa & itoa = Itoa());
};

Content-Location (RFC 2616 §14.14)

//Defined in buffer_handle_http_header/content_location.hpp

template<config Config, bool IsLong = false>
struct content_location_t
{
  template<action Action>
  char * handle(char * buffer, const char * value, std::size_t length);
};

Content-MD5 (RFC 2616 §14.15)

//Defined in buffer_handle_http_header/content_md5.hpp

template<action Action>
char * content_md5(char * buffer, char * & digest_begin, char * & digest_end);
//Defined in buffer_handle_http_header/expires.hpp

template<config Config, action Action,
	     typename Weekday, typename Day, typename Month, typename Year,
	     typename Hours, typename Minutes, typename Seconds>
char * expires(char * buffer, Weekday weekday, Day day, Month month, Year year,
		   Hours hours, Minutes minutes, Seconds seconds);

template<config Config, action Action>
char * expires(char * buffer, std::tm value);

Last-Modified (RFC 2616 §14.29)

//Defined in buffer_handle_http_header/last_modified.hpp

template<config Config, action Action,
	   typename Weekday, typename Day, typename Month, typename Year,
	   typename Hours, typename Minutes, typename Seconds>
char * last_modified(char * buffer, Weekday weekday, Day day, Month month, Year year,
			 Hours hours, Minutes minutes, Seconds seconds);

template<config Config, action Action>
char * last_modified(char * buffer, std::tm value);

Cross Origin Resource Sharing (W3C)

Access-Control-Allow-Credentials (W3C-CORS)

template<config Config, action Action>
char * access_control_allow_credentials(char * buffer, bool value);

Access-Control-Allow-Headers (W3C-CORS)

template<config Config, bool IsLong = false>
struct access_control_allow_headers_t
{
  template<action Action, class Iterator, class Element>
  char * handle(char * buffer, const Iterator & begin, const Iterator & end, Element & element);
};

Access-Control-Allow-Methods (W3C-CORS)

template<config Config, class Method, bool IsLong = false>
struct access_control_allow_methods_t
{
  template<action Action>
  char * handle(char * buffer, typename Method::value_type value);
};

Access-Control-Allow-Origin (W3C-CORS)

template<config Config, bool IsLong = false>
struct access_control_allow_origin_t
{
  template<action Action>
  char * handle(char * bufer, const char * value, std::size_t length);
};

Access-Control-Expose-Headers (W3C-CORS)

template<config Config, bool IsLong = false>
struct access_control_expose_headers_t
{
  template<action Action, class Iterator, class Element>
  char * handle(char * buffer, const Iterator & begin, const Iterator & end, Element & element);
};

Access-Control-Max-Age (W3C-CORS)

//Defined in buffer_handle_http_header/access_control_max_age.hpp

template<config Config, typename I, typename MaxDigits = uint8_t, bool IsLong = false>
struct access_control_max_age_t
{
  template<action Action, class Itoa>
  char * handle(char * buffer, I value, const Itoa & itoa = Itoa());
};

Common

CRLF
//Defined in buffer_handle_http_header/common.hpp

template<config Config, action Action>
char * crlf(char * buffer);
Field name

These methods will write the name of the header field followed by the mandatory colon and space.

//Defined in buffer_handle_http_header/common.hpp

template<action Action>
char * field_(char * buffer, const char * value, std::size_t length);

template<action Action>
char * field_(char * buffer, const char * value);
Fields
template<config Config, typename I, typename MaxDigits = uint8_t, bool IsLong = false>
struct integral_number_field_t :
       buffer_handle::integral_number_t<Config, align::right, ' ', I, MaxDigits, IsLong>
{
  template<action Action, class Itoa>
  char * handle(char * buffer, const char * field, I value, const Itoa & itoa = Itoa());
};

template<config Config, bool IsLong = false>
struct string_field_t : buffer_handle::string_t<Config, align::right, ' ', IsLong>
{
  template<action Action>
  char * handle(char * buffer, const char * field, const char * value, std::size_t length);
};

template<config Config, action Action,
	 typename Weekday, typename Day, typename Month, typename Year,
	 typename Hours, typename Minutes, typename Seconds>
char * date(char * buffer, const char * field,
	    Weekday weekday, Day day, Month month, Year year,
	    Hours hours, Minutes minutes, Seconds seconds);

template<config Config, action Action>
char * date(char * buffer, const char * field, std::tm value);

template<config Config, bool ListSetMaxLength, bool IsLong = false>
struct container_field_t : buffer_handle::container_t<Config, align::right, ' ', IsLong>
{
  void set_max_length(std::size_t length);

  template<class Iterator, class Element, class Separator>
  void set_max_length(const Iterator & begin, const Iterator & end,
		      Element & element, Separator & separator);

  template<action Action, class Iterator, class Element, class Separator>
  char * handle(char * buffer, const char * field, const Iterator & begin, const Iterator & end,
		Element & element, Separator & separator);
};
Set iterator

External functors

Content coding

By default, RFC 2616 §3.5 and RFC 7932 §13 content codings are available.

//Defined in buffer_handle_http_header/content_coding.hpp

enum class content_coding : uint8_t { gzip, compress, deflate, identity, br };

content_coding operator | (content_coding lhs, content_coding rhs);

struct content_coding_t
{
  typedef content_coding value_type;
  static const std::size_t count;
  static const char * get(content_coding encoding);
};

Method

By default, RFC 2616 §5.1.1 methods are available.

//Defined in buffer_handle_http_header/method.hpp

enum class method : uint16_t { OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT };

method operator | (method lhs, method rhs);

struct method_t
{
  typedef method value_type;
  static const std::size_t count;
  static const char * get(method method);
};

Range unit

By default, RFC 2616 §3.12 range units are available.

//Defined in buffer_handle_http_header/range_unit.hpp

enum class range_unit : uint8_t { none, bytes };

struct range_unit_t
{
  typedef range_unit value_type;
  static const std::size_t count;
  static const char * get(range_unit unit);
};

Tests

Run make test to compile and make run-test to execute, or simply make.

Dependencies

To change the paths of these dependencies, create a config.mk file and then assign the BUFFER_HANDLE and CATCH variables with the appropriate locations (. is used by default).

About

Perform elementary actions on http header buffers with a single function

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors