gemsのhttpclientを利用しているrailsアプリで、起動するサーバーアプリを変更したら、railsアプリがproxyへリクエストしてくれなくてハマったのでメモ。
症状
-
前提
- 環境変数のhttp_proxyに、リクエストを流したいproxyを設定しておく
-
thinでrailsアプリを起動
- その中でhttpclientを叩くとproxyへリクエストを流してくれる
-
apache+passengerでrailsアプリを起動
- その中でhttpclientを叩くとproxyへリクエストを流してくれない
下記のようなメッセージがログに残っている
SocketError : getaddrinfo: No address associated with hostname
gems/httpclient-2.3.4.1/lib/httpclient/session.rb:803:in `initialize'
gems/httpclient-2.3.4.1/lib/httpclient/session.rb:803:in `new'
gems/httpclient-2.3.4.1/lib/httpclient/session.rb:803:in `create_socket'
gems/httpclient-2.3.4.1/lib/httpclient/session.rb:752:in `block in connect'
proxyに流れなかった理由
- 該当コード付近
- gems/httpclient-2.3.4.1/lib/httpclient/session.rb:856
def create_socket(site)
socket = nil
begin
@debug_dev << "! CONNECT TO #{site.host}:#{site.port}\n" if @debug_dev
if str = @test_loopback_http_response.shift
socket = LoopBackSocket.new(site.host, site.port, str)
elsif @socket_local == Site::EMPTY
socket = TCPSocket.new(site.host, site.port)
TCPSocket.newのところで、エラーが出ているようです。
もう少し遡ってみましょう
- gems/httpclient-2.3.4.1/lib/httpclient/session.rb:747
# Connect to the server
def connect
site = @proxy || @dest
retry_number = 0
begin
timeout(@connect_timeout, ConnectTimeoutError) do
@socket = create_socket(site)
どうやらこの@proxyがnilになってしまっていて、意図通りになっていない様子
@proxyが設定されている場所を探してきます
- gems/httpclient-2.3.4.1/lib/httpclient.rb:1156
def load_environment
# http_proxy
if getenv('REQUEST_METHOD')
# HTTP_PROXY conflicts with the environment variable usage in CGI where
# HTTP_* is used for HTTP header information. Unlike open-uri, we
# simply ignore http_proxy in CGI env and use cgi_http_proxy instead.
self.proxy = getenv('cgi_http_proxy')
else
self.proxy = getenv('http_proxy')
end
# no_proxy
self.no_proxy = getenv('no_proxy')
end
ここで設定されるようですね。
今回の場合、以下になっていたようです。
- apache+passengerの場合
- 今回はgetenv('REQUEST_METHOD')に'GET'が入る
- cgi_http_proxyという環境変数は設定していないので、self.proxy = nilとなり、結果proxyには流れない
- thinの場合
- getenv('REQUEST_METHOD')がnilなので、getenv('http_proy')が読まれる
コードのコメントによると、衝突回避のようですね。
というわけで、環境変数を設定します
- /etc/httpd/conf.d/myenv.conf
SetEnv CGI_HTTP_PROXY http://proxy.example.com:8080
apacheを再起動して、意図通りに処理される事を確認しましたとさ
まとめ
- railsからhttpclientをproxy経由で使いたい場合は、cgi_http_proxyを使いましょう。
- 使おうとしているライブラリはちゃんと読めって事ですね。
要らんとこでハマりましたね〜(=w=;
ニッチすぎて自分以外が必要としないメモですね・・・w