Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85713112
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
4 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
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)
Attached To
Mode
R28 tesla
Attached
Detach File
Event Timeline
Log In to Comment