рдореИрдВ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ "рдмрдЧ" рд░рд┐рдкреЛрд░реНрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд░рд┐рд╖реНрдХреГрдд рдХрд░рддрд╛ рд╣реВрдВ, рдХреНрдпреЛрдВрдХрд┐ рдЕрдм рдореИрдВрдиреЗ рдЗрд╕реЗ рдирд╡реАрдирддрдо рд╕реНрд░реЛрддреЛрдВ рдХреЗ рд╕рд╛рде рдлреЗрдбреЛрд░рд╛ рдХреЗ рддрд╣рдд рднреА рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рд╣реИред
рдЗрд╕ рдмрдЧ рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдХреЗ рд▓рд┐рдП, рдЖрдк рдЗрд╕ h2o.conf рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
user: www
access-log: /var/log/h2o/h2o-access.log
error-log: /var/log/h2o/h2o-error.log
listen: 8080
hosts:
"<my-ip-address-here>:8080":
paths:
"/dir0":
mruby.handler: |
proc {|env|
resp = H2O.next.call(env)
resp
}
proxy.reverse.url: "https://www.google.com" # this URL is just for testing/demonstration
"/dir1":
file.dir: "/usr/local/www/data/testh2o/dir1"
"/dir2":
file.dir: "/usr/local/www/data/testh2o/dir2"
"/":
file.dir: "/usr/local/www/data/testh2o"
рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ: рдореИрдВ dir1, dir2 рдФрд░ dir3 рдХреЗ рддрд╣рдд рдлрд╛рдЗрд▓реЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рд╕рдХрддрд╛ рд╣реВрдВред рдФрд░ рдЬрдм рдореИрдВ http://<my-ip-address-here>:8080/dir0
рдЕрдиреБрд░реЛрдз рдХрд░рддрд╛ рд╣реВрдВ рддреЛ рдореБрдЭреЗ Google рд╣реЛрдордкреЗрдЬ рдорд┐рд▓рддрд╛ рд╣реИ (рд╕рд┐рд░реНрдл рдбреЗрдореЛ рдХреЗ рд▓рд┐рдП)ред
рд▓реЗрдХрд┐рди рдПрдХ рдФрд░ /path
рд╕реЗрдЧрдореЗрдВрдЯ рдЬреЛрдбрд╝рдиреЗ рд╕реЗ H20.next.call(env) рдЯреВрдЯ рдЬрд╛рддрд╛ рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ HardnedBSD , FreeBSD рдХреЗ рд▓рд┐рдП
рдЯреВрдЯрд╛ рд╣реБрдЖ h2o.conf:
user: www
access-log: /var/log/h2o/h2o-access.log
error-log: /var/log/h2o/h2o-error.log
listen: 8080
hosts:
"<my-ip-address-here>:8080":
paths:
"/dir0":
mruby.handler: |
proc {|env|
resp = H2O.next.call(env)
# In my production conf I have here code to look for a certain header field.
# If it finds it, this handler makes a http_request() to a certain URL on another server
# in order to trigger emptying a cache.
# This bug demo is independent of this code.
resp
}
proxy.reverse.url: "https://www.google.com" # this URL is just for testing/demonstration
"/dir1":
file.dir: "/usr/local/www/data/testh2o/dir1"
"/dir2":
file.dir: "/usr/local/www/data/testh2o/dir2"
"/dir3":
file.dir: "/usr/local/www/data/testh2o/dir3"
"/":
file.dir: "/usr/local/www/data/testh2o"
рдЕрдм рдореБрдЭреЗ рдПрдХ рдЖрдВрддрд░рд┐рдХ рд╕рд░реНрд╡рд░ рддреНрд░реБрдЯрд┐ рдорд┐рд▓рддреА рд╣реИред рдФрд░ рдлреЗрдбреЛрд░рд╛ рдкрд░ рддреНрд░реБрдЯрд┐ рд▓реЙрдЧ рдХрд╣рддрд╛ рд╣реИ:
[h2o_mruby] in request:/dir0:mruby raised: (eval):28: can't modify `SCRIPT_NAME` with `H2O.next`. Is `H2O.reprocess` what you want? (RuntimeError)
рдпрд╣ рдПрдХ рддрд╛рдЬрд╛ рдлреЗрдбреЛрд░рд╛ 31 рдкрд░ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ H2O рдХреЛ рд╕реНрд░реЛрдд рд╕реЗ b9989220bea9bda30f69083b66166c4c657bdf84 рдкрд░ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред
рдЪреВрдВрдХрд┐ рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдиреЗ H2O.reprocess
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджрд┐рдпрд╛ рдерд╛, рдЕрдм рдореИрдВрдиреЗ рдЗрд╕ рд╡рд┐рдХрд▓реНрдк рдХреЛ рдЖрдЬрдорд╛рдпрд╛ рд╣реИред рд╕рдорд╛рди рдкрд░рд┐рдгрд╛рдо: рдЕрдзрд┐рдХ рдкрде-рдЦрдВрдб рдЬреЛрдбрд╝рдиреЗ рд╕реЗ h2o рдХреНрд░реИрд╢ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред
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: |
proc {|env|
env['SCRIPT_NAME'] = '/proxy-wp-admin'
resp = H2O.reprocess.call(env)
resp
}
"/proxy-wp-admin":
proxy.reverse.url: "https://www.google.com"
рдЗрд╕ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рд╕рд╛рде рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ http://test.local/wp-admin
рдЦреЛрд▓рдиреЗ рд╕реЗ рдореБрдЭреЗ Google рд╣реЛрдордкреЗрдЬ рдорд┐рд▓рддрд╛ рд╣реИред
рд▓реЗрдХрд┐рди рдПрдХ рдФрд░ рдкрде рдЦрдВрдб рдЬреЛрдбрд╝рдирд╛, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдЕрддрд┐рд░рд┐рдХреНрдд /dir2
рдореБрдЭреЗ рдирд┐рдореНрди рддреНрд░реБрдЯрд┐ рджреЗрддрд╛ рд╣реИ:
Feb 4 17:12:11 web2 h2o[34490]: received fatal signal 11
Feb 4 17:12:11 web2 h2o[34490]: [34493] 0x4cf6a0 <???> at /usr/local/bin/h2o
Feb 4 17:12:11 web2 h2o[34490]: [34493] 0x8018c5946 <pthread_sigmask+0x536> at /lib/libthr.so.3
Feb 4 17:12:11 web2 h2o[34490]: [34493] 0x8018c4eb2 <pthread_getspecific+0xe12> at /lib/libthr.so.3
рдХреНрдпрд╛ рдЕрдиреБрдордд рдкрде рдЦрдВрдбреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдкрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрддрдиреА рдХрдо рд╕реАрдорд╛ рд╣реИ ??? рдпрд╣ рдПрдХ рдмрдЧ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рд╕рдВрднрд╡рддрдГ H2O.next
рдХреЗ рд╕рдорд╛рди рд╣реАред
рдЪреВрдВрдХрд┐ рджреЛрдиреЛрдВ, H2O.next
рдФрд░ H20.reprocess
рдЯреВрдЯреЗ рд╣реБрдП рдкреНрд░рддреАрдд рд╣реЛрддреЗ рд╣реИрдВ, рдореБрдЭреЗ рдПрдХ рдФрд░ рд╕рдорд╛рдзрд╛рди рддрд▓рд╛рд╢рдирд╛ рдкрдбрд╝рд╛ред рдореИрдВрдиреЗ @kazuho рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рдмрд╛рдж, mruby рдореЗрдВ рдПрдХ рд░рд┐рд╡рд░реНрд╕ рдкреНрд░реЙрдХреНрд╕реА рд╣реИрдВрдбрд▓рд░ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ред
рдореЗрд░реЗ рдкрд░реАрдХреНрд╖рдг рд╕рд░реНрд╡рд░ рдкрд░ рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдореИрдВ рдЗрд╕реЗ рдЬрд▓реНрдж рд╣реА рдЙрддреНрдкрд╛рджрди рдореЗрдВ рддреИрдирд╛рдд рдХрд░реВрдВрдЧрд╛ред рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХрд┐рд╕реА рдФрд░ рдХреЛ рдЙрдкрд░реНрдпреБрдХреНрдд рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рд╕рдорд╛рди рд╕рдорд╕реНрдпрд╛рдУрдВ рдореЗрдВ рдЪрд▓рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗ:
proc {|env|
# copy headers
headers = {}
env.each do |key, value|
if /^HTTP_/.match(key)
headers[$'] = value
end
end
if env['CONTENT_TYPE']
headers['CONTENT_TYPE'] = env['CONTENT_TYPE']
end
# issue the request
input = env["rack.input"] ? env["rack.input"] : ""
if env['QUERY_STRING'].to_s != ''
uri = env['SCRIPT_NAME'] + env['PATH_INFO'] + '?' + env['QUERY_STRING']
else
uri = env['SCRIPT_NAME'] + env['PATH_INFO']
end
req = http_request(
"http://<backend-ip>#{uri}",
method: env["REQUEST_METHOD"],
headers: headers,
body: input,
)
# Extract status, headers and body, so that I can look into the headers
status, headers, body = req.join
# actual work done here, if a certain header is present
[status, headers, body]
}
рдЕрднреА рддрдХ рдХрд╛рдлреА рдХрд╛рдо рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИ:
H2O рдпрд╛ mruby рдореВрд▓ CONTENT_TYPE
рд╣реЗрдбрд░ рдХреЛ HTTP_CONTENT_TYPE
, рдЬреЛ рдПрдХ рд╡рд░реНрдбрдкреНрд░реЗрд╕ рдмреИрдХрдПрдВрдб рдХреЛ рддреЛрдбрд╝ рджреЗрддрд╛ рд╣реИ...
рдЙрджрд╛рд╣рд░рдг:
"CONTENT_TYPE"=>"application/x-www-form-urlencoded; charset=UTF-8"
рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ
"HTTP_CONTENT_TYPE"=>"application/x-www-form-urlencoded; charset=UTF-8"
рдХреНрдпрд╛ рдЗрд╕реЗ рдХреЗрд╡рд▓ CONTENT_TYPE
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рд╣реИ?
рдФрд░ рдпрд╣ рд╕рдм, рд╕рд┐рд░реНрдл рдЗрд╕рд▓рд┐рдП рдХрд┐ рдореИрдВ рдЕрдкрдиреЗ h2o.conf рдореЗрдВ рдПрдХ рдФрд░ /path
рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛...
@utrenkner рджреЗрд░ рд╕реЗ рдЖрдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрд╖рдорд╛ рдХрд░реЗрдВред рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ https://github.com/h2o/h2o/pull/2254 рд╕рдорд╕реНрдпрд╛ рдХреЛ рдареАрдХ рдХрд░ рджреЗрдЧрд╛ред рдЙрд╕ рдкреАрдЖрд░ рдХреЗ рд╕рд╛рде H2O.next
рдФрд░ H2O.reprocess
рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ
H2O рдпрд╛ mruby рдореВрд▓ CONTENT_TYPE рд╣реЗрдбрд░ рдХреЛ HTTP_CONTENT_TYPE рдореЗрдВ рдмрджрд▓ рджреЗрддрд╛ рд╣реИ, рдЬреЛ рд╡рд░реНрдбрдкреНрд░реЗрд╕ рдмреИрдХрдПрдВрдб рдХреЛ рддреЛрдбрд╝ рджреЗрддрд╛ рд╣реИ...
рдореИрдВрдиреЗ рдПрдХ рд╣реА рдореГрдмреА рд╣реИрдВрдбрд▓рд░ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рд▓реЗрдХрд┐рди рдЗрд╕реЗ рдкреБрди: рдкреЗрд╢ рдирд╣реАрдВ рдХрд░ рд╕рдХрд╛ред рдореЗрд░рд╛ рдорддрд▓рдм рд╣реИ, рдореИрдВрдиреЗ рдиреНрдпреВрдирддрдо рдЕрдкрд╕реНрдЯреНрд░реАрдо рд╕рд░реНрд╡рд░ ( echo -ne "HTTP/1.1 200 OK\r\n\r\n" | nc -l 9000
) рдХреЛ рдЬрдиреНрдо рджрд┐рдпрд╛ рдФрд░ h2o рд╕реЗ рднреЗрдЬреЗ рдЧрдП рд╣реЗрдбрд░ рджреЗрдЦреЗрдВред рдЗрд╕рдореЗрдВ CONTENT_TYPE
, рди рдХрд┐ HTTP_CONTENT_TYPE
ред
BTW рдпрджрд┐ рдЖрдк рдЗрд╕ http_request рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рд▓реЗрддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рд╣реЗрдбрд░ рд╣реИрд╢ рдХреБрдВрдЬрд┐рдпреЛрдВ рдореЗрдВ рдЕрдВрдбрд░рд╕реНрдХреЛрд░ рдХреЛ рд╣рд╛рдЗрдлрд╝рди рдореЗрдВ рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛: рдпрд╛рдиреА, рдЖрдкрдХреЛ HTTP_X_FOO
рд╕реЗ X-FOO
рдХрдирд╡рд░реНрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рди рдХрд┐ X_FOO
ред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЙрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рдХрд╛рд░рдг рд╣реИ: рдЖрдкрдХрд╛ рд╕рд░реНрд╡рд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЗрд╕реЗ content-type
рд╢реАрд░реНрд╖рд▓реЗрдЦ рдХреЗ рд░реВрдк рдореЗрдВ рдирд╣реАрдВ рдкрд╣рдЪрд╛рдирддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЬреНрдпрд╛рджрд╛рддрд░ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЗрд▓рд╛рдЬ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рд╣реИред
@ i110 рдмрд╣реБрдд рдмрд╣реБрдд рдзрдиреНрдпрд╡рд╛рдж! рдореИрдВ рдХрд▓ рдЖрдкрдХрд╛ рдкреИрдЪ рдЖрдЬрд╝рдорд╛рдЙрдВрдЧрд╛ред
рдФрд░ рдЙрдкрд░реЛрдХреНрдд рдореГрдмреА рд╣реИрдВрдбрд▓рд░ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рднреА рдзрдиреНрдпрд╡рд╛рджред рджрд░рдЕрд╕рд▓, рдореИрдВ рдЕрдВрдбрд░рд╕реНрдХреЛрд░ рдХреЛ рд╣рд╛рдЗрдлрд╝рди рдореЗрдВ рдмрджрд▓рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рднреВрд▓ рдЧрдпрд╛ рдерд╛ред рдЙрд╕ рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рд╕рд╛рде, рдпрд╣ рдЗрд░рд╛рджрд╛ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдФрд░ CONTENT_TYPE
рд░рд╣рддрд╛ рд╣реИ CONTENT_TYPE
!
@i110 рдмрд╣реБрдд-рдмрд╣реБрдд рдзрдиреНрдпрд╡рд╛рдж! #2254 H2O.next
рдФрд░ H2O.reprocess
рджреЛрдиреЛрдВ рдХреЗ рд╕рд╛рде рдореЗрд░реА рд╕рдорд╕реНрдпрд╛рдУрдВ рдХрд╛ рд╕рдорд╛рдзрд╛рди рдХрд░рддрд╛ рд╣реИред рдореИрдВрдиреЗ h2o.conf рдореЗрдВ рдФрд░ рднреА рдЕрдзрд┐рдХ /path
рд╕реЗрдЧрдореЗрдВрдЯ рдЬреЛрдбрд╝реЗ, рдмрд╕ рдпрд╣ рдЬрд╛рдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдФрд░, рд╣рд╛рдБ, рдпрд╣ рдХрд░рддрд╛ рд╣реИ!