# Setting memcache keys in eval block

**URL:** <https://www.ruby-forum.com/t/setting-memcache-keys-in-eval-block/183117>\
**Category:** NGINX\
**Created:** [February 8, 2010, 1:39pm UTC](https://www.ruby-forum.com/t/setting-memcache-keys-in-eval-block/183117 "2010-02-08T13:39:41Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![mflive](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e99b99/32.png) [@mflive](https://www.ruby-forum.com/u/mflive)\
**Post date:** [February 8, 2010, 1:39pm UTC](https://www.ruby-forum.com/t/setting-memcache-keys-in-eval-block/183117/1 "2010-02-08T13:39:41Z")

</div>

Hello,

How can i set a memcache key using an arbitrary variable? It seems so  
straightforward but i cannot get it up and running. I try to fetch  
memcache  
results using eval, which i will then pass to memcache once again.

This works:  
set $memcached\_key $cookie\_token;  
memcached\_pass 127.0.0.1:11211;

This doesn’t work:  
set $cookie\_token ‘bla’;  
set $memcached\_key $cookie\_token;  
memcached\_pass 127.0.0.1:11211;

Both Memcached modules will complain that the memcached\_key or memc\_key  
variable was not set, this all happens inside an eval block, outside the  
eval  
block does work as expected . I’m using the latest 0.7 stable Nginx and  
tried  
both Memcached modules.

Regards,

Markus J. - Technisch Architect - Buyways BV  
[http://www.linkedin.com/in/markus17](http://www.linkedin.com/in/markus17)  
050-8536620 / 06-50258350

---

<div class="post-metadata">

**Author:** ![mflive](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e99b99/32.png) [@mflive](https://www.ruby-forum.com/u/mflive)\
**Post date:** [February 10, 2010, 11:21am UTC](https://www.ruby-forum.com/t/setting-memcache-keys-in-eval-block/183117/2 "2010-02-10T11:21:26Z")

</div>

Hello,

Thanks for your reply. The manual indeed tells us to set it inside the  
block,  
which i am doing. However, the first result cannot be passed to the  
second  
eval block;

The following does not work; it sends the error message $memc\_key  
variable is  
not set:

```
  eval $key
  {
    # Check if we got the token, a 160bit SHA1 hash
    if ($cookie_token ~* "([A-Za-z0-9]{40})")
    {
      # Attempt to retrieve the token from memcache
      set $memc_cmd 'get';
      set $memc_key $cookie_token;

      # Retrieve the token's value and store it in the local key 

```

variable  
memc\_pass 127.0.0.1:11211;  
}  
}  
eval $email  
{  
set $memc\_cmd ‘get’;  
set $memc\_key $key;  
memc\_pass 127.0.0.1:11211;  
}

```
  echo 'test';
  echo $email;
  echo_flush;

```

I really need two seperate gets. Nesting the second eval in the first  
is also  
not allowed because then we have a duplicate memc\_pass which it  
complains  
about.

For the moment i `solved` this issue by adding a second location which  
the  
first eval proxies to, this does work but shows up as a second HTTP  
request in  
the logs; this feels a bit slow and i really would like to handle this  
subject  
within one location directive.

To summarize the problem; using a variable set by eval in a subsequent  
eval  
block does not work.

Some advice is much appreciated 🙂

Cheers,

The eval module’s handler runs before the ngx\_rewrite module. So make  
sure you always “set” variables inside the eval block. The “set”  
directives outside the eval block does not work because they run after  
the “eval” block and hence the memcached handler complete.

IIRC, this was mentioned in the ngx\_eval module’s documentation.

Markus J. - Technisch Architect - Buyways BV  
[http://www.linkedin.com/in/markus17](http://www.linkedin.com/in/markus17)  
050-8536620 / 06-50258350

---

<div class="post-metadata">

**Author:** ![mflive](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e99b99/32.png) [@mflive](https://www.ruby-forum.com/u/mflive)\
**Post date:** [February 9, 2010, 3:40am UTC](https://www.ruby-forum.com/t/setting-memcache-keys-in-eval-block/183117/3 "2010-02-09T03:40:19Z")

</div>

On Mon, Feb 8, 2010 at 8:36 PM, Markus J. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Both Memcached modules will complain that the memcached\_key or memc\_key  
> variable was not set, this all happens inside an eval block, outside the eval  
> block does work as expected.

The eval module’s handler runs before the ngx\_rewrite module. So make  
sure you always “set” variables inside the eval block. The “set”  
directives outside the eval block does not work because they run after  
the “eval” block and hence the memcached handler complete.

IIRC, this was mentioned in the ngx\_eval module’s documentation.

Cheers,  
-agentzh

---

<div class="post-metadata">

**Author:** ![mflive](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e99b99/32.png) [@mflive](https://www.ruby-forum.com/u/mflive)\
**Post date:** [February 10, 2010, 11:36am UTC](https://www.ruby-forum.com/t/setting-memcache-keys-in-eval-block/183117/4 "2010-02-10T11:36:04Z")

</div>

On Wed, Feb 10, 2010 at 6:18 PM, Markus J. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> Thanks for your reply. The manual indeed tells us to set it inside the block,  
> which i am doing. However, the first result cannot be passed to the second  
> eval block;

No, it won’t work. According to the current implementation, only one  
eval block can take effect in a single location.

I must admit parallel eval blocks can be _very_ useful and I believe  
it should not be that hard to implement. But I have other missions to  
do first atm 😉

Actually I want something much more general, that can be mixed with  
other rewrite directives, like this:

```
 set $foo 'hi';
 set_capture_location $res '/foo';
 if ($res ~ 'xxx') { ... }
 set_capture_subrequest $res POST '/bar' 'body here';
 if ($res ~ 'xxx') { ... }
 ....

```

I’ll ask Marcus C. if he has any plan to add support for such  
things to his set\_var submodule in his grand NDK project. Then an  
ngx\_capture module should be straightforward 😉

Cheers,  
-agentzh

---

<div class="post-metadata">

**Author:** ![mflive](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e99b99/32.png) [@mflive](https://www.ruby-forum.com/u/mflive)\
**Post date:** [February 11, 2010, 5:06am UTC](https://www.ruby-forum.com/t/setting-memcache-keys-in-eval-block/183117/5 "2010-02-11T05:06:13Z")

</div>

Markus J. wrote:

> I did perform some simple benchmarks but they aren’t really alright since i
> 
> > I must admit parallel eval blocks can be very useful and I believe  
> > if ($res ~ ‘xxx’) { … }  
> > …
> > 
> > I’ll ask Marcus C. if he has any plan to add support for such  
> > things to his set\_var submodule in his grand NDK project. Then an  
> > ngx\_capture module should be straightforward 😉

Yes, this currently isn’t possible (AFAICT), because of how the  
http\_rewrite\_module’s phase handler works, but it should be possible  
with easy modification of that, which will allow for recalling rewrites  
after subrequests. I’m busy with other stuff right now, but I’ll try to  
build the generic interface (if not the subrequest part) soon and  
include it in the first launched version of the NDK.

Marcus.

---

<div class="post-metadata">

**Author:** ![mflive](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e99b99/32.png) [@mflive](https://www.ruby-forum.com/u/mflive)\
**Post date:** [February 10, 2010, 11:48am UTC](https://www.ruby-forum.com/t/setting-memcache-keys-in-eval-block/183117/6 "2010-02-10T11:48:57Z")

</div>

Thank you for your quick answer, although it is not quite a satisfaction  
to  
read it’s not possible at the moment.

How can i stay up to date for such a feature if it were to be  
implemented in  
the - hopefully nearby - future?

I have another question, is my current solution really much slower than  
doing  
it all in one location directive? I am now proxying the request the  
myself  
where i can set the second eval block.

I did perform some simple benchmarks but they aren’t really alright  
since i  
cannot really compare the situations but 2 http requests + 2 memcache  
requests  
are quite slow in the end.

Thanks.

> ```
> set $foo 'hi';
> set_capture_location $res '/foo';
> if ($res ~ 'xxx') { ... }
> set_capture_subrequest $res POST '/bar' 'body here';
> if ($res ~ 'xxx') { ... }
> ....
> 
> ```
> 
> I’ll ask Marcus C. if he has any plan to add support for such  
> things to his set\_var submodule in his grand NDK project. Then an  
> ngx\_capture module should be straightforward 😉

Markus J. - Technisch Architect - Buyways BV  
[http://www.linkedin.com/in/markus17](http://www.linkedin.com/in/markus17)  
050-8536620 / 06-50258350

---

<div class="post-metadata">

**Author:** ![mflive](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e99b99/32.png) [@mflive](https://www.ruby-forum.com/u/mflive)\
**Post date:** [February 11, 2010, 10:41am UTC](https://www.ruby-forum.com/t/setting-memcache-keys-in-eval-block/183117/7 "2010-02-11T10:41:36Z")

</div>

On Thu, Feb 11, 2010 at 5:35 PM, agentzh [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> set $res2 $2;
> ...
> }
> 
> ```
> 
> }

Oops, my bad! new subrequests issued by  
echo\_location/echo\_location\_async in an eval block will not work at  
all because ngx\_eval’s output filter cannot capture its  
sub-sub-request’s output.

Sorry about that. My fork of ngx\_eval is currently limited to content  
handlers and output filters that do not issue subrequests themselves.

Cheers,  
-agentzh

---

<div class="post-metadata">

**Author:** ![mflive](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e99b99/32.png) [@mflive](https://www.ruby-forum.com/u/mflive)\
**Post date:** [February 11, 2010, 10:35am UTC](https://www.ruby-forum.com/t/setting-memcache-keys-in-eval-block/183117/8 "2010-02-11T10:35:45Z")

</div>

On Wed, Feb 10, 2010 at 6:45 PM, Markus J. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> How can i stay up to date for such a feature if it were to be implemented in  
> the - hopefully nearby - future?

Yes, hopefully in the near future 🙂 I’m busy with the ngx\_array\_var  
module development as well as the ngx\_srcache module atm. Maybe I’ll  
have some spare time to hack that in after these modules are out.

But there’s a workaround that you can try out _now_. Please read on.

I do have a personal fork of the ngx\_eval module here:

```
http://github.com/agentzh/nginx-eval-module

```

Currently it has support for arbitrary content handlers as well as  
output filters. Here’s some quick examples that you _may_ be  
interested in:

```
location /echo {
    eval_subrequest_in_memory off;
    eval $a {
        echo_before_body BEFORE;
        echo THIS;
    }
    echo '[$a]';
}

```

Then GET /echo yields

```
[BEFORE
THIS]

```

asssuming you configured the ngx\_echo module _after_ the ngx\_eval  
module such that the echo\_before\_body filter runs before ngx\_eval’s.

This also means that you can take advantage of the echo\_location\_async  
or echo\_location directives provided by ngx\_echo to do your multiple  
eval’s in a single location. Like this:

```
location /echo {
    eval_subrequest_in_memory off;
    eval $union {
        echo_location_async /memc1;
        echo 'XXXX';
        echo_location_async /memc2;
    }
    if ($union ~ '(.*)XXXX\n(.*)') {
         set $res1 $1;
         set $res2 $2;
         ...
    }
}
location /memc1 {
      memcached_pass ...;
}
location /memc2 {
      memcached_pass ...;
}

```

This should be more efficient than the internal proxying approach.  
Feel free to do some benchmark on your side to confirm this 😉

Cheers,  
-agentzh

P.S. I’ve sent a pull request to Valery K. in the hope to get  
my patch for ngx\_eval merged into the mainstream. But no reply yet.  
Sigh.

---

<div class="post-metadata">

**Author:** ![mflive](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e99b99/32.png) [@mflive](https://www.ruby-forum.com/u/mflive)\
**Post date:** [February 12, 2010, 4:27am UTC](https://www.ruby-forum.com/t/setting-memcache-keys-in-eval-block/183117/9 "2010-02-12T04:27:04Z")

</div>

On Thu, Feb 11, 2010 at 12:05 PM, Marcus C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> Yes, this currently isn’t possible (AFAICT), because of how the  
> http\_rewrite\_module’s phase handler works, but it should be possible with  
> easy modification of that, which will allow for recalling rewrites after  
> subrequests.

Yay! Marcus you rock 😉

> I’m busy with other stuff right now, but I’ll try to build the  
> generic interface (if not the subrequest part) soon and include it in the  
> first launched version of the NDK.

Heh, I can do the subrequest part, which is easy for me 😉

Thanks!  
-agentzh

---

<div class="post-metadata">

**Author:** ![mflive](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e99b99/32.png) [@mflive](https://www.ruby-forum.com/u/mflive)\
**Post date:** [February 12, 2010, 4:25am UTC](https://www.ruby-forum.com/t/setting-memcache-keys-in-eval-block/183117/10 "2010-02-12T04:25:18Z")

</div>

On Thu, Feb 11, 2010 at 5:40 PM, agentzh [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Oops, my bad! new subrequests issued by  
> echo\_location/echo\_location\_async in an eval block will not work at  
> all because ngx\_eval’s output filter cannot capture its  
> sub-sub-request’s output.
> 
> Sorry about that. My fork of ngx\_eval is currently limited to content  
> handlers and output filters that do not issue subrequests themselves.

I suddenly realized last night that I can fix this by walking through  
the r-\>parent chain to find the “sentinel subrequest” (or “top-level  
subrequest”) that is issued directly by the ngx\_eval module and the  
corresponding ctx object (if any). This also applies to the  
ngx\_srcache module that I’ve been working on, which also needs to  
capture response in an output filter.

Cheers,  
-agentzh

---

<div class="post-metadata">

**Author:** ![mflive](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e99b99/32.png) [@mflive](https://www.ruby-forum.com/u/mflive)\
**Post date:** [February 12, 2010, 10:55am UTC](https://www.ruby-forum.com/t/setting-memcache-keys-in-eval-block/183117/11 "2010-02-12T10:55:04Z")

</div>

Hi,

It sounds quite mysterious to me - i’m not a Nginx developer afterall -  
but i  
suppose this is good news for the use case?

Cheers,

> I suddenly realized last night that I can fix this by walking through  
> the r-\>parent chain to find the “sentinel subrequest” (or “top-level  
> subrequest”) that is issued directly by the ngx\_eval module and the  
> corresponding ctx object (if any). This also applies to the  
> ngx\_srcache module that I’ve been working on, which also needs to  
> capture response in an output filter.

Markus J. - Technisch Architect - Buyways BV  
[http://www.linkedin.com/in/markus17](http://www.linkedin.com/in/markus17)  
050-8536620 / 06-50258350

---

<div class="post-metadata">

**Author:** ![mflive](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e99b99/32.png) [@mflive](https://www.ruby-forum.com/u/mflive)\
**Post date:** [February 14, 2010, 4:32pm UTC](https://www.ruby-forum.com/t/setting-memcache-keys-in-eval-block/183117/12 "2010-02-14T16:32:30Z")

</div>

Markus J. wrote:

> Thank you for your quick answer, although it is not quite a satisfaction to  
> read it’s not possible at the moment.
> 
> How can i stay up to date for such a feature if it were to be implemented in  
> the - hopefully nearby - future?

I just have pushed a change to nginx eval module which allows multiple  
eval blocks in one location:

> **[GitHub - vkholodkov/nginx-eval-module at...](https://github.com/vkholodkov/nginx-eval-module/tree/bba2d53fc1d8f118fb79424250db8c9e832b66c1)**
>
> bba2d53fc1d8f118fb79424250db8c9e832b66c1

Hope this helps!

> > ```
> > set $foo 'hi';
> > set_capture_location $res '/foo';
> > if ($res ~ 'xxx') { ... }
> > set_capture_subrequest $res POST '/bar' 'body here';
> > if ($res ~ 'xxx') { ... }
> > ....
> > 
> > ```
> > 
> > I’ll ask Marcus C. if he has any plan to add support for such  
> > things to his set\_var submodule in his grand NDK project. Then an  
> > ngx\_capture module should be straightforward 😉

–  
Best regards,  
Valery K.

---

<div class="post-metadata">

**Author:** ![mflive](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e99b99/32.png) [@mflive](https://www.ruby-forum.com/u/mflive)\
**Post date:** [February 13, 2010, 11:23am UTC](https://www.ruby-forum.com/t/setting-memcache-keys-in-eval-block/183117/13 "2010-02-13T11:23:49Z")

</div>

On Fri, Feb 12, 2010 at 5:42 PM, Markus J. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> It sounds quite mysterious to me - i’m not a Nginx developer afterall - but i  
> suppose this is good news for the use case?

Good news 🙂 But there’s one missing bit that I’ve forgotten to  
mention: we’ll have to take into account the postponed chain for  
subrequests.

Cheers,  
-agentzh

---

<div class="post-metadata">

**Author:** ![mflive](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e99b99/32.png) [@mflive](https://www.ruby-forum.com/u/mflive)\
**Post date:** [February 15, 2010, 10:56am UTC](https://www.ruby-forum.com/t/setting-memcache-keys-in-eval-block/183117/14 "2010-02-15T10:56:52Z")

</div>

Valery!

It works like a charm! I can now have multiple \*\_pass directives inside  
a  
single location block. Also, multiple eval blocks are supported and work  
as  
expected!

Thanks thanks thanks!

Cheers,

> [GitHub - vkholodkov/nginx-eval-module at bba2d53fc1d8f118fb79424250db8c9e832b66c1 · GitHub](http://github.com/vkholodkov/nginx-eval-module/blob/bba2d53fc1d8f118fb794242)  
> 50db8c9e832b66c1/ngx\_http\_eval\_module.c

Markus J. - Technisch Architect - Buyways BV  
[http://www.linkedin.com/in/markus17](http://www.linkedin.com/in/markus17)  
050-8536620 / 06-50258350

---

<div class="post-metadata">

**Author:** ![mflive](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e99b99/32.png) [@mflive](https://www.ruby-forum.com/u/mflive)\
**Post date:** [February 14, 2010, 9:01pm UTC](https://www.ruby-forum.com/t/setting-memcache-keys-in-eval-block/183117/15 "2010-02-14T21:01:43Z")

</div>

Valery!

This sounds lovely! I’ll try this back at the office tomorrow. I assume  
this also allows for multiple memc\_pass and proxy\_pass directives in a  
single location block?

Anyway, i’m quite happy and thank you very much for your efforts!

Cheers,

Valery K. said:
