GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — massCode/scripts/http-dev-server at main · massCodeIO/massCode

Expand file tree

/

http-dev-server

/
Copy path

Directory actions

More options

More options

Directory actions

More options

More options

Latest commit

 

History

History
History
/

http-dev-server

/
Copy path

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
__tests__
__tests__
 
 
README.md
README.md
 
 
graphql.mjs
graphql.mjs
 
 
index.mjs
index.mjs
 
 
scripts.mjs
scripts.mjs
 
 
server.mjs
server.mjs
 
 
showcase.mjs
showcase.mjs
 
 
transport.mjs
transport.mjs
 
 
websocket.mjs
websocket.mjs
 
 

README.md

Outline

Локальный HTTP-сервер для разработки

Синтетические loopback-серверы для Computer QA пространства HTTP. Не используют vault, внешние сервисы, рабочие данные, TLS или HTTP/2. Задержки и интервалы сервера управляют тестовым сценарием — это не измерения производительности приложения. Для оценки производительности используйте изолированный benchmark vault. Профили собирайте отдельными запусками, чтобы профилирование не влияло на замеры времени.

Запуск

pnpm http:server
pnpm http:server --help
pnpm http:server -- --transport-port 0 --cross-origin-port 0

Все сервисы слушают 127.0.0.1. Флаги принимают целое число от 0 до 65535; 0 выбирает свободный порт автоматически. После готовности всех слушателей stdout выводит одну JSON-строку:

{ "event": "ready", "addresses": { "websocket": "ws://127.0.0.1:5188", "scripts": "http://127.0.0.1:5189", "showcase": "http://127.0.0.1:5190", "graphql": "http://127.0.0.1:4399", "transport": "http://127.0.0.1:5191", "crossOrigin": "http://127.0.0.1:5192" } }

Адреса содержат реальные порты, включая автоматически выбранные. При ошибке запуска сервер закрывает уже открытые слушатели и завершается с ненулевым кодом. SIGINT / SIGTERM закрывают HTTP-соединения, активные WebSocket и таймеры; текущие запросы могут быть прерваны. Ошибки конфигурации выводятся в stderr. Импорт модулей не запускает слушатели: в тестах можно вызвать startServers(ports) и затем дождаться close().

Сервис Порт Флаг Авторизация
WebSocket 5188 --websocket-port /protected: bearer demo-token, X-Client-ID, непустой query-параметр channel
Scripts 5189 --scripts-port Не требуется
Showcase 5190 --showcase-port Bearer demo-commerce-token для commerce-данных
GraphQL 4399 --graphql-port Bearer graphql-demo
Transport 5191 --transport-port Не требуется
Второй HTTP origin 5192 --cross-origin-port Не требуется

Токены — публичные тестовые значения. Все сервисы запускаются одной командой pnpm http:server на указанных выше портах.

Сохранённые сценарии

  • Scripts: /health возвращает {"demo":"masscode-http-scripts"}. Остальные запросы возвращают {"token":"demo-token","received":"<исходное тело>"}. Тело длиннее 65 536 JavaScript-символов получает 413.
  • WebSocket: / повторяет текстовые и бинарные сообщения. /protected сначала отправляет {type:"connected", authenticated:true, channel, clientId}, затем повторяет сообщения. Неверный bearer-токен получает 401; отсутствие channel или client ID — 400; неизвестный путь — 404. Обычный HTTP получает 426. Максимальное сообщение: 1 MiB.
  • GraphQL: POST /graphql с JSON {query, variables?, operationName?}. Поля Query: hello (Hello GraphQL), token (graphql-demo), user(id: ID!) (имя по умолчанию Ada), broken (ошибка поля с кодом DEMO_ERROR). Мутация rename(id: ID!, name: String!) сохраняет имя в текущем экземпляре. Неверная авторизация получает 401, неправильные метод/путь — 404, некорректный JSON или тело длиннее 1 000 000 JavaScript-символов — 400. Ошибки исполнения GraphQL остаются ответами GraphQL со статусом 200.
  • Showcase: необязательный префикс /v1. Публичные маршруты: /health, /metrics, /status/maintenance (503), POST /auth/token. Защищённые: /products (фильтр category), /products/:id, /customers, /customers/:id, /orders, /orders/:id. POST /orders принимает {customerId, items:[{productId, quantity}]} и использует первый товар; некорректные данные получают 422. POST /orders/:id/fulfillment переводит заказ в статус shipped. Исходный заказ — ord_1042, первый новый — ord_1043. Товары: prd_weekender, prd_bottle, prd_tote; покупатели: cus_2048, cus_2049. Ограничение JSON-тела: 65 536 JavaScript-символов (413). Некорректный JSON получает 400. Сохранены исходные данные, фиксированные заголовки request ID, rate limit и no-store.

Контракт Transport

Основной и второй слушатели предоставляют одинаковые маршруты. /cross-origin указывает на реальный /echo соседнего слушателя. Произвольного адреса перенаправления нет. Разные порты позволяют проверить смену HTTP origin; cookies привязаны к хосту и не изолируются портом. Политика браузерного CORS не добавляется.

Маршрут Поведение
GET/HEAD/POST/PUT/PATCH/DELETE/OPTIONS /echo JSON {method, query, headers, body}. query — упорядоченный массив пар [key,value] с сохранением повторов. Заголовки нормализованы Node; тело декодируется как UTF-8. Ограничение тела — 1 MiB, затем 413. HEAD возвращает только заголовки по правилам HTTP.
GET /status/:code Целое 200–599; JSON {status:code}. Статусы 204, 205 и 304 возвращаются без тела.
GET /delay/:ms Целое 0–10 000; после задержки JSON {delay:ms}. Отключение клиента отменяет таймер.
GET /bytes/:size Целое 0–16 777 216; ровно столько ASCII-байтов x, octet-stream с Content-Length.
GET /stream?chunks=4&size=1024&interval=10 Показаны значения по умолчанию. chunks: 1–100; size: 1–65 536 байтов; interval: 0–1000 мс. Всего ≤16 MiB и (chunks-1)*interval ≤10 000 мс. Первый фрагмент отправляется сразу, следующие — с интервалом после записи/освобождения буфера. Фрагмент i повторяет ASCII a + (i modulo 26). TCP/HTTP-клиент может объединять или разделять записи. Сервер учитывает backpressure и отменяет таймеры при отключении.
GET/HEAD/POST/PUT/PATCH/DELETE/OPTIONS /redirect/:code Коды 301, 302, 303, 307, 308; пустое тело и Location /echo. Повтор метода/тела POST определяется клиентом и статусом.
GET/HEAD/POST/PUT/PATCH/DELETE/OPTIONS /chain/:count Целое 0–20. Положительное число даёт 302 на /chain/:count-1; ноль — JSON {remaining:0}.
GET/HEAD/POST/PUT/PATCH/DELETE/OPTIONS /loop Всегда 302 на /loop; ограничьте число редиректов в клиенте или отключите переходы.
GET/HEAD/POST/PUT/PATCH/DELETE/OPTIONS /cross-origin 302 на абсолютный URL /echo второго слушателя.
GET /cookies-set Устанавливает demo=masscode; Path=/; HttpOnly; SameSite=Lax и theme=dark; Path=/; SameSite=Lax; JSON {set:true}.
GET /cookies-echo JSON {cookie:"<исходный заголовок Cookie или пустая строка>"}.
POST /reset Сбрасывает GraphQL users, showcase orders и нумерацию текущей группы; JSON {reset:true}.

Числовые параметры содержат только десятичные цифры. Отсутствующие, отрицательные, дробные, нечисловые и выходящие за границы значения получают 400 с JSON {error}. Неподдерживаемые методы получают 405, неизвестные GET-маршруты — 404. Echo и редиректы принимают обычные HTTP-методы GET, HEAD, POST, PUT, PATCH, DELETE и OPTIONS. Заголовки запроса вроде host и connection закономерно зависят от клиента.

Вызывайте /reset, когда запросы завершены. Сброс не отменяет текущие запросы: параллельная мутация может исполниться после сброса и снова изменить состояние. Разные вызовы startServers() полностью разделяют изменяемое состояние.

Наблюдаемый fixture ассистента

На Transport доступен изолированный журнал по ID прогона ([A-Za-z0-9_-], 1–64 символа):

  • GET /qa/<runId>/state возвращает {runId, requests}. Чтение не увеличивает счётчик; неизвестный ID возвращает пустой журнал.
  • POST /qa/<runId>/reset очищает только этот журнал; новые запросы получают sequence с 1.
  • /qa/<runId>/echo?delay=0 принимает HTTP-запрос, записывает sequence, method, path, body и state; отвечает JSON со статусом 200. delay — 0–10 000 мс. Запись появляется до задержки ответа, поэтому потерянный ответ не означает отсутствие dispatch.

Журнал содержит максимум 100 запросов на ID и 20 ID на слушатель (дальше 429). Тело ограничено 16 KiB (413 с записью rejected); не используйте реальные данные или секреты. Заголовки не сохраняются. Состояния receiving, received, rejected, aborted отражают приём запроса, а не доставку ответа клиенту. После reset старый отложенный ответ не восстанавливает журнал. Разные слушатели имеют разные журналы; глобальный /reset не заменяет reset конкретного QA ID.

Перед проверкой подтверждения сбросьте журнал, после подготовки preview проверьте ноль записей, после принятия — одну запись с ожидаемыми методом/телом. Повтор клика/IPC не должен добавлять вторую. Этот fixture доказывает dispatch; число выполнений пользовательского скрипта проверяется отдельно по runtime-результату/инструментированному тесту, а не по демонстрационному /metrics.

Scoped-команды проверки

pnpm test scripts/http-dev-server
pnpm exec eslint scripts/http-dev-server scripts/http-graphql-fixtures.mjs
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.