追記 2015/11/08
[Elixir]1worker、1portでリクエストを待ってHTTPのリクエストをProxyする で解消済
最近、簡単なHTTP Proxyを書いてみています。Elixir/Erlangの多プロセスで動作する点を利用して、軽量なproxyとして動作できるのかなー?というところがあってです。
https://github.com/KazuCocoa/http_proxy
以下のような感じでportを指定したら、そのportに対してどんなパスでアクセスしたかで接続先を制御できる感じにしています。
use Mix.Config
config :http_proxy,
proxy: %{port: 4000,
default_to: "http://google.com",
path: [
%{from: "", to: "http://yahoo.com"},
%{from: "neko", to: "http://yahoo.co.jp"}
]
}
Plug や Cowboy を結局は使っています。Supervisorのworkerとしてプロセスは起動するようにもしています。
この動作確認の中で、ElixirのSupervisorで複数のPlugを持つ同一モジュールを動かそうとしたらPIDの競合でエラーがでたのでメモ。少し調べてみると、それはPlugが Plug.Adapters.Cowboy.httpや Plug.Adapters.Cowboy.https をSupervisorで起動するときに :name で __MODULE__ を指定しているのが原因な気がしています。
というのも、例えばSupervisorで呼ばれたときにまず起動するここらへんで使われる、start_link で最初に呼ばれるところで ref: を与えたり、
def start_link(proxy) do
{:ok, pid} = Plug.Adapters.Cowboy.http __MODULE__, [ref: proxy[:name]], port: proxy[:port].port
IO.inspect pid
{:ok, pid}
# :timer.sleep(:infinity)
end
workerで与える :id を変えても変化なかったためです。ここな感じ。
def init(:ok) do
import Supervisor.Spec
children = [
worker(HttpProxy, [[port: 4000, name: String.to_atom("HttpProxy1")]], [id: String.to_atom("HttpProxy1")]),
worker(HttpProxy, [[port: 4001, name: String.to_atom("HttpProxy2")]], [id: String.to_atom("HttpProxy2")])
]
supervise children, strategy: :one_for_one
end