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?
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.
Most helpful comment
I have to chime in saying that using mruby for this seems very tedious and complicated for someone coming from NGINX.