Two small questions about embedded perl

Hi there,

i just got two small questions about using embedded perl:
first: i would like to “rewrite” the request using a perl module, since
the
rewrite is a bit more than just regexp. I thought that using
“internal_redirect”
is the right way to do, but i don’t get working.
The module looks like:
package testpackage;
use nginx;
use …;

sub handler {
$r = shift;
… some stuff
if($ok) {
$r->internal_redirect("/$uri");
return OK;
}
}

i tried with and without return, seems to make no difference…

nginx config looks like:

http {
perl_require module.pm;

server {

location /folder {
perl testpackage::handler;
# proxy_pass stuff
}
location / {
proxy_pass stuff
}
}
}

i did put some proxy stuff into the location /folder, after the module,
and
some into location /, but the best i got was a unedited call to the
backend.
The module itself got called, usually i get nothing returned (state 200
but
no data). If i return other codes in the module, they work as expected.
So
the module itself is working, just the rewrite/proxy stuff isn’t.

Next question: is it possible to pass vars to the module? like having a
special
option per location which is passed to the module instead of using a
couple
of modules…

Thanks and regards,
Sven

On Tue, Dec 14, 2010 at 10:36:31PM +0100, Sven ‘Darkman’ Michels wrote:

}

the module itself is working, just the rewrite/proxy stuff isn’t.

Next question: is it possible to pass vars to the module? like having a special
option per location which is passed to the module instead of using a couple
of modules…

Try

  •  proxy_pass  http://backend;
    
  •  proxy_pass  http://backend/;
    


Igor S.
http://sysoev.ru/en/

Hi,

Am 14.12.2010 22:59, schrieb Igor S.:

Try

  •  proxy_pass  http://backend;
    
  •  proxy_pass  http://backend/;
    

ok, now i get a loop…

*1 rewrite or internal redirection cycle while internal redirect to
“/test.jpg”,
client: ::ffff:x.x.x.x, server: test.domain.tld, request: “GET
/old_key/test.jpg
HTTP/1.0”, host: “test.domain.tld”

I guess the problem is that i have a “last resort” code which just does
a
$r->internal_redirect($r->uri);
(this is done in case the request doesn’t match all criterias and thus
should be
passed as is to the proxy…)

some break, last, whatever missing? the config looks like:

location ~ \.(png|jpg|gif)$  {
  perl testpackage::handler;
}
location / {

        proxy_pass             http://internal/;
        proxy_set_header       Host $host;
        proxy_cache            STATIC;
        proxy_cache_valid      200  1d;
        proxy_cache_use_stale  error timeout invalid_header updating
                               http_500 http_502 http_503 http_504;
}

so when location matches, query is checked by the module and afterwards
passed
to the proxy. If no match, just proxy it…

Regards and many thanks!
Sven

On Tue, Dec 14, 2010 at 11:28:39PM +0100, Sven ‘Darkman’ Michels wrote:

*1 rewrite or internal redirection cycle while internal redirect to “/test.jpg”,
client: ::ffff:x.x.x.x, server: test.domain.tld, request: “GET /old_key/test.jpg
HTTP/1.0”, host: “test.domain.tld”

I guess the problem is that i have a “last resort” code which just does a
$r->internal_redirect($r->uri);
(this is done in case the request doesn’t match all criterias and thus should be
passed as is to the proxy…)

You should “return DECLINED;”, in this case nginx will continue to
process usual handler chain: index, static files, etc.

        proxy_cache_valid      200  1d;
        proxy_cache_use_stale  error timeout invalid_header updating
                               http_500 http_502 http_503 http_504;
}

so when location matches, query is checked by the module and afterwards passed
to the proxy. If no match, just proxy it…

 location ~ \.(png|jpg|gif)$  {
   perl testpackage::handler;
   # do $r->internal_redirect("/new/...");
 }

 location /new/ {
    proxy_pass  http://internal/;
 }

 location / {
    proxy_pass  http://internal/;
 }


Igor S.
http://sysoev.ru/en/

Hi,

Am 14.12.2010 23:38, schrieb Igor S.:

You should “return DECLINED;”, in this case nginx will continue to
process usual handler chain: index, static files, etc.

ok, did that but now i get nothing returned again sigh
The log says “GET /file.jpg HTTP/1.0” 0 0 “-” “-”
which is not exactly what i would expect…
the perl module just “return DECLINED;” in this case.

    proxy_pass  http://internal/;
 }

ok, this is what i have done now:
location ~ .(png|jpg|gif)$ {
perl testpackage::handler;
}
location /intredirremoved/ {
rewrite ^/intredirremoved/(.+)$ $1 last;
proxy_pass http://internal/;
proxy_set_header Host $host;
proxy_cache STATIC;
proxy_cache_valid 200 1d;
proxy_cache_use_stale error timeout invalid_header updating
http_500 http_502 http_503 http_504;
}
location / {

        proxy_pass             http://internal/;
        proxy_set_header       Host $host;
        proxy_cache            STATIC;
        proxy_cache_valid      200  1d;
        proxy_cache_use_stale  error timeout invalid_header updating
                               http_500 http_502 http_503 http_504;
}

maybe its some extra work now, but my module should remove old parts of
the
uri. I now add this intredirremoved to get a new location as suggested,
but
have to remove it again before passing it to the proxy. “Should” work,
but
is probably not the best. Anyway, the config doesn’t work at all. I’ll
post
some more of the module:
#!/usr/bin/perl -w
package testpackage;
use nginx;

sub handler {
$r = shift;
if(($r->uri=~m%^/oldstuff/(.+.(jpg|png|gif))$%) &&
$r->uri!~m%^/intredirremoved/$%)) {
$file = $1;
$r->internal_redirect(“/intredirremoved/$file”);
# return OK
# return DECLINED;
} else {
return DECLINED;
}
}

this is what it basicly does, except that the real module is a bit more
complex, not just doing some rewrites. As you can see, i tried with
returning
ok, declined, nothing, but nothing worked.

Regards,
Sven

Hi,

i’m replying to myself because after playing around a lot i think i
found
something i would call “solution” :wink:

The problem was (or is) that the location matches etc. did match
multiple
times, so that the perl module was called twice. The second call ended
up
into “nothing” or something like a loop (it was no loop or similar
reported)
and thus nginx didn’t deliver any content nor contacted the upstream.

Now i’ve rewritten the module and the config like this:

module:
internal_redirect(“/somethinginternal/$file”);

nginx.conf:
location ^~ /somethinginternal/ {
internal;
rewrite ^/somethinginternal/(.+)$ /$1 break;
proxy_pass http://internal-host;

}
location ~* .(png|jpg|gif)$ {
perl testpackage::handler;
}
location / {
proxy_pass http://other-internal;

}

The keypoints where: the ^~ and ~* are for the priority, so that
somethinginternal
stops processing of the locations. Another thing is: rewrite… break;
instead of
rewrite… last; - last seems to abort the processing and the request
doesn’t get
forwarded to the proxy.

This is probably not the best solution, and since its perl, maybe its
slow, too.
But if this will work (will need some more testing) i’ll probably
“force” :wink:
someone to rewrite this as nginx module. Should things make more easy…
i think.

Talking about performance: the perl module is quick, but as far as i
know, it
blocks processing, right? Are there some statistics how the speed
decreases?
Like “processing 1500r/s with plain nginx, using a small embedded perl
module,
the rate drops to 250r/s”?

Just to be clear: the module just does some comparing and rewrite, its
no database
involved or so, just some internal math and stuff (all hopefully as
quick as
possible).

Last question: is it possible to pass some variable to a perl module?
like
“set $myvar 123;” and accessing $myvar somehow in the module?

Thanks for all the support so far.

Many regards,
Sven

Am 15.12.2010 06:42, schrieb Sven ‘Darkman’ Michels: