Přenos: WebSocket, záloha přes HTTP a opětovné připojení
Jak widget komunikuje se serverem chatu – adresy, podprotokol rc.v1, formát rámců, chybové kódy a kódy uzavření, limity, opětovné připojení se seq a deduplikací a záloha přes HTTP pomocí Server-Sent Events a long pollingu.
Tato stránka popisuje, co se děje mezi widgetem v prohlížeči a serverem chatu. Potřebujete ji při řešení problémů (karta síťových požadavků ve vývojářských nástrojích), pro pravidla proxy a firewallu a pro svou Content Security Policy.
Důležité: komunikační protokol je rozhraním mezi naším widgetem a naším serverem. Vlastní klienti komunikující přímo tímto protokolem nejsou oficiálně podporováni; pole se mohou v rámci verze protokolu 1 rozšiřovat. Pro vlastní rozhraní použijte JavaScript API, pro serverová propojení webhooky a serverové API.
Adresy
- WebSocket:
wss://ws.reactive.chat/rc_wss/ - Záloha přes HTTP, offline formulář, nahrávání: stejná adresa s
https://, tedyhttps://ws.reactive.chat/rc_wss/h/…,https://ws.reactive.chat/api/offline/<SITE_KEY>ahttps://ws.reactive.chat/rc_wss/upload/… - Soubory widgetu:
https://cdn.reactive.chat/
Jak widget zjistí adresu WebSocket:
data-rc-ws-urlna značce načítacího skriptu,window.ReactiveChatSettings.wsUrlneboReactiveChat('boot', { wsUrl })– pokud je hodnota nastavena, použije se.- Jinak se odvodí z umístění
loader.js:wss://ws.+ poslední dvě části domény +/rc_wss/. Zcdn.reactive.chatvzniknewss://ws.reactive.chat/rc_wss/.
Z toho vyplývají dvě úskalí:
- Pokud poskytujete
loader.jsz vlastní domény, widget odvodí adresu pod vaší doménou. V takovém případě nastavtedata-rc-ws-url(viz Rychlý start). - U dvoudílných koncovek jako
.co.ukse adresa odvodí nesprávně. Nastavtedata-rc-ws-urlvýslovně.
Cesta WebSocket nevyhodnocuje parametry dotazu.
Navázání spojení
- Načasování: widget se nepřipojuje při načítání stránky, ale při první skutečné interakci (pohyb myši, kliknutí, stisk klávesy, kolečko myši, dotyk, fokus). Připojí se okamžitě, pokud je okno chatu otevřené nebo se otevírá, je známá konverzace návštěvníka nebo čekají neodeslané zprávy. S
data-rc-connect="load"na libovolném prvku (obvykle značce načítacího skriptu) nebowindow.ReactiveChatSettings.connect = 'load'se připojuje při načtení jako dříve. Pravidla spouštěná určitou dobu po zobrazení stránky počítají čas od první interakce. - Podprotokol: widget otevře
new WebSocket(url, 'rc.v1')a server vrátírc.v1. Verze protokolu není v adrese, ale v každém rámci (v: 1). - Pouze textové rámce, v UTF-8; jeden rámec = jedna zpráva. Bez komprese (
permessage-deflateje na straně serveru vypnuté). - Handshake: po
openwidget nejpozději do 5 sekund odešleinit; server odpovíinit_ok. Pokudopennepřijde do 8 sekund, pokus se považuje za neúspěšný; pokudinit_oknepřijde do 10 sekund, widget se znovu připojí. - Kontrola originu: server porovná název hostitele hlavičky
Origins doménami projektu (Povolené originy v účtu). Schéma a port se nepočítají; subdomény odpovídají (www.your-company.comodpovídáyour-company.com,notyour-company.comnikoli). Při selhání: chybaorigin_denied, pak uzavření 1008, bez opakování. Pokud v projektu není zadána žádná doména, kontrola originu neprobíhá – proto své domény vždy zadejte.
Formát rámce
Každá zpráva v obou směrech má tento tvar:
{ "v": 1, "t": "msg", "id": "01JAB3C4D5E6F7G8H9JKMNPQRS", "ts": 1792500000000, "d": { } }
- v (celé číslo, povinné) – verze protokolu, aktuálně
1. - t (řetězec, povinné) – typ zprávy,
[a-z0-9_]{1,24}. - id (řetězec, povinné) – ULID: 26 znaků Crockford Base32, pouze velká písmena. Je také klíčem pro deduplikaci.
- ts (celé číslo, povinné) – milisekundy od roku 1970, pouze pro diagnostiku.
- d (objekt, povinné) – data zprávy, nikdy
null, při prázdném obsahu{}.
Neznámé typy a neznámá pole se tiše ignorují – tím zůstávají starší widgety kompatibilní s novějšími servery.
Přehled typů zpráv
Z widgetu na server:
- init – registrace spojení: klíč webu, ID relace, návštěvníka, karty a konverzace, jazyk, stav souhlasu, případná podepsaná identita (
user), kontext stránky (ctx) a bod obnovení (resume). - msg – zpráva návštěvníka (text, až 5 příloh, odpověď na rychlé odpovědi nebo formuláře).
- typing – indikátor psaní (
start/stop). Obsah vstupního pole se nikdy nepřenáší. - read – přečteno až po
seq. - ctx – změna kontextu, např. při navigaci v SPA nebo po
identify. - csat – hodnocení (palec nahoru/dolů, komentář až 1000 znaků).
- upload_req – žádost o schválení nahrání (název, typ MIME, velikost, SHA-256).
- transcript, forget, consent – konverzace e-mailem, smazání vlastních dat, udělení/odvolání souhlasu.
- ping – udržování spojení.
Ze serveru do widgetu:
- init_ok – potvrzená ID, historie, design, funkce a limity (viz níže), výsledek kontroly identity (
identity.verified). - msg – zprávy (včetně ozvěny vlastní zprávy návštěvníka s
client_id). - bot_typing, bot_stream – asistent AI přemýšlí nebo píše;
bot_streamvždy přenáší celý dosud viditelný text, nejvýše každých 150 ms. - typing, read, handoff, queue_pos, proactive, conv_list, error, pong.
Chybové kódy
Chyba přijde jako rámec t: "error" s d.code, d.message (anglicky, pouze pro vývojáře), d.retry (no, immediate, backoff, after_reinit) a podle potřeby d.retry_after_ms a d.detail. Seznam je uzavřený; neznámý kód se zpracuje jako internal.
- bad_json – neplatný JSON; po třech výskytech uzavření 1008.
- bad_envelope – rámec porušuje formát (také: ULID s odchylkou více než 24 h,
detail.reason: stale_or_future). - unsupported_version – verzi nelze dohodnout; uzavření 4001.
- unknown_site_key – neznámý klíč webu, projekt pozastavený nebo archivovaný; uzavření 4002.
- origin_denied – origin není mezi doménami projektu; uzavření 1008.
- visitor_blocked – návštěvník zablokován; uzavření 1008.
- auth_failed – kontrola identity selhala,
detail.reason:no_hash,bad_hash,bad_exp,expired,exp_too_far. Relace pokračuje anonymně. - not_initialized / already_initialized – zpráva před
initnebo druhéinit. - init_timeout – žádné
initdo 5 s; uzavření 4004. - conversation_not_found / conversation_closed
- rate_limited – omezení četnosti; s
retry_after_ms. Při opakování na stejném spojení server uzavře spojení kódem 4008. - payload_too_large – rámec přes 64 KiB.
- msg_too_long – text delší než limit tarifu,
detail.max. - unsupported_kind, attachment_invalid
- upload_disabled, upload_too_large, upload_mime_denied, upload_expired
- consent_required – akce vyžaduje souhlas.
- dnd_active – režim „Nerušit“ je aktivní.
- session_conflict – příliš mnoho spojení stejné relace (více než 3); uzavření 4003, karta se stane následovníkem.
- internal, unavailable – dočasné; opakování s prodlevou.
Kódy uzavření
- 1000, 1001, 1006, 1011, 1013, 4004 – widget se znovu připojí (s prodlevou).
- 1008 – odmítnutý origin, opakovaně neplatný JSON, blokace ochranou proti zneužití. Na této stránce bez opakování.
- 4001 – verzi nelze dohodnout. Bez opakování.
- 4002 – neznámý klíč webu nebo neaktivní projekt. Bez opakování.
- 4008 – opakované omezení četnosti. Widget počká po dobu
retry_after_msa znovu se připojí. - 4003 – konflikt relace; karta běží jako následovník jiné karty.
Limity na spojení
Server odesílá závazné hodnoty v init_ok.limits a init_ok.features:
- heartbeat_ms 25 000 – widget odešle
ping25 s po poslední odchozí zprávě. - pong_timeout_ms 10 000 – dvě chybějící
pongvedou k opětovnému připojení. - idle_timeout_ms 70 000 – server uzavře spojení po 70 s bez příchozího rámce (1001).
- max_frame_bytes 65 536 – větší rámce:
payload_too_large. - msg_per_10s 20 a frames_per_10s 120 – token bucket pro každé spojení; nad tuto mez
rate_limited. - reconnect_cap_ms 30 000 – nejdelší prodleva mezi opakovanými pokusy.
- dedup_window_ms 86 400 000 – 24 hodin deduplikace.
- features.max_msg_len – znaky (kódové body Unicode) na zprávu návštěvníka: 1000 v tarifu Free, 4000 v placených tarifech. Widget příliš dlouhé texty neodešle.
- features.max_upload_bytes, features.allowed_mime – viz Limity a kvóty.
Opětovné připojení, pořadí, duplicity
- Prodleva:
min(30000, 500 × 2^(attempt−1))ms, z toho se použije náhodná hodnota v horní polovině (pokus 1: 250–500 ms, od pokusu 7: 15–30 s). Na kartách na pozadí trojnásobná.retry_after_msze serveru je dolní mez. Počet pokusů je neomezený; počítadlo se vynuluje pouze přiinit_ok. Pokud prohlížeč oznámíonline, widget to zkusí okamžitě; pokud je offline, čeká. - Pořadí: každá zpráva konverzace nese souvislé
seqzačínající od 1. Zprávy se zobrazují podleseq, nikoli podle času. Při opětovném připojení widget odešleresume.last_seqa až 50 čekajících ID; server doručí vše následující (nejvýše 100 zpráv, jinakhas_more) a zopakuje potvrzení již doručených zpráv. - Bez duplicit: server si pamatuje každé
idzprávy po dobu 24 hodin. Opakovaná zpráva se znovu neuloží, ale dostane stejné potvrzení. „Odeslat znovu“ ve widgetu používá stejnéid. - Stavy odchozí zprávy:
pending→sent→delivered(ozvěna ze serveru) →read;failedpo 5 pokusech, po 24 h nebo přiretry: "no". - Offline vyrovnávací paměť: při výpadku spojení se zprávy ukládají do vyrovnávací paměti (nejvýše 50 položek, 128 KiB, 24 h) – se souhlasem do
localStorage, bez něj dosessionStorage– a odešlou se při dalšíminit_ok. - Několik karet, jedno spojení: karty webu si zvolí vedoucí kartu (Web Locks, jinak udržovací signál v
localStorage); pouze vedoucí karta drží spojení, ostatní komunikují přesBroadcastChannel.
Záloha přes HTTP
Pokud síť nepropustí WebSocket, chat pokračuje přes běžné požadavky HTTPS – se stejnými rámci a stejnými limity. Používá ji pouze widget; rozhraní operátora se vždy připojuje přes WebSocket. Stručná verze pro redaktory je v části Záloha přes HTTP.
Kdy se použije:
- prohlížeč nepodporuje WebSocket;
- dva pokusy o WebSocket za sebou selžou předtím, než byl na této stránce vůbec navázán WebSocket (pokus bez výsledku po 8 sekundách se považuje za neúspěšný);
sessionStorageobsahuje záznamrc_httpmladší než 30 minut (následující stránky na stejné kartě);- vynutíte ji pomocí
data-rc-transport="http"(na libovolném prvku, který je při spuštění v dokumentu) nebowindow.ReactiveChatSettings = { transport: 'http' }před načítacím skriptem.ReactiveChat('boot', { transport: 'http' })nemá účinek – typ spojení se stanoví při spuštění.
Bez fetch v prohlížeči záloha neexistuje. Pokud vypadne existující spojení WebSocket, widget se znovu připojí přes WebSocket. Po přechodu na zálohu jednou na stránku tiše ověří, zda už WebSocket projde; pokud ano, smaže rc_http a další stránka opět použije WebSocket.
Požadavky (pod https://ws.reactive.chat/rc_wss/h/):
- POST h/auf – otevře spojení. Odpověď
{"v":1,"cid":"…","tok":"…","poll_ms":25000,"idle_ms":60000}.tokje krátkodobý token spojení (32 znaků). - GET h/<cid>/sse?tok=… – Server-Sent Events,
id:adata:pro každý rámec, udržovací signál každých 15 s. Zmeškané rámce se doručí přesLast-Event-ID. - GET h/<cid>/poll?tok=…&nach=<n> – long polling; server drží požadavek otevřený až 25 s a odpoví
{"v":1,"n":…,"rahmen":[…]}. - POST h/<cid>/tx?tok=… – odeslání,
text/plain, jeden rámec nebo pole nejvýše 20 rámců; odpověď 204. - POST h/<cid>/zu?tok=… – zavření (přes
sendBeacon).
Widget nejprve zkusí SSE; pokud do 5 sekund nepřijde první rámec (například kvůli bufferování proxy), přejde na long polling. Chyby jako 404 (unbekannt), 403, 413 nebo 429 považuje za výpadek spojení a opakuje pokus s prodlevou. Po 60 sekundách bez požadavku server spojení uzavře. CORS: Access-Control-Allow-Origin odráží origin, bez přihlašovacích údajů; kontrola originu probíhá v init, stejně jako u WebSocket.
Požadavky na vaší straně:
connect-srcvaší CSP obsahuje adresu chatu swss://ihttps://.- Firewally a proxy povolují požadavky trvající alespoň 30 sekund.
- Vaše vlastní proxy předává
/rc_wss/bez bufferování (nginxproxy_buffering offaproxy_cache off, Apacheflushpackets=on, Caddyflush_interval -1) a nezapisuje/rc_wss/h/do přístupového protokolu (token v dotazu). Viz Vlastní doména.
Uloženo v prohlížeči: pouze záznam rc_http v sessionStorage s časem připojení HTTPS, bez osobních údajů.
Která cesta je aktivní
Na kartě síťových požadavků ve vývojářských nástrojích:
- WebSocket: spojení typu WebSocket na
wss://ws.reactive.chat/rc_wss/(nebo vaši subdoménu). V rámcích vidíteinit,init_ok,ping/ponga zprávy. - Záloha přes HTTP: nejprve
h/auf, poté dlouho běžící…/sse(nebo opakované…/poll) a jedno…/txpro každou odeslanou zprávu.
Dále: Limity a kvóty · Řešení problémů
最后更新: