Permalink
Browse files

First commit

Naive port of mod_pagespeed for NGINX
  • Loading branch information...
0 parents commit 0fa9bb59f86fa2f7b37327c95d1a68a5d0800e74 Matthieu Tourne committed Jun 6, 2011
Showing with 763 additions and 0 deletions.
  1. +46 −0 README
  2. +154 −0 config
  3. +2 −0 libs/.gitignore
  4. +438 −0 ngx_http_instaweb_module.cpp
  5. +19 −0 ngx_http_instaweb_module.h
  6. +68 −0 ngx_message_handler.cpp
  7. +36 −0 ngx_message_handler.h
46 README
@@ -0,0 +1,46 @@
+ngx_instaweb module
+-------------------
+
+This module is a very experimental port of Google's mod_pagespeed for Apache
+to NGINX
+
+Right now it compiles and uses a test filter called
+AttrValuesSaverFilter, which saves all the tag attributes
+found in the html code
+
+
+INSTALLATION
+------------
+
+1. Download and Compile mod_pagespeed :
+
+http://code.google.com/p/modpagespeed/wiki/HowToBuild
+
+The config script for this module expects to find mod_pagespeed
+in $HOME and mod_pagespeed built in Release mode
+
+If this is not the case, change PAGESPEED_ROOT and PAGESPEED_BUILDMODE
+in ngx_instaweb/config
+
+
+2. Build NGINX with ngx_instaweb module
+
+ cd nginx
+ ./configure --add-module=/path/to/ngx_instaweb/ --with-debug
+
+ make && make install
+
+
+USAGE
+-----
+The only directive provided is
+instaweb <on/off>
+
+you can tail the http_debug log to see the AttrValuesSaverFilter in action.
+
+
+COPYRIGHT
+--------
+
+Copyright (c) 2010, 2011 CloudFlare, Inc. (http://www.cloudflare.com)
+Copyright (c) 2010, 2011 Matthieu Tourne <matthieu.tourne@gmail.com>
154 config
@@ -0,0 +1,154 @@
+#!/bin/sh
+#
+# Copyright (c) 2010, 2011 CloudFlare, Inc. (http://www.cloudflare.com)
+# Copyright (c) 2010, 2011 Matthieu Tourne <matthieu.tourne@gmail.com>
+#
+# @author Matthieu Tourne <matthieu@cloudflare.com>
+#
+
+ngx_addon_name=ngx_http_instaweb_module
+
+HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES ngx_http_instaweb_module"
+
+PAGESPEED_ROOT="$HOME/mod_pagespeed"
+
+PAGESPEED_BUILDMODE="Release"
+
+PAGESPEED_INCS="\
+ $PAGESPEED_ROOT/src/
+ $PAGESPEED_ROOT/src/third_party/base64 \
+ $PAGESPEED_ROOT/src/third_party/chromium/src \
+ $PAGESPEED_ROOT/src/third_party/google-sparsehash/src \
+ $PAGESPEED_ROOT/src/third_party/google-sparsehash/gen/arch/linux/x64/include \
+ $PAGESPEED_ROOT/src/third_party/libpagespeed/src \
+ $PAGESPEED_ROOT/src/third_party/protobuf/ \
+ $PAGESPEED_ROOT/src/third_party/protobuf/src/ \
+ "
+
+PAGESPEED_SRCS="\
+ $PAGESPEED_ROOT/src/net/instaweb/htmlparse \
+ $PAGESPEED_ROOT/src/third_party/chromium \
+ $PAGESPEED_ROOT/src/third_party/google-sparsehash \
+ "
+
+CFLAGS=`echo $CFLAGS | sed -e 's/-Werror//'`
+echo "CFLAGS: $CFLAGS"
+
+test_output() {
+ if [ $1 -ne "0" ]; then
+ exit 1
+ fi
+}
+
+CORE_INCS="$CORE_INCS \
+ $ngx_addon_dir/libs \
+ $PAGESPEED_INCS \
+ "
+# $ngx_addon_dir/libs \
+
+# create protoc output dirs
+
+CURDIR=`pwd`
+
+PROTOC_BIN="$PAGESPEED_ROOT/src/out/$PAGESPEED_BUILDMODE/protoc"
+
+cd $PAGESPEED_ROOT/src/net/instaweb && \
+ $PROTOC_BIN --proto_path="../.." \
+ "../../net/instaweb/http/http.proto" \
+ --cpp_out="$ngx_addon_dir/libs/"
+
+test_output $?
+
+cd $PAGESPEED_ROOT/src/net/instaweb && \
+ $PROTOC_BIN --proto_path="../.." \
+ "../../net/instaweb/rewriter/cached_result.proto" \
+ --cpp_out="$ngx_addon_dir/libs/"
+
+test_output $?
+
+cd $PAGESPEED_ROOT/src/net/instaweb && \
+ $PROTOC_BIN --proto_path="../.." \
+ "../../net/instaweb/spriter/public/image_spriter.proto" \
+ --cpp_out="$ngx_addon_dir/libs/"
+
+test_output $?
+
+cd $CURDIR
+
+NGX_ADDON_DEPS="$NGX_ADDON_DEPS \
+ $ngx_addon_dir/ngx_http_instaweb_module.h \
+ $ngx_addon_dir/ngx_message_handler.h \
+ $ngx_addon_dir/libs/net/instaweb/http/http.pb.h \
+ $ngx_addon_dir/libs/net/instaweb/rewriter/cached_result.pb.h \
+ $ngx_addon_dir/libs/net/instaweb/spriter/public/image_spriter.pb.h \
+ "
+
+NGX_ADDON_SRCS="$NGX_ADDON_SRCS \
+ $ngx_addon_dir/ngx_http_instaweb_module.cpp \
+ $ngx_addon_dir/ngx_message_handler.cpp \
+ $ngx_addon_dir/libs/net/instaweb/http/http.pb.cc \
+ $ngx_addon_dir/libs/net/instaweb/rewriter/cached_result.pb.cc
+ $ngx_addon_dir/libs/net/instaweb/spriter/public/image_spriter.pb.cc \
+ "
+
+
+CORE_LIBS="$CORE_LIBS -lstdc++ -Wl,-z,noexecstack -lrt"
+
+#for lib in `find $PAGESPEED_ROOT/src/out -iname '*.a'`; do
+# CORE_LIBS="$CORE_LIBS $lib"
+#done
+
+# mod_pagespeed/src/net/instaweb/mod_pagespeed.target.mk
+LIB_LOCATION="$PAGESPEED_ROOT/src/out/$PAGESPEED_BUILDMODE/obj.target"
+
+CORE_LIBS="$CORE_LIBS \
+ $LIB_LOCATION/net/instaweb/libapache.a \
+ $LIB_LOCATION/base/libbase.a \
+ $LIB_LOCATION/third_party/gflags/libgflags.a \
+ $LIB_LOCATION/third_party/serf/libserf.a \
+ $LIB_LOCATION/third_party/zlib/libchrome_zlib.a \
+ $LIB_LOCATION/net/instaweb/libinstaweb_htmlparse.a \
+ $LIB_LOCATION/net/instaweb/libinstaweb_htmlparse_core.a \
+ $LIB_LOCATION/net/instaweb/libinstaweb_util_core.a \
+ $LIB_LOCATION/third_party/protobuf/libprotobuf_lite.a \
+ $LIB_LOCATION/build/temp_gyp/libgoogleurl.a \
+ $LIB_LOCATION/third_party/icu/libicuuc.a \
+ $LIB_LOCATION/third_party/icu/libicudata.a \
+ $LIB_LOCATION/net/instaweb/libinstaweb_util.a \
+ $LIB_LOCATION/net/instaweb/libinstaweb_http.a \
+ $LIB_LOCATION/net/instaweb/libinstaweb_http_pb.a \
+ $LIB_LOCATION/third_party/libpagespeed/src/pagespeed/core/libpagespeed_core.a \
+ $LIB_LOCATION/third_party/libpagespeed/src/pagespeed/proto/libpagespeed_output_pb.a \
+ $LIB_LOCATION/third_party/base64/libbase64.a \
+ $LIB_LOCATION/third_party/chromium/src/net/tools/liburl_to_filename_encoder.a \
+ $LIB_LOCATION/net/instaweb/libinstaweb_rewriter.a \
+ $LIB_LOCATION/net/instaweb/libinstaweb_rewriter_base.a \
+ $LIB_LOCATION/net/instaweb/libinstaweb_rewriter_pb.a \
+ $LIB_LOCATION/net/instaweb/libinstaweb_rewriter_html.a \
+ $LIB_LOCATION/net/instaweb/libinstaweb_rewriter_css.a \
+ $LIB_LOCATION/net/instaweb/libinstaweb_spriter.a \
+ $LIB_LOCATION/net/instaweb/libinstaweb_spriter_pb.a \
+ $LIB_LOCATION/third_party/libpng/libpng.a \
+ $LIB_LOCATION/third_party/css_parser/libcss_parser.a \
+ $LIB_LOCATION/net/instaweb/libinstaweb_rewriter_image.a \
+ $LIB_LOCATION/third_party/libpagespeed/src/pagespeed/image_compression/libpagespeed_jpeg_optimizer.a \
+ $LIB_LOCATION/third_party/libpagespeed/src/pagespeed/image_compression/libpagespeed_jpeg_reader.a \
+ $LIB_LOCATION/third_party/libjpeg/libjpeg.a \
+ $LIB_LOCATION/third_party/libpagespeed/src/third_party/libjpeg_trans/libjpeg_trans.a \
+ $LIB_LOCATION/third_party/libpagespeed/src/pagespeed/image_compression/libpagespeed_png_optimizer.a \
+ $LIB_LOCATION/third_party/libpagespeed/src/third_party/giflib/libdgiflib.a \
+ $LIB_LOCATION/third_party/libpagespeed/src/third_party/giflib/libgiflib_core.a \
+ $LIB_LOCATION/third_party/libpagespeed/src/third_party/optipng/libopngreduc.a \
+ $LIB_LOCATION/third_party/opencv/libhighgui.a \
+ $LIB_LOCATION/third_party/opencv/libcv.a \
+ $LIB_LOCATION/third_party/opencv/libcxcore.a \
+ $LIB_LOCATION/third_party/opencv/libflann.a \
+ $LIB_LOCATION/third_party/opencv/liblapack.a \
+ $LIB_LOCATION/net/instaweb/libinstaweb_rewriter_javascript.a \
+ $LIB_LOCATION/third_party/libpagespeed/src/pagespeed/jsminify/libpagespeed_jsminify.a \
+ $LIB_LOCATION/net/instaweb/libinstaweb_util_pthread.a \
+ "
+
+
+echo "libs included:"
+echo $CORE_LIBS
2 libs/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
438 ngx_http_instaweb_module.cpp
@@ -0,0 +1,438 @@
+/**
+ * Copyright (c) 2010, 2011 CloudFlare, Inc. (http://www.cloudflare.com)
+ * Copyright (c) 2010, 2011 Matthieu Tourne <matthieu.tourne@gmail.com>
+ *
+ * @author Matthieu Tourne <matthieu@cloudflare.com>
+ */
+
+#include "ngx_http_instaweb_module.h"
+#include "net/instaweb/htmlparse/public/html_parse.h"
+#include "net/instaweb/htmlparse/public/empty_html_filter.h"
+#include "net/instaweb/rewriter/public/rewrite_driver.h"
+#include "net/instaweb/rewriter/public/rewrite_options.h"
+
+namespace net_instaweb {
+
+class AttrValuesSaverFilter : public EmptyHtmlFilter {
+ public:
+ AttrValuesSaverFilter() { }
+
+ virtual void StartElement(HtmlElement* element) {
+ for (int i = 0; i < element->attribute_size(); ++i) {
+ value_ += element->attribute(i).value();
+ }
+ }
+
+ const std::string& value() { return value_; }
+ virtual const char* Name() const { return "attr_saver"; }
+
+ private:
+ std::string value_;
+
+ DISALLOW_COPY_AND_ASSIGN(AttrValuesSaverFilter);
+};
+
+typedef struct {
+ ngx_flag_t enable;
+} ngx_http_instaweb_loc_conf_t;
+
+typedef struct {
+ /* IO */
+ ngx_chain_t *in;
+ ngx_chain_t *out;
+ ngx_chain_t **last_out;
+ ngx_chain_t *busy;
+ ngx_chain_t *free;
+
+ ngx_buf_t *buf;
+
+ u_char *pos;
+ u_char *copy_start;
+ u_char *copy_end;
+
+ HtmlParse *html_parser;
+ AttrValuesSaverFilter *filter;
+
+ RewriteOptions options_;
+ RewriteDriver rewrite_driver_;
+} ngx_http_instaweb_ctx_t;
+
+static ngx_int_t ngx_http_instaweb_init(ngx_conf_t *cf);
+
+static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
+static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
+
+static ngx_int_t ngx_http_instaweb_header_filter(ngx_http_request_t *r);
+static ngx_int_t ngx_http_instaweb_body_filter(ngx_http_request_t *r,
+ ngx_chain_t *in);
+
+static ngx_int_t ngx_http_instaweb_output(ngx_http_request_t *r,
+ ngx_http_instaweb_ctx_t *ctx);
+
+static void *ngx_http_instaweb_create_loc_conf(ngx_conf_t *cf);
+static char *ngx_http_instaweb_merge_loc_conf(ngx_conf_t *cf,
+ void *parent, void *child);
+
+static ngx_command_t ngx_http_instaweb_module_commands[] = {
+ { ngx_string("instaweb"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF
+ |NGX_HTTP_LIF_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_instaweb_loc_conf_t, enable),
+ NULL },
+
+ ngx_null_command
+};
+
+
+static ngx_http_module_t ngx_http_instaweb_module_ctx = {
+ NULL, /* preconfiguration */
+ ngx_http_instaweb_init, /* postconfiguration */
+
+ NULL, /* create main configuration */
+ NULL, /* init main configuration */
+
+ NULL, /* create server configuration */
+ NULL, /* merge server configuration */
+
+ ngx_http_instaweb_create_loc_conf, /* create location configuration */
+ ngx_http_instaweb_merge_loc_conf /* merge location configuration */
+};
+
+extern "C" {
+ngx_module_t ngx_http_instaweb_module = {
+ NGX_MODULE_V1,
+ &ngx_http_instaweb_module_ctx, /* module context */
+ ngx_http_instaweb_module_commands, /* module directives */
+ NGX_HTTP_MODULE, /* module type */
+ NULL, /* init master */
+ NULL, /* init module */
+ NULL, /* init process */
+ NULL, /* init thread */
+ NULL, /* exit thread */
+ NULL, /* exit process */
+ NULL, /* exit master */
+ NGX_MODULE_V1_PADDING
+};
+}
+
+static ngx_int_t
+ngx_http_instaweb_header_filter(ngx_http_request_t *r) {
+ ngx_http_instaweb_loc_conf_t *lcf;
+ ngx_http_instaweb_ctx_t *ctx;
+ HtmlParse *html_parser;
+ NgxMessageHandler *message_handler;
+ // TODO (mtourne) : review this
+ u_char full_uri[512];
+ ngx_uint_t len;
+
+ lcf = (ngx_http_instaweb_loc_conf_t *)
+ ngx_http_get_module_loc_conf(r, ngx_http_instaweb_module);
+
+ if (!lcf->enable) {
+ return ngx_http_next_header_filter(r);
+ }
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "instaweb header filter");
+
+ message_handler = new NgxMessageHandler(r->connection->log);
+ html_parser = new HtmlParse(message_handler);
+ len = ngx_snprintf(full_uri, 512, "%s://%V/%V", (r->connection->ssl) ? "https" : "http",
+ &r->headers_in.server, &r->unparsed_uri) - full_uri;
+ if (!html_parser->StartParse(StringPiece((const char*) full_uri,
+ len))) {
+ return ngx_http_next_header_filter(r);
+ }
+
+ ctx = (ngx_http_instaweb_ctx_t*) ngx_pcalloc(
+ r->pool, sizeof(ngx_http_instaweb_ctx_t));
+ if (ctx == NULL) {
+ return NGX_ERROR;
+ }
+ ctx->last_out = &ctx->out;
+ ctx->html_parser = html_parser;
+
+ ctx->filter = new AttrValuesSaverFilter();
+ ctx->html_parser->AddFilter(ctx->filter);
+
+ ngx_http_set_ctx(r, ctx, ngx_http_instaweb_module);
+
+ /* loads the content of the response in : in->buf */
+ r->filter_need_in_memory = 1;
+
+ /* clear content length */
+ if (r == r->main) {
+ ngx_http_clear_content_length(r);
+ ngx_http_clear_last_modified(r);
+ }
+
+ return ngx_http_next_header_filter(r);
+}
+
+static ngx_int_t
+ngx_http_instaweb_body_filter(ngx_http_request_t *r, ngx_chain_t *in) {
+ //ngx_int_t rc;
+ ngx_buf_t *b;
+ ngx_chain_t *cl = NULL;
+ ngx_http_instaweb_ctx_t *ctx;
+
+
+ ctx = (ngx_http_instaweb_ctx_t*) ngx_http_get_module_ctx(
+ r, ngx_http_instaweb_module);
+
+ if (ctx == NULL) {
+ return ngx_http_next_body_filter(r, in);
+ }
+
+ if ((in == NULL
+ && ctx->buf == NULL
+ && ctx->in == NULL
+ && ctx->busy == NULL))
+ {
+ return ngx_http_next_body_filter(r, in);
+ }
+
+ /* add the incoming chain to the chain ctx->in */
+
+ if (in) {
+ if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
+ return NGX_ERROR;
+ }
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http instaweb filter \"%V\"", &r->uri);
+
+ while (ctx->in || ctx->buf) {
+
+ if (ctx->buf == NULL ){
+ ctx->buf = ctx->in->buf;
+ ctx->in = ctx->in->next;
+ ctx->pos = ctx->buf->pos;
+ }
+
+ // TODO (mtourne): only if start state
+ ctx->copy_start = ctx->pos;
+ ctx->copy_end = ctx->pos;
+
+ b = NULL;
+
+ while (ctx->pos < ctx->buf->last) {
+ // do stuff
+ ctx->html_parser->ParseText((const char*) ctx->pos,
+ ctx->buf->last - ctx->pos);
+ // TODO (mtourne): loop probably useless
+ ctx->copy_end = ctx->pos = ctx->buf->last;
+ }
+
+ if (ctx->copy_start != ctx->copy_end) {
+
+ if (ctx->free) {
+ cl = ctx->free;
+ ctx->free = ctx->free->next;
+ b = cl->buf;
+
+ } else {
+ b = (ngx_buf_t*) ngx_alloc_buf(r->pool);
+ if (b == NULL) {
+ return NGX_ERROR;
+ }
+
+ cl = ngx_alloc_chain_link(r->pool);
+ if (cl == NULL) {
+ return NGX_ERROR;
+ }
+
+ cl->buf = b;
+ }
+
+ ngx_memcpy(b, ctx->buf, sizeof(ngx_buf_t));
+
+ b->pos = ctx->copy_start;
+ b->last = ctx->copy_end;
+ b->shadow = NULL;
+ b->last_buf = 0;
+ b->recycled = 0;
+
+ if (b->in_file) {
+ b->file_last = b->file_pos + (b->last - ctx->buf->pos);
+ b->file_pos += b->pos - ctx->buf->pos;
+ }
+
+ cl->next = NULL;
+ *ctx->last_out = cl;
+ ctx->last_out = &cl->next;
+ }
+
+ ctx->html_parser->Flush();
+ std::string val = ctx->filter->value();
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "instaweb attributes: \"%s\"",
+ val.c_str());
+
+ if (ctx->buf->last_buf || ngx_buf_in_memory(ctx->buf)) {
+ if (b == NULL) {
+ if (ctx->free) {
+ cl = ctx->free;
+ ctx->free = ctx->free->next;
+ b = cl->buf;
+ ngx_memzero(b, sizeof(ngx_buf_t));
+
+ } else {
+ b = (ngx_buf_t*) ngx_calloc_buf(r->pool);
+ if (b == NULL) {
+ return NGX_ERROR;
+ }
+
+ cl = ngx_alloc_chain_link(r->pool);
+ if (cl == NULL) {
+ return NGX_ERROR;
+ }
+
+ cl->buf = b;
+ }
+
+ b->sync = 1;
+
+ cl->next = NULL;
+ *ctx->last_out = cl;
+ ctx->last_out = &cl->next;
+ }
+
+ b->last_buf = ctx->buf->last_buf;
+ b->shadow = ctx->buf;
+
+ b->recycled = ctx->buf->recycled;
+ }
+
+ if (ctx->buf->last_buf) {
+ ctx->html_parser->FinishParse();
+ }
+
+ ctx->buf = NULL;
+ }
+
+ if (ctx->out == NULL && ctx->busy == NULL) {
+ return NGX_OK;
+ }
+
+ return ngx_http_instaweb_output(r, ctx);
+}
+
+static ngx_int_t
+ngx_http_instaweb_output(ngx_http_request_t *r, ngx_http_instaweb_ctx_t *ctx)
+{
+ ngx_int_t rc;
+ ngx_buf_t *b;
+ ngx_chain_t *cl;
+
+#if 1
+ b = NULL;
+ for (cl = ctx->out; cl; cl = cl->next) {
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "instaweb out: %p %p", cl->buf, cl->buf->pos);
+ if (cl->buf == b) {
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ "the same buf was used in instaweb");
+ ngx_debug_point();
+ return NGX_ERROR;
+ }
+ b = cl->buf;
+ }
+#endif
+
+ rc = ngx_http_next_body_filter(r, ctx->out);
+
+ if (ctx->busy == NULL) {
+ ctx->busy = ctx->out;
+
+ } else {
+ for (cl = ctx->busy; cl->next; cl = cl->next) { /* void */ }
+ cl->next = ctx->out;
+ }
+
+ ctx->out = NULL;
+ ctx->last_out = &ctx->out;
+
+ while (ctx->busy) {
+
+ cl = ctx->busy;
+ b = cl->buf;
+
+ if (ngx_buf_size(b) != 0) {
+ break;
+ }
+
+ if (b->shadow) {
+ b->shadow->pos = b->shadow->last;
+ }
+
+ ctx->busy = cl->next;
+
+ if (ngx_buf_in_memory(b) || b->in_file) {
+ /* add data bufs only to the free buf chain */
+
+ cl->next = ctx->free;
+ ctx->free = cl;
+ }
+ }
+
+ if (ctx->in || ctx->buf) {
+ r->buffered |= NGX_HTTP_SUB_BUFFERED;
+
+ } else {
+ r->buffered &= ~NGX_HTTP_SUB_BUFFERED;
+ }
+
+ return rc;
+}
+
+static void*
+ngx_http_instaweb_create_loc_conf(ngx_conf_t *cf) {
+ ngx_http_instaweb_loc_conf_t *conf;
+
+ conf = (ngx_http_instaweb_loc_conf_t *)
+ ngx_pcalloc(cf->pool, sizeof(ngx_http_instaweb_loc_conf_t));
+ if (conf == NULL) {
+ return NULL;
+ }
+
+ /*
+ * set by ngx_pcalloc():
+ *
+ */
+
+ conf->enable = NGX_CONF_UNSET;
+
+ return conf;
+}
+
+static char*
+ngx_http_instaweb_merge_loc_conf(ngx_conf_t *cf,
+ void *parent, void *child) {
+ ngx_http_instaweb_loc_conf_t *prev =
+ (ngx_http_instaweb_loc_conf_t *) parent;
+
+ ngx_http_instaweb_loc_conf_t *conf =
+ (ngx_http_instaweb_loc_conf_t *) child;
+
+ ngx_conf_merge_value(conf->enable, prev->enable, 0);
+
+ return NGX_CONF_OK;
+}
+
+static ngx_int_t
+ngx_http_instaweb_init(ngx_conf_t *cf) {
+
+ ngx_http_next_header_filter = ngx_http_top_header_filter;
+ ngx_http_top_header_filter = ngx_http_instaweb_header_filter;
+
+ ngx_http_next_body_filter = ngx_http_top_body_filter;
+ ngx_http_top_body_filter = ngx_http_instaweb_body_filter;
+
+ return NGX_OK;
+}
+
+} // !namespace net_instaweb
19 ngx_http_instaweb_module.h
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2010, 2011 CloudFlare, Inc. (http://www.cloudflare.com)
+ * Copyright (c) 2010, 2011 Matthieu Tourne <matthieu.tourne@gmail.com>
+ *
+ * @author Matthieu Tourne <matthieu@cloudflare.com>
+ */
+
+#ifndef NGX_HTTP_INSTAWEB_MODULE_H_
+#define NGX_HTTP_INSTAWEB_MODULE_H_
+
+extern "C" {
+ #include <ngx_config.h>
+ #include <ngx_core.h>
+ #include <ngx_http.h>
+}
+
+#include "ngx_message_handler.h"
+
+#endif /* !NGX_HTTP_INSTAWEB_MODULE_H_ */
68 ngx_message_handler.cpp
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 2010, 2011 CloudFlare, Inc. (http://www.cloudflare.com)
+ * Copyright (c) 2010, 2011 Matthieu Tourne <matthieu.tourne@gmail.com>
+ *
+ * @author Matthieu Tourne <matthieu@cloudflare.com>
+ */
+
+#include "ngx_message_handler.h"
+
+namespace {
+
+const char kModuleName[] = "instaweb";
+
+}
+
+namespace net_instaweb {
+
+NgxMessageHandler::NgxMessageHandler(ngx_log_t *log)
+ : log_(log) {
+ // empty
+}
+
+ngx_uint_t
+NgxMessageHandler::GetNgxLogLevel(MessageType type) {
+ switch (type) {
+ case kInfo:
+ return NGX_LOG_INFO;
+ case kWarning:
+ return NGX_LOG_WARN;
+ case kError:
+ return NGX_LOG_ERR;
+ case kFatal:
+ return NGX_LOG_CRIT;
+ }
+}
+
+void
+NgxMessageHandler::MessageVImpl(MessageType type, const char* msg, va_list args) {
+ ngx_uint_t log_level = GetNgxLogLevel(type);
+ std::string formatted_message = Format(msg, args);
+
+ ngx_log_error(log_level, log_, 0, "[%s] %s",
+ kModuleName, formatted_message.c_str());
+}
+
+void
+NgxMessageHandler::FileMessageVImpl(MessageType type, const char* filename,
+ int line, const char* msg, va_list args) {
+
+ ngx_uint_t log_level = GetNgxLogLevel(type);
+ std::string formatted_message = Format(msg, args);
+
+ ngx_log_error(log_level, log_, 0, "[%s] %s:%d: %s",
+ kModuleName, filename, line,
+ formatted_message.c_str());
+}
+
+// copied from apache_message_handler.cc :
+std::string NgxMessageHandler::Format(const char* msg, va_list args) {
+ std::string buffer;
+
+ // Ignore the name of this routine: it formats with vsnprintf.
+ // See base/stringprintf.cc.
+ StringAppendV(&buffer, msg, args);
+ return buffer;
+}
+
+}
36 ngx_message_handler.h
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2010, 2011 CloudFlare, Inc. (http://www.cloudflare.com)
+ * Copyright (c) 2010, 2011 Matthieu Tourne <matthieu.tourne@gmail.com>
+ *
+ * @author Matthieu Tourne <matthieu@cloudflare.com>
+ */
+
+#ifndef NGX_MESSAGE_HANDLER_H_
+#define NGX_MESSAGE_HANDLER_H_
+
+#include <string>
+#include "ngx_http_instaweb_module.h"
+#include "net/instaweb/util/public/message_handler.h"
+#include "base/string_util.h"
+
+namespace net_instaweb {
+
+class NgxMessageHandler : public MessageHandler {
+ public:
+ NgxMessageHandler(ngx_log_t *log);
+
+ protected:
+ virtual void MessageVImpl(MessageType type, const char* msg, va_list args);
+
+ virtual void FileMessageVImpl(MessageType type, const char* filename,
+ int line, const char* msg, va_list args);
+ private:
+ ngx_uint_t GetNgxLogLevel(MessageType type);
+ std::string Format(const char* msg, va_list args);
+
+ ngx_log_t *log_;
+};
+
+}
+
+#endif // !NGX_MESSAGE_HANDLER_H_

0 comments on commit 0fa9bb5

Please sign in to comment.