在Elixir中使用plug_cowboy时如何配置允许CORS跨域请求?
Plug Cowboy 配置CORS跨域权限教程
步骤1:添加CORS处理依赖
在项目的mix.exs文件的依赖列表中添加Corsica,这是Elixir生态中通用的CORS处理库:
defp deps do [ # 项目原有其他依赖 {:corsica, "~> 2.0"} ] end
添加完成后执行mix deps.get安装依赖。
步骤2:修改Endpoint配置CORS规则
CORS处理插件必须放在所有业务处理插件之前,避免浏览器的预检请求被其他逻辑拦截。修改后的Api.Endpoint完整代码如下:
defmodule Api.Endpoint do @moduledoc """ A plug that parses requests as JSON, dispatches responses and makes necessary changes elsewhere. """ use Plug.Router plug Plug.Logger # 新增CORS配置,放于所有业务处理逻辑最前方 plug Corsica, origins: ["http://localhost:3000"], allow_headers: ["content-type"], allow_methods: ["GET", "POST", "OPTIONS"], max_age: 86400 plug :match # Using Poison for JSON decoding plug(Plug.Parsers, parsers: [:json], json_decoder: Poison) plug :dispatch # 新增预检OPTIONS请求专用处理路由 options _ do send_resp(conn, 204, "") end get "/ping" do send_resp(conn, 200, Poison.encode!(%{response: "pong!"})) end post "/events" do {status, body} = case conn.body_params do %{"events" => events} -> {200, process_events(events)} _ -> {422, missing_events()} end send_resp(conn, status, body) end defp process_events(events) when is_list(events) do Poison.encode!(%{response: "Received Events!"}) end defp process_events(_) do Poison.encode!(%{response: "Please Send Some Events!"}) end defp missing_events do Poison.encode!(%{error: "Expected Payload: { 'events': [...] }"}) end match _ do send_resp(conn, 404, "oops... Nothing here :(") end end
配置规则说明
origins:指定允许跨域访问的来源,这里仅放行你的React应用地址http://localhost:3000,生产环境可以替换为实际前端域名;如果需要允许所有来源可设置为"*",不推荐在生产环境使用。allow_headers:指定允许的请求头,这里配置了JSON请求必需的content-type,如果有自定义请求头可自行添加。allow_methods:指定允许的请求方法,覆盖了当前用到的GET、POST,以及浏览器跨域必需的OPTIONS预检方法。- 新增的
options _路由专门处理所有预检请求,返回204状态码即可。
无第三方依赖的手动实现方案
如果你不想引入额外依赖,也可以手动编写简易CORS处理Plug:
defmodule CorsPlug do import Plug.Conn def init(opts), do: opts def call(conn, _opts) do conn |> put_resp_header("access-control-allow-origin", "http://localhost:3000") |> put_resp_header("access-control-allow-methods", "GET, POST, OPTIONS") |> put_resp_header("access-control-allow-headers", "content-type") end end
将这个Plug添加到Api.Endpoint的最前方即可,同样需要保留OPTIONS路由的处理逻辑。
内容的提问来源于stack exchange,提问作者Ewan H
相关产品推荐
相关产品推荐

