如何在Elixir中使用Application与Plug.Router实现端口监听
解决Plug应用未监听端口的问题
问题场景
现有以下代码:
Application 文件 (lib/my_api.ex)
defmodule MyApi do use Application def start(_type, _args) do children = [ MyApi.Router ] opts = [strategy: :one_for_one, name: MyApi.Supervisor] Supervisor.start_link(children, opts) end end
路由文件 (lib/my_api/router.ex)
defmodule MyApi.Router do use Plug.Router plug :match plug :dispatch # Dummy data to store items in memory @items [ %MyApi.Item{id: 1, name: "Item 1", description: "Description for Item 1"}, %MyApi.Item{id: 2, name: "Item 2", description: "Description for Item 2"} ] # Route to get all items get "/api/items" do send_resp(conn, 200, Jason.encode!(@items)) end # Handle requests to unknown routes match _ do send_resp(conn, 404, "Not found") end end
运行iex -S mix后,应用未监听端口,执行curl请求时出现错误:
bash-3.2$ curl http://localhost:4000/api/items curl: (7) Failed to connect to localhost port 4000 after 9 ms: Connection refused
解决方案
要让应用监听端口并响应请求,需要完成以下步骤:
1. 添加Plug.Cowboy依赖
Plug本身仅提供路由能力,需要Cowboy作为HTTP服务器实现端口监听。修改mix.exs的依赖列表:
defp deps do [ {:plug_cowboy, "~> 2.0"}, {:jason, "~> 1.0"} # 确保已添加,用于JSON编码 ] end
执行mix deps.get安装依赖。
2. 修改Application启动逻辑
直接将Router加入Supervisor的子进程列表不会启动HTTP服务,需要通过Plug.Cowboy.child_spec配置并启动服务器:
defmodule MyApi do use Application def start(_type, _args) do children = [ # 配置Cowboy服务器,指定协议、路由模块和监听端口 Plug.Cowboy.child_spec( scheme: :http, plug: MyApi.Router, options: [port: 4000] ) ] opts = [strategy: :one_for_one, name: MyApi.Supervisor] Supervisor.start_link(children, opts) end end
3. 定义MyApi.Item模块
路由中使用了%MyApi.Item{}结构体,但当前不存在该模块,需要创建lib/my_api/item.ex:
defmodule MyApi.Item do defstruct [:id, :name, :description] end
4. 测试运行
重新启动应用:
iex -S mix
此时应用会监听4000端口,执行curl请求即可得到响应:
curl http://localhost:4000/api/items
返回结果:
[{"id":1,"name":"Item 1","description":"Description for Item 1"},{"id":2,"name":"Item 2","description":"Description for Item 2"}]
内容的提问来源于stack exchange,提问作者Alexander Mills
相关产品推荐
相关产品推荐

