From 58556d445148f40d65dbfee9f87ddae009d08cae Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Wed, 24 Apr 2013 14:07:26 +0200 Subject: [PATCH] New filter http_rewrite1 Which serves as purpose on how to rewrite HTTP content with Metaproxy. --- etc/config4.xml | 3 + src/Makefile.am | 1 + src/factory_static.cpp | 2 + src/filter_http_rewrite1.cpp | 183 +++++++++++++++++++++++++++++++++++ src/filter_http_rewrite1.hpp | 55 +++++++++++ xml/schema/filter_http_rewrite1.rnc | 15 +++ xml/schema/metaproxy.rnc | 2 + 7 files changed, 261 insertions(+) create mode 100644 src/filter_http_rewrite1.cpp create mode 100644 src/filter_http_rewrite1.hpp create mode 100644 xml/schema/filter_http_rewrite1.rnc diff --git a/etc/config4.xml b/etc/config4.xml index 15cd2eb..26124e5 100644 --- a/etc/config4.xml +++ b/etc/config4.xml @@ -18,6 +18,9 @@ /etc + + + localhost:9999 diff --git a/src/Makefile.am b/src/Makefile.am index 04e2f81..2fd7878 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,6 +30,7 @@ libmetaproxy_la_SOURCES = \ filter_frontend_net.cpp filter_frontend_net.hpp \ filter_http_client.cpp filter_http_client.hpp \ filter_http_file.cpp filter_http_file.hpp \ + filter_http_rewrite1.cpp filter_http_rewrite1.hpp \ filter_limit.cpp filter_limit.hpp \ filter_load_balance.cpp filter_load_balance.hpp \ filter_log.cpp filter_log.hpp \ diff --git a/src/factory_static.cpp b/src/factory_static.cpp index 3942637..57636d6 100644 --- a/src/factory_static.cpp +++ b/src/factory_static.cpp @@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "filter_frontend_net.hpp" #include "filter_http_client.hpp" #include "filter_http_file.hpp" +#include "filter_http_rewrite1.hpp" #include "filter_limit.hpp" #include "filter_load_balance.hpp" #include "filter_log.hpp" @@ -67,6 +68,7 @@ mp::FactoryStatic::FactoryStatic() &metaproxy_1_filter_frontend_net, &metaproxy_1_filter_http_client, &metaproxy_1_filter_http_file, + &metaproxy_1_filter_http_rewrite1, &metaproxy_1_filter_limit, &metaproxy_1_filter_load_balance, &metaproxy_1_filter_log, diff --git a/src/filter_http_rewrite1.cpp b/src/filter_http_rewrite1.cpp new file mode 100644 index 0000000..8192c1f --- /dev/null +++ b/src/filter_http_rewrite1.cpp @@ -0,0 +1,183 @@ +/* This file is part of Metaproxy. + Copyright (C) 2005-2013 Index Data + +Metaproxy is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "config.hpp" +#include +#include +#include +#include "filter_http_rewrite1.hpp" + +#include +#include + +#include +#include + +#include +#include + +#if HAVE_SYS_TYPES_H +#include +#endif + +namespace mp = metaproxy_1; +namespace yf = mp::filter; + +namespace metaproxy_1 { + namespace filter { + class HttpRewrite1::Rule { + public: + std::string content_type; + std::string pattern; + std::string replacement; + std::string mode; + }; + class HttpRewrite1::Rep { + friend class HttpRewrite1; + void rewrite_response(mp::odr &o, Z_HTTP_Response *hres); + std::list rules; + }; + } +} + +yf::HttpRewrite1::HttpRewrite1() : m_p(new Rep) +{ +} + +yf::HttpRewrite1::~HttpRewrite1() +{ +} + +void yf::HttpRewrite1::Rep::rewrite_response(mp::odr &o, Z_HTTP_Response *hres) +{ + const char *ctype = z_HTTP_header_lookup(hres->headers, "Content-Type"); + if (ctype && hres->content_buf) + { + std::string text(hres->content_buf, hres->content_len); + std::list::const_iterator it; + int number_of_replaces = 0; + for (it = rules.begin(); it != rules.end(); it++) + { + if (strcmp(ctype, it->content_type.c_str()) == 0) + { + boost::regex::flag_type b_mode = boost::regex::perl; + if (it->mode.find_first_of('i') != std::string::npos) + b_mode |= boost::regex::icase; + boost::regex e(it->pattern, b_mode); + boost::match_flag_type match_mode = boost::format_first_only; + if (it->mode.find_first_of('g') != std::string::npos) + match_mode = boost::format_all; + text = regex_replace(text, e, it->replacement, match_mode); + number_of_replaces++; + } + } + if (number_of_replaces > 0) + { + hres->content_buf = odr_strdup(o, text.c_str()); + hres->content_len = strlen(hres->content_buf); + } + } +} + +void yf::HttpRewrite1::process(mp::Package &package) const +{ + Z_GDU *gdu_req = package.request().get(); + if (gdu_req && gdu_req->which == Z_GDU_HTTP_Request) + { + Z_HTTP_Request *hreq = gdu_req->u.HTTP_Request; + + assert(hreq); // not changing request (such as POST content) + package.move(); + + Z_GDU *gdu_res = package.response().get(); + Z_HTTP_Response *hres = gdu_res->u.HTTP_Response; + if (hres) + { + mp::odr o; + m_p->rewrite_response(o, hres); + package.response() = gdu_res; + } + } + else + package.move(); +} + +void mp::filter::HttpRewrite1::configure(const xmlNode * ptr, bool test_only, + const char *path) +{ + for (ptr = ptr->children; ptr; ptr = ptr->next) + { + if (ptr->type != XML_ELEMENT_NODE) + continue; + else if (!strcmp((const char *) ptr->name, "replace")) + { + HttpRewrite1::Rule rule; + + const struct _xmlAttr *attr; + for (attr = ptr->properties; attr; attr = attr->next) + { + if (!strcmp((const char *) attr->name, "pattern")) + rule.pattern = mp::xml::get_text(attr->children); + else if (!strcmp((const char *) attr->name, "replacement")) + rule.replacement = mp::xml::get_text(attr->children); + else if (!strcmp((const char *) attr->name, "mode")) + rule.mode = mp::xml::get_text(attr->children); + else if (!strcmp((const char *) attr->name, "content-type")) + rule.content_type = mp::xml::get_text(attr->children); + else + throw mp::filter::FilterException + ("Bad attribute " + + std::string((const char *) attr->name) + + " in replace section of http_rewrite1"); + } + if (rule.pattern.length() > 0) + m_p->rules.push_back(rule); + } + else + { + throw mp::filter::FilterException + ("Bad element " + + std::string((const char *) ptr->name) + + " in http_rewrite1 filter"); + } + } +} + +static mp::filter::Base* filter_creator() +{ + return new mp::filter::HttpRewrite1; +} + +extern "C" { + struct metaproxy_1_filter_struct metaproxy_1_filter_http_rewrite1 = { + 0, + "http_rewrite1", + filter_creator + }; +} + + +/* + * Local variables: + * c-basic-offset: 4 + * c-file-style: "Stroustrup" + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ + diff --git a/src/filter_http_rewrite1.hpp b/src/filter_http_rewrite1.hpp new file mode 100644 index 0000000..ee80f42 --- /dev/null +++ b/src/filter_http_rewrite1.hpp @@ -0,0 +1,55 @@ +/* This file is part of Metaproxy. + Copyright (C) 2005-2013 Index Data + +Metaproxy is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef FILTER_HTTP_REWRITE1_HPP +#define FILTER_HTTP_REWRITE1_HPP + +#include + +#include + +namespace metaproxy_1 { + namespace filter { + class HttpRewrite1 : public Base { + class Rep; + class Rule; + boost::scoped_ptr m_p; + public: + HttpRewrite1(); + ~HttpRewrite1(); + void process(metaproxy_1::Package & package) const; + void configure(const xmlNode * ptr, bool test_only, + const char *path); + }; + } +} + +extern "C" { + extern struct metaproxy_1_filter_struct metaproxy_1_filter_http_rewrite1; +} + +#endif +/* + * Local variables: + * c-basic-offset: 4 + * c-file-style: "Stroustrup" + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ + diff --git a/xml/schema/filter_http_rewrite1.rnc b/xml/schema/filter_http_rewrite1.rnc new file mode 100644 index 0000000..d729f95 --- /dev/null +++ b/xml/schema/filter_http_rewrite1.rnc @@ -0,0 +1,15 @@ +# Metaproxy XML config file schema + +namespace mp = "http://indexdata.com/metaproxy" + +filter_http_rewrite1 = + attribute type { "http_rewrite1" }, + attribute id { xsd:NCName }?, + attribute name { xsd:NCName }?, + element mp:replace { + attribute pattern { xsd:string }, + attribute replacement { xsd:string }?, + attribute mode { xsd:string }?, + attribute content-type { xsd:string }? + }* + diff --git a/xml/schema/metaproxy.rnc b/xml/schema/metaproxy.rnc index 39a02bd..8063d89 100644 --- a/xml/schema/metaproxy.rnc +++ b/xml/schema/metaproxy.rnc @@ -30,6 +30,7 @@ include "filter_cql_rpn.rnc" include "filter_frontend_net.rnc" include "filter_http_client.rnc" include "filter_http_file.rnc" +include "filter_http_rewrite1.rnc" include "filter_limit.rnc" include "filter_load_balance.rnc" include "filter_log.rnc" @@ -79,6 +80,7 @@ filter = | filter_frontend_net | filter_http_client | filter_http_file + | filter_http_rewrite1 | filter_limit | filter_load_balance | filter_log -- 1.7.10.4