Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

H2O.next.call(env) breaks with too many paths #2207

Closed
utrenkner opened this issue Dec 16, 2019 · 3 comments
Closed

H2O.next.call(env) breaks with too many paths #2207

utrenkner opened this issue Dec 16, 2019 · 3 comments

Comments

@utrenkner
Copy link
Contributor

utrenkner commented Dec 16, 2019

I have a h2o.conf with various paths. One is for the /wp-admin directory of a WordPress installation which gets reproxied:

hosts:
  "www.example.test":
    listen:
      [...]
    paths:
      "/.well-known":
        file.dir: "/path/to/.well-known"
      "/robots.txt":
        file.file: "/path/to/robots_block.txt"
     [...]
      "/wp-admin":
        mruby.handler: |
          Proc.new do |env|
            resp = H2O.next.call(env)
            # IN REALITY I DO SOMETHING WITH THE RESPONSE
            # BUT FOR THE TEST I STRIPPED IT OUT
            [399, {}, []]
          end
        proxy.reverse.url: "http://10.0.0.2/wp-admin"
      [...]

This works fine - until I add one more path to the host config. No matter what it contains, it breaks the MRuby line H2O.next.call(env). E.g. adding a /robots2.txt file, breaks it:

hosts:
  "www.example.test":
    listen:
      [...]
    paths:
      "/.well-known":
        file.dir: "/path/to/.well-known"
      "/robots.txt":
        file.file: "/path/to/robots_block.txt"
      "/robots2.txt":
        file.file: "/path/to/robots_block.txt"
     [...]
      "/wp-admin":
        mruby.handler: |
          Proc.new do |env|
            resp = H2O.next.call(env)
            # IN REALITY I DO SOMETHING WITH THE RESPONSE
            # BUT FOR THE TEST I STRIPPED IT OUT
            [399, {}, []]
          end
        proxy.reverse.url: "http://10.0.0.2/wp-admin"
      [...]

A browser request to e.g. https://www.example.test/wp-admin/css/login.min.css is not answered - with no entry in either the access or error log.

After many tests, it seems as if only the number of path-entries triggers the problem. I deleted some paths and added others without any problem. But always at the same number of paths, H2O.next.call(env) stops working. Any call to the /wp-admin directory fails.

Other paths are not affected and continue to function as intended.

Any ideas as to why this problem shows up? Any work-around?

@i110
Copy link
Contributor

i110 commented Jan 4, 2020

@utrenkner I couldn't reproduce not answered - with no entry in either the access or error log behavior, but I guess [399, {}, []] is not what you intended. Returning 399 status code allows you to dispatch the request to the next handler (in your case, proxy.reverse.url) and it never returns to the mruby handler, while your H2O.call.next(env) also dispatch but it captures the response. Thus your handlers under /wp-admin forward the request twice, and your modification to the return value of H2O.next.call is not reflected to the final response. I bet it's not what you want. To fix this problem, just return resp instead of returning 399.

Aside from that, it's odd that the behavior depends on the number of path entries. If it's possible, would you mind sharing your whole configuration to see deeper into the problem?

@utrenkner
Copy link
Contributor Author

@i110 Thank you for your reply. Indeed, I should have just reused resp. But it worked nevertheless, because I do not tweak the response, so re-issuing the same request did not lead to any visible problem. I now changed it to use resp directly as response.

I was able to come up with a very simple configuration, which demonstrates how to trigger the problem.

h2o.conf (just the host section)

hosts:
  test.local:
    listen:
      port: 80
      host: 10.0.0.10
    paths:
      "/dir0":
        file.dir: "/usr/local/www/data/testh2o/dir0"
      "/dir1":
        file.dir: "/usr/local/www/data/testh2o/dir1"
      "/wp-admin":
        mruby.handler-file: /usr/local/etc/h2o/purgeall_cache.rb
        proxy.reverse.url: "https://www.google.com" # this URL is just for testing/demonstration
      "/":
        file.dir: "/usr/local/www/data/testh2o"

/usr/local/etc/h2o/purgeall_cache.rb (it usually looks for a certain header field and if it finds it, issues a http_request to a URL which triggers the purging of a cache, there - for the test/demo it is irrelevant):

proc {|env|
        resp = H2O.next.call(env)
        resp
}

This works! But if I add another path, e.g.

      "/dir2":
        file.dir: "/usr/local/www/data/testh2o/dir2"

I get an Internal Server Error. The error log then says:

in request:/wp-admin:mruby raised: (eval):28: can't modify `SCRIPT_NAME` with `H2O.next`. Is `H2O.reprocess` what you want? (RuntimeError)

Why would that happen? Is there anything I could change to make it work, or is it a bug?

@utrenkner
Copy link
Contributor Author

Refiled this as a bug report.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants