commit: cfc8d7aade526b8f119683984977064cd3cd3d87
parent ff6f5a417f1f22d53b1196cc19e1ba9ad6e0ed2c
Author: Mark Felder <feld@feld.me>
Date: Tue, 28 May 2024 13:14:34 -0400
IPFS uploader: dialyzer fixes
lib/pleroma/uploaders/ipfs.ex:43:no_return
Function put_file/1 has no local return.
________________________________________________________________________________
lib/pleroma/uploaders/ipfs.ex:49:call
The function call will not succeed.
Pleroma.HTTP.post(
binary(),
_mp :: %Tesla.Multipart{
:boundary => binary(),
:content_type_params => [binary()],
:parts => [
%Tesla.Multipart.Part{
:body => binary(),
:dispositions => [any()],
:headers => [any()]
},
...
]
},
[],
[{:params, [{:"cid-version", <<49>>}]}]
)
will never return since the success typing is:
(binary(), binary(), [{binary(), binary()}], Keyword.t()) ::
{:error, _}
| {:ok,
%Tesla.Env{
:__client__ => %Tesla.Client{
:adapter => nil | {_, _} | {_, _, _},
:fun => _,
:post => [any()],
:pre => [any()]
},
:__module__ => atom(),
:body => _,
:headers => [{_, _}],
:method => :delete | :get | :head | :options | :patch | :post | :put | :trace,
:opts => [{_, _}],
:query => [{_, _}],
:status => nil | integer(),
:url => binary()
}}
and the contract is
(Pleroma.HTTP.Request.url(), String.t(), Pleroma.HTTP.Request.headers(), :elixir.keyword()) ::
{:ok, Tesla.Env.t()} | {:error, any()}
Diffstat:
5 files changed, 55 insertions(+), 62 deletions(-)
diff --git a/changelog.d/ipfs-dialyzer.skip b/changelog.d/ipfs-dialyzer.skip
@@ -0,0 +1 @@
+no comment
diff --git a/config/config.exs b/config/config.exs
@@ -83,8 +83,8 @@ config :ex_aws, :s3,
scheme: "https://"
config :pleroma, Pleroma.Uploaders.IPFS,
- post_gateway_url: nil,
- get_gateway_url: nil
+ post_gateway_url: "http://localhost:5001",
+ get_gateway_url: "http://localhost:8080"
config :pleroma, :emoji,
shortcode_globs: ["/emoji/custom/**/*.png"],
diff --git a/lib/pleroma/http.ex b/lib/pleroma/http.ex
@@ -37,7 +37,7 @@ defmodule Pleroma.HTTP do
See `Pleroma.HTTP.request/5`
"""
- @spec post(Request.url(), String.t(), Request.headers(), keyword()) ::
+ @spec post(Request.url(), Tesla.Env.body(), Request.headers(), keyword()) ::
{:ok, Env.t()} | {:error, any()}
def post(url, body, headers \\ [], options \\ []),
do: request(:post, url, body, headers, options)
@@ -56,7 +56,7 @@ defmodule Pleroma.HTTP do
`{:ok, %Tesla.Env{}}` or `{:error, error}`
"""
- @spec request(method(), Request.url(), String.t(), Request.headers(), keyword()) ::
+ @spec request(method(), Request.url(), Tesla.Env.body(), Request.headers(), keyword()) ::
{:ok, Env.t()} | {:error, any()}
def request(method, url, body, headers, options) when is_binary(url) do
uri = URI.parse(url)
diff --git a/lib/pleroma/uploaders/ipfs.ex b/lib/pleroma/uploaders/ipfs.ex
@@ -8,23 +8,10 @@ defmodule Pleroma.Uploaders.IPFS do
alias Tesla.Multipart
+ @api_add "/api/v0/add"
+ @api_delete "/api/v0/files/rm"
@config_impl Application.compile_env(:pleroma, [__MODULE__, :config_impl], Pleroma.Config)
- defp get_final_url(method) do
- config = @config_impl.get([__MODULE__])
- post_base_url = Keyword.get(config, :post_gateway_url)
-
- Path.join([post_base_url, method])
- end
-
- def put_file_endpoint do
- get_final_url("/api/v0/add")
- end
-
- def delete_file_endpoint do
- get_final_url("/api/v0/files/rm")
- end
-
@placeholder "{CID}"
def placeholder, do: @placeholder
@@ -40,26 +27,26 @@ defmodule Pleroma.Uploaders.IPFS do
end
@impl true
- def put_file(%Pleroma.Upload{} = upload) do
+ def put_file(%Pleroma.Upload{tempfile: tempfile}) do
mp =
Multipart.new()
|> Multipart.add_content_type_param("charset=utf-8")
- |> Multipart.add_file(upload.tempfile)
+ |> Multipart.add_file(tempfile)
- case Pleroma.HTTP.post(put_file_endpoint(), mp, [], params: ["cid-version": "1"]) do
- {:ok, ret} ->
- case Jason.decode(ret.body) do
- {:ok, ret} ->
- if Map.has_key?(ret, "Hash") do
- {:ok, {:file, ret["Hash"]}}
- else
- {:error, "JSON doesn't contain Hash key"}
- end
+ endpoint = ipfs_endpoint(@api_add)
- error ->
- Logger.error("#{__MODULE__}: #{inspect(error)}")
- {:error, "JSON decode failed"}
- end
+ with {:ok, %{body: body}} when is_binary(body) <-
+ Pleroma.HTTP.post(endpoint, mp, [], params: ["cid-version": "1"], pool: :upload),
+ {_, {:ok, decoded}} <- {:json, Jason.decode(body)},
+ {_, true} <- {:hash, Map.has_key?(decoded, "Hash")} do
+ {:ok, {:file, decoded["Hash"]}}
+ else
+ {:hash, false} ->
+ {:error, "JSON doesn't contain Hash key"}
+
+ {:json, error} ->
+ Logger.error("#{__MODULE__}: #{inspect(error)}")
+ {:error, "JSON decode failed"}
error ->
Logger.error("#{__MODULE__}: #{inspect(error)}")
@@ -69,9 +56,17 @@ defmodule Pleroma.Uploaders.IPFS do
@impl true
def delete_file(file) do
- case Pleroma.HTTP.post(delete_file_endpoint(), "", [], params: [arg: file]) do
+ endpoint = ipfs_endpoint(@api_delete)
+
+ case Pleroma.HTTP.post(endpoint, "", [], params: [arg: file]) do
{:ok, %{status: 204}} -> :ok
error -> {:error, inspect(error)}
end
end
+
+ defp ipfs_endpoint(path) do
+ URI.parse(@config_impl.get([__MODULE__, :post_gateway_url]))
+ |> Map.put(:path, path)
+ |> URI.to_string()
+ end
end
diff --git a/test/pleroma/uploaders/ipfs_test.exs b/test/pleroma/uploaders/ipfs_test.exs
@@ -14,25 +14,6 @@ defmodule Pleroma.Uploaders.IPFSTest do
alias Pleroma.UnstubbedConfigMock, as: Config
- describe "get_final_url" do
- setup do
- Config
- |> expect(:get, fn [Pleroma.Uploaders.IPFS] ->
- [post_gateway_url: "http://localhost:5001"]
- end)
-
- :ok
- end
-
- test "it returns the final url for put_file" do
- assert IPFS.put_file_endpoint() == "http://localhost:5001/api/v0/add"
- end
-
- test "it returns the final url for delete_file" do
- assert IPFS.delete_file_endpoint() == "http://localhost:5001/api/v0/files/rm"
- end
- end
-
describe "get_file/1" do
setup do
Config
@@ -71,8 +52,8 @@ defmodule Pleroma.Uploaders.IPFSTest do
describe "put_file/1" do
setup do
Config
- |> expect(:get, fn [Pleroma.Uploaders.IPFS] ->
- [post_gateway_url: "http://localhost:5001"]
+ |> expect(:get, fn [Pleroma.Uploaders.IPFS, :post_gateway_url] ->
+ "http://localhost:5001"
end)
file_upload = %Pleroma.Upload{
@@ -92,7 +73,11 @@ defmodule Pleroma.Uploaders.IPFSTest do
test "save file", %{file_upload: file_upload} do
with_mock Pleroma.HTTP,
- post: fn "http://localhost:5001/api/v0/add", _mp, [], params: ["cid-version": "1"] ->
+ post: fn "http://localhost:5001/api/v0/add",
+ _mp,
+ [],
+ params: ["cid-version": "1"],
+ pool: :upload ->
{:ok,
%Tesla.Env{
status: 200,
@@ -107,7 +92,11 @@ defmodule Pleroma.Uploaders.IPFSTest do
test "returns error", %{file_upload: file_upload} do
with_mock Pleroma.HTTP,
- post: fn "http://localhost:5001/api/v0/add", _mp, [], params: ["cid-version": "1"] ->
+ post: fn "http://localhost:5001/api/v0/add",
+ _mp,
+ [],
+ params: ["cid-version": "1"],
+ pool: :upload ->
{:error, "IPFS Gateway upload failed"}
end do
assert capture_log(fn ->
@@ -118,7 +107,11 @@ defmodule Pleroma.Uploaders.IPFSTest do
test "returns error if JSON decode fails", %{file_upload: file_upload} do
with_mock Pleroma.HTTP, [],
- post: fn "http://localhost:5001/api/v0/add", _mp, [], params: ["cid-version": "1"] ->
+ post: fn "http://localhost:5001/api/v0/add",
+ _mp,
+ [],
+ params: ["cid-version": "1"],
+ pool: :upload ->
{:ok, %Tesla.Env{status: 200, body: "invalid"}}
end do
assert capture_log(fn ->
@@ -130,7 +123,11 @@ defmodule Pleroma.Uploaders.IPFSTest do
test "returns error if JSON body doesn't contain Hash key", %{file_upload: file_upload} do
with_mock Pleroma.HTTP, [],
- post: fn "http://localhost:5001/api/v0/add", _mp, [], params: ["cid-version": "1"] ->
+ post: fn "http://localhost:5001/api/v0/add",
+ _mp,
+ [],
+ params: ["cid-version": "1"],
+ pool: :upload ->
{:ok, %Tesla.Env{status: 200, body: "{\"key\": \"value\"}"}}
end do
assert IPFS.put_file(file_upload) == {:error, "JSON doesn't contain Hash key"}
@@ -141,8 +138,8 @@ defmodule Pleroma.Uploaders.IPFSTest do
describe "delete_file/1" do
setup do
Config
- |> expect(:get, fn [Pleroma.Uploaders.IPFS] ->
- [post_gateway_url: "http://localhost:5001"]
+ |> expect(:get, fn [Pleroma.Uploaders.IPFS, :post_gateway_url] ->
+ "http://localhost:5001"
end)
:ok