Packages
plug
0.8.0
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/parsers.ex
defmodule Plug.Parsers do
message = "the request is too large. If you are willing to process " <>
"larger requests, please give a :length to Plug.Parsers"
defmodule RequestTooLargeError do
@moduledoc """
Error raised when the request is too large
"""
defexception [:message]
defimpl Plug.Exception do
def status(_exception), do: 413
end
end
defmodule UnsupportedMediaTypeError do
@moduledoc """
Error raised when the request body cannot be parsed
"""
defexception [:message]
defimpl Plug.Exception do
def status(_exception), do: 415
end
end
@moduledoc """
A plug for parsing the request body.
## Options
* `:parsers` - a set of modules to be invoked for parsing.
These modules need to implement the behaviour outlined in
this module.
* `:accept` - an optional list of accepted mime type strings. Any mime
not handled by a parser and not explicitly accepted will
`raise UnsupportedMediaTypeError`. For example:
* `["*/*"]` - never raises
* `["text/html", "application/*"]` - doesn't raise for those values
* `[]` - always raises (default)
All options supported by `Plug.Conn.read_body/2` are also
supported here.
## Examples
plug Plug.Parsers, parsers: [:urlencoded, :multipart]
plug Plug.Parsers, parsers: [:urlencoded, :multipart],
accept: ["application/json", "text/*"]
## Built-in parsers
Plug ships with the following parsers:
* `Plug.Parsers.URLENCODED` - parses "application/x-www-form-urlencoded" requests
* `Plug.Parsers.MULTIPART` - parses "multipart/form-data" and "multipart/mixed" requests
This plug will raise `Plug.Parsers.UnsupportedMediaTypeError` by default if the request
cannot be parsed by any of the given types and the mime type has not been
explicity accepted in the `:accept` option.
`Plug.Parsers.RequestTooLargeError` will be raised if the request goes over the
given limit.
## File handling
If a file is uploaded via any of the parsers, Plug will
stream the uploaded contents to a file in a temporary directory,
avoiding loading the whole file into memory. For such, it is
required that the `:plug` application is started.
In those cases, the parameter will return a `Plug.Upload`
struct with information about the file and its content type.
You can customize the temporary directory by setting the `PLUG_TMPDIR`
environment variable in your system.
"""
alias Plug.Conn
use Behaviour
@doc """
Attempt to parse the connection request body given the type,
subtype and headers. Returns `{:ok, conn}` if the parser can
handle the given content type, `{:halt, conn}` otherwise.
"""
defcallback parse(Conn.t, type :: binary, subtype :: binary,
headers :: Keyword.t, opts :: Keyword.t) ::
{:ok, Conn.params, Conn.t} |
{:error, :too_large, Conn.t} |
{:skip, Conn.t}
@behaviour Plug
@methods ~w(POST PUT PATCH)
def init(opts) do
parsers = Keyword.get(opts, :parsers) || raise_missing_parsers
opts
|> Keyword.put(:parsers, convert_parsers(parsers))
|> Keyword.put_new(:length, 8_000_000)
|> Keyword.put_new(:accept, [])
end
defp raise_missing_parsers do
raise ArgumentError, message: "Plug.Parsers expects a set of parsers to be given in :parsers"
end
defp convert_parsers(parsers) do
for parser <- parsers do
case Atom.to_string(parser) do
"Elixir." <> _ -> parser
reference -> Module.concat(Plug.Parsers, String.upcase(reference))
end
end
end
def call(%Conn{req_headers: req_headers, method: method} = conn, opts) when method in @methods do
conn = Plug.Conn.fetch_params(conn)
case List.keyfind(req_headers, "content-type", 0) do
{"content-type", ct} ->
case Plug.Conn.Utils.content_type(ct) do
{:ok, type, subtype, headers} ->
reduce(conn, Keyword.fetch!(opts, :parsers), type, subtype, headers, opts)
:error ->
conn
end
nil ->
conn
end
end
def call(conn, _opts) do
Plug.Conn.fetch_params(conn)
end
defp reduce(conn, [h|t], type, subtype, headers, opts) do
case h.parse(conn, type, subtype, headers, opts) do
{:ok, post, %Conn{params: get} = conn} ->
%{conn | params: Map.merge(get, post)}
{:next, conn} ->
reduce(conn, t, type, subtype, headers, opts)
{:error, :too_large, _conn} ->
raise Plug.Parsers.RequestTooLargeError
end
end
defp reduce(conn, [], type, subtype, _headers, opts) do
ensure_accepted_mimes(conn, type, subtype, Keyword.fetch!(opts, :accept))
end
defp ensure_accepted_mimes(conn, _type, _subtype, ["*/*"]), do: conn
defp ensure_accepted_mimes(conn, type, subtype, accept) do
if "#{type}/#{subtype}" in accept || "#{type}/*" in accept do
conn
else
raise UnsupportedMediaTypeError, message: "unsupported media type #{type}/#{subtype}"
end
end
end