Сервер вызывает вас
Веб-сервер на Node.js строится из обработчиков: функций вида (req: IncomingMessage, res: ServerResponse) => void из встроенного модуля node:http. Сервер принимает соединения и вызывает ваш обработчик один раз на каждый запрос — req содержит всё о запросе, а всё, что вы запишете в res, становится ответом.
Настоящий сервер запускается вызовом server.listen(8080) и работает бесконечно. Примеры здесь вместо этого вызывают server.listen(0): порт 0 означает «любой свободный порт», поэтому конфликтов не будет. Затем каждый пример читает реальный порт, сам отправляет запрос с помощью fetch и вызывает server.close() — так что каждая программа запускается и завершается сама.
Первый обработчик
Самый маленький из возможных обработчиков выводит строку текста. Всё, что делает API — JSON, коды состояния, маршрутизация — происходит внутри этой же формы функции.
Привет от обработчика
Обработчик пишет в res; клиент читает именно это как тело ответа, а статус 200 OK подставляется автоматически.
Вывод: программа на TypeScript и захваченный вывод
import { createServer, type IncomingMessage, type ServerResponse } from "node:http"
// Самый простой обработчик: один запрос на входе, одна строка текста на выходе.
function hello(req: IncomingMessage, res: ServerResponse): void {
res.end("привет от сервера\n")
}
async function main(): Promise<void> {
const server = createServer(hello)
await new Promise<void>(resolve => server.listen(0, () => resolve()))
const port = (server.address() as { port: number }).port
const res = await fetch(`http://localhost:${port}/`)
const body = await res.text()
console.log("статус:", res.status, res.statusText)
process.stdout.write("тело: " + body)
server.close()
}
main()
Ответ в формате JSON
Обработчик API делает три вещи: устанавливает заголовок Content-Type, выбирает код состояния и записывает данные. res.writeHead(200, { "Content-Type": "application/json" }) делает первые два, а res.end(JSON.stringify(value)) записывает тело.
Порядок важен: статус и заголовки должны быть установлены до записи тела.
Конечная точка JSON
Обработчик превращает UserRecord в текст JSON и отправляет его. Клиент получает корректный JSON и правильный тип содержимого — это основа каждой конечной точки в остальной части этой группы.
Вывод: программа на TypeScript и захваченный вывод
import { createServer, type IncomingMessage, type ServerResponse } from "node:http"
interface UserRecord {
id: number
name: string
}
function userHandler(req: IncomingMessage, res: ServerResponse): void {
const user: UserRecord = { id: 1, name: "Ana" }
// Сначала заголовки и статус, затем тело.
res.writeHead(200, { "Content-Type": "application/json" })
res.end(JSON.stringify(user))
}
async function main(): Promise<void> {
const server = createServer(userHandler)
await new Promise<void>(resolve => server.listen(0, () => resolve()))
const port = (server.address() as { port: number }).port
const res = await fetch(`http://localhost:${port}/user`)
const body = await res.text()
console.log("статус:", res.status, res.statusText)
console.log("тип: ", res.headers.get("content-type"))
console.log("тело: ", body)
server.close()
}
main()