So yesterday I mentioned the mod_rewrite-compatible proxy server. Today I've spent several hours getting to grips with that.
I've progressed far enough along that the trivial cases are handled, as the following test case shows:
void
TestParamteredMatch (CuTest * tc)
{
/**
* We pretend this came in via the network.
*/
char *request = "GET /login/steve.kemp/secret#password HTTP/1.1\n\n";
/**
* This is the mod_rewrite rule we're going to test.
*/
char *rule = "RewriteRule
^/login/(.*)/(.*)/*$
/cgi-bin/index.cgi?mode=login;lname=$1;lpass=$2";
int res = 0;
/* Parse the HTTP request */
struct http_request *req = http_request_new (request);
CuAssertPtrNotNull (tc, req);
/* Ensure it looks sane. */
CuAssertStrEquals(tc, "/login/steve.kemp/secret#password", req->path );
/* Create the rewrite rule */
struct rewrite_rule *r = rewrite_rule_new (rule);
CuAssertPtrNotNull (tc, r);
/* Assert it contains what we think it should. */
CuAssertStrEquals(tc, "^/login/(.*)/(.*)/*$", r->pattern );
/* Apply - expect success (==1) */
res = rewrite_rule_apply( r, req );
CuAssertIntEquals (tc, 1, res );
/* Ensure path is updated. */
CuAssertStrEquals(tc, "/cgi-bin/index.cgi?mode=login;lname=steve.kemp;lpass=secret#password", req->path );
free_http_request (req);
free_rewrite_rule (r);
}
So all is good? Sadly not.
I was expecting to handle a linked list of simple rules, but I've now realised that this isn't sufficient. Consider the following two (real) examples:
#
# If the path is /robots.txt and the hostname isn't repository.steve.org.uk
# then redirect to the master one.
#
RewriteCond %{http_host} !^repository\.steve\.org\.uk
RewriteRule /robots.txt$ http://repository.steve.org.uk/robots.txt [R=permanent,L]
#
# Request for : http://foo.repository.steve.org.uk
# becomes: http://repository.steve.org.uk/cgi-bin/hgwebdir.cgi/foo/file/tip
#
RewriteCond %{http_host} .
RewriteCond %{http_host} !^repository.steve.org.uk [NC]
RewriteCond %{http_host} ^([^.]+)\.repository.steve.org.uk [NC]
RewriteRule ^/$ http://repository.steve.org.uk/cgi-bin/hgwebdir.cgi/%1/file/tip [QSA,L]
So rather than having a simple linked list of rules for each domain I need to have a list of rules - each of which might in turn contain sub-rules. In terms of parsing this is harder than I'd like because it means I need to maintain state to marry up the RewriteCond & RewriteRules.
Still the problem isn't insurmountable and I'm pleased with the progress I've made. Currently I can implement enough of mod_rewrite that I could handle all of my existing sites except the single site I have with the complex rule demonstrated above.
(In all honesty I guess I could simplify my setup by dropping the wildcard hostname handling for the repository.steve.org.uk name, but I do kinda like it, and it makes for simple canonical mercurial repositories.)
ObQuote: - 300
Tags: c, http, mod_rewrite, proxy No comments