์ด ๋ฌธ์ ๋ฅผ "๋ฒ๊ทธ" ๋ณด๊ณ ์๋ก ๋ค์ ์์ฑํฉ๋๋ค. ์ด์ ์ต์ ์์ค๋ฅผ ์ฌ์ฉํ์ฌ Fedora์์๋ ํ ์คํธํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ด ๋ฒ๊ทธ์ ๋ฐ๋ชจ๋ฅผ ์ํด ๋ค์ 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
์ธ๊ทธ๋จผํธ๋ฅผ ํ๋ ๋ ์ถ๊ฐํ๋ฉด HardenedBSD, 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"
์ด์ ๋ด๋ถ ์๋ฒ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ Fedora์ ์ค๋ฅ ๋ก๊ทธ๋ ๋ค์๊ณผ ๊ฐ์ด ๋งํฉ๋๋ค.
[h2o_mruby] in request:/dir0:mruby raised: (eval):28: can't modify `SCRIPT_NAME` with `H2O.next`. Is `H2O.reprocess` what you want? (RuntimeError)
์ด๊ฒ์ b9989220bea9bda30f69083b66166c4c657bdf84 ์ ์์ค์์ ๋น๋๋ H2O์ ํจ๊ป ์๋ก์ด Fedora 31์
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
๋ก ๋ฐ๊พธ์ด WordPress ๋ฐฑ์๋๋ฅผ ์ค๋จํฉ๋๋ค...
์์:
"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์ผ๋ก ๋ณํํ์ฌ WordPress ๋ฐฑ์๋๋ฅผ ์ค๋จํฉ๋๋ค...
๋์ผํ mruby ์ฒ๋ฆฌ๊ธฐ๋ฅผ ์๋ํ์ง๋ง ์ฌํํ ์ ์์ต๋๋ค. ๋ด ๋ง์, ์ต์ํ์ ์
์คํธ๋ฆผ ์๋ฒ( echo -ne "HTTP/1.1 200 OK\r\n\r\n" | nc -l 9000
)๋ฅผ ์์ฑํ๊ณ h2o์์ ๋ณด๋ธ ํค๋๋ฅผ ํ์ธํฉ๋๋ค. ์ฌ๊ธฐ์๋ CONTENT_TYPE
์ด ์๋๋ผ HTTP_CONTENT_TYPE
.
์ด HTTP_REQUEST ์ ๊ทผ์ BTW, ๋น์ ์ ํ์ดํ ํค๋ ํด์ ํค์ ๋ณํ ๋ฐ์ค์ ์์ต๋๋ค์
๋๋ค, ๋น์ ์ ๋ณํํด์ผ HTTP_X_FOO
์ X-FOO
ํ์ง X_FOO
. ์ด๊ฒ์ด ๊ทธ ๋ฌธ์ ์ ์์ธ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์๋ฒ ๊ตฌํ์ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ํน๋ณํ ์ฒ๋ฆฌํด์ผ ํ๋ content-type
ํค๋๋ก ์ธ์ํ์ง ๋ชปํฉ๋๋ค.
@i110 ์ ๋ง ๊ฐ์ฌํฉ๋๋ค! ๋ด์ผ ํจ์น๋ฅผ ์ํํด ๋ณด๊ฒ ์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์์ mruby ํธ๋ค๋ฌ๋ฅผ ํ
์คํธํด์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค. ์ฌ์ค, ๋ฐ์ค์ ํ์ดํ์ผ๋ก ๋ฐ๊พธ๋ ๊ฒ์ ์์ ํ ์์ด ๋ฒ๋ ธ์ต๋๋ค. ์ด ๋ณ๊ฒฝ์ผ๋ก ์ธํด ์๋ํ ๋๋ก ์๋ํ๊ณ CONTENT_TYPE
๋ CONTENT_TYPE
!
@i110 ์ ๋ง ๊ฐ์ฌํฉ๋๋ค! #2254 ๋ H2O.next
๋ฐ H2O.reprocess
๋ฌธ์ ๋ฅผ ๋ชจ๋ ํด๊ฒฐํฉ๋๋ค. ์ค์ ๋ก ์๋ํ๋์ง ํ์ธํ๊ธฐ ์ํด h2o.conf์ /path
์ธ๊ทธ๋จผํธ๋ฅผ ๋ ์ถ๊ฐํ์ต๋๋ค. ์, ๊ทธ๋ ์ต๋๋ค!