Công cụ kiểm tra backlink web trong Next.js, khóa được giữ trên máy chủ
CORS được mở, vì vậy trình duyệt có thể gọi API trực tiếp. Việc làm điều này với một khóa trả phí là một sai lầm. Trang này hiển thị lớp máy chủ mỏng giúp khắc phục vấn đề đó.

Quan niệm sai lầm so với thực tế
| Quan niệm sai lầm | Thực tế |
|---|---|
| "CORS mở có nghĩa là tôi có thể đưa khóa vào bundle React của mình." | CORS mở có nghĩa là lệnh gọi hoạt động. Bất kỳ ai cũng vẫn có thể đọc khóa từ tab mạng và tiêu tốn số dư của bạn. |
| "Một bảng liên kết phải được render trên client vì đó là bảng điều khiển." | Truy vấn trên máy chủ và gửi HTML. Người dùng của bạn thấy các hàng ngay lần hiển thị đầu tiên và khóa của bạn không bao giờ rời khỏi máy chủ. |
| "Các hành động miễn phí cũng cần được bảo vệ." | domain, overview, stats và suggest không cần khóa, vì vậy trình duyệt có thể gọi chúng trực tiếp. |
| "Tôi nên truy vấn lại ở mỗi lần xem trang." | Chỉ mục được xây dựng lại khoảng hàng tháng. Bộ nhớ đệm 24 giờ không làm mất dữ liệu nào. |
| "Proxy nên chuyển tiếp mọi thứ mà client gửi." | Cho phép danh sách các hành động bạn sử dụng. Một action=search được chuyển tiếp tốn 3 tín dụng. |
Handler route
App Router, file app/api/links/route.ts. Biến môi trường không bao giờ đạt đến bundle client vì nó không có tiền tố NEXT_PUBLIC_.
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" } });
}Tại sao handler trông như vậy
Danh sách cho phép các hành động
Một lỗi trong giao diện người dùng của bạn không nên có khả năng kích hoạt lệnh gọi search tốn 3 tín dụng một cách tình cờ.
Regex trên q
Chỉ một tên máy chủ đơn giản mới được thông qua. Không có lược đồ, không có đường dẫn, không có chuỗi truy vấn được ngấm ngầm gửi lên.
revalidate: 86400
Một lệnh gọi upstream mỗi domain mỗi ngày. Với dữ liệu hàng tháng, thời gian dài hơn cũng được.
402 được ánh xạ thành 503
Khách truy cập của bạn không cần phải học rằng số dư của bạn đã hết. Bạn cần biết, vì vậy hãy ghi log nó.

Render: những gì một crawler và một khách hàng đều thấy
Nếu bảng điều khiển này nằm sau đăng nhập, việc render phía máy chủ hay client là một lựa chọn trải nghiệm người dùng. Nếu bất kỳ phần nào là công khai, chẳng hạn như một trang tra cứu miễn phí mà bạn muốn được lập chỉ mục, hãy render bảng đầu tiên trên máy chủ.
Một trang đến dưới dạng một vỏ trống và điền dữ liệu sau khi hydration là một rủi ro cho việc lập chỉ mục và đối với các điện thoại chậm. Google có thể thực thi JavaScript, nhưng nó xếp hàng bước đó và không phải lúc nào cũng thực hiện nhanh chóng.
Giữ phần tổng quan miễn phí trên máy chủ
Đặt lệnh gọi overview rẻ, miễn phí vào một Server Component và cho phép khách truy cập kích hoạt các lệnh gọi trả phí, sâu hơn từ một nút bấm. Sự phân chia đó cũng giúp chi tiêu tín dụng của bạn có thể dự đoán được.
Các lệnh gọi miễn phí không tốn gì, vì vậy một phần tổng quan được render trên máy chủ không làm tăng chi tiêu tín dụng. Chỉ các lệnh gọi trả phí mới cần một nút bấm và một phiên.
Hãy nghĩ về trạng thái trống trước. Một khách truy cập landing trên một bảng trống sẽ cho rằng công cụ bị lỗi, và một lần hiển thị thứ hai nhanh chóng không thể xóa bỏ ấn tượng ban đầu đó.
Chọn các hành động miễn phí cho màn hình đầu tiên và các hành động trả phí cho các phần chi tiết. Một khách truy cập mở một trang và thấy một bản tóm tắt miễn phí sẽ không có lý do gì để nhấn nút trả phí một cách tình cờ.
Liên kết phần giải thích, không chỉ con số
Dán nối các con số là phần dễ dàng. Giải thích chúng khó hơn, vì vậy hãy liên kết công thức DR từ tooltip và đề cập rằng chỉ mục làm mới hàng tháng.
Một khách truy cập thấy một điểm số mà không có công thức của nó sẽ đoán mò, vì vậy liên kết phải nằm bên cạnh con số trên màn hình.

Các phần máy chủ và client của một bảng điều khiển
Hầu hết các bảng điều khiển đều cần cả hai loại mã. Việc sở hữu quyết định sự phân chia. Khóa, dữ liệu và các quy tắc truy cập mỗi thứ đều có một nơi duy nhất. Một trang web backlink checker công khai cần sự phân chia tương tự như một trang nằm sau đăng nhập.
Truy vấn trên máy chủ, sắp xếp trên client
Một bảng backlink là một component client hợp lý khi mọi người sắp xếp, lọc và phân trang qua nó. Các hàng nên đến từ một component máy chủ đã gọi route của bạn, vì vậy trình duyệt không bao giờ giữ khóa hoặc URL upstream.
Sắp xếp mười hàng thì tức thì trên client. Sắp xếp năm nghìn hàng trong một yêu cầu mới mỗi lần thì chậm, vì vậy hãy giữ toàn bộ tập hợp trong component bạn đã tải rồi.
Giữ nó đơn giản. Một bảng sắp xếp tức thì thì tốt hơn một bảng truy vấn lại ở mỗi lần nhấp.
Giữ ranh giới client thấp
Đẩy ranh giới xuống sâu nhất có thể trong cây. Một widget chỉ dành cho client được import động sẽ render trong trình duyệt, trong khi component đã truy vấn các hàng vẫn ở trên máy chủ. Truyền các hàng dưới dạng props và giữ lệnh truy vấn ở trên ranh giới.
Nếu bạn di chuyển lệnh truy vấn xuống dưới ranh giới, trình duyệt sẽ tự thực hiện lệnh gọi. Đó là sai lầm mà phần rò rỉ khóa cảnh báo, vì vậy hãy kiểm tra tab Network sau mỗi lần thay đổi ranh giới này.
Đường界限 chính xác nằm ở đâu? Vẽ nó trên giấy trước, với một hộp cho lệnh truy vấn và một hộp cho mỗi điều khiển tương tác, và đếm các mũi tên cắt ngang nó.
Vỏ và kiểm tra phiên vẫn ở trên máy chủ
Bố cục và kiểm tra phiên quyết định những gì một khách truy cập có thể thấy, vì vậy chúng thuộc về máy chủ. Các bảng tương tác, biểu mẫu và biểu đồ có thể hydration sau đó mà không thay đổi quyết định đó.
Một guard phía client có thể ẩn một nút, nhưng nó không thể ngăn một yêu cầu. Handler route và layout máy chủ là nơi quyền truy cập thực sự được thực thi.
Sau đó, gửi cùng một yêu cầu mà không có cookie và xác nhận máy chủ từ chối nó, không chỉ trang web.
Quy tắc tương tự áp dụng cho chính proxy. Một kiểm tra phiên chỉ xảy ra trong trình duyệt không thể bảo vệ route, vì vậy route cũng kiểm tra phiên trước khi chi tiêu một tín dụng.
Bộ nhớ đệm theo domain, không phải theo khách truy cập
Route xây dựng URL upstream của nó từ domain, vì vậy khóa bộ nhớ đệm cũng theo domain. Một khách truy cập tra cứu một trang web sẽ làm nóng trang cho khách truy cập tiếp theo hỏi về cùng một trang web đó.
Đó là điểm của việc revalidate hàng ngày trong handler. Hai khách truy cập trên cùng một domain tốn một lệnh gọi upstream, và một nghìn khách truy cập trên một nghìn domain tốn một nghìn lệnh gọi, vì vậy bộ nhớ đệm là ngân sách.
Hãy chú ý đến trường hợp ngược lại. Một trang thay đổi chuỗi truy vấn của nó bằng dấu thời gian sẽ vô hiệu hóa hoàn toàn bộ nhớ đệm, và hóa đơn sẽ hiển thị nó trước khi logs làm vậy.
Revalidate theo lịch trình phù hợp với chỉ mục. Cửa sổ hàng ngày phù hợp với dữ liệu hàng tháng, và một cửa sổ ngắn hơn chỉ thêm các lệnh gọi mà không thêm sự thật mới.
Củng cố, theo thứ tự chúng ta sẽ thực hiện
Handler là phần dễ dàng. Việc củng cố là nơi khóa bị rò rỉ hoặc số dư cạn kiệt, vì vậy hãy làm theo thứ tự này.
Quét tab Network của chính bạn
Mở Chrome DevTools trên bảng điều khiển của chính bạn và đọc tab Network. Hãy nhìn kỹ. Nếu một yêu cầu ở đó hiển thị sk_live_ ở bất cứ đâu, hãy xoay khóa ngay hôm nay. Kiểm tra đó mất một phút và tìm ra lỗ hổng phổ biến nhất.
Tìm kiếm trong thân phản hồi cũng như trong các tiêu đề yêu cầu. Một khóa được phản ánh trong thông báo lỗi vẫn là một lỗ hổng.
Giới hạn số lệnh gọi mỗi người dùng
Tiếp theo, thêm giới hạn mỗi người dùng. Đặt nó ở phía trước route. Handler ở trên chi tiêu tín dụng của bạn cho bất kỳ ai có thể truy cập nó, vì vậy hãy gắn nó với một phiên và giới hạn số lệnh gọi mỗi giờ. Chọn giới hạn từ toán học ngân sách trên trang tín dụng.
Bắt đầu hào phóng và siết chặt sau. Một giới hạn chặn người dùng thực sự vào ngày đầu tiên sẽ dạy họ tìm một công cụ khác.
Chỉ định ai là người nạp thêm
Cũng đáng một dòng trong sổ tay vận hành: ai sẽ được thông báo khi số dư giảm xuống dưới một mức nhất định, và ai sẽ nạp thêm. Hãy nêu tên người đó.
Viết bước nạp thêm thành một danh sách kiểm tra với liên kết trang tài khoản và thời gian xử lý dự kiến. Một sổ tay vận hành chỉ tồn tại trong đầu một người sẽ thất bại vào lần đầu tiên người đó nghỉ phép. Bản thân bước đó chỉ mất vài phút, vì vậy việc viết ra là công việc lớn hơn.
Ghi log số dư trước khi nó cạn kiệt
Sau đó, ghi log _credits từ mỗi phản hồi upstream vào các chỉ số của riêng bạn. Một biểu đồ số dư còn lại, được lấy mẫu hàng ngày, sẽ cảnh báo bạn một tuần trước khi HTTP 402 xảy ra.
Chọn mức cảnh báo từ việc sử dụng hàng tuần của chính bạn. Một con số được chọn từ một mẫu hiếm khi khớp với các lệnh gọi thực tế của bạn.
Giữ giá trị cuối cùng bạn đã thấy trong bộ nhớ cũng như trong log, vì vậy route có thể từ chối các lệnh gọi trả phí một khi con số giảm dưới mức cảnh báo. Kiểm tra đó chỉ là một dòng, và nó ngăn một đợt lưu lượng truy cập bùng nổ tiêu tốn phần còn lại.
Giữ danh sách cho phép ở một nơi
Một thói quen khác cũng mang lại lợi ích. Hãy giữ danh sách cho phép trong một hằng số được chia sẻ, được import bởi handler và các bài kiểm tra, vì vậy một hành động mới không thể đạt đến sản xuất mà không có ai đó chỉnh sửa một danh sách hiển thị và một người xem nhận ra nó.
Một file, một import. Không ai phải tìm kiếm danh sách trong ba component để biết proxy sẽ chấp nhận gì.
Kiểm tra thời gian chạy bạn triển khai
Cuối cùng, hãy chạy handler dưới Node 20 hoặc thời gian chạy edge mà bạn chọn và kiểm tra cả hai. Việc phát trực tuyến thân upstream, như mã làm, hoạt động trong mỗi cái, nhưng xử lý tiêu đề khác nhau và đáng để kiểm tra.
Thêm một bài kiểm tra gọi route với một hành động không hợp lệ và một bài kiểm tra với một hành động hợp lệ, và xác nhận trên các mã trạng thái. Hai bài kiểm tra đó bắt được hầu hết các lỗi hồi quy trong danh sách cho phép và xử lý tiêu đề.
Dán nối proxy theo thứ tự
- 1
Thêm khóa trên máy chủ
Lưu khóa trong môi trường máy chủ của bạn dưới một tên không có tiền tố công khai, sau đó khởi động lại máy chủ dev để nó tải.
- 2
Viết danh sách cho phép trước
Liệt kê các hành động mà màn hình của bạn thực sự gọi. Bất kỳ thứ gì khác sẽ nhận được 400 từ route của chính bạn, trước khi nó đạt đến API upstream.
- 3
Truy vấn route của bạn từ một component máy chủ
Render các hàng nơi dữ liệu đến. Trình duyệt chỉ gọi domain của chính bạn, vì vậy địa chỉ upstream vẫn không xuất hiện trên trang.
- 4
Theo dõi số dư
Ghi log
_creditstrên mỗi phản hồi upstream và đặt mức cảnh báo mà bạn có thể hành động, trước khi 402 đạt đến khách truy cập dưới dạng 503.