Packages
phoenix
1.4.1
1.8.9
1.8.8
1.8.7
1.8.6
1.8.5
1.8.4
1.8.3
1.8.2
1.8.1
1.8.0
1.8.0-rc.4
1.8.0-rc.3
1.8.0-rc.2
1.8.0-rc.1
1.8.0-rc.0
1.7.24
1.7.23
1.7.22
1.7.21
1.7.20
1.7.19
1.7.18
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.7.0-rc.3
1.7.0-rc.2
1.7.0-rc.1
1.7.0-rc.0
1.6.17
1.6.16
1.6.15
1.6.14
1.6.13
1.6.12
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.6.0-rc.1
1.6.0-rc.0
1.5.15
1.5.14
1.5.13
1.5.12
1.5.11
1.5.10
1.5.9
1.5.8
1.5.7
1.5.6
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.5.0-rc.0
1.4.18
1.4.17
1.4.16
1.4.15
1.4.14
1.4.13
1.4.12
1.4.11
1.4.10
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.4.0-rc.3
1.4.0-rc.2
1.4.0-rc.1
1.4.0-rc.0
1.3.5
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.3.0-rc.3
1.3.0-rc.2
1.3.0-rc.1
1.3.0-rc.0
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.2.0-rc.1
1.2.0-rc.0
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.17.1
0.17.0
0.16.1
0.16.0
0.15.0
0.14.0
0.13.1
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.0
0.7.2
0.7.1
0.7.0
0.6.2
0.6.1
0.6.0
0.5.0
0.4.1
0.4.0
0.3.1
0.3.0
0.2.11
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.0
Productive. Reliable. Fast. A productive web framework that does not compromise speed or maintainability.
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/phoenix/endpoint/cowboy_adapter.ex
defmodule Phoenix.Endpoint.CowboyAdapter do
@moduledoc """
The Cowboy adapter for Phoenix.
It implements the required `child_spec/3` function as well
as the handler for the WebSocket transport.
## Custom dispatch options
*NOTE*: This feature depends on the internals of Cowboy 1.0 API
and how it integrates with Phoenix. Those may change at *any time*,
without backwards compatibility.
You can provide custom dispatch options in order to use Phoenix's
builtin Cowboy server with custom handlers. For example, to handle
raw WebSockets [as shown in Cowboy's docs](https://github.com/ninenines/cowboy/tree/1.0.x/examples)).
The options are passed to both `:http` and `:https` keys in the
endpoint configuration. However, once you pass your custom dispatch
options, you will need to manually wire all Phoenix endpoints,
including the socket transports.
You will need the following rules:
* Per websocket transport:
```
{"/socket/websocket", Phoenix.Endpoint.CowboyWebSocket,
{Phoenix.Transports.WebSocket,
{MyAppWeb.Endpoint, MyAppWeb.UserSocket, websocket_config}}}
```
* Per longpoll transport:
```
{"/socket/long_poll", Plug.Adapters.Cowboy.Handler,
{Phoenix.Transports.LongPoll,
{MyAppWeb.Endpoint, MyAppWeb.UserSocket, longpoll_config}}}
```
* For the live-reload websocket:
```
{"/phoenix/live_reload/socket/websocket", Phoenix.Endpoint.CowboyWebSocket,
{Phoenix.Transports.WebSocket,
{MyAppWeb.Endpoint, Phoenix.LiveReloader.Socket, websocket_config}}}
```
If you decide to include the live-reload websocket, you should
disable it when building for production.
* For the endpoint:
```
{:_, Plug.Adapters.Cowboy.Handler, {MyAppWeb.Endpoint, []}}
```
For example:
config :myapp, MyAppWeb.Endpoint,
http: [dispatch: [
{:_, [
{"/foo", MyAppWeb.CustomHandler, []},
{"/bar", MyAppWeb.AnotherHandler, []},
{"/phoenix/live_reload/socket/websocket", Phoenix.Endpoint.CowboyWebSocket,
{Phoenix.Transports.WebSocket,
{MyAppWeb.Endpoint, Phoenix.LiveReloader.Socket, websocket_config}}},
{:_, Plug.Adapters.Cowboy.Handler, {MyAppWeb.Endpoint, []}}
]}]]
Note: if you reconfigure HTTP options in `MyAppWeb.Endpoint.init/1`,
your dispatch options set in mix config will be overwritten.
It is also important to specify your handlers first, otherwise
Phoenix will intercept the requests before they get to your handler.
"""
import Phoenix.Endpoint.Cowboy2Adapter, only: [info: 3]
require Logger
@doc false
def child_spec(scheme, endpoint, config) do
if scheme == :https do
Application.ensure_all_started(:ssl)
end
dispatches =
for {path, socket, socket_opts} <- endpoint.__sockets__,
transport <- transports(endpoint, path, socket, socket_opts),
do: transport
dispatches = dispatches ++ [{:_, Plug.Adapters.Cowboy.Handler, {endpoint, []}}]
config = Keyword.put_new(config, :dispatch, [{:_, dispatches}])
spec = Plug.Cowboy.child_spec(scheme: scheme, plug: {endpoint, []}, options: config)
update_in(spec.start, &{__MODULE__, :start_link, [scheme, endpoint, &1]})
end
defp transports(endpoint, path, socket, socket_opts) do
case deprecated_transports(socket) do
transports when transports == %{} ->
socket_transports(endpoint, path, socket, socket_opts)
transports ->
for {transport, {module, config}} <- transports,
handler = config[:cowboy] || default_for(module),
do:
{Path.join(path, Atom.to_string(transport)), handler,
{module, {endpoint, socket, config}}}
end
end
defp deprecated_transports(socket) do
if Code.ensure_loaded?(socket) and function_exported?(socket, :__transports__, 0) do
socket.__transports__
else
%{}
end
end
defp socket_transports(endpoint, path, socket, opts) do
paths = []
websocket = Keyword.get(opts, :websocket, true)
longpoll = Keyword.get(opts, :longpoll, false)
paths =
if websocket do
config = socket_config(websocket, Phoenix.Transports.WebSocket)
init = {endpoint, socket, config}
[
{socket_path(path, config), Phoenix.Endpoint.CowboyWebSocket,
{Phoenix.Transports.WebSocket, init}}
| paths
]
else
paths
end
paths =
if longpoll do
config = socket_config(longpoll, Phoenix.Transports.LongPoll)
init = {endpoint, socket, config}
[
{socket_path(path, config), Plug.Adapters.Cowboy.Handler,
{Phoenix.Transports.LongPoll, init}}
| paths
]
else
paths
end
paths
end
defp socket_path(path, config) do
end_path_fragment = Keyword.fetch!(config, :path)
parts = String.split(path <> "/" <> end_path_fragment, "/", trim: true)
"/" <> Path.join(parts)
end
defp socket_config(true, module), do: module.default_config()
defp socket_config(config, module), do: Keyword.merge(module.default_config(), config)
defp default_for(Phoenix.Transports.LongPoll), do: Plug.Adapters.Cowboy.Handler
defp default_for(Phoenix.Transports.WebSocket), do: Phoenix.Endpoint.CowboyWebSocket
defp default_for(_), do: nil
@doc false
def start_link(scheme, endpoint, {m, f, [ref | _] = a}) do
# ref is used by Ranch to identify its listeners, defaulting
# to plug.HTTP and plug.HTTPS and overridable by users.
case apply(m, f, a) do
{:ok, pid} ->
Logger.info(fn -> info(scheme, endpoint, ref) end)
{:ok, pid}
{:error, {:shutdown, {_, _, {{_, {:error, :eaddrinuse}}, _}}}} = error ->
Logger.error(fn -> [info(scheme, endpoint, ref), " failed, port already in use"] end)
error
{:error, _} = error ->
error
end
end
end