Packages
plug
1.1.8
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/test/conn.ex
defmodule Plug.Adapters.Test.Conn do
@behaviour Plug.Conn.Adapter
@moduledoc false
## Test helpers
def conn(conn, method, uri, body_or_params) do
maybe_flush()
uri = URI.parse(uri)
method = method |> to_string |> String.upcase
query = uri.query || ""
owner = self()
{body, params, req_headers} = body_or_params(body_or_params, query, conn.req_headers)
state = %{method: method, params: params, req_body: body,
chunks: nil, ref: make_ref(), owner: owner}
%Plug.Conn{conn |
adapter: {__MODULE__, state},
host: uri.host || conn.host || "www.example.com",
method: method,
owner: owner,
path_info: split_path(uri.path),
port: uri.port || 80,
peer: {{127, 0, 0, 1}, 111317},
remote_ip: {127, 0, 0, 1},
req_headers: req_headers,
request_path: uri.path,
query_string: query,
params: params || %Plug.Conn.Unfetched{aspect: :params},
scheme: (uri.scheme || "http") |> String.downcase |> String.to_atom}
end
## Connection adapter
def send_resp(%{method: "HEAD"} = state, status, headers, _body) do
do_send state, status, headers, ""
end
def send_resp(state, status, headers, body) do
do_send state, status, headers, IO.iodata_to_binary(body)
end
def send_file(%{method: "HEAD"} = state, status, headers, _path, _offset, _length) do
do_send state, status, headers, ""
end
def send_file(state, 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
{:ok, data} = File.open!(path, [:read, :binary], fn device ->
:file.pread(device, offset, length)
end)
do_send state, status, headers, data
end
def send_chunked(state, _status, _headers),
do: {:ok, "", %{state | chunks: ""}}
def chunk(%{method: "HEAD"} = state, _body),
do: {:ok, "", state}
def chunk(%{chunks: chunks} = state, body) do
body = chunks <> IO.iodata_to_binary(body)
{:ok, body, %{state | chunks: body}}
end
defp do_send(%{owner: owner, ref: ref} = state, status, headers, body) do
send owner, {ref, {status, headers, body}}
{:ok, body, state}
end
def read_req_body(%{req_body: body} = state, opts \\ []) do
size = min(byte_size(body), Keyword.get(opts, :length, 8_000_000))
data = :binary.part(body, 0, size)
rest = :binary.part(body, size, byte_size(body) - size)
tag =
case rest do
"" -> :ok
_ -> :more
end
{tag, data, %{state | req_body: rest}}
end
def parse_req_multipart(%{params: multipart} = state, _limit, _callback) do
{:ok, multipart, %{state | params: nil}}
end
## Private helpers
defp body_or_params(nil, _query, headers),
do: {"", nil, headers}
defp body_or_params(body, _query, headers) when is_binary(body) do
{body, nil, headers}
end
defp body_or_params(params, query, headers) when is_list(params) do
body_or_params(Enum.into(params, %{}), query, headers)
end
defp body_or_params(params, query, headers) when is_map(params) do
content_type = List.keyfind(headers, "content-type", 0, {"content-type", "multipart/mixed; charset: utf-8"})
headers = List.keystore(headers, "content-type", 0, content_type)
params = Map.merge(Plug.Conn.Query.decode(query), stringify_params(params))
{"", params, headers}
end
defp stringify_params([{_, _}|_] = params),
do: Enum.into(params, %{}, &stringify_kv/1)
defp stringify_params([_|_] = params),
do: Enum.map(params, &stringify_params/1)
defp stringify_params(%{__struct__: mod} = struct) when is_atom(mod),
do: struct
defp stringify_params(%{} = params),
do: Enum.into(params, %{}, &stringify_kv/1)
defp stringify_params(other),
do: other
defp stringify_kv({k, v}),
do: {to_string(k), stringify_params(v)}
defp split_path(path) do
segments = :binary.split(path, "/", [:global])
for segment <- segments, segment != "", do: segment
end
@already_sent {:plug_conn, :sent}
defp maybe_flush() do
receive do
@already_sent -> :ok
after
0 -> :ok
end
end
end