Packages
plug
1.2.4
1.20.3
1.20.2
1.20.1
retired
1.20.0
retired
1.19.5
1.19.4
1.19.3
1.19.2
1.19.1
1.19.0
1.18.5
1.18.4
1.18.3
1.18.2
1.18.1
1.18.0
1.17.4
1.17.3
1.17.2
1.17.1
1.17.0
1.16.6
1.16.5
1.16.4
1.16.3
1.16.2
1.16.1
1.16.0
1.15.6
1.15.5
1.15.4
1.15.3
1.15.2
1.15.1
1.15.0
1.14.2
1.14.1
1.14.0
1.13.6
1.13.5
1.13.4
1.13.3
1.13.2
1.13.1
retired
1.13.0
retired
1.12.1
1.12.0
1.11.1
1.11.0
1.10.4
1.10.3
1.10.2
1.10.1
1.10.0
1.9.0
1.8.3
1.8.2
1.8.1
1.8.0
1.7.2
1.7.1
1.7.0
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.1
1.5.0
1.5.0-rc.2
1.5.0-rc.1
1.5.0-rc.0
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.4.0-rc.0
1.3.6
1.3.5
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
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.14.0
0.13.1
0.13.0
0.12.2
0.12.1
0.12.0
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.0
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.0
0.6.0
0.5.3
0.5.2
0.5.1
0.5.0
0.4.4
0.4.3
0.4.2
0.4.1
Compose web applications with functions
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/plug/adapters/cowboy/conn.ex
defmodule Plug.Adapters.Cowboy.Conn do
@behaviour Plug.Conn.Adapter
@moduledoc false
alias :cowboy_req, as: Request
def conn(req, transport) do
{path, req} = Request.path req
{host, req} = Request.host req
{port, req} = Request.port req
{meth, req} = Request.method req
{hdrs, req} = Request.headers req
{qs, req} = Request.qs req
{peer, req} = Request.peer req
{remote_ip, _} = peer
%Plug.Conn{
adapter: {__MODULE__, req},
host: host,
method: meth,
owner: self(),
path_info: split_path(path),
peer: peer,
port: port,
remote_ip: remote_ip,
query_string: qs,
req_headers: hdrs,
request_path: path,
scheme: scheme(transport)
}
end
def send_resp(req, status, headers, body) do
{:ok, req} = Request.reply(status, headers, body, req)
{:ok, nil, req}
end
def send_file(req, status, headers, path, offset, length) do
%File.Stat{type: :regular, size: size} = File.stat!(path)
length =
cond do
length == :all -> size
is_integer(length) -> length
end
body_fun = fn(socket, transport) -> transport.sendfile(socket, path, offset, length) end
{:ok, req} = Request.reply(status, headers, Request.set_resp_body_fun(length, body_fun, req))
{:ok, nil, req}
end
def send_chunked(req, status, headers) do
{:ok, req} = Request.chunked_reply(status, headers, req)
{:ok, nil, req}
end
def chunk(req, body) do
Request.chunk(body, req)
end
def read_req_body(req, opts \\ []) do
Request.body(req, opts)
end
def parse_req_multipart(req, opts, callback) do
# We need to remove the length from the list
# otherwise cowboy will attempt to load the
# whole length at once.
{limit, opts} = Keyword.pop(opts, :length, 8_000_000)
{:ok, limit, acc, req} = parse_multipart(Request.part(req), limit, opts, [], callback)
params = Enum.reduce(acc, %{}, &Plug.Conn.Query.decode_pair/2)
if limit > 0 do
{:ok, params, req}
else
{:more, params, req}
end
end
## Helpers
defp scheme(:tcp), do: :http
defp scheme(:ssl), do: :https
defp split_path(path) do
segments = :binary.split(path, "/", [:global])
for segment <- segments, segment != "", do: segment
end
## Multipart
defp parse_multipart({:ok, headers, req}, limit, opts, acc, callback) when limit >= 0 do
case callback.(headers) do
{:binary, name} ->
{:ok, limit, body, req} =
parse_multipart_body(Request.part_body(req, opts), limit, opts, "")
Plug.Conn.Utils.validate_utf8!(body, Plug.Parsers.BadEncodingError, "multipart body")
parse_multipart(Request.part(req), limit, opts, [{name, body}|acc], callback)
{:file, name, path, %Plug.Upload{} = uploaded} ->
{:ok, file} = File.open(path, [:write, :binary, :delayed_write, :raw])
{:ok, limit, req} =
parse_multipart_file(Request.part_body(req, opts), limit, opts, file)
:ok = File.close(file)
parse_multipart(Request.part(req), limit, opts, [{name, uploaded}|acc], callback)
:skip ->
parse_multipart(Request.part(req), limit, opts, acc, callback)
end
end
defp parse_multipart({:ok, _headers, req}, limit, _opts, acc, _callback) do
{:ok, limit, acc, req}
end
defp parse_multipart({:done, req}, limit, _opts, acc, _callback) do
{:ok, limit, acc, req}
end
defp parse_multipart_body({:more, tail, req}, limit, opts, body) when limit >= byte_size(tail) do
parse_multipart_body(Request.part_body(req, opts), limit - byte_size(tail), opts, body <> tail)
end
defp parse_multipart_body({:more, tail, req}, limit, _opts, body) do
{:ok, limit - byte_size(tail), body, req}
end
defp parse_multipart_body({:ok, tail, req}, limit, _opts, body) when limit >= byte_size(tail) do
{:ok, limit - byte_size(tail), body <> tail, req}
end
defp parse_multipart_body({:ok, tail, req}, limit, _opts, body) do
{:ok, limit - byte_size(tail), body, req}
end
defp parse_multipart_file({:more, tail, req}, limit, opts, file) when limit >= byte_size(tail) do
IO.binwrite(file, tail)
parse_multipart_file(Request.part_body(req, opts), limit - byte_size(tail), opts, file)
end
defp parse_multipart_file({:more, tail, req}, limit, _opts, _file) do
{:ok, limit - byte_size(tail), req}
end
defp parse_multipart_file({:ok, tail, req}, limit, _opts, file) when limit >= byte_size(tail) do
IO.binwrite(file, tail)
{:ok, limit - byte_size(tail), req}
end
defp parse_multipart_file({:ok, tail, req}, limit, _opts, _file) do
{:ok, limit - byte_size(tail), req}
end
end