3
A brief file description
5
@section license License
7
Licensed to the Apache Software Foundation (ASF) under one
8
or more contributor license agreements. See the NOTICE file
9
distributed with this work for additional information
10
regarding copyright ownership. The ASF licenses this file
11
to you under the Apache License, Version 2.0 (the
12
"License"); you may not use this file except in compliance
13
with the License. You may obtain a copy of the License at
15
http://www.apache.org/licenses/LICENSE-2.0
17
Unless required by applicable law or agreed to in writing, software
18
distributed under the License is distributed on an "AS IS" BASIS,
19
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
See the License for the specific language governing permissions and
21
limitations under the License.
24
#include "RemapProcessor.h"
26
RemapProcessor remapProcessor;
27
extern ClassAllocator<RemapPlugins> pluginAllocator;
30
RemapProcessor::start(int num_threads)
32
ET_REMAP = eventProcessor.spawn_event_threads(num_threads); // ET_REMAP is a class member
37
Most of this comes from UrlRewrite::Remap(). Generally, all this does
38
is set "map" to the appropriate entry from the global rewrite_table
39
such that we will then have access to the correct url_mapping inside
44
RemapProcessor::setup_for_remap(HttpTransact::State * s)
46
Debug("url_rewrite", "setting up for remap: %x", s);
47
URL *request_url = NULL;
48
bool mapping_found = false;
49
HTTPHdr *request_header = &s->hdr_info.client_request;
50
char **redirect_url = &s->remap_redirect;
51
char **orig_url = &s->unmapped_request_url;
53
const char *request_host;
56
bool proxy_request = false;
58
s->reverse_proxy = rewrite_table->reverse_proxy;
59
s->url_map.set(s->hdr_info.client_request.m_heap);
61
ink_assert(redirect_url != NULL);
63
if (unlikely(rewrite_table->num_rules_forward == 0)) {
64
ink_assert(rewrite_table->forward_mappings.empty());
67
// Since we are called before request validity checking
68
// occurs, make sure that we have both a valid request
69
// header and a valid URL
70
if (unlikely(!request_header || (request_url = request_header->url_get()) == NULL || !request_url->valid())) {
71
Error("NULL or invalid request data");
75
request_host = request_header->host_get(&request_host_len);
76
request_port = request_header->port_get();
77
proxy_request = request_header->is_target_in_url() || ! s->reverse_proxy;
79
// Default to empty host.
85
Debug("url_rewrite", "[lookup] attempting %s lookup", proxy_request ? "proxy" : "normal");
87
mapping_found = rewrite_table->forwardMappingLookup(request_url, request_port, request_host, request_host_len, s->url_map, tag);
89
if (!proxy_request) { // do extra checks on a server request
91
// Save this information for later
92
// @amc: why is this done only for requests without a host in the URL?
93
s->hh_info.host_len = request_host_len;
94
s->hh_info.request_host = request_host;
95
s->hh_info.request_port = request_port;
97
// If no rules match and we have a host, check empty host rules since
98
// they function as default rules for server requests.
99
// If there's no host, we've already done this.
100
if (!mapping_found && rewrite_table->nohost_rules && request_host_len) {
101
Debug("url_rewrite", "[lookup] nothing matched");
102
mapping_found = rewrite_table->forwardMappingLookup(request_url, 0, "", 0, s->url_map, tag);
105
if (mapping_found && orig_url) {
106
// Downstream mapping logic (e.g., self::finish_remap())
107
// apparently assumes the presence of the target in the URL, so
108
// we need to copy it. Perhaps it's because it's simpler to just
109
// do the remap on the URL and then fix the field at the end.
110
request_header->set_url_target_from_host_field();
111
*orig_url = request_url->string_get_ref(NULL);
116
request_header->mark_target_dirty();
118
Debug("url_rewrite", "RemapProcessor::setup_for_remap did not find a mapping");
121
return mapping_found;
125
RemapProcessor::finish_remap(HttpTransact::State * s)
127
url_mapping *map = NULL;
128
HTTPHdr *request_header = &s->hdr_info.client_request;
129
URL *request_url = request_header->url_get();
130
char **orig_url = &s->unmapped_request_url;
131
char **redirect_url = &s->remap_redirect;
132
const int host_buf_len = MAXDNAME + 12 + 1 + 1;
133
char host_hdr_buf[host_buf_len], tmp_referer_buf[4096], tmp_redirect_buf[4096], tmp_buf[2048], *c;
134
const char *remapped_host;
135
int remapped_host_len, remapped_port, tmp;
137
bool remap_found = false;
140
map = s->url_map.getMapping();
144
// Do fast ACL filtering (it is safe to check map here)
145
rewrite_table->PerformACLFiltering(s, map);
147
// Check referer filtering rules
148
if ((s->filter_mask & URL_REMAP_FILTER_REFERER) != 0 && (ri = map->referer_list) != 0) {
149
const char *referer_hdr = 0;
151
bool enabled_flag = map->optional_referer ? true : false;
153
if (request_header->presence(MIME_PRESENCE_REFERER) &&
154
(referer_hdr = request_header->value_get(MIME_FIELD_REFERER, MIME_LEN_REFERER, &referer_len)) != NULL) {
155
if (referer_len >= (int) sizeof(tmp_referer_buf))
156
referer_len = (int) (sizeof(tmp_referer_buf) - 1);
157
memcpy(tmp_referer_buf, referer_hdr, referer_len);
158
tmp_referer_buf[referer_len] = 0;
159
for (enabled_flag = false; ri; ri = ri->next) {
162
if (!map->negative_referer)
164
} else if (ri->regx_valid && (pcre_exec(ri->regx, NULL, tmp_referer_buf, referer_len, 0, 0, NULL, 0) != -1)) {
165
enabled_flag = ri->negative ? false : true;
172
if (!map->default_redirect_url) {
173
if ((s->filter_mask & URL_REMAP_FILTER_REDIRECT_FMT) != 0 && map->redir_chunk_list) {
174
redirect_tag_str *rc;
175
tmp_redirect_buf[(tmp = 0)] = 0;
176
for (rc = map->redir_chunk_list; rc; rc = rc->next) {
183
c = (referer_len && referer_hdr) ? &tmp_referer_buf[0] : 0;
188
(rc->type == 'f') ? map->fromURL.string_get_buf(tmp_buf, (int) sizeof(tmp_buf),
189
&from_len) : ((s->url_map).getToURL())->string_get_buf(tmp_buf, (int)
192
if (remapped_host && from_len > 0) {
201
if (c && tmp < (int) (sizeof(tmp_redirect_buf) - 1)) {
202
tmp += snprintf(&tmp_redirect_buf[tmp], sizeof(tmp_redirect_buf) - tmp, "%s", c);
205
tmp_redirect_buf[sizeof(tmp_redirect_buf) - 1] = 0;
206
*redirect_url = xstrdup(tmp_redirect_buf);
209
*redirect_url = xstrdup(rewrite_table->http_default_redirect_url);
212
if (*redirect_url == NULL) {
214
xstrdup(map->filter_redirect_url ? map->filter_redirect_url : rewrite_table->http_default_redirect_url);
223
// We also need to rewrite the "Host:" header if it exists and
224
// pristine host hdr is not enabled
226
const char *host_hdr = request_header->value_get(MIME_FIELD_HOST, MIME_LEN_HOST, &host_len);
228
if (request_url && host_hdr != NULL && s->txn_conf.maintain_pristine_host_hdr == 0) {
229
remapped_host = request_url->host_get(&remapped_host_len);
230
remapped_port = request_url->port_get_raw();
232
// Debug code to print out old host header. This was easier before
233
// the header conversion. Now we have to copy to gain null
234
// termination for the Debug() call
235
if (is_debug_tag_set("url_rewrite")) {
236
int old_host_hdr_len;
237
char *old_host_hdr = (char *) request_header->value_get(MIME_FIELD_HOST,
241
old_host_hdr = xstrndup(old_host_hdr, old_host_hdr_len);
242
Debug("url_rewrite", "Host: Header before rewrite %.*s", old_host_hdr_len, old_host_hdr);
247
// Create the new host header field being careful that our
248
// temporary buffer has adequate length
250
if (host_buf_len > remapped_host_len) {
251
tmp = remapped_host_len;
252
memcpy(host_hdr_buf, remapped_host, remapped_host_len);
254
tmp += snprintf(host_hdr_buf + remapped_host_len, host_buf_len - remapped_host_len - 1, ":%d", remapped_port);
260
// It is possible that the hostname is too long. If it is punt,
261
// and remove the host header. If it is too long the HostDB
262
// won't be able to resolve it and the request will not go
264
if (tmp >= host_buf_len) {
265
request_header->field_delete(MIME_FIELD_HOST, MIME_LEN_HOST);
266
Debug("url_rewrite", "Host: Header too long after rewrite");
268
Debug("url_rewrite", "Host: Header after rewrite %.*s", tmp, host_hdr_buf);
269
request_header->value_set(MIME_FIELD_HOST, MIME_LEN_HOST, host_hdr_buf, tmp);
277
RemapProcessor::perform_remap(Continuation * cont, HttpTransact::State * s)
279
Debug("url_rewrite", "Beginning RemapProcessor::perform_remap");
280
HTTPHdr *request_header = &s->hdr_info.client_request;
281
URL *request_url = request_header->url_get();
282
url_mapping *map = s->url_map.getMapping();
283
host_hdr_info *hh_info = &(s->hh_info);
286
Error("Could not find corresponding url_mapping for this transaction %x", s);
287
Debug("url_rewrite", "Could not find corresponding url_mapping for this transaction");
288
ink_debug_assert(!"this should never happen -- call setup_for_remap first");
289
cont->handleEvent(EVENT_REMAP_ERROR, NULL);
290
return ACTION_RESULT_DONE;
293
// EThread *t = cont->mutex->thread_holding;
294
// RemapPlugins *plugins = THREAD_ALLOC_INIT(pluginAllocator, t);
296
RemapPlugins *plugins = pluginAllocator.alloc();
298
plugins->setMap(&(s->url_map));
299
plugins->setRequestUrl(request_url);
300
plugins->setRequestHeader(request_header);
301
plugins->setState(s);
302
plugins->setHostHeaderInfo(hh_info);
304
if (!_use_separate_remap_thread) { // lets not schedule anything on our thread group (ET_REMAP), instead, just execute inline
307
ret = plugins->run_single_remap();
309
//THREAD_FREE(plugins, pluginAllocator, t);
310
pluginAllocator.free(plugins);
311
return ACTION_RESULT_DONE;
313
ink_debug_assert(cont->mutex->thread_holding == this_ethread());
314
plugins->mutex = cont->mutex;
315
plugins->action = cont;
316
SET_CONTINUATION_HANDLER(plugins, &RemapPlugins::run_remap);
317
eventProcessor.schedule_imm(plugins, ET_REMAP);
318
return &plugins->action;