2021年3月1日 星期一

Elixir: Plug.Cowboy Server

Cowboy 是 Erlang 原生的 HTTP Server Framework,但是在 Elixir 也有 Plug.Cowboy 可以支援使用原生 Erlang 的功能,建構一個簡易的 HTTP Server。

本文的目的是接續下一段文章,要將 Cowboy 的 Router 用 Proxy 撈取資料再回傳到 Requestor 的手上,在這之前,紀錄 build 一個 cowboy server 的流程。


建立專案及 dependencies


首先,透過 mix 建立一個專案的 template (--sup 會建立一個 OTP App ,這是必要的):

mix new cowserver --sup
cd cowserver


然後,修改 mix.exs 檔案,在 deps 這個 function 中加入這個 deps 描述:

defp deps do
    [
      {:plug_cowboy, "~> 2.0"}
    ]
end


加入完成後,就可以用 deps.get 安裝:

mix deps.get


第一種伺服器 - 針對所有流量都回應 Hello World


在 cowserver/lib 底下,建立一個 hello_plug.ex 檔案,建立內容如下:

defmodule Cowserver.HelloPlug do
    import Plug.Conn

    # 初始化回傳 opts 參數
    def init(opts), do: opts

    # 被 user 用 http 呼叫後執行的事件
    def call(conn, _opts) do
        conn
        |> put_resp_content_type("text/plain")
        |> send_resp(200, "Hello World!\n")
    end
end


在 cowserver/lib/cowserver 可能會找到 application.ex ,如果沒有 (一開始 new 沒有用 --sup 的話),也可以自己新增,建立內容如下:

defmodule Cowserver.Application do 
    use Application
    
    # 被當作常駐應用程式啟動的行為
    def start(_type, _args) do
        children = [
            {Plug.Cowboy, scheme: :http, plug: Cowserver.HelloPlug, options: [port: 8081]}
        ]

        opts = [strategy: :one_for_one, name: Cowserver.Supervisor]

        Supervisor.start_link(children, opts)
    end
end


最後,在 cowserver 目錄下修改 mix.exs 的  def application do 這個 function:

def application do
  [
    extra_applications: [:logger], #注意逗號
    # 把 Application 帶進來啟動
    mod: {Cowserver.Application, []}
  ]
end

完成後,使用指令啟動,然後在瀏覽器打開 localhost:8081:

mix run --no-halt


第二種伺服器 - 建立 Router 機制


第二種伺服器是含有 Router 機制的程式,可以直接接著上面的功能,在 cowserver/lib 這個資料夾中建立 router.ex,建立檔案內容如下:

defmodule Cowserver.Router do
	use Plug.Router

	plug :match
	plug :dispatch

	get "/" do
		send_resp(conn, 200, "Hello World")
	end

	match _ do
		send_resp(conn, 404, "Not Found!")
	end
end

然後,需要再次修改 application.ex 檔案中的 children 引用的 Plug,修改為:

defmodule Cowserver.Application do 
    use Application
    
    # 被當作常駐應用程式啟動的行為
    def start(_type, _args) do
        children = [
        	# 這裡的 Cowserver.Router 是新修改的內容
            {Plug.Cowboy, scheme: :http, plug: Cowserver.Router, options: [port: 8081]}
        ]

        opts = [strategy: :one_for_one, name: Cowserver.Supervisor]

        Supervisor.start_link(children, opts)
    end
end


如此一來,開啟 localhost:8081/ 會回傳 Hello World,其他的路由器都會回傳 404 Not Found!


Reference:

https://elixirschool.com/en/lessons/specifics/plug/
https://gist.github.com/bhelx/062ae2d78ab4768ab527d3db74f1869e
https://hexdocs.pm/plug_cowboy/Plug.Cowboy.html#http/3
https://hexdocs.pm/plug/Plug.Conn.Adapter.html#c:read_req_body/2


沒有留言:

張貼留言

© Mac Taylor, 歡迎自由轉貼。
Background Email Pattern by Toby Elliott
Since 2014