# Two small questions about embedded perl

**URL:** <https://www.ruby-forum.com/t/two-small-questions-about-embedded-perl/200538>\
**Category:** NGINX\
**Created:** [December 14, 2010, 10:38pm UTC](https://www.ruby-forum.com/t/two-small-questions-about-embedded-perl/200538 "2010-12-14T22:38:17Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Dobai-Pataky\_BSSSSl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/77aa72/32.png) [@Dobai-Pataky\_BSSSSl](https://www.ruby-forum.com/u/Dobai-Pataky_BSSSSl)\
**Post date:** [December 14, 2010, 10:38pm UTC](https://www.ruby-forum.com/t/two-small-questions-about-embedded-perl/200538/1 "2010-12-14T22:38:17Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Sven\_SDarkmanS\_Mich](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e99b99/32.png) [@Sven\_SDarkmanS\_Mich](https://www.ruby-forum.com/u/Sven_SDarkmanS_Mich)\
**Post date:** [December 14, 2010, 11:00pm UTC](https://www.ruby-forum.com/t/two-small-questions-about-embedded-perl/200538/2 "2010-12-14T23:00:16Z")

</div>

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.

> **[Igor Sysoev](http://sysoev.ru/en/)**

---

<div class="post-metadata">

**Author:** ![Sven\_SDarkmanS\_Mich](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e99b99/32.png) [@Sven\_SDarkmanS\_Mich](https://www.ruby-forum.com/u/Sven_SDarkmanS_Mich)\
**Post date:** [December 14, 2010, 11:29pm UTC](https://www.ruby-forum.com/t/two-small-questions-about-embedded-perl/200538/3 "2010-12-14T23:29:45Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Sven\_SDarkmanS\_Mich](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e99b99/32.png) [@Sven\_SDarkmanS\_Mich](https://www.ruby-forum.com/u/Sven_SDarkmanS_Mich)\
**Post date:** [December 14, 2010, 11:39pm UTC](https://www.ruby-forum.com/t/two-small-questions-about-embedded-perl/200538/4 "2010-12-14T23:39:46Z")

</div>

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.

> **[Igor Sysoev](http://sysoev.ru/en/)**

---

<div class="post-metadata">

**Author:** ![Sven\_SDarkmanS\_Mich](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e99b99/32.png) [@Sven\_SDarkmanS\_Mich](https://www.ruby-forum.com/u/Sven_SDarkmanS_Mich)\
**Post date:** [December 15, 2010, 6:44am UTC](https://www.ruby-forum.com/t/two-small-questions-about-embedded-perl/200538/5 "2010-12-15T06:44:05Z")

</div>

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/](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

---

<div class="post-metadata">

**Author:** ![Sven\_SDarkmanS\_Mich](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e99b99/32.png) [@Sven\_SDarkmanS\_Mich](https://www.ruby-forum.com/u/Sven_SDarkmanS_Mich)\
**Post date:** [December 16, 2010, 10:00pm UTC](https://www.ruby-forum.com/t/two-small-questions-about-embedded-perl/200538/6 "2010-12-16T22:00:27Z")

</div>

Hi,

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

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](http://internal-host);  
…  
}  
location ~\* .(png|jpg|gif)$ {  
perl testpackage::handler;  
}  
location / {  
proxy\_pass [http://other-internal](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” 😉  
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:
