MastodonAPI: Support idempotency key.
authorlain <lain@soykaf.club>
Fri, 4 May 2018 18:30:29 +0000 (20:30 +0200)
committerlain <lain@soykaf.club>
Fri, 4 May 2018 18:30:29 +0000 (20:30 +0200)
lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
test/web/mastodon_api/mastodon_api_controller_test.exs

index c84c226e8176ab7ea28634df3cfb4d5adff2dc89..e2243538a361f02cf82cb72dd993840d5a7da022 100644 (file)
@@ -275,7 +275,19 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
       |> Map.put("in_reply_to_status_id", params["in_reply_to_id"])
       |> Map.put("no_attachment_links", true)
 
-    {:ok, activity} = CommonAPI.post(user, params)
+    idempotency_key =
+      case get_req_header(conn, "idempotency-key") do
+        [key] -> key
+        _ -> Ecto.UUID.generate()
+      end
+
+    {:ok, activity} =
+      Cachex.get!(
+        :user_cache,
+        "idem:#{idempotency_key}",
+        fallback: fn _ -> CommonAPI.post(user, params) end
+      )
+
     render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity})
   end
 
index 5293b9364ee375441a130f0f121e22c5c1718a87..432dca28a4aa6224eb562dfc1b1942faa7c5ad4d 100644 (file)
@@ -63,9 +63,12 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
   test "posting a status", %{conn: conn} do
     user = insert(:user)
 
-    conn =
+    idempotency_key = "Pikachu rocks!"
+
+    conn_one =
       conn
       |> assign(:user, user)
+      |> put_req_header("idempotency-key", idempotency_key)
       |> post("/api/v1/statuses", %{
         "status" => "cofe",
         "spoiler_text" => "2hu",
@@ -73,9 +76,23 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
       })
 
     assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} =
-             json_response(conn, 200)
+             json_response(conn_one, 200)
 
     assert Repo.get(Activity, id)
+
+    conn_two =
+      conn
+      |> assign(:user, user)
+      |> put_req_header("idempotency-key", idempotency_key)
+      |> post("/api/v1/statuses", %{
+        "status" => "cofe",
+        "spoiler_text" => "2hu",
+        "sensitive" => "false"
+      })
+
+    assert %{"id" => second_id} = json_response(conn_two, 200)
+
+    assert id == second_id
   end
 
   test "posting a sensitive status", %{conn: conn} do