|
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
|