24

I know a Rack middleware filter is a Ruby class with an initialize and a call method. I know the call method takes an "env" argument. Something like this:

class MyFilter
  def initialize(app)
  end

  def call(env)
  end
end

My question is: what exactly is the "env" argument sent to "call"? Is this the same as the Rails ENV environment (ie. development, testing, production).

Thanks!

User314159
  • 7,733
  • 9
  • 39
  • 63

5 Answers5

45

env is just a hash. Rack itself and various middlewares add values into it.

To understand what the various keys are in the hash, check out the Rack Specification.

And here is a sample env hash:

{
  "GATEWAY_INTERFACE" => "CGI/1.1",
  "PATH_INFO" => "/index.html",
  "QUERY_STRING" => "",
  "REMOTE_ADDR" => "::1",
  "REMOTE_HOST" => "localhost",
  "REQUEST_METHOD" => "GET",
  "REQUEST_URI" => "http://localhost:3000/index.html",
  "SCRIPT_NAME" => "",
  "SERVER_NAME" => "localhost",
  "SERVER_PORT" => "3000",
  "SERVER_PROTOCOL" => "HTTP/1.1",
  "SERVER_SOFTWARE" => "WEBrick/1.3.1 (Ruby/2.0.0/2013-11-22)",
  "HTTP_HOST" => "localhost:3000",
  "HTTP_USER_AGENT" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0",
  "HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
  "HTTP_ACCEPT_LANGUAGE" => "zh-tw,zh;q=0.8,en-us;q=0.5,en;q=0.3",
  "HTTP_ACCEPT_ENCODING" => "gzip, deflate",
  "HTTP_COOKIE" => "jsonrpc.session=3iqp3ydRwFyqjcfO0GT2bzUh.bacc2786c7a81df0d0e950bec8fa1a9b1ba0bb61",
  "HTTP_CONNECTION" => "keep-alive",
  "HTTP_CACHE_CONTROL" => "max-age=0",
  "rack.version" => [1, 2],
  "rack.input" => #<StringIO:0x007fa1bce039f8>,
  "rack.errors" => #<IO:<STDERR>>,
  "rack.multithread" => true,
  "rack.multiprocess" => false,
  "rack.run_once" => false,
  "rack.url_scheme" => "http",
  "HTTP_VERSION" => "HTTP/1.1",
  "REQUEST_PATH" => "/index.html"
}

And to make it easier to use, checkout Rack::Request which makes it easier to access the values inside the env hash.

lulalala
  • 17,572
  • 15
  • 110
  • 169
10

I suggest that you can try to print the 'env' variable with writing a simple programming.

require "rubygems"
require "rack" 
def pp(hash)
  hash.map {|key,value| "#{key} => #{value}"}.sort.join("<br/>") 
end
Rack::Handler::WEBrick.run lambda {|env| [200,{},[pp(env)]]} , :Port=>3000

enter the link localhost:3000

Joy Hu
  • 556
  • 5
  • 9
  • Nice! A slight update to render actual HTML: `Rack::Handler::WEBrick.run lambda {|env| [200, {'Content-Type' => 'text/html'},[pp(env)]]} , :Port=>5000` – Jan Klimo May 24 '18 at 07:44
  • @JanKlimo, that's good idea. I actually modified a little to output proper HTML when viewed from a browser and plain text when done by curl. https://gist.github.com/akostadinov/02361c02cca88ecfdde81ecfc914e89f – akostadinov Nov 18 '21 at 14:20
5

The env variable is a hash, which contains a lot of useful information including request headers and body, and run-time environment data that may have been added by upstream middleware.

rossta
  • 11,394
  • 1
  • 43
  • 47
1

Looking at the source code depending on which web server you have you can get different values in your env hash. I recommend only using what's in the documentation.

Basically the env is a hash version of the request object specific to the web server. Rack does some work to give a normalized env so the middleware can behave consistently across web servers.

akostadinov
  • 17,364
  • 6
  • 77
  • 85
Garry Polley
  • 4,253
  • 1
  • 22
  • 29
0

I am aware that this is an old question.

However, I'll make an effort to help upcoming ROR developers.

In Rack middleware, the env variable is a hash that holds details about the environment and the incoming HTTP request. It contains details like the request method, route, headers, and other data.

The call function serves as the main entry point for handling incoming requests in a Rack application, which is why you have access to the env hash when you put def call(env) in your middleware. A request is given to the call method of the top Rack component when it is received by a Rack-based application.

The env hash is supplied as an argument to the call function in this scenario because you are creating a unique middleware that is a component of the Rack stack. The call method can read and modify the data in the env hash, which includes information about the environment and the incoming request, in order to process the request.

I suggest looking at this tutorial: link to learn more about the env variable and its function in Rack middleware.

The env variable is explained in detail in this lesson, along with how it is utilized and modified by various Rack stack components.

Adif_Sgaid
  • 79
  • 10