00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef restcgi_hdr_h
00023 #define restcgi_hdr_h
00024 #include "apidefs.h"
00025 #include "cookie.h"
00026 #include "utils.h"
00027 #include <string.h>
00028 #include <string>
00029 #include <map>
00030 #include <iostream>
00031 #ifdef _WIN32
00032 #pragma warning (disable: 4251)
00033 #endif
00034 namespace restcgi {
00035 class env;
00036 class date_time;
00037 class request_hdr;
00038 class content_hdr;
00070 class RESTCGI_API hdr {
00071 public:
00073 enum fld_category {
00074 fc_null,
00075 fc_general = 1<<0,
00076 fc_request = 1<<1,
00077 fc_response = 1<<2,
00078 fc_other = 1<<3,
00079 fc_entity_rsp = 1<<4,
00080 fc_entity_cnt = 1<<5,
00081 };
00083 class RESTCGI_API fld_traits {
00084 public:
00085 bool operator <(const fld_traits& rhs) const {return ln_ ? (rhs.ln_ ? (::strcmp(ln_, rhs.ln_) < 0) : false) : (rhs.ln_ != 0);}
00086 const char* lower_name_as_cstring() const {return ln_;}
00087 const char* name_as_cstring() const {return n_;}
00088 fld_category category() const {return category_;}
00089 private:
00090 friend class hdr;
00091 fld_traits(const char* ln, const char* n = 0, fld_category cat = fc_null);
00092 const char* ln_;
00093 const char* n_;
00094 fld_category category_;
00095 };
00099 class RESTCGI_API key {
00100 public:
00101 key(const std::string& name, bool lookup = false);
00102 bool is_null() const {return !p_ && name_.empty();}
00103 bool operator ==(const key& rhs) const {return p_ == rhs.p_ && lower_name_ == rhs.lower_name_;}
00104 bool operator <(const key& rhs) const;
00105 const char* name_as_cstring() const {return p_ ? p_->name_as_cstring() : name_.c_str();}
00106 const char* lower_name_as_cstring() const {return p_ ? p_->lower_name_as_cstring() : lower_name_.c_str();}
00107 fld_category category() const {return p_ ? p_->category() : fc_other;}
00108 private:
00109 friend class hdr;
00110 key(const fld_traits* p = 0) : p_(p) {}
00111 const fld_traits* p_;
00112 std::string name_;
00113 std::string lower_name_;
00114 };
00115 typedef std::map<key, std::string> map_type;
00116 typedef map_type::const_iterator const_iterator;
00117 virtual ~hdr();
00118 bool empty() const {return map_.empty();}
00119 const_iterator begin() const {return map_.begin();}
00120 const_iterator end() const {return map_.end();}
00121
00122
00123
00124
00125
00126
00127 template<typename T> bool insert(const std::string& name, const T& value) {
00128 if (name.empty())
00129 return false;
00130 key k(name, true);
00131 std::string v = uripp::convert(value);
00132 return insert(k, v);
00133 }
00138 template<typename T> bool find(const std::string& name, T& value) const {
00139 if (name.empty())
00140 return false;
00141 key k(name, true);
00142 const_iterator it = map_.find(k);
00143 if (it == end())
00144 return false;
00145 try {uripp::convert(it->second, value);}
00146 catch (const std::exception& e) {throw_bad_request(k.name_as_cstring(), e.what());}
00147 return true;
00148 }
00149 bool erase(const std::string& name);
00150
00151 std::ostream& operator <<(std::ostream& os) const;
00153 static const fld_traits* find_fld_traits(const std::string& lower_name);
00154 static const char FLD_NAME_END_CHAR;
00155 static const char EOL_CSTR[3];
00156 protected:
00157 hdr(int categories);
00158 bool insert(int fld_traits_off, const std::string& v);
00159 bool insert(const key& k, const std::string& value, bool update = false);
00160 std::string find(int fld_traits_off) const;
00161 static void throw_bad_request(const char* name, const char* what);
00162 virtual void on_inserted(const_iterator it) {}
00163 const int categories_;
00164 private:
00165 friend void RESTCGI_API copy(const env& e, request_hdr& rh, content_hdr& ch);
00166 map_type map_;
00167 static const fld_traits flds_traits_[];
00168 static const fld_traits* flds_traits_end_;
00169 };
00178 class RESTCGI_API general_hdr : public hdr, private cookies::observer {
00179 public:
00180 typedef restcgi::cookies cookies_type;
00181 std::string cache_control() const;
00182 bool cache_control(const std::string& v);
00183 std::string connection() const;
00184 bool connection(const std::string& v);
00185 bool date(date_time& v, const date_time& dflt) const;
00186 bool date(const date_time& v);
00187 std::string pragma() const;
00188 bool pragma(const std::string& v);
00189 std::string trailer() const;
00190 bool trailer(const std::string& v);
00191 std::string transfer_encoding() const;
00192 bool transfer_encoding(const std::string& v);
00193 std::string upgrade() const;
00194 bool upgrade(const std::string& v);
00195 std::string via() const;
00196 bool via(const std::string& v);
00197 std::string warning() const;
00198 bool warning(const std::string& v);
00199 cookies_type& cookies() {return cookies_;}
00200 const cookies_type& cookies() const {return cookies_;}
00201 protected:
00202 general_hdr(int categories);
00203 ~general_hdr();
00204 private:
00205 void on_inserted(const_iterator it);
00206 void on_updated_reset();
00207 void on_updated(const cookies_type& v);
00208 bool on_updated_;
00209 cookies_type cookies_;
00210 };
00213 class RESTCGI_API request_hdr : public general_hdr {
00214 public:
00215 request_hdr();
00216 std::string accept() const;
00217 std::string accept_charset() const;
00218 std::string accept_encoding() const;
00219 std::string accept_language() const;
00220 std::string authorization() const;
00221 std::string expect() const;
00222 std::string from() const;
00223 std::string host() const;
00224 std::string if_match() const;
00225 bool if_modified_since(date_time& v, const date_time& dflt) const;
00226 std::string if_none_match() const;
00227 std::string if_range() const;
00228 bool if_unmodified_since(date_time& v, const date_time& dflt) const;
00229 bool max_forwards(size_t& v, size_t dflt) const;
00230 std::string proxy_authorization() const;
00231 std::string range() const;
00232 std::string referer() const;
00233 std::string te() const;
00234 std::string user_agent() const;
00235 };
00249 class RESTCGI_API response_hdr : public general_hdr {
00250 public:
00251 response_hdr();
00252 std::string accept_ranges() const;
00253 bool accept_ranges(const std::string& v);
00254 bool age(size_t& v, size_t dflt) const;
00255 bool age(size_t v);
00256 std::string allow() const;
00257 bool allow(const std::string& v);
00258 std::string content_location() const;
00259 bool content_location(const std::string& v);
00260 std::string etag() const;
00261 bool etag(const std::string& v);
00262 bool expires(date_time& v, const date_time& dflt) const;
00263 bool expires(const date_time& v);
00264 bool last_modified(date_time& v, const date_time& dflt) const;
00265 bool last_modified(const date_time& v);
00266 std::string location() const;
00267 bool location(const std::string& v);
00268 std::string proxy_authenticate() const;
00269 bool proxy_authenticate(const std::string& v);
00270 bool retry_after(date_time& dt, size_t& secs) const;
00271 bool retry_after(const date_time& v);
00272 bool retry_after(size_t v);
00273 std::string server() const;
00274 bool server(const std::string& v);
00275 std::string vary() const;
00276 bool vary(const std::string& v);
00277 std::string www_authenticate() const;
00278 bool www_authenticate(const std::string& v);
00279 };
00287 class RESTCGI_API content_hdr : public hdr {
00288 public:
00289 content_hdr();
00290 std::string content_encoding() const;
00291 bool content_encoding(const std::string& v);
00292 std::string content_language() const;
00293 bool content_language(const std::string& v);
00294 bool content_length(size_t& v, size_t dflt) const;
00295 bool content_length(size_t v);
00296 std::string content_md5() const;
00297 bool content_md5(const std::string& v);
00298 std::string content_range() const;
00299 bool content_range(const std::string& v);
00300 std::string content_type() const;
00301 bool content_type(const std::string& v);
00302 };
00304 inline std::ostream& operator <<(std::ostream& os, const hdr& v) {return v.operator <<(os);}
00309 void RESTCGI_API copy(const env& e, request_hdr& rh, content_hdr& ch);
00312 content_hdr RESTCGI_API content_hdr_from_type(const std::string& type);
00313 }
00314 #endif