handler.ex (2174B)
1 defmodule Plug.Cowboy.Handler do 2 @moduledoc false 3 @connection Plug.Cowboy.Conn 4 @already_sent {:plug_conn, :sent} 5 6 def init(req, {plug, opts}) do 7 conn = @connection.conn(req) 8 9 try do 10 conn 11 |> plug.call(opts) 12 |> maybe_send(plug) 13 |> case do 14 %Plug.Conn{adapter: {@connection, %{upgrade: {:websocket, websocket_args}} = req}} = conn -> 15 {handler, state, cowboy_opts} = websocket_args 16 {__MODULE__, copy_resp_headers(conn, req), {handler, state}, cowboy_opts} 17 18 %Plug.Conn{adapter: {@connection, req}} -> 19 {:ok, req, {plug, opts}} 20 end 21 catch 22 kind, reason -> 23 exit_on_error(kind, reason, __STACKTRACE__, {plug, :call, [conn, opts]}) 24 after 25 receive do 26 @already_sent -> :ok 27 after 28 0 -> :ok 29 end 30 end 31 end 32 33 def upgrade(req, env, __MODULE__, {handler, state}, opts) do 34 :cowboy_websocket.upgrade(req, env, handler.module_info(:module), state, opts) 35 end 36 37 defp copy_resp_headers(%Plug.Conn{} = conn, req) do 38 Enum.reduce(conn.resp_headers, req, fn {key, val}, acc -> 39 :cowboy_req.set_resp_header(key, val, acc) 40 end) 41 end 42 43 defp exit_on_error( 44 :error, 45 %Plug.Conn.WrapperError{kind: kind, reason: reason, stack: stack}, 46 _stack, 47 call 48 ) do 49 exit_on_error(kind, reason, stack, call) 50 end 51 52 defp exit_on_error(:error, value, stack, call) do 53 exception = Exception.normalize(:error, value, stack) 54 :erlang.raise(:exit, {{exception, stack}, call}, []) 55 end 56 57 defp exit_on_error(:throw, value, stack, call) do 58 :erlang.raise(:exit, {{{:nocatch, value}, stack}, call}, []) 59 end 60 61 defp exit_on_error(:exit, value, _stack, call) do 62 :erlang.raise(:exit, {value, call}, []) 63 end 64 65 defp maybe_send(%Plug.Conn{state: :unset}, _plug), do: raise(Plug.Conn.NotSentError) 66 defp maybe_send(%Plug.Conn{state: :set} = conn, _plug), do: Plug.Conn.send_resp(conn) 67 defp maybe_send(%Plug.Conn{} = conn, _plug), do: conn 68 69 defp maybe_send(other, plug) do 70 raise "Cowboy2 adapter expected #{inspect(plug)} to return Plug.Conn but got: " <> 71 inspect(other) 72 end 73 end