CodeSampleX

サンプル

@hono/node-server 2.1.1: serveStatic

検証済みサンプル — npm @hono/node-server 2.1.1: serveStatic. node 22 · linux debian/x64 · docker で contract を実行し、成功しました: @hono/node-server/serve-static exports…

sha256:f779197c7b9d476c9aed141f7df1cc2c7827f8cdf9a4510e08f9ab101b3fb5a3

このネットワークが提供するのは一つだけです。ビルドされるサンプル。サンドボックスで実行し、署名済みの受領証を保管します。等級はつけず、何も保証しません — 同じコードがあなたの環境でビルドされるかは測定していません。 合格した契約受領証を提出した異なる署名鍵の数です。1 なら作者だけ、2 以上なら他の誰かもビルドしています。鍵は自己生成で背後に登録された身元がないため、数えているのは人ではなく鍵です。 MIT-0

実行証拠

宣言された環境と署名済みの実行を分けてあります。このサンプルが何をどこで実行したかをそのまま確認できます。

証拠の基準
署名済みコントラクト合格
検証レシート
1
ビルドした署名鍵
1
宣言された環境 linux 24 · ubuntu · glibc 2.39 x64 npm

検証実行環境

環境 コントラクト ステージ 実行日
node 22 · linux debian/x64 · docker ed25519:c1973797be207ac4 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1node:22@sha256:8a34c4ab3ea2…
2026-09-06

ケース

HOW
ゴール
verify @hono/node-server.serveStatic in pkg:npm/%40hono/node-server@2.1.1
パッケージ
シンボル
  • @hono/node-server.serveStatic
作成日
2026-09-06T04:43:14Z

コントラクト

  1. @hono/node-server/serve-static exports serveStatic function
  2. serveStatic returns an asynchronous middleware handler function
  3. serveStatic serves existing static files with correct MIME type and 200 status
  4. serveStatic serves directory requests using default index.html
  5. serveStatic responds to HEAD requests with content headers and empty body
  6. serveStatic calls onNotFound and delegates to next middleware when file does not exist
  7. serveStatic prevents directory traversal and rejects dot-segment paths
  8. serveStatic supports HTTP range requests with 206 Partial Content
  9. serveStatic responds with 416 for unsatisfiable range requests
  10. serveStatic supports explicit path option override
  11. serveStatic serves precompressed files when matching Accept-Encoding header is present
  12. serveStatic invokes onFound callback when requested file is resolved

ファイル

  • PROMPT.md
  • csx.json
  • index.js
  • package-lock.json
  • package.json
  • spec.json
  • test/contract.mjs

ソースアーティファクトをダウンロード (tar.gz)

ソース

PROMPT.md
Clean-room public code sample — generation instructions

Write a brand-new, minimal, self-contained code sample in this clean-room directory.
Do not copy, paraphrase, or reference any existing project source. Work only from this spec.

A csx.json manifest scaffold already exists. Do not recreate it from memory. Preserve its case.goal, packages and symbols; fill its empty case.contract with exact assertions and correct its environment, commands and verifierAdapter for the files you generate.

Goal: verify @hono/node-server.serveStatic in pkg:npm/%40hono/node-server@2.1.1
Kind: HOW

Use EXACTLY these public packages and versions:
  - pkg:npm/%40hono/node-server@2.1.1
Demonstrate these symbols/APIs:
  - @hono/node-server.serveStatic

Rules:
  - One focused purpose; the smallest project that proves the goal.
  - Include a contract test (test/contract.*) that runs OFFLINE and exits 0 exactly when the goal behavior works.
  - Pin every dependency with a lockfile so resolution is reproducible.
  - No secrets, credentials, or tokens. No real URLs (only example.com or localhost). No absolute paths.
  - No personal names, emails, company names, or project identifiers of any kind.
  - No binaries and no generated output (node_modules, dist, target, venv, .git, .env).
  - Keep it under 200 files and 256KB packed.
csx.json
{"case":{"caseId":"case:sha256:1d7dedb990b89541932896931d232234126be4b47381988c7bf4763d63bd7a1e","contract":["@hono/node-server/serve-static exports serveStatic function","serveStatic returns an asynchronous middleware handler function","serveStatic serves existing static files with correct MIME type and 200 status","serveStatic serves directory requests using default index.html","serveStatic responds to HEAD requests with content headers and empty body","serveStatic calls onNotFound and delegates to next middleware when file does not exist","serveStatic prevents directory traversal and rejects dot-segment paths","serveStatic supports HTTP range requests with 206 Partial Content","serveStatic responds with 416 for unsatisfiable range requests","serveStatic supports explicit path option override","serveStatic serves precompressed files when matching Accept-Encoding header is present","serveStatic invokes onFound callback when requested file is resolved"],"goal":"verify @hono/node-server.serveStatic in pkg:npm/%40hono/node-server@2.1.1","kind":"HOW","packages":["pkg:npm/%40hono/node-server@2.1.1"],"schemaVersion":1,"symbols":["@hono/node-server.serveStatic"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"npm","libc":"glibc","libcVersion":"2.39","os":"linux","osVersionBucket":"24","packageManager":"npm","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/%40hono/node-server@2.1.1"],"schemaVersion":1,"subject":"pkg:npm/%40hono/node-server@2.1.1","symbols":["@hono/node-server.serveStatic"],"verifierAdapter":"node-typescript@1"}
index.js
export { serveStatic } from '@hono/node-server/serve-static';
package-lock.json
{
  "name": "sample-hono-node-server-servestatic",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "sample-hono-node-server-servestatic",
      "version": "1.0.0",
      "license": "MIT-0",
      "dependencies": {
        "@hono/node-server": "2.1.1"
      }
    },
    "node_modules/@hono/node-server": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-2.1.1.tgz",
      "integrity": "sha512-ELuehkj5VCBdgEw9zs+ivkKwyzzUCSQuE96YmiPvn1ECBoZCczbFXJLeEGMTYjphP6gydh4pHMqEYPVMYUVgQg==",
      "license": "MIT",
      "engines": {
        "node": ">=20"
      },
      "peerDependencies": {
        "hono": "^4"
      }
    },
    "node_modules/hono": {
      "version": "4.13.7",
      "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.7.tgz",
      "integrity": "sha512-c8/gF9ac8Y78/agExVocyLevgR+JlpNB444Py0FSX8pJoPdYUfUzRcXtYEYGwt6l19qIlVZPN5Mfsw9jFShmQQ==",
      "license": "MIT",
      "peer": true,
      "engines": {
        "node": ">=16.9.0"
      }
    }
  }
}
package.json
{
  "name": "sample-hono-node-server-servestatic",
  "version": "1.0.0",
  "private": true,
  "description": "verify @hono/node-server.serveStatic in pkg:npm/%40hono/node-server@2.1.1",
  "type": "module",
  "main": "index.js",
  "scripts": {
    "test": "node test/contract.mjs"
  },
  "dependencies": {
    "@hono/node-server": "2.1.1"
  },
  "license": "MIT-0"
}
spec.json
{
  "schemaVersion": 1,
  "goal": "verify @hono/node-server.serveStatic in pkg:npm/%40hono/node-server@2.1.1",
  "kind": "HOW",
  "packages": [
    "pkg:npm/%40hono/node-server@2.1.1"
  ],
  "symbols": [
    "@hono/node-server.serveStatic"
  ]
}
test/contract.mjs
import assert from 'node:assert/strict';
import fs from 'node:fs';
import path from 'node:path';
import zlib from 'node:zlib';
import { Hono } from 'hono';
import { serveStatic } from '../index.js';

// Setup isolated local fixtures directory
const fixturesDir = './test-fixtures';
fs.mkdirSync(fixturesDir, { recursive: true });
fs.writeFileSync(path.join(fixturesDir, 'hello.txt'), 'Hello from serveStatic!');
fs.writeFileSync(path.join(fixturesDir, 'data.json'), JSON.stringify({ message: 'ok' }));
fs.mkdirSync(path.join(fixturesDir, 'nested'), { recursive: true });
fs.writeFileSync(path.join(fixturesDir, 'nested', 'index.html'), '<h1>Index Page</h1>');

// Create precompressed gz file for hello.txt
const gzData = zlib.gzipSync(Buffer.from('Hello from serveStatic!'));
fs.writeFileSync(path.join(fixturesDir, 'hello.txt.gz'), gzData);

try {
  // 1. @hono/node-server/serve-static exports serveStatic function
  assert.strictEqual(typeof serveStatic, 'function', 'serveStatic must be exported as a function');

  // 2. serveStatic returns an asynchronous middleware handler function
  const mw = serveStatic({ root: fixturesDir });
  assert.strictEqual(typeof mw, 'function', 'serveStatic must return a middleware function');

  // 3. serveStatic serves existing static files with correct MIME type and 200 status
  // 12. serveStatic invokes onFound callback when requested file is resolved
  let foundPath = null;
  let notFoundPath = null;

  const app = new Hono();
  app.use('/static/*', serveStatic({
    root: fixturesDir,
    rewriteRequestPath: (p) => p.replace(/^\/static/, ''),
    onFound: (p) => { foundPath = p; },
    onNotFound: (p) => { notFoundPath = p; }
  }));

  // GET hello.txt
  const resTxt = await app.request('http://localhost/static/hello.txt');
  assert.strictEqual(resTxt.status, 200, 'resTxt status should be 200');
  assert.strictEqual(resTxt.headers.get('content-type'), 'text/plain; charset=utf-8', 'resTxt content-type must match');
  assert.strictEqual(await resTxt.text(), 'Hello from serveStatic!', 'resTxt body must match file content');
  assert.ok(foundPath && foundPath.endsWith('hello.txt'), 'onFound must receive resolved file path');

  // GET data.json
  const resJson = await app.request('http://localhost/static/data.json');
  assert.strictEqual(resJson.status, 200, 'resJson status should be 200');
  assert.strictEqual(resJson.headers.get('content-type'), 'application/json', 'resJson content-type must match');
  const jsonData = await resJson.json();
  assert.deepStrictEqual(jsonData, { message: 'ok' }, 'resJson body must match json content');

  // 4. serveStatic serves directory requests using default index.html
  const resDir = await app.request('http://localhost/static/nested/');
  assert.strictEqual(resDir.status, 200, 'resDir status should be 200');
  assert.strictEqual(resDir.headers.get('content-type'), 'text/html; charset=utf-8', 'resDir content-type must match');
  assert.strictEqual(await resDir.text(), '<h1>Index Page</h1>', 'resDir must serve default index.html');

  // 5. serveStatic responds to HEAD requests with content headers and empty body
  const resHead = await app.request('http://localhost/static/hello.txt', { method: 'HEAD' });
  assert.strictEqual(resHead.status, 200, 'resHead status should be 200');
  assert.strictEqual(resHead.headers.get('content-type'), 'text/plain; charset=utf-8', 'resHead content-type must match');
  assert.strictEqual(resHead.headers.get('content-length'), '23', 'resHead content-length must match file size');
  const headText = await resHead.text();
  assert.strictEqual(headText, '', 'resHead body must be empty');

  // 6. serveStatic calls onNotFound and delegates to next middleware when file does not exist
  const res404 = await app.request('http://localhost/static/nonexistent.file');
  assert.strictEqual(res404.status, 404, 'res404 status should be 404');
  assert.ok(notFoundPath && notFoundPath.includes('nonexistent.file'), 'onNotFound must receive non-existent path');

  // 7. serveStatic prevents directory traversal and rejects dot-segment paths
  const resTraversal = await app.request('http://localhost/static/../hello.txt');
  assert.strictEqual(resTraversal.status, 404, 'resTraversal status should be 404');

  // 8. serveStatic supports HTTP range requests with 206 Partial Content
  const resRange = await app.request('http://localhost/static/hello.txt', {
    headers: { Range: 'bytes=0-4' }
  });
  assert.strictEqual(resRange.status, 206, 'resRange status should be 206');
  assert.strictEqual(resRange.headers.get('content-range'), 'bytes 0-4/23', 'resRange content-range must match');
  assert.strictEqual(resRange.headers.get('accept-ranges'), 'bytes', 'resRange accept-ranges must be bytes');
  assert.strictEqual(await resRange.text(), 'Hello', 'resRange body must match requested byte range');

  // 9. serveStatic responds with 416 for unsatisfiable range requests
  const resInvalidRange = await app.request('http://localhost/static/hello.txt', {
    headers: { Range: 'bytes=100-200' }
  });
  assert.strictEqual(resInvalidRange.status, 416, 'resInvalidRange status should be 416');
  assert.strictEqual(resInvalidRange.headers.get('content-range'), 'bytes */23', 'resInvalidRange content-range must match');

  // 10. serveStatic supports explicit path option override
  const directApp = new Hono();
  directApp.use('/fixed', serveStatic({
    path: path.join(fixturesDir, 'hello.txt')
  }));
  const resFixed = await directApp.request('http://localhost/fixed');
  assert.strictEqual(resFixed.status, 200, 'resFixed status should be 200');
  assert.strictEqual(await resFixed.text(), 'Hello from serveStatic!', 'resFixed body must match file content');

  // 11. serveStatic serves precompressed files when matching Accept-Encoding header is present
  const precompApp = new Hono();
  precompApp.use('/precomp/*', serveStatic({
    root: fixturesDir,
    precompressed: true,
    rewriteRequestPath: (p) => p.replace(/^\/precomp/, '')
  }));
  const resGz = await precompApp.request('http://localhost/precomp/hello.txt', {
    headers: { 'Accept-Encoding': 'gzip, deflate' }
  });
  assert.strictEqual(resGz.status, 200, 'resGz status should be 200');
  assert.strictEqual(resGz.headers.get('content-encoding'), 'gzip', 'resGz content-encoding should be gzip');
  assert.strictEqual(resGz.headers.get('vary'), 'Accept-Encoding', 'resGz vary header should be Accept-Encoding');
  const decompressed = zlib.gunzipSync(Buffer.from(await resGz.arrayBuffer())).toString();
  assert.strictEqual(decompressed, 'Hello from serveStatic!', 'decompressed content must match original text');

  console.log('Contract tests passed successfully.');
} finally {
  // Clean up fixtures directory
  fs.rmSync(fixturesDir, { recursive: true, force: true });
}

オリジンシーダー

匿名