H2o: Rewrite... again, sorry!

Created on 4 Feb 2016  ·  3Comments  ·  Source: h2o/h2o

It seems there are quite a few users who are looking for how to rewrite URLs in h2o. mruby makes it possible, but is not clear how. I quickly explain my latest challenge:

On our server, we have to map query strings to actual files on the server; and these may include blank spaces (or %20 when URL-encoded). For example:
example.com/search?item=something%20and%somethingelse should get the file
example.com/search/something_and_somethingelse

I read the mruby examples for h2o and the Rack specs, but I do not quite understand what I need to write to tell h2o to use a different path. I can read the PATH_INFO and QUERY_STRING environment variables, but how do I communicate the new values back to the h2o server ("look here instead of there")?

On a related note, I found a seemingly well-known gem called "rack-rewrite". And I was wondering, if this might help me with my rewrite rules, and how such a gem could be combined with my h2o server. Do you have an example somewhere?

enhancement help wanted mruby

Most helpful comment

I have to chime in saying that using mruby for this seems very tedious and complicated for someone coming from NGINX.

All 3 comments

I can read the PATH_INFO and QUERY_STRING environment variables, but how do I communicate the new values back to the h2o server ("look here instead of there")?

You should set reproxy: on in your configuration file and return a response with an x-reproxy-url header set. That instructs the reproxy handler to return the contents of the URL specified with the header.
see also: https://h2o.examp1e.net/configure/mruby_directives.html#delegating-request

On a related note, I found a seemingly well-known gem called "rack-rewrite". And I was wondering, if this might help me with my rewrite rules, and how such a gem could be combined with my h2o server. Do you have an example somewhere?

Rack-rewrite depends on the _libraries_ provided by Rack, and I am afraid you cannot use it as is from mruby (though IMO porting it to mruby would not be hard).

I do understand there is a need for a more declarative way of specifying redirects rather than writing the rules down using mruby; it would be great if somebody could come up with a port of rack-rewrite or something similar.

Thank you so much! Now I got it.

For the record - and everyone looking for something similar: The following part of h2o.conf replaces a single empty space with an underscore in all URLs under /test/

E.g. https://www.example.com/test/something%20and%20somethingelse is rewritten to
https://www.example.com/test/something_and_somethingelse

Should h2o not find the rewritten file, it internally redirects to a PHP script which - in my case - makes a lookup from a database to fetch the desired content.

      "/test":
        reproxy: ON
        mruby.handler: |
          lambda do |env|
            if /^\/([^ ]+[ ][^ ]+)/.match(env["PATH_INFO"]) # All URLs with at least one empty space NOT in the beginning or end
              str = "#{$1}"
              str = str.gsub( %r{[ ]}, '_') # replace every single empty space with an underscore
              return [307, {"x-reproxy-url" => "https://www.example.com/test/#{str}"}, []] # reproxy to rewritten URL
            end
            return [399, {}, []]
          end
        file.dir: "/usr/local/www/apache22/data/test/json"   # serve static files if found
        redirect:           # if not found, internally redirect to /test/index.php/<path>
          url: /test/index.php/
          internal: YES
          status: 307

I have to chime in saying that using mruby for this seems very tedious and complicated for someone coming from NGINX.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

utrenkner picture utrenkner  ·  7Comments

Ys88 picture Ys88  ·  5Comments

daniel-lucio picture daniel-lucio  ·  5Comments

proyb6 picture proyb6  ·  5Comments

paulpref picture paulpref  ·  5Comments