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