pion  5.0.6
http_types.cpp
1 // ---------------------------------------------------------------------
2 // pion: a Boost C++ framework for building lightweight HTTP interfaces
3 // ---------------------------------------------------------------------
4 // Copyright (C) 2007-2014 Splunk Inc. (https://github.com/splunk/pion)
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 // See http://www.boost.org/LICENSE_1_0.txt
8 //
9 
10 #include <boost/lexical_cast.hpp>
11 #include <boost/thread/mutex.hpp>
12 #include <pion/http/types.hpp>
13 #include <pion/algorithm.hpp>
14 #include <cstdio>
15 #include <ctime>
16 
17 
18 namespace pion { // begin namespace pion
19 namespace http { // begin namespace http
20 
21 
22 // generic strings used by HTTP
23 const std::string types::STRING_EMPTY;
24 const std::string types::STRING_CRLF("\x0D\x0A");
25 const std::string types::STRING_HTTP_VERSION("HTTP/");
26 const std::string types::HEADER_NAME_VALUE_DELIMITER(": ");
27 const std::string types::COOKIE_NAME_VALUE_DELIMITER("=");
28 
29 // common HTTP header names
30 const std::string types::HEADER_HOST("Host");
31 const std::string types::HEADER_COOKIE("Cookie");
32 const std::string types::HEADER_SET_COOKIE("Set-Cookie");
33 const std::string types::HEADER_CONNECTION("Connection");
34 const std::string types::HEADER_CONTENT_TYPE("Content-Type");
35 const std::string types::HEADER_CONTENT_LENGTH("Content-Length");
36 const std::string types::HEADER_CONTENT_LOCATION("Content-Location");
37 const std::string types::HEADER_CONTENT_ENCODING("Content-Encoding");
38 const std::string types::HEADER_CONTENT_DISPOSITION("Content-Disposition");
39 const std::string types::HEADER_LAST_MODIFIED("Last-Modified");
40 const std::string types::HEADER_IF_MODIFIED_SINCE("If-Modified-Since");
41 const std::string types::HEADER_TRANSFER_ENCODING("Transfer-Encoding");
42 const std::string types::HEADER_LOCATION("Location");
43 const std::string types::HEADER_AUTHORIZATION("Authorization");
44 const std::string types::HEADER_REFERER("Referer");
45 const std::string types::HEADER_USER_AGENT("User-Agent");
46 const std::string types::HEADER_X_FORWARDED_FOR("X-Forwarded-For");
47 const std::string types::HEADER_CLIENT_IP("Client-IP");
48 
49 // common HTTP content types
50 const std::string types::CONTENT_TYPE_HTML("text/html");
51 const std::string types::CONTENT_TYPE_TEXT("text/plain");
52 const std::string types::CONTENT_TYPE_XML("text/xml");
53 const std::string types::CONTENT_TYPE_URLENCODED("application/x-www-form-urlencoded");
54 const std::string types::CONTENT_TYPE_MULTIPART_FORM_DATA("multipart/form-data");
55 
56 // common HTTP request methods
57 const std::string types::REQUEST_METHOD_HEAD("HEAD");
58 const std::string types::REQUEST_METHOD_GET("GET");
59 const std::string types::REQUEST_METHOD_PUT("PUT");
60 const std::string types::REQUEST_METHOD_POST("POST");
61 const std::string types::REQUEST_METHOD_DELETE("DELETE");
62 
63 // common HTTP response messages
64 const std::string types::RESPONSE_MESSAGE_OK("OK");
65 const std::string types::RESPONSE_MESSAGE_CREATED("Created");
66 const std::string types::RESPONSE_MESSAGE_ACCEPTED("Accepted");
67 const std::string types::RESPONSE_MESSAGE_NO_CONTENT("No Content");
68 const std::string types::RESPONSE_MESSAGE_FOUND("Found");
69 const std::string types::RESPONSE_MESSAGE_UNAUTHORIZED("Unauthorized");
70 const std::string types::RESPONSE_MESSAGE_FORBIDDEN("Forbidden");
71 const std::string types::RESPONSE_MESSAGE_NOT_FOUND("Not Found");
72 const std::string types::RESPONSE_MESSAGE_METHOD_NOT_ALLOWED("Method Not Allowed");
73 const std::string types::RESPONSE_MESSAGE_NOT_MODIFIED("Not Modified");
74 const std::string types::RESPONSE_MESSAGE_BAD_REQUEST("Bad Request");
75 const std::string types::RESPONSE_MESSAGE_SERVER_ERROR("Server Error");
76 const std::string types::RESPONSE_MESSAGE_NOT_IMPLEMENTED("Not Implemented");
77 const std::string types::RESPONSE_MESSAGE_CONTINUE("Continue");
78 
79 // common HTTP response codes
80 const unsigned int types::RESPONSE_CODE_OK = 200;
81 const unsigned int types::RESPONSE_CODE_CREATED = 201;
82 const unsigned int types::RESPONSE_CODE_ACCEPTED = 202;
83 const unsigned int types::RESPONSE_CODE_NO_CONTENT = 204;
84 const unsigned int types::RESPONSE_CODE_FOUND = 302;
85 const unsigned int types::RESPONSE_CODE_UNAUTHORIZED = 401;
86 const unsigned int types::RESPONSE_CODE_FORBIDDEN = 403;
87 const unsigned int types::RESPONSE_CODE_NOT_FOUND = 404;
88 const unsigned int types::RESPONSE_CODE_METHOD_NOT_ALLOWED = 405;
89 const unsigned int types::RESPONSE_CODE_NOT_MODIFIED = 304;
90 const unsigned int types::RESPONSE_CODE_BAD_REQUEST = 400;
91 const unsigned int types::RESPONSE_CODE_SERVER_ERROR = 500;
92 const unsigned int types::RESPONSE_CODE_NOT_IMPLEMENTED = 501;
93 const unsigned int types::RESPONSE_CODE_CONTINUE = 100;
94 
95 
96 // static member functions
97 
98 std::string types::get_date_string(const time_t t)
99 {
100  // use mutex since time functions are normally not thread-safe
101  static boost::mutex time_mutex;
102  static const char *TIME_FORMAT = "%a, %d %b %Y %H:%M:%S GMT";
103  static const unsigned int TIME_BUF_SIZE = 100;
104  char time_buf[TIME_BUF_SIZE+1];
105 
106  boost::mutex::scoped_lock time_lock(time_mutex);
107  if (strftime(time_buf, TIME_BUF_SIZE, TIME_FORMAT, gmtime(&t)) == 0)
108  time_buf[0] = '\0'; // failed; resulting buffer is indeterminate
109  time_lock.unlock();
110 
111  return std::string(time_buf);
112 }
113 
114 std::string types::make_query_string(const ihash_multimap& query_params)
115 {
116  std::string query_string;
117  for (ihash_multimap::const_iterator i = query_params.begin(); i != query_params.end(); ++i) {
118  if (i != query_params.begin())
119  query_string += '&';
120  query_string += algorithm::url_encode(i->first);
121  query_string += '=';
122  query_string += algorithm::url_encode(i->second);
123  }
124  return query_string;
125 }
126 
127 std::string types::make_set_cookie_header(const std::string& name,
128  const std::string& value,
129  const std::string& path,
130  const bool has_max_age,
131  const unsigned long max_age)
132 {
133  // note: according to RFC6265, attributes should not be quoted
134  std::string set_cookie_header(name);
135  set_cookie_header += "=\"";
136  set_cookie_header += value;
137  set_cookie_header += "\"; Version=1";
138  if (! path.empty()) {
139  set_cookie_header += "; Path=";
140  set_cookie_header += path;
141  }
142  if (has_max_age) {
143  set_cookie_header += "; Max-Age=";
144  set_cookie_header += boost::lexical_cast<std::string>(max_age);
145  }
146  return set_cookie_header;
147 }
148 
149 
150 } // end namespace http
151 } // end namespace pion
static std::string url_encode(const std::string &str)
encodes strings so that they are safe for URLs (with%20spaces)
Definition: algorithm.cpp:196
static std::string get_date_string(const time_t t)
converts time_t format into an HTTP-date string
Definition: http_types.cpp:98
static std::string make_set_cookie_header(const std::string &name, const std::string &value, const std::string &path, const bool has_max_age=false, const unsigned long max_age=0)
Definition: http_types.cpp:127
static std::string make_query_string(const ihash_multimap &query_params)
builds an HTTP query string from a collection of query parameters
Definition: http_types.cpp:114