Muvaffaqiyatlar va veb-hokiklar
O'yin (video, rasm, musiqa) * asynchronoz*: siz taskin (ijod) ni yaratasiz va natija tayyor bo'lganda olib ketasiz. Tasavvur qilish) va webhuk (tushirish) bilan tugallangan vazifalarni aniqlashning ikkita usuli mavjud: so'rovnoma* (so'rovnoma) va saytnoma* (tushish).
Muammoning hayot davri
POST /media/generate → status: processing ──► done (result_url готов)
│ └─► failed (error, средства возвращены)
└── (опционально) callback_url → пуш-вебхук на done/failed- Tavsiyat.
POST /media/generatemodel va parametrlari bilanidva so'rov uchun bog'liq bo'lgan ni qaytarib beradi:
{ "id": "beefb531-…", "model": "image/nano-banana-2", "status": "processing",
"poll": "https://nordrouter.com/media/job/beefb531-…" }Tashkilot. Muammoni bajarish
processing→done(yokifailed).Nomur. Bajarilgan vazifa
result_url(nordrouter.com) ga bog'liq) bilan to'ldirilgan; fayl cheklangan vaqt saqlanadi (retention_daysGET /media/models) Uni saqlash uchun yuklab oling.
Javobning formatini GET /media/job/:id (va veb-xokning jismlari) quyidagicha ko'rish mumkin:
{ "id": "beefb531-…", "status": "done",
"result_url": "https://nordrouter.com/media/file/beefb531-…",
"cost_usd": 0.052, "error": null }status—processing|done|failed.result_urlfaqatdoneda to'ldiriladi, agar yo'q bo'lsanullda to'ldiriladi.result_url_2Musiqa modellarining (Suno) ikkinchi treki, boshqachanull.cost_usdhaqiqiy qiymat (faxt bo'yicha ro'yxatga olinadi; muvaffaqiyatsiz ishlab chiqarilgan tariflanmaydi zaxira qaytariladi).errorfailedda xato matni, agar yo'q bo'lsanullda xato matni.
1. usul. So'rovnoma (so'rovnoma)
Eng oson yo'l - vaqti-vaqti bilan so'rash. GET /media/job/:idHozircha status bo'lmaydi. done/failed:
curl https://nordrouter.com/media/job/beefb531-…So'rov har 23 soniyada bir marta o'tkaziladi.So'rov har doim ishlaydi va ommaviy manzilni talab qilmaydi.Skriptlar, noutbuklar, CI uchun mos keladi.
2-taxt. veb-hukki (tush)
So'rovni o'tkazmaslik uchun callback_url ni POST /media/generate ga yuboring va vazifa tugallanganida biz POSTni o'zimiz yuboramiz:
curl https://nordrouter.com/media/generate \
-H "Authorization: Bearer sk-nr-YOUR-KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "image/nano-banana-2",
"input": { "prompt": "…" },
"callback_url": "https://your-server.com/webhooks/nordrouter",
"callback_secret": "любая-ваша-строка"
}'Agar callback_url qabul qilinsa, yaratishga javob "webhook": "registered" ni o'z ichiga oladi. callback_url vazifa yaratishda birdan **** tekshirilgan: agar u mos kelmasa (https emas, xususiy/lokal manzil) so'rov 400 ni sabab bilan qaytaradi, vazifa yaratilmaydi.
Vebhuqa tanasi
Muammoni done/failed ga yetkazganida, sizning callback_url ga POST bilan bir xil jism bilan keladi, GET /media/job/:id bilan bir qatorda event sohasi.
{ "event": "media.completed", "id": "beefb531-…", "status": "done",
"result_url": "https://nordrouter.com/media/file/beefb531-…",
"cost_usd": 0.052, "error": null }eventmedia.completed(success) yokimedia.failed(o'rtoq).
Imzolarni tekshirish
Agar siz callback_secret ga kirgan bo'lsangiz, X-NR-Signature sarlavhasida sha256=<hmac> HMAC-SHA256 so'rovning xom ostiga qo'yilgan, kalit = siringiz bor.
import hmac, hashlib
def verify(raw_body: bytes, header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, header) # сравнение за константное времяimport crypto from "node:crypto";
function verify(rawBody, header, secret) {
const expected = "sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(header));
}HMACni baytlardan boshlab, xuddi kelganidek hisoblang, JSON-parsingga qadar o'qing, aks holda imzo o'zgarmaydi.
10 satr ichida tayyor qabul qiluvchi
Veb-hokni qabul qiladigan ishchi server imzoni tekshiradi va javob beradi 2xx. sir siz callback_secretga o'tkazilgan sirga o'xshaydi.
Node.js / Express:
import express from "express";
import crypto from "node:crypto";
const SECRET = "любая-ваша-строка"; // = ваш callback_secret
const app = express();
app.post("/webhooks/nordrouter",
express.raw({ type: "application/json" }), // сырое тело — обязательно для подписи
(req, res) => {
const expected = "sha256=" + crypto.createHmac("sha256", SECRET).update(req.body).digest("hex");
const got = req.headers["x-nr-signature"] || "";
if (expected.length !== got.length || !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(got)))
return res.sendStatus(401); // подпись не сошлась — не наш запрос
const job = JSON.parse(req.body);
if (job.event === "media.completed") console.log("готово:", job.result_url, "$" + job.cost_usd);
res.sendStatus(200); // ответьте 2xx, иначе будет повтор
});
app.listen(3000);Python / FastAPI:
import hmac, hashlib
from fastapi import FastAPI, Request, Response
SECRET = b"любая-ваша-строка" # = ваш callback_secret
app = FastAPI()
@app.post("/webhooks/nordrouter")
async def hook(request: Request):
raw = await request.body() # сырые байты — обязательно для подписи
expected = "sha256=" + hmac.new(SECRET, raw, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, request.headers.get("X-NR-Signature", "")):
return Response(status_code=401) # подпись не сошлась — не наш запрос
job = await request.json()
if job["event"] == "media.completed":
print("готово:", job["result_url"], "$", job["cost_usd"])
return Response(status_code=200) # ответьте 2xx, иначе будет повторMahalliy ravishda tekshirish
callback_url ommaviy bo'lishi kerak https. Yozatuv uchun noutbukda tunnelni ko'taring, masalan, ngrok http 3000 va unga berilgan https-manzilni callback_url. sifatida yuboring.
Etkazib berish va ishonchlilik
- To'rtta urinishgacha (≈3 → 6 → 9 c), har bir 15 c vaqtga qadar.
2xxga javob bering, aks holda takrorlanadi. - Yo'llanmalar ** yo'q ** yo'llanmalar ** yo'q ** yo'q to'g'ridan-to'g'ri javob bering
callback_url. - best-effort: agar to'rtta urinish ham muvaffaqiyatsiz tugasa (serveringiz yotgan), veb-hok no keyinroq qayta yuboriladi.
Veb-xukkalar so'rovnoma o'rniga o'tirmaydi.
Vebhuk tezlashtirish, kafolat emas. GET /media/job/:id Agar pul o'z vaqtida kelmasa, o'zingiz statusni so'rang. id.
Talablar callback_url
- Faqat
https://bilan. - Faqatgina ommaviy** manzil. Mahalliy va xususiy manzillar (
localhost,*.local,10.x,172.16–31.x,192.168.x,127.x,169.254.x,100.64–127.x, IPv6 loopback/ULA/link-local) ** Manzillar rad etiladi** bu SSRF himoyasi. Bu SSRF himoyasi.
Nima tanlash kerak?
| So'rov | Veb-xo'k | |
|---|---|---|
Ochiq https-manzil | kerak emas | kerak emas kerak |
| So'rovlar davrasidan oldin | ni olishni kechiktirish | deyarli darhol |
| Kezlatma | siz nazorat qilasiz | best-effort + so'rovni ehtiyot sifatida nazorat qilasiz |
| Har qanday qulay joyda | skriptlari, CI, noutbuk | serverlari, produkshn-bakendlar |
Tavsiya: orqa tomonda veb-huq + sug'urta sifatida so'rovnoma; skript/notabda shunchaki so'rovnoma.