Sari la conținut

Date despre backlink-uri în format JSON: $100 credit gratuit, fără card, autentificare cu Google.

SEOMasters.dev
SEOMasters.devÎnregistrare

Un verificator de backlink-uri web în Next.js, cu cheia păstrată pe server

CORS este deschis, deci un browser poate apela API-ul direct. Faptul că faci asta cu o cheie plătită este greșeala. Această pagină prezintă stratul subțire de server care rezolvă problema.

Cabluri blindate conectează o casă de sticlă la o sală de servere subterană securizată cu lacăle grele

Mit versus realitate

MitRealitate
"CORS deschis înseamnă că pot livra cheia în bundle-ul meu React."CORS deschis înseamnă că apelul funcționează. Orice cineva poate citi totuși cheia din tab-ul de rețea și poate cheltui soldul tău.
"Un tabel de link-uri trebuie randat în client deoarece este un panou de control."Fă cererea pe server și trimite HTML. Utilizatorul tău vede rândurile la prima randare, iar cheia nu părăsește niciodată serverul.
"Acțiunile gratuite au nevoie de protecție la fel de mult."domain, overview, stats și suggest nu necesită cheie, deci un browser le poate apela direct.
"Ar trebui să refac cererea la fiecare vizualizare a paginii."Indexul se reconstruiește aproximativ lunar. Un cache de 24 de ore nu pierde nimic.
"Proxy-ul ar trebui să transmită orice trimite clientul."Permite doar acțiunile pe care le folosești. Un action=search transmis costă 3 credite.

Handler-ul de rută

App Router, fișierul app/api/links/route.ts. Variabila de mediu nu ajunge niciodată în bundle-ul clientului deoarece nu are prefixul NEXT_PUBLIC_.

ts
import { NextRequest, NextResponse } from "next/server";

const ALLOWED = new Set(["refdomains", "anchors", "toppages"]);

export async function GET(req: NextRequest) {
  const p = req.nextUrl.searchParams;
  const action = p.get("action") ?? "";
  const q = (p.get("q") ?? "").toLowerCase();
  if (!ALLOWED.has(action) || !/^[a-z0-9.-]+$/.test(q)) {
    return NextResponse.json({ ok: false, error: "bad request" }, { status: 400 });
  }
  const url = `https://seomasters.dev/api.php?action=${action}&q=${q}&per=100`;
  const upstream = await fetch(url, {
    headers: { Authorization: `Bearer ${process.env.SEO_API_KEY}` },
    next: { revalidate: 86400 },
  });
  if (upstream.status === 402) {
    return NextResponse.json({ ok: false, error: "data temporarily unavailable" }, { status: 503 });
  }
  return new NextResponse(upstream.body, { status: upstream.status, headers: { "content-type": "application/json" } });
}

De ce arată handler-ul așa

Lista de acțiuni permise

Un bug în interfața ta nu ar trebui să poată declanșa accidental un apel search de 3 credite.

Regex pe q

Doar un nume de gazdă simplu trece. Fără schemă, fără cale, fără șir de interogare ascuns în aval.

revalidate: 86400

Un apel la sursă pe domeniu pe zi. Cu date lunare, o perioadă mai lungă este, de asemenea, acceptabilă.

402 mappat la 503

Vizitatorii tăi nu trebuie să învețe că soldul tău este gol. Tu da, așa că logheaz-o.

Un drumeț merge pe o punte de piatră în timp ce un dronă plutește deasupra văii cețoase

Randare: ceea ce văd atât un crawler, cât și un client

Dacă acest panou de control este protejat prin parolă, randarea pe server sau pe client este o alegere UX. Dacă este public, de exemplu o pagină de căutare gratuită pe care vrei să fie indexată, randează primul tabel pe server.

O pagină care ajunge ca un schelet gol și se completează după hidratare este un risc atât pentru indexare, cât și pentru telefoanele lente. Google poate executa JavaScript, dar coasează acest pas și nu ajunge întotdeauna la el rapid.

Păstrează prezentarea gratuită pe server

Pune apelul gratuit și ieftin overview într-un Server Component și lasă vizitatorul să declanșeze apelurile plătite și mai profunde de la un buton. Această separare menține, de asemenea, cheltuielile de credite predictibile.

Apelurile gratuite nu costă nimic, deci o prezentare randată pe server nu adaugă cheltuieli de credite. Doar apelurile plătite necesită un buton și o sesiune.

Gândește-te mai întâi la starea goală. Un vizitator care ajunge pe un tabel gol va presupune că instrumentul este defect, iar o randare rapidă a doua nu anulează acea prima impresie.

Alege acțiunile gratuite pentru primul ecran și pe cele plătite pentru detaliere. Un vizitator care deschide o pagină și vede un rezumat gratuit nu are niciun motiv să apese accidental un buton plătit.

Leagă explicația, nu doar numărul

Conectarea numerelor este partea ușoară. Explicarea lor este mai grea, așa că leagă formula DR din tooltip și menționează că indexul se reîmprospătează lunar.

Un vizitator care vede un scor fără formula sa va ghici, așa că link-ul trebuie să fie lângă numărul de pe ecran.

Un meșteșugar ține o cheie de alamă lângă un sertar încuiat în spatele unei partiții de lemn

Părțile de server și client ale unui singur panou de control

Majoritatea panourilor de control au nevoie de ambele tipuri de cod. Proprietatea decide separarea. Cheia, datele și regulile de acces au fiecare un singur loc de origine. O pagină web de verificare a backlink-urilor care este publică are nevoie de aceeași separare ca una protejată prin parolă.

Fă cererea pe server, sortează în client

Un tabel de backlink-uri este un component client rezonabil când oamenii sortează, filtrează și navighează prin el. Rândurile ar trebui să vină dintr-un component server care a apelat deja ruta ta, astfel încât browserul să nu dețină niciodată cheia sau URL-ul sursă.

Sortarea a zece rânduri este instantanee în client. Sortarea a cinci mii de rânduri într-o cerere proaspătă de fiecare dată este lentă, așa că păstrează setul complet în componentul pe care l-ai încărcat deja.

Păstrează-l simplu. Un tabel care sortează instantaneu bate unul care refac cererea la fiecare clic.

Păstrează limita clientului jos

Mută limita cât mai jos în arbore. Un widget importat dinamic, doar în client, se randează în browser, în timp ce componentul care a făcut cererea rămâne pe server. Transmite rândurile ca props și păstrează cererea deasupra limitei.

Dacă muți cererea sub limită, browserul face apelul însuși. Aceasta este greșeala de care avertizează secțiunea despre scurgerea cheii, așa că verifică tab-ul Network după fiecare modificare a acestei limite.

Unde anume cade linia? Deseneaz-o mai întâi pe hârtie, cu o cutie pentru cerere și câte una pentru fiecare control interactiv, și numără săgețile care o traversează.

Scheletul și verificările de sesiune rămân pe server

Layout-ul și verificările de sesiune decid ce poate vedea un vizitator în totalitate, așa că aparțin serverului. Tabelele interactive, formularele și graficele se pot hidrata ulterior fără a schimba acea decizie.

Un gardă în client poate ascunde un buton, dar nu poate opri o cerere. Handler-ul de rută și layout-ul serverului sunt locurile unde accesul este de fapt impus.

Apoi trimite aceeași cerere fără cookie și confirmă că serverul o refuză, nu doar pagina.

Aceeași regulă acoperă și proxy-ul însuși. O verificare a sesiunii care are loc doar în browser nu poate proteja ruta, așa că ruta verifică și ea sesiunea înainte de a cheltui un credit.

Cache pe domeniu, nu pe vizitator

Ruta își construiește URL-ul sursă din domeniu, așa că cheia cache-ului urmează și ea domeniul. Un vizitator care caută un site încălzește pagina pentru următorul vizitator care întreabă despre același site.

Acesta este punctul de revalidare zilnică din handler. Doi vizitatori pe același domenie costă un singur apel la sursă, iar o mie de vizitatori pe o mie de domenii costă o mie de apeluri, așa că cache-ul este bugetul.

Fii atent și la cazul opus. O pagină care își variază șirul de interogare printr-un timestamp anulează complet cache-ul, iar factura se vede înainte de loguri.

Revalidează pe un program care se potrivește cu indexul. O fereastră zilnică se potrivește cu datele lunare, iar una mai scurtă adaugă doar apeluri fără fapte noi.

Întărire, în ordinea în care am face-o

Handler-ul este partea ușoară. Întărirea este locul unde o cheie se scurge sau un sold se golește, așa că lucrează prin acestea în ordine.

Scanează-ți propriul tab Network

Deschide Chrome DevTools pe propriul tău panou de control și citește tab-ul Network. Uită-te cu atenție. Dacă o cerere acolo arată sk_live_ undeva, rotește cheia astăzi. Acea verificare durează un minut și găsește cea mai comună scurgere.

Caută și în corpurile de răspuns, nu doar în anteturile de cerere. O cheie reprodusă într-un mesaj de eroare este tot o scurgere.

Captează apelurile pe utilizator

În continuare, adaugă o limită pe utilizator. Pune-o în fața rutei. Handler-ul de mai sus cheltuie creditul tău pentru oricine poate ajunge la el, așa că leagă-l de o sesiune și captează apelurile pe oră. Alege capul din matematica bugetului de pe pagina de credite.

Începe generos și strânge mai târziu. O limită care blochează utilizatorii reali în prima zi îi învață să găsească un alt instrument.

Numează pe cineva care completează

Merită, de asemenea, o linie în manualul de rulare: cine este alertat când soldul scade sub un anumit nivel și cine îl completează. Numează persoana.

Scrie pasul de completare ca o listă de verificare cu link-ul către pagina de cont și timpul de răspuns așteptat. Un manual de rulare care există doar în capul unei singure persoane eșuează prima dată când acea persoană este în concediu. Pasul însuși durează minute, așa că scrierea este sarcina mai mare.

Loghează soldul înainte să se epuizeze

Apoi loghează _credits din fiecare răspuns sursă în propriile tale metrici. Un grafic al soldului rămas, eșantionat zilnic, te avertizează cu o săptămână înainte ca HTTP 402 să o facă.

Alege nivelul de alertă din utilizarea ta săptămânală. Un număr ales dintr-un șablon rar se potrivește cu apelurile tale reale.

Păstrează ultima valoare văzută în memorie, nu doar în log, astfel încât ruta să poată refuza apelurile plătite odată ce numărul scade sub nivelul de alertă. Acea verificare este o singură linie și oprește un val de trafic să cheltuiască restul.

Păstrează lista de acțiuni permise într-un singur loc

Un alt obicei care plătește. Păstrează lista de acțiuni permise într-o constantă partajată, importată de handler și de teste, astfel încât o acțiune nouă să nu poată ajunge în producție fără ca cineva să editeze o listă vizibilă și un reviewer să o observe.

Un fișier, un import. Nimeni nu ar trebui să trebuiască să caute lista în trei componente pentru a ști ce va accepta proxy-ul.

Testează mediul de rulare la care faci deploy

În final, rulează handler-ul sub Node 20 sau sub runtime-ul edge la alegere și testează ambele. Streaming-ul corpului sursă, așa cum face codul, funcționează în fiecare, dar manipularea anteturilor diferă și merită un test.

Adaugă un test care apelează ruta cu o acțiune invalidă și unul cu o acțiune validă și afirmă codurile de status. Aceste două teste prind majoritatea regresiilor în lista de acțiuni permise și manipularea anteturilor.

Conectarea proxy-ului în ordine

  1. 1

    Adaugă cheia pe server

    Stochează cheia în mediul tău de server sub un nume fără prefix public, apoi repornește serverul de dezvoltare pentru a se încărca.

  2. 2

    Scrie mai întâi lista de acțiuni permise

    Listează acțiunile pe care ecranele tale le apelează cu adevărat. Orice altceva primește un 400 de la propria ta rută, înainte să ajungă la API-ul sursă.

  3. 3

    Fă cererea la ruta ta dintr-un component server

    Randează rândurile acolo unde ajung datele. Browserul apelează doar propriul tău domeniu, astfel încât adresa sursă rămâne în afara paginii.

  4. 4

    Uită-te la sold

    Loghează _credits la fiecare răspuns sursă și setează un nivel de alertă la care poți acționa, înainte ca un 402 să ajungă la un vizitator ca un 503.