Page MenuHomePhorge

No OneTemporary

Size
4 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/tesla/middleware/form_urlencoded.ex b/lib/tesla/middleware/form_urlencoded.ex
index 951135f..e2680b0 100644
--- a/lib/tesla/middleware/form_urlencoded.ex
+++ b/lib/tesla/middleware/form_urlencoded.ex
@@ -1,51 +1,77 @@
defmodule Tesla.Middleware.FormUrlencoded do
@behaviour Tesla.Middleware
@moduledoc """
Send request body as application/x-www-form-urlencoded
Longer description, including e.g. additional dependencies.
### Example usage
```
defmodule Myclient do
use Tesla
plug Tesla.Middleware.FormUrlencoded
end
Myclient.post("/url", %{key: :value})
```
"""
- def call(env, next, opts) do
- opts = opts || []
+ @content_type "application/x-www-form-urlencoded"
+ def call(env, next, _opts) do
env
- |> encode(opts)
+ |> encode()
|> Tesla.run(next)
+ |> case do
+ {:ok, env} -> {:ok, decode(env)}
+ error -> error
+ end
end
- defp encode(env, opts) do
+ defp encode(env) do
if encodable?(env) do
env
- |> Map.update!(:body, &encode_body(&1, opts))
- |> Tesla.put_headers([{"content-type", "application/x-www-form-urlencoded"}])
+ |> Map.update!(:body, &encode_body(&1))
+ |> Tesla.put_headers([{"content-type", @content_type}])
else
env
end
end
- defp encode_body(body, _opts) when is_binary(body), do: body
-
- defp encode_body(body, _opts), do: do_process(body)
-
defp encodable?(%{body: nil}), do: false
defp encodable?(%{body: %Tesla.Multipart{}}), do: false
defp encodable?(_), do: true
- defp do_process(data) do
- URI.encode_query(data)
+ defp encode_body(body) when is_binary(body), do: body
+ defp encode_body(body), do: do_encode(body)
+
+ defp decode(env) do
+ if decodable?(env) do
+ env
+ |> Map.update!(:body, &decode_body(&1))
+ else
+ env
+ end
+ end
+
+ defp decodable?(env), do: decodable_body?(env) && decodable_content_type?(env)
+
+ defp decodable_body?(env) do
+ (is_binary(env.body) && env.body != "") || (is_list(env.body) && env.body != [])
+ end
+
+ defp decodable_content_type?(env) do
+ case Tesla.get_header(env, "content-type") do
+ nil -> false
+ content_type -> String.starts_with?(content_type, @content_type)
+ end
end
+
+ defp decode_body(body), do: do_decode(body)
+
+ defp do_encode(data), do: URI.encode_query(data)
+ defp do_decode(data), do: URI.decode_query(data)
end
diff --git a/test/tesla/middleware/form_urlencoded_test.exs b/test/tesla/middleware/form_urlencoded_test.exs
index 7bcb13f..e54d634 100644
--- a/test/tesla/middleware/form_urlencoded_test.exs
+++ b/test/tesla/middleware/form_urlencoded_test.exs
@@ -1,64 +1,73 @@
defmodule Tesla.Middleware.FormUrlencodedTest do
use ExUnit.Case
defmodule Client do
use Tesla
plug Tesla.Middleware.FormUrlencoded
adapter fn env ->
{status, headers, body} =
case env.url do
"/post" ->
{201, [{"content-type", "text/html"}], env.body}
"/check_incoming_content_type" ->
{201, [{"content-type", "text/html"}], Tesla.get_header(env, "content-type")}
+
+ "/decode_response" ->
+ {200, [{"content-type", "application/x-www-form-urlencoded; charset=utf-8"}],
+ "x=1&y=2"}
end
{:ok, %{env | status: status, headers: headers, body: body}}
end
end
test "encode body as application/x-www-form-urlencoded" do
assert {:ok, env} = Client.post("/post", %{"foo" => "%bar "})
assert URI.decode_query(env.body) == %{"foo" => "%bar "}
end
test "leave body alone if binary" do
assert {:ok, env} = Client.post("/post", "data")
assert env.body == "data"
end
test "check header is set as application/x-www-form-urlencoded" do
assert {:ok, env} = Client.post("/check_incoming_content_type", %{"foo" => "%bar "})
assert env.body == "application/x-www-form-urlencoded"
end
+ test "decode response" do
+ assert {:ok, env} = Client.get("/decode_response")
+ assert env.body == %{"x" => "1", "y" => "2"}
+ end
+
defmodule MultipartClient do
use Tesla
plug Tesla.Middleware.FormUrlencoded
adapter fn %{url: url, body: %Tesla.Multipart{}} = env ->
{status, headers, body} =
case url do
"/upload" ->
{200, [{"content-type", "text/html"}], "ok"}
end
{:ok, %{env | status: status, headers: headers, body: body}}
end
end
test "skips encoding multipart bodies" do
alias Tesla.Multipart
mp =
Multipart.new()
|> Multipart.add_field("param", "foo")
assert {:ok, env} = MultipartClient.post("/upload", mp)
assert env.body == "ok"
end
end

File Metadata

Mime Type
text/x-diff
Expires
Sat, Sep 19, 3:59 PM (17 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1769613
Default Alt Text
(4 KB)

Event Timeline