Fresh repository history for elektrine/tarakan hosted at https://git.elektrine.com/elektrine/tarakan.
68 lines
2 KiB
Elixir
68 lines
2 KiB
Elixir
defmodule TarakanWeb.Plugs.CodeBrowserRateLimitTest do
|
|
use Tarakan.DataCase, async: true
|
|
|
|
import Plug.Conn
|
|
import Plug.Test
|
|
|
|
alias TarakanWeb.Plugs.CodeBrowserRateLimit
|
|
|
|
test "allows requests under the per-IP budget" do
|
|
opts = CodeBrowserRateLimit.init(limit: 2, window_seconds: 60)
|
|
|
|
for path <- [
|
|
"/findings/55d5c681-240a-4e3a-a1f8-45933a30c4ef/code",
|
|
"/github.com/openai/codex"
|
|
] do
|
|
conn = conn(:get, path) |> CodeBrowserRateLimit.call(opts)
|
|
refute conn.halted
|
|
end
|
|
end
|
|
|
|
test "answers 429 once the per-IP budget is exceeded" do
|
|
opts = CodeBrowserRateLimit.init(limit: 2, window_seconds: 60)
|
|
|
|
for _ <- 1..2 do
|
|
conn = conn(:get, "/github.com/openai/codex") |> CodeBrowserRateLimit.call(opts)
|
|
refute conn.halted
|
|
end
|
|
|
|
conn = conn(:get, "/github.com/openai/codex") |> CodeBrowserRateLimit.call(opts)
|
|
|
|
assert conn.halted
|
|
assert conn.status == 429
|
|
assert [retry_after] = get_resp_header(conn, "retry-after")
|
|
assert String.to_integer(retry_after) > 0
|
|
end
|
|
|
|
test "IPv6 clients in the same /64 share one bucket" do
|
|
opts = CodeBrowserRateLimit.init(limit: 1, window_seconds: 60)
|
|
|
|
first =
|
|
conn(:get, "/github.com/openai/codex")
|
|
|> Map.put(:remote_ip, {0x2001, 0x0DB8, 0, 0, 0, 0, 0, 1})
|
|
|> CodeBrowserRateLimit.call(opts)
|
|
|
|
refute first.halted
|
|
|
|
second =
|
|
conn(:get, "/github.com/openai/codex")
|
|
|> Map.put(:remote_ip, {0x2001, 0x0DB8, 0, 0, 0xFFFF, 0xEEEE, 0xDDDD, 0xCCCC})
|
|
|> CodeBrowserRateLimit.call(opts)
|
|
|
|
assert second.halted
|
|
assert second.status == 429
|
|
end
|
|
|
|
test "admins and moderators are exempt from the budget" do
|
|
opts = CodeBrowserRateLimit.init(limit: 1, window_seconds: 60)
|
|
|
|
for role <- ["admin", "moderator"], _ <- 1..3 do
|
|
conn =
|
|
conn(:get, "/github.com/openai/codex")
|
|
|> assign(:current_scope, %{platform_role: role})
|
|
|> CodeBrowserRateLimit.call(opts)
|
|
|
|
refute conn.halted
|
|
end
|
|
end
|
|
end
|