X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Ffilter_http_rewrite.cpp;h=d417f46cead1f552277b757294e2315554dac812;hb=1751c7afd96e1984f5710284cdcb245a93d9ce6c;hp=492d97a310b5d117a4810277f6fdf7d362b0346d;hpb=bec25ede71e21b5905c696590da2dad757941411;p=metaproxy-moved-to-github.git diff --git a/src/filter_http_rewrite.cpp b/src/filter_http_rewrite.cpp index 492d97a..d417f46 100644 --- a/src/filter_http_rewrite.cpp +++ b/src/filter_http_rewrite.cpp @@ -40,15 +40,13 @@ namespace metaproxy_1 { namespace filter { class HttpRewrite::Replace { public: - std::string regex; + boost::regex re; + boost::smatch what; std::string recipe; std::map group_index; - const std::string search_replace( - std::map & vars, - const std::string & txt) const; std::string sub_vars( const std::map & vars) const; - void parse_groups(); + void parse_groups(std::string pattern); }; class HttpRewrite::Rule { @@ -56,7 +54,7 @@ namespace metaproxy_1 { std::list replace_list; const std::string test_patterns( std::map & vars, - const std::string & txt) const; + const std::string & txt); }; class HttpRewrite::Within { public: @@ -85,7 +83,8 @@ namespace metaproxy_1 { void anyTagEnd(const char *tag, int tag_len, int close_it); void attribute(const char *tag, int tag_len, const char *attr, int attr_len, - const char *value, int val_len); + const char *value, int val_len, + const char *sep); void closeTag(const char *tag, int tag_len); void text(const char *value, int len); const Phase *m_phase; @@ -157,8 +156,12 @@ void yf::HttpRewrite::Phase::rewrite_reqline (mp::odr & o, else { //TODO what about proto + const char *host = z_HTTP_header_lookup(hreq->headers, "Host"); + if (!host) + return; + path += "http://"; - path += z_HTTP_header_lookup(hreq->headers, "Host"); + path += host; path += hreq->path; } @@ -304,7 +307,8 @@ void yf::HttpRewrite::Event::anyTagEnd(const char *tag, int tag_len, void yf::HttpRewrite::Event::attribute(const char *tag, int tag_len, const char *attr, int attr_len, - const char *value, int val_len) + const char *value, int val_len, + const char *sep) { std::list::const_iterator it = m_phase->within_list.begin(); bool subst = false; @@ -332,19 +336,23 @@ void yf::HttpRewrite::Event::attribute(const char *tag, int tag_len, wrbuf_putc(m_w, ' '); wrbuf_write(m_w, attr, attr_len); - wrbuf_puts(m_w, "=\""); - - std::string output; - if (subst) + if (value) { - std::string input(value, val_len); - output = it->rule->test_patterns(m_vars, input); + wrbuf_puts(m_w, "="); + wrbuf_puts(m_w, sep); + + std::string output; + if (subst) + { + std::string input(value, val_len); + output = it->rule->test_patterns(m_vars, input); + } + if (output.empty()) + wrbuf_write(m_w, value, val_len); + else + wrbuf_puts(m_w, output.c_str()); + wrbuf_puts(m_w, sep); } - if (output.empty()) - wrbuf_write(m_w, value, val_len); - else - wrbuf_puts(m_w, output.c_str()); - wrbuf_puts(m_w, "\""); } void yf::HttpRewrite::Event::closeTag(const char *tag, int tag_len) @@ -377,70 +385,65 @@ void yf::HttpRewrite::Event::text(const char *value, int len) wrbuf_puts(m_w, output.c_str()); } - -/** - * Tests pattern from the vector in order and executes recipe on - the first match. - */ const std::string yf::HttpRewrite::Rule::test_patterns( std::map & vars, - const std::string & txt) const + const std::string & txt) { - std::list::const_iterator it = replace_list.begin(); - - for (; it != replace_list.end(); it++) - { - std::string out = it->search_replace(vars, txt); - if (!out.empty()) return out; - } - return ""; -} - -const std::string yf::HttpRewrite::Replace::search_replace( - std::map & vars, - const std::string & txt) const -{ - //exec regex against value - boost::regex re(regex); - boost::smatch what; + std::string out; std::string::const_iterator start, end; start = txt.begin(); end = txt.end(); - std::string out; - while (regex_search(start, end, what, re)) //find next full match + while (1) { + std::list::iterator bit = replace_list.end(); + { + std::string::const_iterator best_pos = txt.end(); + std::list::iterator it = replace_list.begin(); + for (; it != replace_list.end(); it++) + { + if (regex_search(start, end, it->what, it->re)) + { + if (it->what[0].first < best_pos) + { + best_pos = it->what[0].first; + bit = it; + } + } + } + if (bit == replace_list.end()) + break; + } + size_t i; - for (i = 1; i < what.size(); ++i) + for (i = 1; i < bit->what.size(); ++i) { //check if the group is named - std::map::const_iterator it - = group_index.find(i); - if (it != group_index.end()) + std::map::const_iterator git + = bit->group_index.find(i); + if (git != bit->group_index.end()) { //it is - if (!what[i].str().empty()) - vars[it->second] = what[i]; + vars[git->second] = bit->what[i]; } } //prepare replacement string - std::string rvalue = sub_vars(vars); + std::string rvalue = bit->sub_vars(vars); yaz_log(YLOG_LOG, "! Rewritten '%s' to '%s'", - what.str(0).c_str(), rvalue.c_str()); - out.append(start, what[0].first); + bit->what.str(0).c_str(), rvalue.c_str()); + out.append(start, bit->what[0].first); out.append(rvalue); - start = what[0].second; //move search forward + start = bit->what[0].second; //move search forward } - //if we had a match cat the last part if (start != txt.begin()) out.append(start, end); return out; } -void yf::HttpRewrite::Replace::parse_groups() +void yf::HttpRewrite::Replace::parse_groups(std::string pattern) { int gnum = 0; bool esc = false; - const std::string & str = regex; + const std::string &str = pattern; std::string res; yaz_log(YLOG_LOG, "Parsing groups from '%s'", str.c_str()); for (size_t i = 0; i < str.size(); ++i) @@ -496,7 +499,7 @@ void yf::HttpRewrite::Replace::parse_groups() } esc = false; } - regex = res; + re = res; } std::string yf::HttpRewrite::Replace::sub_vars( @@ -582,11 +585,12 @@ void yf::HttpRewrite::configure_phase(const xmlNode *ptr, Phase &phase) if (!strcmp((const char *) p->name, "rewrite")) { Replace replace; + std::string from; const struct _xmlAttr *attr; for (attr = p->properties; attr; attr = attr->next) { if (!strcmp((const char *) attr->name, "from")) - replace.regex = mp::xml::get_text(attr->children); + from = mp::xml::get_text(attr->children); else if (!strcmp((const char *) attr->name, "to")) replace.recipe = mp::xml::get_text(attr->children); else @@ -596,10 +600,12 @@ void yf::HttpRewrite::configure_phase(const xmlNode *ptr, Phase &phase) + " in rewrite section of http_rewrite"); } yaz_log(YLOG_LOG, "Found rewrite rule from '%s' to '%s'", - replace.regex.c_str(), replace.recipe.c_str()); - replace.parse_groups(); - if (!replace.regex.empty()) + from.c_str(), replace.recipe.c_str()); + if (!from.empty()) + { + replace.parse_groups(from); rule->replace_list.push_back(replace); + } } else throw mp::filter::FilterException