rack-devel archive mirror (unofficial) https://groups.google.com/group/rack-devel
 help / color / mirror / Atom feed
* Why env.object_id is different in each middleware?
@ 2009-12-09 22:59 Iñaki Baz Castillo
  2009-12-09 23:15 ` Iñaki Baz Castillo
  0 siblings, 1 reply; 7+ messages in thread
From: Iñaki Baz Castillo @ 2009-12-09 22:59 UTC (permalink / raw)
  To: rack-devel

Hi, I've realized that env.object_id is different when inspecting it in each 
middleware or final application in a Rack builder. How is possible?

In my case I use this simple builder:

---------------------------------------
::Rack::Builder.new do

  use ::Clogger, ...

  map "/", &::MyApp.handle_request

end


class MyApp
  def self.handle_request
    proc do run Proc.new { |env|
      ::MyApp::Request.handle(env)
    } end
  end
end
---------------------------------------

If I check env.object_id into Clogger call method, and also into 
MyApp.ahndle_request, they have different values.

Since env is a hash I cannot understand why its object_id changes. Any 
explanatuion for it?
This explains that when I change env[XXX] into my final appplication 
MyApp.handle_request the change doesn't exist after calling
 resp = @app.call(env)
in the first middleware.

Thanks a lot.
-- 
Iñaki Baz Castillo <ibc@aliax.net>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Why env.object_id is different in each middleware?
  2009-12-09 22:59 Why env.object_id is different in each middleware? Iñaki Baz Castillo
@ 2009-12-09 23:15 ` Iñaki Baz Castillo
  2010-01-04  0:50   ` Tim Carey-Smith
  0 siblings, 1 reply; 7+ messages in thread
From: Iñaki Baz Castillo @ 2009-12-09 23:15 UTC (permalink / raw)
  To: rack-devel

El Miércoles, 9 de Diciembre de 2009, Iñaki Baz Castillo escribió:
> Since env is a hash I cannot understand why its object_id changes. Any 
> explanation for it?
> This explains that when I change env[XXX] into my final appplication 
> MyApp.handle_request the change doesn't exist after calling
>  resp = @app.call(env)
> in the first middleware.

If I add a env["LALA"] in the first middleware then it's visible for following 
middlewares.
However if I add env["LOLO"] in the second middleware this is not visible for 
first middleware after calling "@app.call(env)".

Is it the expected behavior?

Thanks.


-- 
Iñaki Baz Castillo <ibc@aliax.net>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Why env.object_id is different in each middleware?
  2009-12-09 23:15 ` Iñaki Baz Castillo
@ 2010-01-04  0:50   ` Tim Carey-Smith
  2010-01-04  0:58     ` Iñaki Baz Castillo
                       ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Tim Carey-Smith @ 2010-01-04  0:50 UTC (permalink / raw)
  To: rack-devel

On 10/12/2009, at 12:15 PM, Iñaki Baz Castillo wrote:

> El Miércoles, 9 de Diciembre de 2009, Iñaki Baz Castillo escribió:
>> Since env is a hash I cannot understand why its object_id changes.  
>> Any
>> explanation for it?
>> This explains that when I change env[XXX] into my final appplication
>> MyApp.handle_request the change doesn't exist after calling
>> resp = @app.call(env)
>> in the first middleware.
>
> If I add a env["LALA"] in the first middleware then it's visible for  
> following
> middlewares.
> However if I add env["LOLO"] in the second middleware this is not  
> visible for
> first middleware after calling "@app.call(env)".
>
> Is it the expected behavior?
>
> Thanks.

Hi there,

I've hit this before. This is because you are using Rack::URLMap (via  
Builder#map).
The inner app is called with a new env hash.

> diff --git a/lib/rack/urlmap.rb b/lib/rack/urlmap.rb
> index b699d35..3374535 100644
> --- a/lib/rack/urlmap.rb
> +++ b/lib/rack/urlmap.rb
> @@ -45,7 +45,7 @@ module Rack
>          next unless rest.empty? || rest[0] == ?/
>
>          return app.call(
> -          env.merge(
> +          env.merge!(
>              'SCRIPT_NAME' => (script_name + location),
>              'PATH_INFO'   => rest))
>        }

Is this patch useful?
Is it useful to assume that a request will only have a single env hash?
Will it make Rack::Cascade and friends behave incorrectly?

Should URLMap revert the change in an ensure to allow subsequent  
requests to function?

Hope this explains the behaviour,
Tim

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Why env.object_id is different in each middleware?
  2010-01-04  0:50   ` Tim Carey-Smith
@ 2010-01-04  0:58     ` Iñaki Baz Castillo
  2010-01-04 19:44     ` Iñaki Baz Castillo
  2010-01-05 20:57     ` Ryan Tomayko
  2 siblings, 0 replies; 7+ messages in thread
From: Iñaki Baz Castillo @ 2010-01-04  0:58 UTC (permalink / raw)
  To: rack-devel

El Lunes, 4 de Enero de 2010, Tim Carey-Smith escribió:

> > diff --git a/lib/rack/urlmap.rb b/lib/rack/urlmap.rb
> > index b699d35..3374535 100644
> > --- a/lib/rack/urlmap.rb
> > +++ b/lib/rack/urlmap.rb
> > @@ -45,7 +45,7 @@ module Rack
> >          next unless rest.empty? || rest[0] == ?/
> >
> >          return app.call(
> > -          env.merge(
> > +          env.merge!(
> >              'SCRIPT_NAME' => (script_name + location),
> >              'PATH_INFO'   => rest))
> >        }
> 
> Is this patch useful?
> Is it useful to assume that a request will only have a single env hash?
> Will it make Rack::Cascade and friends behave incorrectly?
> 
> Should URLMap revert the change in an ensure to allow subsequent
> requests to function?
> 
> Hope this explains the behaviour,

Yes it does :)
Thanks.



-- 
Iñaki Baz Castillo <ibc@aliax.net>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Why env.object_id is different in each middleware?
  2010-01-04  0:50   ` Tim Carey-Smith
  2010-01-04  0:58     ` Iñaki Baz Castillo
@ 2010-01-04 19:44     ` Iñaki Baz Castillo
  2010-01-05 20:57     ` Ryan Tomayko
  2 siblings, 0 replies; 7+ messages in thread
From: Iñaki Baz Castillo @ 2010-01-04 19:44 UTC (permalink / raw)
  To: rack-devel

El Lunes, 4 de Enero de 2010, Tim Carey-Smith escribió:
> Is this patch useful?
> Is it useful to assume that a request will only have a single env hash?
> Will it make Rack::Cascade and friends behave incorrectly?
> 
> Should URLMap revert the change in an ensure to allow subsequent  
> requests to function?

A workaround is creating an initial middleware (like rack-config), adding some 
empty entries to env hash and latter, in other middlewares or final 
application, using env["NEW_ENTRY"].replace.

Of course this is a hack as it's only valid if the new entry is a String or an 
object supporting "replace".


  class Init
    def initialize(app)
      @app = app
    end

   def call(env)
      # Create env["REMOTE_USER"] so it can be latter replaced
      # (String#replaced) by the main application and Clogger will log it.
      env["REMOTE_USER"] = ""
      @app.call(env)
    end
  end



And in config.ru:

  ---------------------------------
  use Init

  use ::Clogger, xxxxx

  run MyApp.new
  ---------------------------------


Then in case env["REMOTE_USER"] is set into MyApp it should be set as follows:

  class MyApp
    def call(env)
      ...getting username string...
      env["REMOTE_USER"].replace(username)
      ...
    end
  end


Would be any performance penalty in using env.merge! like you suggest rather 
than env.merge?

Regards.

-- 
Iñaki Baz Castillo <ibc@aliax.net>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Why env.object_id is different in each middleware?
  2010-01-04  0:50   ` Tim Carey-Smith
  2010-01-04  0:58     ` Iñaki Baz Castillo
  2010-01-04 19:44     ` Iñaki Baz Castillo
@ 2010-01-05 20:57     ` Ryan Tomayko
  2010-01-05 23:47       ` Iñaki Baz Castillo
  2 siblings, 1 reply; 7+ messages in thread
From: Ryan Tomayko @ 2010-01-05 20:57 UTC (permalink / raw)
  To: rack-devel

On Sun, Jan 3, 2010 at 4:50 PM, Tim Carey-Smith <g@spork.in> wrote:
> On 10/12/2009, at 12:15 PM, Iñaki Baz Castillo wrote:
>
>> El Miércoles, 9 de Diciembre de 2009, Iñaki Baz Castillo escribió:
>>>
>>> Since env is a hash I cannot understand why its object_id changes. Any
>>> explanation for it?
>>> This explains that when I change env[XXX] into my final appplication
>>> MyApp.handle_request the change doesn't exist after calling
>>> resp = @app.call(env)
>>> in the first middleware.
>>
>> If I add a env["LALA"] in the first middleware then it's visible for
>> following
>> middlewares.
>> However if I add env["LOLO"] in the second middleware this is not visible
>> for
>> first middleware after calling "@app.call(env)".
>>
>> Is it the expected behavior?
>>
>> Thanks.
>
> Hi there,
>
> I've hit this before. This is because you are using Rack::URLMap (via
> Builder#map).
> The inner app is called with a new env hash.
>
>> diff --git a/lib/rack/urlmap.rb b/lib/rack/urlmap.rb
>> index b699d35..3374535 100644
>> --- a/lib/rack/urlmap.rb
>> +++ b/lib/rack/urlmap.rb
>> @@ -45,7 +45,7 @@ module Rack
>>         next unless rest.empty? || rest[0] == ?/
>>
>>         return app.call(
>> -          env.merge(
>> +          env.merge!(
>>             'SCRIPT_NAME' => (script_name + location),
>>             'PATH_INFO'   => rest))
>>       }
>
> Is this patch useful?
> Is it useful to assume that a request will only have a single env hash?
> Will it make Rack::Cascade and friends behave incorrectly?
>
> Should URLMap revert the change in an ensure to allow subsequent requests to
> function?

This is something I've always thought should be included in the rack
spec. Should a rack component, A, that calls another component, B, be
able to assume that env modifications made by B (or downstream) will
be visible in the env passed by A when B returns? As of right now,
there's a number of core and contrib middleware that assume: no. The
URLMap example above is a good one. A lot of middleware pass a copy of
the env downstream instead of modifying and relaying the env provided.

I see this come up fairly often but I'm not sure there's ever been a
good use case for it. It's usually a sign that you're using the env
where you should be using the response tuple. e.g., instead of putting
something in the env, put it in the response headers or convey it via
status code.

Or maybe this really is something the env could be useful for and I've
just never run into a good case. Can anyone provide real examples of
where it would be necessary?

Thanks,
Ryan

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Why env.object_id is different in each middleware?
  2010-01-05 20:57     ` Ryan Tomayko
@ 2010-01-05 23:47       ` Iñaki Baz Castillo
  0 siblings, 0 replies; 7+ messages in thread
From: Iñaki Baz Castillo @ 2010-01-05 23:47 UTC (permalink / raw)
  To: rack-devel

El Martes, 5 de Enero de 2010, Ryan Tomayko escribió:
> Or maybe this really is something the env could be useful for and I've
> just never run into a good case. Can anyone provide real examples of
> where it would be necessary?

My real case:

I want to use Clogger to log the authenticated user ($env["REMOTE_USER"]).

Clogger expects that it runs after an authentication middleware which adds 
such env entry. However in my case I need to decide the "remote_user" in the 
final Rack application so I need that changes done in env by the last Rack 
application are visible for previous middlewares (Clogger).

Perhaps env shouldn't be used for this purpose, but what else? adding such 
info in the response headers seem a hack to me, what about if I want to pass 
an object or a hash rather than a single string?


-- 
Iñaki Baz Castillo <ibc@aliax.net>

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2010-01-05 23:47 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-12-09 22:59 Why env.object_id is different in each middleware? Iñaki Baz Castillo
2009-12-09 23:15 ` Iñaki Baz Castillo
2010-01-04  0:50   ` Tim Carey-Smith
2010-01-04  0:58     ` Iñaki Baz Castillo
2010-01-04 19:44     ` Iñaki Baz Castillo
2010-01-05 20:57     ` Ryan Tomayko
2010-01-05 23:47       ` Iñaki Baz Castillo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).