LoginSignup
1
0

More than 3 years have passed since last update.

Proxy環境下でElixirのHTTPoison利用する

Last updated at Posted at 2019-11-20

2019.11.20時点のHTTPoisonの最新版v1.6.2で動作を確認しています。

Proxy環境下でElixirのHTTPoisonを利用する場合、Proxyの値を適切に設定しないとリクエストがProxy環境下のネットワークから出ていかない場合があります。
古いバージョンと新しいバージョンで動作が違ったので、簡単に整理しておきます。

前提

  • 上述の通り、HTTPoisonの最新版v1.6.2で動作確認をしています。
  • 本文中でのProxyサーバの設定値は「 http://proxyserver.jp:8080 」です。
  • リクエストを発行する関数については、「HTTPoison.get!/3」を例にして記述しています。ただし、post/3やhead/3などでも同じ対応です。
  • Elixirはv.1.9.0を利用しました。

設定方法

v.1.6.2の時点では、2種類ありました。

  1. 環境変数にHTTP_PROXYの値を設定します
  2. HTTPoison.get!/3 の関数の第3引数「options」にProxyを設定して渡します

1. 環境変数にHTTP_PROXYの値を設定します

CHANGELOG をみると、v.1.1.0 からの機能です。
それ以前のバージョンでは利用できません。

Elixir側ではなく、Elixirを動作させるサーバ側の設定です。
環境変数「HTTP_PROXY」「http_proxy」「HTTPS_PROXY」「https_proxy」にProxyサーバの設定値を入れておけば、自動でProxyを設定してリクエストを発行してくれます。

ただし、HTTPoison.get!/3 の第3引数「options」に対して「:proxy」を設定していない無い場合にのみ動作します。

なお、環境変数の設定値には優先度があります。
ソースコードをみると以下のようになっていました。

  • HTTP_PROXYhttp_proxyでは、HTTP_PROXYを優先
  • HTTPS_PROXYhttps_proxyでは、HTTPS_PROXYを優先する。

また、HTTPoison.get!/3の第1引数urlのスキーマが「http」か「https」かで、HTTP_PROXYHTTPS_PROXYのどちらを利用するか判断されています。

2. HTTPoison.get!/3の関数の第3引数「options」にProxyを設定して渡します

明示的にProxyの値を渡したい場合に利用します。
v.1.1.0より以前のバージョンでは、こちらがメインです。
CHANGELOGをみると、v.0.6.1から利用できていたようです。

HTTPoison.get!/3 の第3引数「options」に対して「:proxy」を設定します。
設定値は、「{プロキシサーバ, ポート番号}」のようにタプル形式で指定します。
なお、プロキシサーバはString、ポート番号はIntegerで設定します。

設定例:

[ proxy: {"proxyserver.jp", 8080} ] 

この方法は、古いバージョン(例:v0.7.5やv0.6.1)でも動作します。
https://hexdocs.pm/httpoison/0.7.5/HTTPoison.html#request!/5
https://hexdocs.pm/httpoison/0.6.1/HTTPoison.html#request!/5

なお、HTTPプロキシではなく「SOCKSプロキシ」も指定できます。
こちらは、v1.2.0からドキュメントに記載されていました。

[ proxy: {:socks5, "proxyserver.jp", 8080} ])}

それと、詳しいバージョンまでは不明ですが、タプルの部分は「"http(s)://プロキシサーバ:ポート番号"」としても動作します。
こちらの方が直感的に分かりやすいかもしれません。

[ proxy: "http://proxyserver.jp:8080" ]

おまけ1:リクエストのログについて

iex -S mix で動作確認してた際に、リクエストの値がログに出力されていました。
optionsの値の違いが確認できたので、参考までに載せておきます。

  • Proxyを明示的に指定していないとき:
  request: %HTTPoison.Request{
    body: "",
    headers: [],
    method: :get,
    options: [],
    params: %{},
    url: "https://qiita.com/api/v2/items?query=Elixir"
  },
  request_url: "https://qiita.com/api/v2/items?query=Elixir",
  status_code: 200
}
  • Proxyを明示的に指定したとき(タプルの場合):
  request: %HTTPoison.Request{
    body: "",
    headers: [],
    method: :get,
    options: [proxy: {"proxyserver.jp", 8080}],
    params: %{},
    url: "https://qiita.com/api/v2/items?query=Elixir"
  },
  request_url: "https://qiita.com/api/v2/items?query=Elixir",
  status_code: 200
}
  • Proxyを明示的に指定したとき(文字列の場合):
  request: %HTTPoison.Request{
    body: "",
    headers: [],
    method: :get,
    options: [proxy: "http://proxyserver.jp:8080"],
    params: %{},
    url: "https://qiita.com/api/v2/items?query=Elixir"
  },
  request_url: "https://qiita.com/api/v2/items?query=Elixir",
  status_code: 200
}

おまけ2: 動作確認に利用したソースコード

ソースコードは、こちらのスライドの内容を参考にして作成しました。

lib/crawl.ex
defmodule Crawl do

  def get() do
    url = "https://qiita.com/api/v2/items?query=Elixir"

### Proxyを明示しないで、環境変数から取得するパターン
#   HTTPoison.get!(url) 

### タプル設定の場合
#    HTTPoison.get!(url, [], [ proxy: {"proxyserver.jp", 8080} ])

### SOCKSプロキシの場合
#    HTTPoison.get!(url, [], [ proxy: {:socks5, "proxyserver.jp", 8080} ])

### 文字列を渡す場合(+環境変数から取得する場合)
#    px = System.get_env("HTTP_PROXY")
#    HTTPoison.get!(url, [], [ proxy: px ])


    ## QiitaAPIを利用してデータを取得してtitleだけにします。
    HTTPoison.get!(url) |> body() |> Poison.decode!() |> Enum.map( fn( %{"title" => title} ) -> title end )
  end

  def body( %{status_code: 200, body: json_body}  ), do: json_body
end

こちらは、mix.exsに設定したhttpoisonのバージョン。

mix.exs
defmodule Crawl.MixProject do
  use Mix.Project

  def project do
    [
      app: :crawl,
      version: "0.1.0",
      elixir: "~> 1.9",
      start_permanent: Mix.env() == :prod,
      deps: deps()
    ]
  end

  # Run "mix help compile.app" to learn about applications.
  def application do
    [
      extra_applications: [:logger]
    ]
  end

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
      # {:dep_from_hexpm, "~> 0.3.0"},
      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
      { :httpoison, " ~> 1.6" },
      { :poison, " ~> 1.5 " }
    ]
  end
end

まとめ

HTTPoisonのバージョンがv.1.1.0以上の場合ならば、環境変数(HTTP_PROXY、http_proxy、HTTPS_PROXY、 https_proxy)を利用した方法が良い考えます。
コード内に環境依存の情報を記述しませんので。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0