curl and Terminal Clients

curl, Wget, HTTPie and xh get a page's first frame as truecolor ANSI text. Configure its size or turn it off.

לקוחות HTTP בטרמינל מקבלים את הפריים הראשון של הדף כטקסט ANSI בצבע מלא במקום מסמך ה-HTML. אין צורך להגדיר דבר.

curl https://my-app.example.com/about

אילו בקשות מקבלות פריים

בקשה מקבלת פריים כשכל התנאים הבאים מתקיימים:

  • המתודה היא GET או HEAD;
  • ה-User-Agent מתחיל ב-curl/, ב-Wget/, ב-wget2/, ב-HTTPie/ או ב-xh/;
  • הכותרת Accept חסרה או אינה מציינת text/html.

דפדפנים, סורקים ותצוגות מקדימות של קישורים מקבלים את דף ה-HTML. כדי לקבל את ה-HTML דרך curl, יש לבקש אותו:

curl -H 'Accept: text/html' https://my-app.example.com/about

הפריים נבחר בנקודה שבה הדף היה מוגש: אחרי middleware, rewrites ומטפלי נתיב, ולעולם לא עבור קבצים או נתיבים שהמקטע האחרון שלהם מכיל נקודה. הפניות של middleware, תגובות 401, כותרות ושכתובים חלים על curl כפי שהם חלים על דפדפנים. /api/health עדיין מפעיל את המטפל שלו ו-/robots.txt עדיין מגיש את הקובץ.

תוכן הפריים

הפריים הוא הרינדור הראשון של הדף, כמו במעטפת ברינדור מראש: כל גבול <Suspense> שעדיין ממתין מציג את תוכן הגיבוי שלו. רכיבי שרת אסינכרוניים אינם רצים, ו-fetch() לעולם אינו מסתיים, כך שנתונים שנטענים באפקטים נשארים במצב טעינה.

  • גודל: ⁦80 × 24⁩ תאים. אפליקציה עם אזור תצוגה קבוע (viewport.responsive: false) משתמשת במקום זאת ב-viewport.width × viewport.height.
  • צבעים: קודי מילוט SGR של 24 סיביות לפי viewport.theme של האפליקציה. כל שורה מסתיימת באיפוס, והפריים מסתיים בירידת שורה.
  • סטטוס: 200, או 404 עם דף "לא נמצא" של האפליקציה כשאין דף תואם או כשהדף קורא ל-notFound(). דף שקורא ל-redirect() במהלך הרינדור מגיש HTML.

התגובות הן מסוג text/plain; charset=utf-8 עם Vary: User-Agent, Accept ו-Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate, כך שמטמונים משותפים לעולם אינם שומרים פריים ומגישים אותו לדפדפן. דף ה-HTML בנתיב שבו curl מקבל פריים נושא את אותה כותרת Vary.

סביבות נתמכות

סביבת אירוחדפים סטטייםדפים דינמיים, נתיבים לא מוכרים
text devרינדור לפי בקשהרינדור לפי בקשה
text start, bunרינדור מראש באמצעות text buildרינדור לפי בקשה
vercel, cloudflareרינדור מראש באמצעות text buildדף HTML
staticדף HTMLדף HTML

דפים מרונדרים בצד השרת דורשים text start או bun (ראו פריסה).

סביבות אירוח סטטיות אינן יכולות להשיב ללקוח אחד באופן שונה מלאחר, ולכן המתאם static אינו תומך בפריימים. ב-Vercel וב-Cloudflare, פריימים לדפים סטטיים נכללים בתוצר הבנייה. דפים דינמיים ([id], force-dynamic) מגישים שם HTML, מפני שהמתאמים vercel ו-cloudflare אינם פורסים מנגנון רינדור.

text start ו-bun dist/server.js מרנדרים את שאר הדפים לפי בקשה באמצעות .text/server/live.mjs, ושומרים את 128 הפריימים האחרונים למשך 10 שניות. כל שרת מרנדר לכל היותר 20 דפים שאינם במטמון בכל 10 שניות. מעבר לכך, curl מקבל את דף ה-HTML עד שהמכסה מתחדשת. אם אי אפשר לטעון את live.mjs בשרת, למשל מפני שמודול של דף קורא את window ברמה העליונה, הדפים האלה מגישים HTML.

text build מדווח על הפריימים שרונדרו מראש:

 ✓ Prerendering curl frames (5/5)

הגדרות

לשינוי הגודל בכל האפליקציה, או להשבתת פריימים:

text.config.tsts
import { defineConfig } from "@textjs/app";export default defineConfig({  ansi: { cols: 100, rows: 30 },  // ansi: false,});

דף יכול לשנות את הגודל שלו, או להגיש HTML גם לטרמינלים:

app/dashboard/page.tsxtsx
export const ansi = { cols: 120, rows: 40 };// export const ansi = false;

הגדלים מוגבלים לטווח של ⁦1–500⁩ תאים. כשההגדרה ansi: false מופיעה ב-text.config.ts, המערכת מתעלמת מהייצואים של הדפים.

⁦HTTP⁩ רגיל

⁦curl⁩ אינו עוקב אחר הפניות אלא אם מעבירים -L. Vercel מפנה בקשות http:// אל https://, וכך גם Cloudflare כשהאפשרות שימוש תמיד ב-HTTPS מופעלת, ולכן curl http://… מדפיס את ההפניה במקום את הפריים. יש לשתף כתובות https://.

שרתים מותאמים אישית

@textjs/app/ansi מייצא פונקציות עזר לזיהוי ולתגובה, עבור שרתים ופונקציות שאינם מריצים text start או מתאם:

import { ansiResponse, wantsAnsi } from "@textjs/app/ansi";import { frameToAnsi } from "@textjs/react";if (wantsAnsi(request)) return ansiResponse(frameToAnsi(buffer, { theme: "geistDark" }), request.method);

wantsAnsi(request) מקבל גם (method, headers) עם Headers של Web או IncomingHttpHeaders של Node. הפונקציה frameToAnsi(buffer, { theme }) מקודדת CellBuffer מרונדר באותו אופן שבו הפריימוורק עושה זאת.

עריכת הדף ב-GitHub