From 11d27349e32d23649dd4e5ba6a3597f62199e6e5 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Wed, 30 Jul 2025 11:05:49 -0700 Subject: [PATCH] Fix HTTP client making invalid requests due to no percent encoding processing or validation. --- changelog.d/url-encoding.fix | 1 + lib/pleroma/http.ex | 10 ++-- lib/pleroma/tesla/middleware/encode_url.ex | 53 ++++++++++++++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 changelog.d/url-encoding.fix create mode 100644 lib/pleroma/tesla/middleware/encode_url.ex diff --git a/changelog.d/url-encoding.fix b/changelog.d/url-encoding.fix new file mode 100644 index 000000000..3cca87ded --- /dev/null +++ b/changelog.d/url-encoding.fix @@ -0,0 +1 @@ +Fix HTTP client making invalid requests due to no percent encoding processing or validation. diff --git a/lib/pleroma/http.ex b/lib/pleroma/http.ex index c11317850..1833f5f85 100644 --- a/lib/pleroma/http.ex +++ b/lib/pleroma/http.ex @@ -105,20 +105,24 @@ defmodule Pleroma.HTTP do end defp adapter_middlewares(Tesla.Adapter.Gun, extra_middleware) do - [Tesla.Middleware.FollowRedirects, Pleroma.Tesla.Middleware.ConnectionPool] ++ + default_middleware() ++ + [Pleroma.Tesla.Middleware.ConnectionPool] ++ extra_middleware end defp adapter_middlewares({Tesla.Adapter.Finch, _}, extra_middleware) do - [Tesla.Middleware.FollowRedirects] ++ extra_middleware + default_middleware() ++ extra_middleware end defp adapter_middlewares(_, extra_middleware) do if Pleroma.Config.get(:env) == :test do # Emulate redirects in test env, which are handled by adapters in other environments - [Tesla.Middleware.FollowRedirects] + default_middleware() else extra_middleware end end + + defp default_middleware(), + do: [Tesla.Middleware.FollowRedirects, Pleroma.Tesla.Middleware.EncodeUrl] end diff --git a/lib/pleroma/tesla/middleware/encode_url.ex b/lib/pleroma/tesla/middleware/encode_url.ex new file mode 100644 index 000000000..df10e13c2 --- /dev/null +++ b/lib/pleroma/tesla/middleware/encode_url.ex @@ -0,0 +1,53 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2025 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Tesla.Middleware.EncodeUrl do + @moduledoc """ + Middleware to encode URLs properly + + We must decode and then re-encode to ensure correct encoding. + If we only encode it will re-encode each % as %25 causing a space + already encoded as %20 to be %2520. + + Similar problem for query parameters which need spaces to be the + character + """ + + @behaviour Tesla.Middleware + + @impl Tesla.Middleware + def call(%Tesla.Env{url: url} = env, next, _) do + url = + URI.parse(url) + |> then(fn parsed -> + path = encode_path(parsed.path) + query = encode_query(parsed.query) + + %{parsed | path: path, query: query} + end) + |> URI.to_string() + + env = %{env | url: url} + + case Tesla.run(env, next) do + {:ok, env} -> {:ok, env} + err -> err + end + end + + defp encode_path(nil), do: nil + + defp encode_path(path) when is_binary(path) do + path + |> URI.decode() + |> URI.encode() + end + + defp encode_query(nil), do: nil + + defp encode_query(query) when is_binary(query) do + query + |> URI.decode_query() + |> URI.encode_query() + end +end