views:

248

answers:

4

I'm using webrick (the built-in ruby webserver) to serve .rhtml files (html with ruby code embedded --like jsp).

It works fine, but I can't figure out how to access parameters (e.g. http://localhost/mypage.rhtml?foo=bar) from within the ruby code in the .rhtml file. (Note that I'm not using the rails framework, only webrick + .rhtml files)

Thanks

+1  A: 

Browsing the documentation, it looks like you should have an HTTPRequest from which you can get the query string. You can then use parse_query to get a name/value hash.

Alternatively, it's possible that just calling query() will give you the hash directly... my Ruby-fu isn't quite up to it, but you might want to at least give it a try.

Jon Skeet
The problem is I need to get the *instance* of HTTPRequest associated with the request.
cibercitizen1
query() within the .rhtml failsBy the way the class name HTTPRequest is available within the .rhtml,and also I can access the webrick HTTPServer object
cibercitizen1
+2  A: 

According to the source code of erbhandler it runs the rhtml files this way:

    Module.new.module_eval{
      meta_vars = servlet_request.meta_vars
      query = servlet_request.query
      erb.result(binding)
    }

So the binding should contain a query (which contains a hash of the query string) and a meta_vars variable (which contains a hash of the environment, like SERVER_NAME) that you can access inside the rhtml files (and the servlet_request and servlet_response might be available too, but I'm not sure about them).

If that is not the case you can also try querying the CGI parameter ENV["QUERY_STRING"] and parse it, but this should only be as a last resort (and it might only work with CGI files).

SztupY
@SztupY: well, your answer drove me to the actual solution. See it below.
cibercitizen1
A: 

You don't give much details, but I imagine you have a servlet to serve the files you will process with erb, and by default the web server serves any static file in a public directory.

require 'webrick'
include WEBrick
require 'erb'

s = HTTPServer.new( :Port => 8080,:DocumentRoot    => Dir::pwd + "/public" )

class MyServlet < HTTPServlet::AbstractServlet
  def do_GET(req, response)
    File.open('public/my.rhtml','r') do |f|
     @template = ERB.new(f.read)
    end
    response.body = @template.result(binding)
    response['Content-Type'] = "text/html"
   end
end

s.mount("/my", MyServlet)

trap("INT"){
  s.shutdown
}
s.start

This example is limited, when you go to /my always the same file is processed. Here you should construct the file path based on the request path. Here I said a important word: "request", everything you need is there.

To get the HTTP header parameters, use req[header_name]. To get the parameters in the query string, use req.query[param_name]. req is the HTTPRequest object passed to the servlet.

Once you have the parameter you need, you have to bind it to the template. In the example we pass the binding object from self (binding is defined in Kernel, and it represents the context where code is executing), so every local variable defined in the do_GET method would be available in the template. However, you can create your own binding for example passing a Proc object and pass it to the ERB processor when calling 'result'.

Everything together, your solution would look like:

  def do_GET(req, response)
    File.open('public/my.rhtml','r') do |f|
     @template = ERB.new(f.read)
    end

    foo = req.query["foo"]
    response.body = @template.result(binding)
    response['Content-Type'] = "text/html"
   end
duncan
+1  A: 

This is the solution:

(suppose the request is http://your.server.com/mypage.rhtml?foo=bar)

 <html>

    <body>

    This is my page (mypage.rhtml, served by webrick)

    <%
    # embedded ruby code

    servlet_request.query ["foo"] # this simply prints bar on console

    %>

    </body>

</html>
cibercitizen1
It's kinda strange that you have to use eval
SztupY
@SztupY: Well, it's the way the official docs (http://ruby-doc.org/core/classes/Binding.html) explains how to find out the value of a variable by its string name in the context (binding) you are.
cibercitizen1
Yes but the `binding` method returns the actual binding, so `eval("x",binding)` should be equivalent to `eval("x")` which is equivalent to simply `x`.
SztupY
You are right! My problem was just only not knowing servlet_request.query. (I change my answer).
cibercitizen1