Mailing List Archive

[mod_backhand-users] Another New Candidacy Function: byChooseMeOverLocal
OK, this one deserves a bit of explaining.... I'm running mod_backhand
as a proxy server for heavy mod_perl servers. I had the bulk of my
docroot proxied with the following rules:

BackhandSelfRedirect On
<Directory /path/to/docroot>
Backhand byAge 3
Backhand byRandom
BackhandFromSO libexec/byChooseN.so byChooseN 2
Backhand byLoad -1000
</Directory>

Which worked exceptionally well 99.99% of the time. However,
occasionally (very occasionally) byAge 3 would eliminate all of my
server candidates. The default behavior for mod_proxy in this case is
is to attempt to handle the request itself. Since my mod_backhand is
supposed to proxy *all* requests, this results in a "File does not
Exist" error. My logs for these cases look like:

Func executed for (null) [byAge(3)] (512 -> 0)
Func executed for (null) [byRandom(NULL)] (0 -> 0)
Func executed for (null) [libexec/byChooseN.so::byChooseN(2)] (0 -> 0)
Func executed for (null) [byLoad(-1000)] (0 -> 0)
All funcs executed -> local
[error] File does not exist: /path/to/docroot/myfile.html

Apparently in this case 'BackhandSelfRedirect On' doesn't step in, and
the proxy server attempts to handle the request intended for the
mod_perl server. This is probably a bug, but I didn't feel like
hacking the internals to get self redirection to take effect in this
case.

So, I wrote a new candidacy function, which simply inserts "ME" into
the candidacy list if the list empty. My new configuration looks
like:

<Directory /path/to/docroot>
Backhand byAge 3
Backhand byRandom
BackhandFromSO libexec/byChooseN.so byChooseN 2
Backhand byLoad -1000
BackhandFromSO libexec/byChooseMeOverLocal.so byChooseMeOverLocal
</Directory>

And the logs for a request that would have caused the above error read:

Func executed for (null) [byAge(3)] (512 -> 0)
Func executed for (null) [byRandom(NULL)] (0 -> 0)
Func executed for (null) [libexec/byChooseN.so::byChooseN(2)] (0 -> 0)
Func executed for (null) [byLoad(-1000)] (0 -> 0)
Func executed for (null) [libexec/byChooseMeOverLocal.so::
byChooseMeOverLocal(NULL)] (0 -> 1)
All funcs executed -> myhost.mydomain.com

This essentially avoids the situation of a null candidacy list, which
solves the immediate problem. A better solution would be to follow
the BackhandSelfRedirect setting in this case, but the quick solution
seems to work well enough for me.

I didn't try to optimize the new code, as the meat of it is only
invoked on about 1 out of 20,000 requests. Though, the new list ist
trivial, so I'm sure there is a better way to generate it. Feel free
to distribute/modify at will.

--------------- BEGIN byChooseMeOverLocal.c ----------
#include "httpd.h"
#include "http_log.h"
#include "mod_backhand.h"
int byChooseMeOverLocal(request_rec *r, int *servers, int *n, char *arg) {
int size=*n, i;
if(size == 0) {
for(i=0; i<MAXSERVERS; i++) {
if(servers[i] == 0)
servers[0]=servers[i];
}
size = 1;
*n = 1;
}
return size;
}
--------------- END byChooseMeOverLocal.c ----------


On a separate note, the one remaining issue I have with using
mod_backhand as a proxy for mod_perl is the lack of an analogue to
mod_proxy's ProxyPassReverse directive.

Under my current setup mod_backhand is on port 80 and mod_perl is on
port 81. If mod_perl issues a redirect (for instance from
'http://mydomain.com' to 'http://mydomain.com/') the resulting url is
passed directly back to the client. I'd like to be able to munge the
headers a bit, so I can force the client to come back through
mod_backhand.

I'd like to be able to modify the headers at step #4 below.

1.) client->backhand: GET http://mydomain.com
2.) backhand->mod_perl: forwards to mod_perl
3.) mod_perl->backhand: redirect to http://mydomain.com:81/
4.) backhand->client: redirect to http://mydomain.com:81/
(would like this to be http://mydomain.com/)

Has anyone thought about or done anything along these lines?

-Blake