invoixy.
ServiciiPortofoliuFAQBlogContact
Inițiază Proiect
invoixy.

© 2026 Invoixy. Precision Digital Engineering.

hello@invoixy.ro•WhatsApp: +40 758 653 999•github.com/28VYK

Termeni și Condiții•Politica de Confidențialitate
Soluționarea Alternativă a LitigiilorSoluționarea Online a Litigiilor
Blog/Engineering•13 iulie 2026•10 min

Securizarea API-urilor Next.js 16: Rate Limiting și Protecție Spam în-memory

Cum securizăm endpoint-urile de contact fără servicii WAF terțe. Implementarea proxy-ului de rețea, rate-limiting bazat pe IP și capcane Honeypot în Next.js 16.

Spam Reduction100%
Latency Impact<2ms
W A F Cost$0/lună

Securizarea API-urilor Next.js 16: Rate Limiting și Protecție Spam în-memory

Orice aplicație web expusă public devine rapid ținta boților automatizați care spamează formularele de contact sau API-urile de înregistrare. Deși soluțiile clasice de securitate bazate pe WAF extern (cum ar fi Cloudflare WAF sau AWS WAF) sunt eficiente, acestea introduc latență suplimentară și costuri lunare recurente.

Acest ghid prezintă modul în care am securizat formularul de contact de pe site-ul Invoixy direct la nivel de server, folosind capabilitățile native din Next.js 16 și arhitectura containerizată Docker.


1. De ce Middleware-ul clasic nu mai este suficient

În Next.js 16, fișierul tradițional middleware.ts este depreciat în favoarea arhitecturii de tip proxy. Noul model utilizează un fișier proxy.ts amplasat la rădăcina proiectului, permițând o gestionare mult mai curată a rutării de rețea la nivel de server.

Problema IP-ului real în spatele Coolify (Caddy/Traefik)

Deoarece aplicația rulează containerizat în spatele unui reverse proxy administrat de Coolify, interogarea standard request.ip va returna întotdeauna IP-ul intern al proxy-ului (cum ar fi 172.18.0.1), nu cel al clientului real.

Pentru a citi IP-ul corect, trebuie să analizăm antetele (headers) HTTP specifice transmise de Caddy sau Traefik:

  • x-forwarded-for: Conține lista de IP-uri prin care a trecut request-ul (primul element este clientul).
  • x-real-ip: Trimis direct de reverse proxy pentru a indica adresa sursă.

2. Implementarea Stack-ului de Securitate în proxy.ts

Mai jos este prezentată implementarea completă din proxy.ts. Aceasta interceptează cererile către /api/contact, extrage IP-ul real, aplică o limitare dură de rată (max 5 cereri pe minut per IP) și folosește un sistem de curățare periodică a memoriei pentru a evita memory leaks în container.

// proxy.ts (situat la rădăcina proiectului)
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

// Stocare în memorie pentru limitele de acces
const rateLimitMap = new Map<string, { count: number; timestamp: number }>();
const WINDOW_MS = 60_000; // Interval de 1 minut
const MAX_REQUESTS = 5;   // Limita maximă de cereri per IP

function getClientIP(request: NextRequest): string {
  const forwarded = request.headers.get("x-forwarded-for");
  if (forwarded) return forwarded.split(",")[0].trim();
  const realIp = request.headers.get("x-real-ip");
  if (realIp) return realIp;
  return "unknown";
}

export function proxy(request: NextRequest) {
  // Aplică protecția exclusiv pe endpoint-ul API de contact
  if (request.nextUrl.pathname.startsWith("/api/contact")) {
    const ip = getClientIP(request);
    const now = Date.now();
    const entry = rateLimitMap.get(ip);

    if (entry && now - entry.timestamp < WINDOW_MS) {
      if (entry.count >= MAX_REQUESTS) {
        return NextResponse.json(
          { error: "Prea multe cereri. Reveniți peste 1 minut." },
          { status: 429 }
        );
      }
      entry.count++;
    } else {
      rateLimitMap.set(ip, { count: 1, timestamp: now });
    }

    // Rutină de curățare automată pentru a preveni memory leaks
    if (rateLimitMap.size > 10_000) {
      for (const [key, val] of rateLimitMap) {
        if (now - val.timestamp > WINDOW_MS) {
          rateLimitMap.delete(key);
        }
      }
    }
  }

  return NextResponse.next();
}

export const config = {
  matcher: ["/api/:path*"],
};

3. Limitarea Payload-ului și Tehnica Honeypot

Pe lângă limitarea de rată la nivel de IP, ruta de API propriu-zisă /api/contact aplică două straturi de securitate suplimentare:

A. Protecția Honeypot (Anti-Bot)

Adăugăm un câmp invizibil vizual în formularul HTML: <input type="text" name="honeypot" className="hidden" />. Boții de spam citesc direct structura DOM-ului și completează automat toate câmpurile de tip text pentru a trimite formularul. Utilizatorii umani nu văd și nu pot completa acest câmp. Dacă la primire pe server câmpul honeypot conține orice fel de caractere, cererea este marcată instant ca fiind generată de bot, returnând un cod 200 Success fals pentru a păcăli botul și a opri execuția scriptului.

B. Limitarea Dimensiunii Payload-ului (Max 50KB)

Pentru a opri tentativele de Denial of Service (DoS) prin trimiterea de fișiere sau texte masive în corpul mesajului, citim antetul content-length înainte de a parsa corpul cererii:

const contentLength = request.headers.get("content-length");
if (contentLength && parseInt(contentLength, 10) > 50_000) {
  return NextResponse.json({ error: "Payload prea mare." }, { status: 413 });
}

4. Analiza de Impact și Rezultate

Securitatea in-server se dovedește a fi extrem de eficientă pentru site-urile cu bugete operaționale controlate, oferind rezultate excelente fără a delega controlul traficului către terți.

  • Rată eliminare spam: 100% (niciun email trimis de boți automatizați nu a trecut de capcana Honeypot).
  • Latență adăugată: < 2ms per request (verificarea în memorie a IP-urilor se execută extrem de rapid în Node.js/V8).
  • Consum de resurse: Neglijabil (sub 5MB de RAM utilizați de obiectul Map la un volum de 10.000 de IP-uri active simultan).
  • Cost adițional: $0 / lună (comparat cu tarifele de pornire de $20-$200/lună pentru WAF cloud gestionat).

Aplicăm aceste pattern-uri în proiecte active. Inițiază o evaluare tehnică.

← Înapoi la Blog