You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Micha Lenk <mi...@lenk.info> on 2011/07/08 18:29:50 UTC

[PATCH 51489] ProxyPassReverse issue + patch

Hi Apache developers,

I'm using Apache as a reverse proxy in a simple load balancer setup.
I use ProxyPassReverse in order to re-write the backend server name in 
HTTP redirections (ie. in the Location header of the HTTP response).
My configuration for the virtual host essentially looks like this:

<Proxy balancer://196f045aca6adc82a0b6eea93ed286a1>
	BalancerMember http://server-1.local status=-SE
	BalancerMember http://server-2.local status=-SE
</Proxy>
<VirtualHost 10.8.16.33:80>
	ServerName frontend.local

	<Location />
		ProxyPass balancer://196f045aca6adc82a0b6eea93ed286a1/
		ProxyPassReverse balancer://196f045aca6adc82a0b6eea93ed286a1/
	</Location>
</VirtualHost>

Now, I was wondering why redirects get an additional slash between the 
server name and the path. Example:

1. The backend server redirects the URL http://server-1.local/foo to
    the URL http://server-1.local/foo/ because this is actually a
    directory (so far no issue)

2. With the configuration above the reverse proxy redirects the URL
    http://frontend.local/foo to http://frontend.local//foo/

What I bother about is the additional slash before '/foo/', so I digged 
into the source code and found the following lines in 
modules/proxy/proxy_util.c:

PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r,
                               proxy_dir_conf *conf, const char *url)
{
     [...]
     l1 = strlen(url);
     [...]
     for (i = 0; i < conf->raliases->nelts; i++) {
         if (ap_proxy_valid_balancer_name((char *)real, 0) &&
             (balancer = ap_proxy_get_balancer(r->pool, sconf, real))) {
             int n, l3 = 0;
             proxy_worker **worker = (proxy_worker 
**)balancer->workers->elts;
             const char *urlpart = ap_strchr_c(real, '/');
             if (urlpart) {
                 if (!urlpart[1])
                     urlpart = NULL;
                 else
                     l3 = strlen(urlpart);
             }
             for (n = 0; n < balancer->workers->nelts; n++) {
                 l2 = strlen((*worker)->s->name);
                 if (urlpart) {
                     /* urlpart (l3) assuredly starts with its own '/' */
                     if ((*worker)->s->name[l2 - 1] == '/')
                         --l2;
                     if (l1 >= l2 + l3
                             && strncasecmp((*worker)->s->name, url, l2) 
== 0
                             && strncmp(urlpart, url + l2, l3) == 0) {
                         u = apr_pstrcat(r->pool, ent[i].fake, &url[l2 + 
l3],
                                         NULL);
                         return ap_construct_url(r->pool, u, r);
                     }
                 }
                 else if (l1 >= l2 && strncasecmp((*worker)->s->name, 
url, l2) == 0) {
                     u = apr_pstrcat(r->pool, ent[i].fake, &url[l2], NULL);
                     return ap_construct_url(r->pool, u, r);
                 }
                 worker++;
             }
             [...]

Right now I don't really understand the reason for the special casing of 
urlpart == "/" in modules/proxy/proxy_util.c, lines 1126 to 1129 (SVN 
rev. 1144374). If urlpart == "/", then the code in lines 1151 and 1152 
gets executed, which seems to add the slash.

I tried to remove the special casing (see submitted patch), and 
apparently the removal fixes the issue.

Does anybody know the reason for the special casing mentioned above?
If not I want to suggest to commit my patch.

Regards,
Micha

Re: [PATCH 51489] ProxyPassReverse issue + patch

Posted by Micha Lenk <mi...@lenk.info>.
Hi Nick,

On 9 Jul 2011, at 11:16, Nick Kew wrote:
> On 8 Jul 2011, at 17:29, Micha Lenk wrote:
>
>> I'm using Apache as a reverse proxy in a simple load balancer setup.
>> I use ProxyPassReverse in order to re-write the backend server name in HTTP redirections (ie. in the Location header of the HTTP response).
>> My configuration for the virtual host essentially looks like this:
>>
>> <Proxy balancer://196f045aca6adc82a0b6eea93ed286a1>
>> 	BalancerMember http://server-1.local status=-SE
>> 	BalancerMember http://server-2.local status=-SE
>> </Proxy>
>
> Is the absence of slashes after local there intentional?  You have a
> slash in your ProxyPass[Reverse] directives.

Yes, the absence of slashes after local is intentional. If I added them, 
the double slash in the Location: header of a redirect response would 
indeed be gone, but it would in turn cause a double slash to be added to 
*every* backend request. In case of a thttpd as backend, this would 
cause the backend to refuse all requests entirely. :(

This seems to be different issue, but maybe I should try to fix this 
instead...

>> What I bother about is the additional slash before '/foo/', so
>> I  digged into the source code and found the following lines in
>> modules/proxy/proxy_util.c:
>
> That's not easy to follow: your comments don't cross-reference to the code
> until I've opened a lot more windows than I have screen space for.
> A link to your bugzilla report would've helped, and your reference to
> source is ambiguous - I guessed /trunk/.

Correct.

> When digging in source for this kind of thing, the "annotate" feature of svn
> is your best tool:
> http://svn.eu.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/proxy_util.c?annotate=1138627
> The lines you're unhappy about were introduced in r771587:
> http://svn.eu.apache.org/viewvc?view=revision&revision=771587
> which has quite an informative commit message.  Maybe that might help
> to figure out the purpose?

Thank you for the hints. I will take a closer look on the diff once time 
permits. I should have done that before...

Cheers,
Micha

Re: [PATCH 51489] ProxyPassReverse issue + patch

Posted by Nick Kew <ni...@webthing.com>.
On 8 Jul 2011, at 17:29, Micha Lenk wrote:

> Hi Apache developers,
> 
> I'm using Apache as a reverse proxy in a simple load balancer setup.
> I use ProxyPassReverse in order to re-write the backend server name in HTTP redirections (ie. in the Location header of the HTTP response).
> My configuration for the virtual host essentially looks like this:
> 
> <Proxy balancer://196f045aca6adc82a0b6eea93ed286a1>
> 	BalancerMember http://server-1.local status=-SE
> 	BalancerMember http://server-2.local status=-SE
> </Proxy>

Is the absence of slashes after local there intentional?  You have a
slash in your ProxyPass[Reverse] directives.

> What I bother about is the additional slash before '/foo/', so I digged into the source code and found the following lines in modules/proxy/proxy_util.c:

That's not easy to follow: your comments don't cross-reference to the code
until I've opened a lot more windows than I have screen space for.
A link to your bugzilla report would've helped, and your reference to
source is ambiguous - I guessed /trunk/.

When digging in source for this kind of thing, the "annotate" feature of svn
is your best tool:
http://svn.eu.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/proxy_util.c?annotate=1138627
The lines you're unhappy about were introduced in r771587:
http://svn.eu.apache.org/viewvc?view=revision&revision=771587
which has quite an informative commit message.  Maybe that might help
to figure out the purpose?

I confess in this case I too am at a loss to see the purpose of that test.
Well, we do need to normalise the case of a missing URL, but that test appears
to be doing it the wrong way and making a special case of a normal one.

-- 
Nick Kew

Available for work, contract or permanent
http://www.webthing.com/~nick/cv.html


Re: [PATCH 51489] ProxyPassReverse issue + patch

Posted by Micha Lenk <mi...@lenk.info>.
Hi Andrew,

Am 08.07.2011 19:10, schrieb Andrew Oliver:
> This seems more like a job for mod_rewrite to me.

Using mod_rewrite sounds rather like a kludge to me. I am interested in 
a real fix.

Micha

Re: [PATCH 51489] ProxyPassReverse issue + patch

Posted by Andrew Oliver <ac...@gmail.com>.
This seems more like a job for mod_rewrite to me.
On Jul 8, 2011 12:32 PM, "Micha Lenk" <mi...@lenk.info> wrote:
> Hi Apache developers,
>
> I'm using Apache as a reverse proxy in a simple load balancer setup.
> I use ProxyPassReverse in order to re-write the backend server name in
> HTTP redirections (ie. in the Location header of the HTTP response).
> My configuration for the virtual host essentially looks like this:
>
> <Proxy balancer://196f045aca6adc82a0b6eea93ed286a1>
> BalancerMember http://server-1.local status=-SE
> BalancerMember http://server-2.local status=-SE
> </Proxy>
> <VirtualHost 10.8.16.33:80>
> ServerName frontend.local
>
> <Location />
> ProxyPass balancer://196f045aca6adc82a0b6eea93ed286a1/
> ProxyPassReverse balancer://196f045aca6adc82a0b6eea93ed286a1/
> </Location>
> </VirtualHost>
>
> Now, I was wondering why redirects get an additional slash between the
> server name and the path. Example:
>
> 1. The backend server redirects the URL http://server-1.local/foo to
> the URL http://server-1.local/foo/ because this is actually a
> directory (so far no issue)
>
> 2. With the configuration above the reverse proxy redirects the URL
> http://frontend.local/foo to http://frontend.local//foo/
>
> What I bother about is the additional slash before '/foo/', so I digged
> into the source code and found the following lines in
> modules/proxy/proxy_util.c:
>
> PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r,
> proxy_dir_conf *conf, const char *url)
> {
> [...]
> l1 = strlen(url);
> [...]
> for (i = 0; i < conf->raliases->nelts; i++) {
> if (ap_proxy_valid_balancer_name((char *)real, 0) &&
> (balancer = ap_proxy_get_balancer(r->pool, sconf, real))) {
> int n, l3 = 0;
> proxy_worker **worker = (proxy_worker
> **)balancer->workers->elts;
> const char *urlpart = ap_strchr_c(real, '/');
> if (urlpart) {
> if (!urlpart[1])
> urlpart = NULL;
> else
> l3 = strlen(urlpart);
> }
> for (n = 0; n < balancer->workers->nelts; n++) {
> l2 = strlen((*worker)->s->name);
> if (urlpart) {
> /* urlpart (l3) assuredly starts with its own '/' */
> if ((*worker)->s->name[l2 - 1] == '/')
> --l2;
> if (l1 >= l2 + l3
> && strncasecmp((*worker)->s->name, url, l2)
> == 0
> && strncmp(urlpart, url + l2, l3) == 0) {
> u = apr_pstrcat(r->pool, ent[i].fake, &url[l2 +
> l3],
> NULL);
> return ap_construct_url(r->pool, u, r);
> }
> }
> else if (l1 >= l2 && strncasecmp((*worker)->s->name,
> url, l2) == 0) {
> u = apr_pstrcat(r->pool, ent[i].fake, &url[l2], NULL);
> return ap_construct_url(r->pool, u, r);
> }
> worker++;
> }
> [...]
>
> Right now I don't really understand the reason for the special casing of
> urlpart == "/" in modules/proxy/proxy_util.c, lines 1126 to 1129 (SVN
> rev. 1144374). If urlpart == "/", then the code in lines 1151 and 1152
> gets executed, which seems to add the slash.
>
> I tried to remove the special casing (see submitted patch), and
> apparently the removal fixes the issue.
>
> Does anybody know the reason for the special casing mentioned above?
> If not I want to suggest to commit my patch.
>
> Regards,
> Micha

Re: [PATCH 51489] ProxyPassReverse issue + patch

Posted by Micha Lenk <mi...@lenk.info>.
Hi Jim,

Am 10.07.2011 16:57, schrieb Jim Jagielski:
> Try:
>
> 	<Proxy balancer://196f045aca6adc82a0b6eea93ed286a1/>

Thank you for your hint. I tried that, but it doesn't change anything. :(

Micha

Re: [PATCH 51489] ProxyPassReverse issue + patch

Posted by Jim Jagielski <ji...@jaguNET.com>.
Try:

	<Proxy balancer://196f045aca6adc82a0b6eea93ed286a1/ >

On Jul 8, 2011, at 12:29 PM, Micha Lenk wrote:

> Hi Apache developers,
> 
> I'm using Apache as a reverse proxy in a simple load balancer setup.
> I use ProxyPassReverse in order to re-write the backend server name in HTTP redirections (ie. in the Location header of the HTTP response).
> My configuration for the virtual host essentially looks like this:
> 
> <Proxy balancer://196f045aca6adc82a0b6eea93ed286a1>
> 	BalancerMember http://server-1.local status=-SE
> 	BalancerMember http://server-2.local status=-SE
> </Proxy>
> <VirtualHost 10.8.16.33:80>
> 	ServerName frontend.local
> 
> 	<Location />
> 		ProxyPass balancer://196f045aca6adc82a0b6eea93ed286a1/
> 		ProxyPassReverse balancer://196f045aca6adc82a0b6eea93ed286a1/
> 	</Location>
> </VirtualHost>
> 
> Now, I was wondering why redirects get an additional slash between the server name and the path. Example:
> 
> 1. The backend server redirects the URL http://server-1.local/foo to
>   the URL http://server-1.local/foo/ because this is actually a
>   directory (so far no issue)
> 
> 2. With the configuration above the reverse proxy redirects the URL
>   http://frontend.local/foo to http://frontend.local//foo/
> 
> What I bother about is the additional slash before '/foo/', so I digged into the source code and found the following lines in modules/proxy/proxy_util.c:
> 
> PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r,
>                              proxy_dir_conf *conf, const char *url)
> {
>    [...]
>    l1 = strlen(url);
>    [...]
>    for (i = 0; i < conf->raliases->nelts; i++) {
>        if (ap_proxy_valid_balancer_name((char *)real, 0) &&
>            (balancer = ap_proxy_get_balancer(r->pool, sconf, real))) {
>            int n, l3 = 0;
>            proxy_worker **worker = (proxy_worker **)balancer->workers->elts;
>            const char *urlpart = ap_strchr_c(real, '/');
>            if (urlpart) {
>                if (!urlpart[1])
>                    urlpart = NULL;
>                else
>                    l3 = strlen(urlpart);
>            }
>            for (n = 0; n < balancer->workers->nelts; n++) {
>                l2 = strlen((*worker)->s->name);
>                if (urlpart) {
>                    /* urlpart (l3) assuredly starts with its own '/' */
>                    if ((*worker)->s->name[l2 - 1] == '/')
>                        --l2;
>                    if (l1 >= l2 + l3
>                            && strncasecmp((*worker)->s->name, url, l2) == 0
>                            && strncmp(urlpart, url + l2, l3) == 0) {
>                        u = apr_pstrcat(r->pool, ent[i].fake, &url[l2 + l3],
>                                        NULL);
>                        return ap_construct_url(r->pool, u, r);
>                    }
>                }
>                else if (l1 >= l2 && strncasecmp((*worker)->s->name, url, l2) == 0) {
>                    u = apr_pstrcat(r->pool, ent[i].fake, &url[l2], NULL);
>                    return ap_construct_url(r->pool, u, r);
>                }
>                worker++;
>            }
>            [...]
> 
> Right now I don't really understand the reason for the special casing of urlpart == "/" in modules/proxy/proxy_util.c, lines 1126 to 1129 (SVN rev. 1144374). If urlpart == "/", then the code in lines 1151 and 1152 gets executed, which seems to add the slash.
> 
> I tried to remove the special casing (see submitted patch), and apparently the removal fixes the issue.
> 
> Does anybody know the reason for the special casing mentioned above?
> If not I want to suggest to commit my patch.
> 
> Regards,
> Micha
> 


Re: [PATCH 51489] ProxyPassReverse issue + patch

Posted by Micha Lenk <mi...@lenk.info>.
Hi Ruediger,

On 08/22/2011 02:40 PM CEST +02:00, "Plüm, Rüdiger, VF-Group" wrote:
>> On 07/13/2011 06:36 PM CEST +02:00, Ruediger Pluem wrote:
>>> Try
>>>
>>> ProxyPassReverse balancer://196f045aca6adc82a0b6eea93ed286a1
>>>
>>> instead.
>>
>> This results in an Internal Server Error:
>>
>> [warn] proxy: No protocol handler was valid for the URL <request URL>.
>> If you are using a DSO version of mod_proxy, make sure the proxy
>> submodules are included in the configuration using LoadModule.
>>
>> Doesn't seem to be a solution... :(
> 
> This means that your config is wrong and you have not loaded the required protocol
> handlers like mod_proxy_http or mod_proxy_ajp.
> Or your config does not load mod_proxy_balancer.

I do have the protocol handler mod_proxy_http loaded and
mod_proxy_balancer is loaded as well.

However, I guess the 'your config is wrong' is nevertheless true. I
found out that I have no issue at all if the config consistently uses a
slash after the load balancer id.

<Proxy balancer://196f045aca6adc82a0b6eea93ed286a1/>
    BalancerMember http://server-1.local/ status=-SE
    BalancerMember http://server-2.local/ status=-SE
</Proxy>
<VirtualHost 10.8.16.33:80>
    ServerName frontend.local

    <Location />
	ProxyPass balancer://196f045aca6adc82a0b6eea93ed286a1/
	ProxyPassReverse balancer://196f045aca6adc82a0b6eea93ed286a1/
    </Location>
</VirtualHost>

So, please consider the case as solved and the patch as void.

Regards,
Micha

RE: [PATCH 51489] ProxyPassReverse issue + patch

Posted by "Plüm, Rüdiger, VF-Group" <ru...@vodafone.com>.
 

> -----Original Message-----
> From: Micha Lenk [mailto:micha@lenk.info] 
> Sent: Montag, 22. August 2011 14:19
> To: dev@httpd.apache.org
> Subject: Re: [PATCH 51489] ProxyPassReverse issue + patch
> 
> Hi Ruediger,
> 
> sorry, things piled up recently...
> 
> On 07/13/2011 06:36 PM CEST +02:00, Ruediger Pluem wrote:
> > Try
> > 
> > ProxyPassReverse balancer://196f045aca6adc82a0b6eea93ed286a1
> > 
> > instead.
> 
> This results in an Internal Server Error:
> 
> [warn] proxy: No protocol handler was valid for the URL <request URL>.
> If you are using a DSO version of mod_proxy, make sure the proxy
> submodules are included in the configuration using LoadModule.
> 
> Doesn't seem to be a solution... :(

This means that your config is wrong and you have not loaded the required protocol
handlers like mod_proxy_http or mod_proxy_ajp.
Or your config does not load mod_proxy_balancer.

Regards

Rüdiger

 

Re: [PATCH 51489] ProxyPassReverse issue + patch

Posted by Micha Lenk <mi...@lenk.info>.
Hi Ruediger,

sorry, things piled up recently...

On 07/13/2011 06:36 PM CEST +02:00, Ruediger Pluem wrote:
> Try
> 
> ProxyPassReverse balancer://196f045aca6adc82a0b6eea93ed286a1
> 
> instead.

This results in an Internal Server Error:

[warn] proxy: No protocol handler was valid for the URL <request URL>.
If you are using a DSO version of mod_proxy, make sure the proxy
submodules are included in the configuration using LoadModule.

Doesn't seem to be a solution... :(

Regards,
Micha

Re: [PATCH 51489] ProxyPassReverse issue + patch

Posted by Ruediger Pluem <rp...@apache.org>.

On 07/08/2011 06:29 PM, Micha Lenk wrote:
> Hi Apache developers,
> 
> I'm using Apache as a reverse proxy in a simple load balancer setup.
> I use ProxyPassReverse in order to re-write the backend server name in
> HTTP redirections (ie. in the Location header of the HTTP response).
> My configuration for the virtual host essentially looks like this:
> 
> <Proxy balancer://196f045aca6adc82a0b6eea93ed286a1>
>     BalancerMember http://server-1.local status=-SE
>     BalancerMember http://server-2.local status=-SE
> </Proxy>
> <VirtualHost 10.8.16.33:80>
>     ServerName frontend.local
> 
>     <Location />
>         ProxyPass balancer://196f045aca6adc82a0b6eea93ed286a1/
>         ProxyPassReverse balancer://196f045aca6adc82a0b6eea93ed286a1/

Try

ProxyPassReverse balancer://196f045aca6adc82a0b6eea93ed286a1


instead.

Regards

Rüdiger