blob: 5348bc05617c4ab27afd814a7600cc1adacf71e7 [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)
#ifndef NET_INSTAWEB_REWRITER_PUBLIC_REWRITE_FILTER_H_
#define NET_INSTAWEB_REWRITER_PUBLIC_REWRITE_FILTER_H_
#include "base/basictypes.h"
#include "net/instaweb/rewriter/public/common_filter.h"
#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/util/public/base64_util.h"
#include "net/instaweb/util/public/proto_util.h"
#include "net/instaweb/util/public/string_util.h"
#include "net/instaweb/util/public/url_async_fetcher.h"
namespace net_instaweb {
class OutputResource;
class UrlAsyncFetcher;
class Writer;
class RewriteFilter : public CommonFilter {
public:
explicit RewriteFilter(RewriteDriver* driver, StringPiece filter_prefix)
: CommonFilter(driver->html_parse()),
filter_prefix_(filter_prefix.data(), filter_prefix.size()),
driver_(driver) {
}
virtual ~RewriteFilter();
// Fetches a resource written using the filter. Filters that
// encode all the data (URLs, meta-data) needed to reconstruct
// a rewritten resource in a URL component, this method is the
// mechanism for the filter to serve the rewritten resource.
//
// The flow is that a RewriteFilter is instantiated with
// a path prefix, e.g. a two letter abbreviation of the
// filter, like "ce" for CacheExtender. When it rewrites a
// resource, it replaces the href with a url constructed as
// HOST://PREFIX/ce/WEB64_ENCODED_PROTOBUF
// The WEB64_ENCODED_PROTOBUF can then be decoded. for
// CacheExtender, the protobuf contains the content hash plus
// the original URL. For "ir" (ImgRewriterFilter) the protobuf
// might include the original image URL, plus the pixel-dimensions
// to which the image was resized.
virtual bool Fetch(OutputResource* output_resource,
Writer* writer,
const MetaData& request_header,
MetaData* response_headers,
UrlAsyncFetcher* fetcher,
MessageHandler* message_handler,
UrlAsyncFetcher::Callback* callback) = 0;
// Encodes an arbitrary protobuf to a web-safe string, gzipping it first.
// The protobuf type used is specific to the filter. E.g. CssCombineFilter
// needs a protobuf that can store an variable size array of css files.
template<class Protobuf>
static void Encode(const Protobuf& protobuf, std::string* url_safe_id) {
std::string serialized_url;
// Add extra scope to ensure that StringOutputStream is destructed
// prior to using the string it has encoded. See comment in declaration
// of StringOutputStream in protobuf/io/zero_copy_stream_impl_lite.h,
// which says:
// The string remains property of the caller, but it MUST NOT be
// accessed in any way until the stream is destroyed.
{
StringOutputStream sstream(&serialized_url);
GzipOutputStream::Options options;
options.format = GzipOutputStream::ZLIB;
GzipOutputStream zostream(&sstream, options);
options.compression_level = 9;
protobuf.SerializeToZeroCopyStream(&zostream);
zostream.Flush();
}
Web64Encode(serialized_url, url_safe_id);
}
// Decodes an arbitrary web64-encoded & compressed protobuf.
template<class Protobuf>
static bool Decode(StringPiece url_safe_id, Protobuf* protobuf) {
bool ret = false;
std::string decoded_resource;
if (Web64Decode(url_safe_id, &decoded_resource)) {
ArrayInputStream input(decoded_resource.data(), decoded_resource.size());
GzipInputStream zistream(&input, GzipInputStream::ZLIB);
ret = protobuf->ParseFromZeroCopyStream(&zistream);
}
return ret;
}
const std::string& id() const { return filter_prefix_; }
HtmlParse* html_parse() { return driver_->html_parse(); }
ResourceManager* resource_manager() { return driver_->resource_manager(); }
protected:
std::string filter_prefix_; // Prefix that should be used in front of all
// rewritten URLs
RewriteDriver* driver_;
private:
DISALLOW_COPY_AND_ASSIGN(RewriteFilter);
};
} // namespace net_instaweb
#endif // NET_INSTAWEB_REWRITER_PUBLIC_REWRITE_FILTER_H_