How to access html request parameters for a .rhtml

2019-03-31 03:37发布

问题:

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:

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).



回答2:

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>


回答3:

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.



回答4:

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