Skip to main content
Glama

Sentry MCP

Official
by getsentry
rate-limiter.test.ts5.03 kB
import { describe, it, expect, vi, beforeEach } from "vitest"; import { checkRateLimit } from "./rate-limiter"; import type { RateLimit } from "@cloudflare/workers-types"; describe("checkRateLimit", () => { let mockRateLimiter: RateLimit; beforeEach(() => { // Reset mocks before each test vi.clearAllMocks(); }); it("allows request when rate limiter binding is not available", async () => { const result = await checkRateLimit("192.168.1.1", undefined, { keyPrefix: "test", errorMessage: "Rate limited", }); expect(result.allowed).toBe(true); expect(result.errorMessage).toBeUndefined(); }); it("allows request when rate limit not exceeded", async () => { mockRateLimiter = { limit: vi.fn().mockResolvedValue({ success: true }), } as unknown as RateLimit; const result = await checkRateLimit("192.168.1.1", mockRateLimiter, { keyPrefix: "test", errorMessage: "Rate limited", }); expect(result.allowed).toBe(true); expect(result.errorMessage).toBeUndefined(); expect(mockRateLimiter.limit).toHaveBeenCalledWith({ key: expect.stringMatching(/^test:/), }); }); it("denies request when rate limit exceeded", async () => { mockRateLimiter = { limit: vi.fn().mockResolvedValue({ success: false }), } as unknown as RateLimit; const result = await checkRateLimit("192.168.1.1", mockRateLimiter, { keyPrefix: "test", errorMessage: "Rate limit exceeded. Please wait.", }); expect(result.allowed).toBe(false); expect(result.errorMessage).toBe("Rate limit exceeded. Please wait."); }); it("uses hashed identifier for privacy", async () => { mockRateLimiter = { limit: vi.fn().mockResolvedValue({ success: true }), } as unknown as RateLimit; await checkRateLimit("192.168.1.1", mockRateLimiter, { keyPrefix: "test", errorMessage: "Rate limited", }); // Verify the key is hashed and not the raw IP expect(mockRateLimiter.limit).toHaveBeenCalledWith({ key: expect.not.stringContaining("192.168.1.1"), }); // Verify the key has the correct format (prefix:hash) const callArg = (mockRateLimiter.limit as any).mock.calls[0][0]; expect(callArg.key).toMatch(/^test:[0-9a-f]{16}$/); }); it("uses consistent hash for same identifier", async () => { mockRateLimiter = { limit: vi.fn().mockResolvedValue({ success: true }), } as unknown as RateLimit; await checkRateLimit("192.168.1.1", mockRateLimiter, { keyPrefix: "test", errorMessage: "Rate limited", }); const firstKey = (mockRateLimiter.limit as any).mock.calls[0][0].key; // Clear and call again with same IP vi.clearAllMocks(); await checkRateLimit("192.168.1.1", mockRateLimiter, { keyPrefix: "test", errorMessage: "Rate limited", }); const secondKey = (mockRateLimiter.limit as any).mock.calls[0][0].key; // Same identifier should produce same hash expect(firstKey).toBe(secondKey); }); it("uses different keys for different identifiers", async () => { mockRateLimiter = { limit: vi.fn().mockResolvedValue({ success: true }), } as unknown as RateLimit; await checkRateLimit("192.168.1.1", mockRateLimiter, { keyPrefix: "test", errorMessage: "Rate limited", }); const firstKey = (mockRateLimiter.limit as any).mock.calls[0][0].key; // Clear and call with different IP vi.clearAllMocks(); await checkRateLimit("192.168.1.2", mockRateLimiter, { keyPrefix: "test", errorMessage: "Rate limited", }); const secondKey = (mockRateLimiter.limit as any).mock.calls[0][0].key; // Different identifiers should produce different hashes expect(firstKey).not.toBe(secondKey); }); it("includes key prefix in rate limit key", async () => { mockRateLimiter = { limit: vi.fn().mockResolvedValue({ success: true }), } as unknown as RateLimit; await checkRateLimit("192.168.1.1", mockRateLimiter, { keyPrefix: "mcp:ip", errorMessage: "Rate limited", }); expect(mockRateLimiter.limit).toHaveBeenCalledWith({ key: expect.stringMatching(/^mcp:ip:/), }); }); it("allows request when rate limiter throws error", async () => { const consoleErrorSpy = vi .spyOn(console, "error") .mockImplementation(() => {}); mockRateLimiter = { limit: vi.fn().mockRejectedValue(new Error("Rate limiter service error")), } as unknown as RateLimit; const result = await checkRateLimit("192.168.1.1", mockRateLimiter, { keyPrefix: "test", errorMessage: "Rate limited", }); // Should allow request to proceed even if rate limiter fails expect(result.allowed).toBe(true); expect(result.errorMessage).toBeUndefined(); // Should log the error expect(consoleErrorSpy).toHaveBeenCalledWith( "Rate limiter error:", expect.any(Error), ); consoleErrorSpy.mockRestore(); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/getsentry/sentry-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server