00001
00014
00016
00017 #ifndef NET_INSTAWEB_HTTP_PUBLIC_RESPONSE_HEADERS_H_
00018 #define NET_INSTAWEB_HTTP_PUBLIC_RESPONSE_HEADERS_H_
00019
00020 #include "net/instaweb/http/public/content_type.h"
00021 #include "net/instaweb/http/public/headers.h"
00022 #include "net/instaweb/http/public/meta_data.h"
00023 #include "net/instaweb/util/public/basictypes.h"
00024 #include "net/instaweb/util/public/string.h"
00025 #include "net/instaweb/util/public/string_util.h"
00026 #include "net/instaweb/util/public/timer.h"
00027
00028 namespace net_instaweb {
00029
00030 class HttpResponseHeaders;
00031 class MessageHandler;
00032 class Writer;
00033
00035 class ResponseHeaders : public Headers<HttpResponseHeaders> {
00036 public:
00040 static const int64 kImplicitCacheTtlMs = 5 * Timer::kMinuteMs;
00041
00042 ResponseHeaders();
00043 virtual ~ResponseHeaders();
00044
00049 void FixDateHeaders(int64 now_ms);
00050
00051 virtual void Clear();
00052
00053 void CopyFrom(const ResponseHeaders& other);
00054
00056 virtual void Add(const StringPiece& name, const StringPiece& value);
00057
00060 bool MergeContentType(const StringPiece& content_type);
00061
00063 virtual bool Remove(const StringPiece& name, const StringPiece& value);
00064
00066 virtual bool RemoveAll(const StringPiece& name);
00067
00069 virtual bool RemoveAllFromSet(const StringSetInsensitive& names);
00070
00073 virtual void Replace(const StringPiece& name, const StringPiece& value);
00074
00080 virtual void UpdateFrom(const Headers<HttpResponseHeaders>& other);
00081
00083 virtual bool WriteAsBinary(Writer* writer, MessageHandler* message_handler);
00084
00088 virtual bool ReadFromBinary(const StringPiece& buf, MessageHandler* handler);
00089
00091 virtual bool WriteAsHttp(Writer* writer, MessageHandler* handler) const;
00092
00097 void ComputeCaching();
00098 bool IsCacheable() const;
00099 bool IsProxyCacheable() const;
00103 int64 CacheExpirationTimeMs() const;
00104
00109 void SetDateAndCaching(int64 date_ms, int64 ttl_ms,
00110 const StringPiece& cache_control_suffix);
00111 void SetDateAndCaching(int64 date_ms, int64 ttl_ms) {
00112 SetDateAndCaching(date_ms, ttl_ms, "");
00113 }
00114
00116 void SetTimeHeader(const StringPiece& header, int64 time_ms);
00117 void SetDate(int64 date_ms) { SetTimeHeader(HttpAttributes::kDate, date_ms); }
00118 void SetLastModified(int64 last_modified_ms) {
00119 SetTimeHeader(HttpAttributes::kLastModified, last_modified_ms);
00120 }
00121
00125 void SetCacheControlMaxAge(int64 ttl_ms);
00126
00128 bool Sanitize();
00129
00131 bool headers_complete() const { return has_status_code(); }
00132
00133 int status_code() const;
00134 bool has_status_code() const;
00135 void set_status_code(const int code);
00136 const char* reason_phrase() const;
00137 void set_reason_phrase(const StringPiece& reason_phrase);
00138 int64 implicit_cache_ttl_ms() const { return implicit_cache_ttl_ms_; }
00139 void set_implicit_cache_ttl_ms(const int64 ttl) {
00140 implicit_cache_ttl_ms_ = ttl;
00141 }
00142
00143 int64 last_modified_time_ms() const;
00144 int64 date_ms() const;
00145 bool has_date_ms() const;
00146 int64 cache_ttl_ms() const;
00147 bool is_implicitly_cacheable() const;
00148
00149 GoogleString ToString() const;
00150
00152 void SetStatusAndReason(HttpStatus::Code code);
00153
00154 void DebugPrint() const;
00155
00157 static bool ParseTime(const char* time_str, int64* time_ms);
00158
00160 inline bool IsErrorStatus() {
00161 int status = status_code();
00162 return status >= 400 && status <= 599;
00163 }
00164
00166 inline bool IsServerErrorStatus() {
00167 int status = status_code();
00168 return status >= 500 && status <= 599;
00169 }
00170
00172 bool IsGzipped() const;
00173 bool WasGzippedLast() const;
00174
00177 const ContentType* DetermineContentType() const;
00178
00180 bool IsHtmlLike() const {
00181 const ContentType* type = DetermineContentType();
00182 return (type != NULL && type->IsHtmlLike());
00183 }
00184
00186 GoogleString DetermineCharset() const;
00187
00192 void DetermineContentTypeAndCharset(const ContentType** content_type_out,
00193 GoogleString* charset_out) const;
00194
00195
00199 bool ParseDateHeader(const StringPiece& attr, int64* date_ms) const;
00200
00203 bool IsDateLaterThan(int64 time_ms) const {
00204 return date_ms() > time_ms;
00205 }
00206
00208 void ParseFirstLine(const StringPiece& first_line);
00209
00211 void ParseFirstLineHelper(const StringPiece& first_line);
00212
00214 void set_first_line(int major_version, int minor_version, int status_code,
00215 const StringPiece& reason_phrase) {
00216 set_major_version(major_version);
00217 set_minor_version(minor_version);
00218 set_status_code(status_code);
00219 set_reason_phrase(reason_phrase);
00220 }
00221
00224 bool VaryCacheable() const;
00225
00228 bool FindContentLength(int64* content_length);
00229
00230 private:
00231
00237 bool CombineContentTypes(const StringPiece& orig, const StringPiece& fresh);
00238
00239 friend class ResponseHeadersTest;
00240 bool cache_fields_dirty_;
00241
00244 int64 implicit_cache_ttl_ms_;
00245
00246 DISALLOW_COPY_AND_ASSIGN(ResponseHeaders);
00247 };
00248
00249 }
00250
00251 #endif ///< NET_INSTAWEB_HTTP_PUBLIC_RESPONSE_HEADERS_H_