blob: 08aa19afa350da24e55684f749fd237370af12bb [file] [log] [blame]
/**
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Author: jmarantz@google.com (Joshua Marantz)
#include "net/instaweb/util/public/meta_data.h"
#include <stdio.h>
#include "net/instaweb/util/public/time_util.h"
#include "pagespeed/core/resource_util.h"
namespace net_instaweb {
const char HttpAttributes::kAcceptEncoding[] = "Accept-Encoding";
const char HttpAttributes::kCacheControl[] = "Cache-Control";
const char HttpAttributes::kContentEncoding[] = "Content-Encoding";
const char HttpAttributes::kContentLength[] = "Content-Length";
const char HttpAttributes::kContentType[] = "Content-Type";
const char HttpAttributes::kDate[] = "Date";
const char HttpAttributes::kDeflate[] = "deflate";
const char HttpAttributes::kEtag[] = "Etag";
const char HttpAttributes::kExpires[] = "Expires";
const char HttpAttributes::kGzip[] = "gzip";
const char HttpAttributes::kLastModified[] = "Last-Modified";
const char HttpAttributes::kLocation[] = "Location";
const char HttpAttributes::kServer[] = "Server";
const char HttpAttributes::kSetCookie[] = "Set-Cookie";
const char HttpAttributes::kTransferEncoding[] = "Transfer-Encoding";
const char HttpAttributes::kUserAgent[] = "User-Agent";
MetaData::~MetaData() {
}
void MetaData::CopyFrom(const MetaData& other) {
set_major_version(other.major_version());
set_minor_version(other.minor_version());
set_status_code(other.status_code());
set_reason_phrase(other.reason_phrase());
set_headers_complete(other.headers_complete());
for (int i = 0; i < other.NumAttributes(); ++i) {
Add(other.Name(i), other.Value(i));
}
ComputeCaching();
}
const char* HttpStatus::GetReasonPhrase(HttpStatus::Code rc) {
switch (rc) {
case HttpStatus::kContinue : return "Continue";
case HttpStatus::kSwitchingProtocols : return "Switching Protocols";
case HttpStatus::kOK : return "OK";
case HttpStatus::kCreated : return "Created";
case HttpStatus::kAccepted : return "Accepted";
case HttpStatus::kNonAuthoritative :
return "Non-Authoritative Information";
case HttpStatus::kNoContent : return "No Content";
case HttpStatus::kResetContent : return "Reset Content";
case HttpStatus::kPartialContent : return "Partial Content";
// 300 range: redirects
case HttpStatus::kMultipleChoices : return "Multiple Choices";
case HttpStatus::kMovedPermanently : return "Moved Permanently";
case HttpStatus::kFound : return "Found";
case HttpStatus::kSeeOther : return "Not Modified";
case HttpStatus::kUseProxy : return "Use Proxy";
case HttpStatus::kTemporaryRedirect : return "OK";
// 400 range: client errors
case HttpStatus::kBadRequest : return "Bad Request";
case HttpStatus::kUnauthorized : return "Unauthorized";
case HttpStatus::kPaymentRequired : return "Payment Required";
case HttpStatus::kForbidden : return "Forbidden";
case HttpStatus::kNotFound : return "Not Found";
case HttpStatus::kMethodNotAllowed : return "Method Not Allowed";
case HttpStatus::kNotAcceptable : return "Not Acceptable";
case HttpStatus::kProxyAuthRequired :
return "Proxy Authentication Required";
case HttpStatus::kRequestTimeout : return "Request Time-out";
case HttpStatus::kConflict : return "Conflict";
case HttpStatus::kGone : return "Gone";
case HttpStatus::kLengthRequired : return "Length Required";
case HttpStatus::kPreconditionFailed : return "Precondition Failed";
case HttpStatus::kEntityTooLarge :
return "Request Entity Too Large";
case HttpStatus::kUriTooLong : return "Request-URI Too Large";
case HttpStatus::kUnsupportedMediaType : return "Unsupported Media Type";
case HttpStatus::kRangeNotSatisfiable :
return "Requested range not satisfiable";
case HttpStatus::kExpectationFailed : return "Expectation Failed";
// 500 range: server errors
case HttpStatus::kInternalServerError : return "Internal Server Error";
case HttpStatus::kNotImplemented : return "Not Implemented";
case HttpStatus::kBadGateway : return "Bad Gateway";
case HttpStatus::kUnavailable : return "Service Unavailable";
case HttpStatus::kGatewayTimeout : return "Gateway Time-out";
default:
// We don't have a name for this response code, so we'll just
// take the blame
return "Internal Server Error";
}
return "";
}
void MetaData::SetStatusAndReason(HttpStatus::Code code) {
set_status_code(code);
set_reason_phrase(HttpStatus::GetReasonPhrase(code));
}
bool MetaData::ParseTime(const char* time_str, int64* time_ms) {
return pagespeed::resource_util::ParseTimeValuedHeader(time_str, time_ms);
}
bool MetaData::IsGzipped() const {
CHECK(headers_complete());
CharStarVector v;
return (Lookup(HttpAttributes::kContentEncoding, &v) && (v.size() == 1) &&
(strcmp(v[0], HttpAttributes::kGzip) == 0));
}
bool MetaData::AcceptsGzip() const {
CharStarVector v;
if (Lookup(HttpAttributes::kAcceptEncoding, &v)) {
for (int i = 0, nv = v.size(); i < nv; ++i) {
std::vector<StringPiece> encodings;
SplitStringPieceToVector(v[i], ",", &encodings, true);
for (int j = 0, nencodings = encodings.size(); j < nencodings; ++j) {
if (strcasecmp(encodings[j].as_string().c_str(),
HttpAttributes::kGzip) == 0) {
return true;
}
}
}
}
return false;
}
bool MetaData::ParseDateHeader(const char* attr, int64* date_ms) const {
CharStarVector values;
return (Lookup(attr, &values) &&
(values.size() == 1) &&
ConvertStringToTime(values[0], date_ms));
}
void MetaData::UpdateDateHeader(const char* attr, int64 date_ms) {
RemoveAll(attr);
std::string buf;
ConvertTimeToString(date_ms, &buf);
Add(attr, buf.c_str());
}
void MetaData::DebugPrint() const {
fprintf(stderr, "%s\n", ToString().c_str());
}
} // namespace net_instaweb