Graham Dumpleton
grahamd at dscpl.com.au
Fri Mar 3 04:41:23 EST 2006
>> FWIW, if req.proxyreq is made writable, it would be good at the same >> time to make req.uri writable as well. This would allow for example a >> PythonTransHandler which did something like the following: >> >> def transhandler(req): >> if req.proxyreq: >> return apache.DECLINED >> >> if req.uri.find('/search/') == 0: >> req.proxyreq = apache.PROXYREQ_PROXY >> req.uri = 'http://www.google.com/' + req.uri[len('/search/'):] >> req.filename= "proxy:%s' % req.uri >> req.handler= 'proxy-server' >> return apache.OK >> >> return apache.DECLINED >> >> That is, you could from within a mod_python handler when detecting >> a certain URL prefix, dynamically cause Apache to proxy the request to >> another location. >> >> This example is based on a mod_perl example which does something >> similar. See: >> >> http://162.105.203.19/apache-doc/88.htm#BIN194 >> >> I'll definitely create a JIRA issue for this, as can see a use for >> this >> in some stuff I have to do. I was going to create a static snippet of >> Apache configuration with lots of proxy stuff, but this would be more >> interesting. > > Hmm, interesting idea. It would be great to see something like that. I > can think of all kinds of stuff I've done with mod_rewrite and > horrible PHP hackery that would have been a lot better and simpler > with mod_python and something similar to what you mentioned. Well, if you want to play further, patch for making both req.proxyreq and req.uri modifiable is at end of this email. An example to play with is as follows. Doesn't even need to be a transhandler. This example does it as a fixuphandler which is possibly easier as it can be in .htaccess file for a specific directory. The example will take any part of the URL mapping below the directory and map it onto the remote site instead. Of course, the site has to be proxy friendly and relocatable within the URL namespace in as much as always using relative URLs and not absolute URLs. # ProxyPassReverse equivalent. import posixpath from mod_python import apache def fixuphandler(req): if req.proxyreq: return apache.DECLINED normalised_uri = posixpath.normpath(req.uri) if normalised_uri: if normalised_uri != '/' and req.uri[-1] == '/': normalised_uri += '/' length = len(req.filename) length -= len(req.hlist.directory) - 1 length += len(req.path_info or '') baseurl = normalised_uri[:-length] path = normalised_uri[len(baseurl):] req.proxyreq = apache.PROXYREQ_REVERSE req.uri = 'http://www.dscpl.com.au' + path req.filename = 'proxy:%s' % req.uri req.handler = 'proxy-server' return apache.OK # Actual patches. Index: src/requestobject.c =================================================================== --- src/requestobject.c (revision 382636) +++ src/requestobject.c (working copy) @@ -1515,6 +1515,15 @@ apr_pstrdup(self->request_rec->pool, PyString_AsString(val)); return 0; } + else if (strcmp(name, "uri") == 0) { + if (! PyString_Check(val)) { + PyErr_SetString(PyExc_TypeError, "uri must be a string"); + return -1; + } + self->request_rec->uri = + apr_pstrdup(self->request_rec->pool, PyString_AsString(val)); + return 0; + } return PyMember_SetOne((char*)self->request_rec, find_memberdef(request_rec_mbrs, (char*)name), @@ -1675,7 +1684,7 @@ {"main", (getter)getmakeobj, NULL, "If subrequest, pointer to the main request", "main"}, {"the_request", (getter)getreq_recmbr, NULL, "First line of request", "the_request"}, {"assbackwards", (getter)getreq_recmbr, (setter)setreq_recmbr, "HTTP/0.9 \"simple\" request", "assbackwards"}, - {"proxyreq", (getter)getreq_recmbr, NULL, "A proxy request: one of apache.PROXYREQ_* values", "proxyreq"}, + {"proxyreq", (getter)getreq_recmbr, (setter)setreq_recmbr, "A proxy request: one of apache.PROXYREQ_* values", "proxyreq"}, {"header_only", (getter)getreq_recmbr, NULL, "HEAD request, as oppsed to GET", "header_only"}, {"protocol", (getter)getreq_recmbr, NULL, "Protocol as given to us, or HTTP/0.9", "protocol"}, {"proto_num", (getter)getreq_recmbr, NULL, "Protocol version. 1.1 = 1001", "proto_num"}, @@ -1709,7 +1718,7 @@ {"no_cache", (getter)getreq_recmbr, NULL, "This response in non-cacheable", "no_cache"}, {"no_local_copy", (getter)getreq_recmbr, NULL, "There is no local copy of the response", "no_local_copy"}, {"unparsed_uri", (getter)getreq_recmbr, NULL, "The URI without any parsing performed", "unparsed_uri"}, - {"uri", (getter)getreq_recmbr, NULL, "The path portion of URI", "uri"}, + {"uri", (getter)getreq_recmbr, (setter)setreq_recmbr, "The path portion of URI", "uri"}, {"filename", (getter)getreq_recmbr, (setter)setreq_recmbr, "The file name on disk that this request corresponds to", "filename"}, {"canonical_filename", (getter)getreq_recmbr, NULL, "The true filename (req.filename is canonicalized if they dont match)", "canonical_filename"}, {"path_info", (getter)getreq_recmbr, (setter)setreq_recmbr, "Path_info, if any", "path_info"}, Graham
|