00001 // ------------------------------------------------------------------ 00002 // pion-net: a C++ framework for building lightweight HTTP interfaces 00003 // ------------------------------------------------------------------ 00004 // Copyright (C) 2007-2008 Atomic Labs, Inc. (http://www.atomiclabs.com) 00005 // 00006 // Distributed under the Boost Software License, Version 1.0. 00007 // See http://www.boost.org/LICENSE_1_0.txt 00008 // 00009 00010 #include <boost/lexical_cast.hpp> 00011 #include <boost/thread/mutex.hpp> 00012 #include <pion/net/HTTPTypes.hpp> 00013 #include <pion/PionAlgorithms.hpp> 00014 #include <cstdio> 00015 #include <ctime> 00016 00017 00018 namespace pion { // begin namespace pion 00019 namespace net { // begin namespace net (Pion Network Library) 00020 00021 00022 // generic strings used by HTTP 00023 const std::string HTTPTypes::STRING_EMPTY; 00024 const std::string HTTPTypes::STRING_CRLF("\x0D\x0A"); 00025 const std::string HTTPTypes::STRING_HTTP_VERSION("HTTP/"); 00026 const std::string HTTPTypes::HEADER_NAME_VALUE_DELIMITER(": "); 00027 00028 // common HTTP header names 00029 const std::string HTTPTypes::HEADER_HOST("Host"); 00030 const std::string HTTPTypes::HEADER_COOKIE("Cookie"); 00031 const std::string HTTPTypes::HEADER_SET_COOKIE("Set-Cookie"); 00032 const std::string HTTPTypes::HEADER_CONNECTION("Connection"); 00033 const std::string HTTPTypes::HEADER_CONTENT_TYPE("Content-Type"); 00034 const std::string HTTPTypes::HEADER_CONTENT_LENGTH("Content-Length"); 00035 const std::string HTTPTypes::HEADER_CONTENT_LOCATION("Content-Location"); 00036 const std::string HTTPTypes::HEADER_CONTENT_ENCODING("Content-Encoding"); 00037 const std::string HTTPTypes::HEADER_LAST_MODIFIED("Last-Modified"); 00038 const std::string HTTPTypes::HEADER_IF_MODIFIED_SINCE("If-Modified-Since"); 00039 const std::string HTTPTypes::HEADER_TRANSFER_ENCODING("Transfer-Encoding"); 00040 const std::string HTTPTypes::HEADER_LOCATION("Location"); 00041 const std::string HTTPTypes::HEADER_AUTHORIZATION("Authorization"); 00042 const std::string HTTPTypes::HEADER_REFERER("Referer"); 00043 const std::string HTTPTypes::HEADER_USER_AGENT("User-Agent"); 00044 const std::string HTTPTypes::HEADER_X_FORWARDED_FOR("X-Forwarded-For"); 00045 const std::string HTTPTypes::HEADER_CLIENT_IP("Client-IP"); 00046 00047 // common HTTP content types 00048 const std::string HTTPTypes::CONTENT_TYPE_HTML("text/html"); 00049 const std::string HTTPTypes::CONTENT_TYPE_TEXT("text/plain"); 00050 const std::string HTTPTypes::CONTENT_TYPE_XML("text/xml"); 00051 const std::string HTTPTypes::CONTENT_TYPE_URLENCODED("application/x-www-form-urlencoded"); 00052 00053 // common HTTP request methods 00054 const std::string HTTPTypes::REQUEST_METHOD_HEAD("HEAD"); 00055 const std::string HTTPTypes::REQUEST_METHOD_GET("GET"); 00056 const std::string HTTPTypes::REQUEST_METHOD_PUT("PUT"); 00057 const std::string HTTPTypes::REQUEST_METHOD_POST("POST"); 00058 const std::string HTTPTypes::REQUEST_METHOD_DELETE("DELETE"); 00059 00060 // common HTTP response messages 00061 const std::string HTTPTypes::RESPONSE_MESSAGE_OK("OK"); 00062 const std::string HTTPTypes::RESPONSE_MESSAGE_CREATED("Created"); 00063 const std::string HTTPTypes::RESPONSE_MESSAGE_NO_CONTENT("No Content"); 00064 const std::string HTTPTypes::RESPONSE_MESSAGE_FOUND("Found"); 00065 const std::string HTTPTypes::RESPONSE_MESSAGE_UNAUTHORIZED("Unauthorized"); 00066 const std::string HTTPTypes::RESPONSE_MESSAGE_FORBIDDEN("Forbidden"); 00067 const std::string HTTPTypes::RESPONSE_MESSAGE_NOT_FOUND("Not Found"); 00068 const std::string HTTPTypes::RESPONSE_MESSAGE_METHOD_NOT_ALLOWED("Method Not Allowed"); 00069 const std::string HTTPTypes::RESPONSE_MESSAGE_NOT_MODIFIED("Not Modified"); 00070 const std::string HTTPTypes::RESPONSE_MESSAGE_BAD_REQUEST("Bad Request"); 00071 const std::string HTTPTypes::RESPONSE_MESSAGE_SERVER_ERROR("Server Error"); 00072 const std::string HTTPTypes::RESPONSE_MESSAGE_NOT_IMPLEMENTED("Not Implemented"); 00073 const std::string HTTPTypes::RESPONSE_MESSAGE_CONTINUE("Continue"); 00074 00075 // common HTTP response codes 00076 const unsigned int HTTPTypes::RESPONSE_CODE_OK = 200; 00077 const unsigned int HTTPTypes::RESPONSE_CODE_CREATED = 201; 00078 const unsigned int HTTPTypes::RESPONSE_CODE_NO_CONTENT = 204; 00079 const unsigned int HTTPTypes::RESPONSE_CODE_FOUND = 302; 00080 const unsigned int HTTPTypes::RESPONSE_CODE_UNAUTHORIZED = 401; 00081 const unsigned int HTTPTypes::RESPONSE_CODE_FORBIDDEN = 403; 00082 const unsigned int HTTPTypes::RESPONSE_CODE_NOT_FOUND = 404; 00083 const unsigned int HTTPTypes::RESPONSE_CODE_METHOD_NOT_ALLOWED = 405; 00084 const unsigned int HTTPTypes::RESPONSE_CODE_NOT_MODIFIED = 304; 00085 const unsigned int HTTPTypes::RESPONSE_CODE_BAD_REQUEST = 400; 00086 const unsigned int HTTPTypes::RESPONSE_CODE_SERVER_ERROR = 500; 00087 const unsigned int HTTPTypes::RESPONSE_CODE_NOT_IMPLEMENTED = 501; 00088 const unsigned int HTTPTypes::RESPONSE_CODE_CONTINUE = 100; 00089 00090 00091 // static member functions 00092 00093 std::string HTTPTypes::get_date_string(const time_t t) 00094 { 00095 // use mutex since time functions are normally not thread-safe 00096 static boost::mutex time_mutex; 00097 static const char *TIME_FORMAT = "%a, %d %b %Y %H:%M:%S GMT"; 00098 static const unsigned int TIME_BUF_SIZE = 100; 00099 char time_buf[TIME_BUF_SIZE+1]; 00100 00101 boost::mutex::scoped_lock time_lock(time_mutex); 00102 if (strftime(time_buf, TIME_BUF_SIZE, TIME_FORMAT, gmtime(&t)) == 0) 00103 time_buf[0] = '\0'; // failed; resulting buffer is indeterminate 00104 time_lock.unlock(); 00105 00106 return std::string(time_buf); 00107 } 00108 00109 std::string HTTPTypes::make_query_string(const QueryParams& query_params) 00110 { 00111 std::string query_string; 00112 for (QueryParams::const_iterator i = query_params.begin(); i != query_params.end(); ++i) { 00113 if (i != query_params.begin()) 00114 query_string += '&'; 00115 query_string += algo::url_encode(i->first); 00116 query_string += '='; 00117 query_string += algo::url_encode(i->second); 00118 } 00119 return query_string; 00120 } 00121 00122 std::string HTTPTypes::make_set_cookie_header(const std::string& name, 00123 const std::string& value, 00124 const std::string& path, 00125 const bool has_max_age, 00126 const unsigned long max_age) 00127 { 00128 std::string set_cookie_header(name); 00129 set_cookie_header += "=\""; 00130 set_cookie_header += value; 00131 set_cookie_header += "\"; Version=\"1\""; 00132 if (! path.empty()) { 00133 set_cookie_header += "; Path=\""; 00134 set_cookie_header += path; 00135 set_cookie_header += '\"'; 00136 } 00137 if (has_max_age) { 00138 set_cookie_header += "; Max-Age=\""; 00139 set_cookie_header += boost::lexical_cast<std::string>(max_age); 00140 set_cookie_header += '\"'; 00141 } 00142 return set_cookie_header; 00143 } 00144 00145 00146 } // end namespace net 00147 } // end namespace pion 00148