From 936af7bdf9229243e3256ac0397f39e1071110c1 Mon Sep 17 00:00:00 2001 From: Tomoki Miyauchi Date: Mon, 13 Feb 2023 18:12:53 +0900 Subject: [PATCH 1/9] feat(types): add middleware interface --- deps.ts | 6 ++++++ mod.ts | 5 +++++ types.ts | 9 +++++++++ 3 files changed, 20 insertions(+) create mode 100644 deps.ts create mode 100644 mod.ts create mode 100644 types.ts diff --git a/deps.ts b/deps.ts new file mode 100644 index 0000000..5f69a73 --- /dev/null +++ b/deps.ts @@ -0,0 +1,6 @@ +// Copyright 2023-latest the httpland authors. All rights reserved. MIT license. +// This module is browser compatible. + +export { + type HttpHandler as Handler, +} from "https://deno.land/x/http_utils@1.0.0-beta.6/handlers.ts"; diff --git a/mod.ts b/mod.ts new file mode 100644 index 0000000..8fb374f --- /dev/null +++ b/mod.ts @@ -0,0 +1,5 @@ +// Copyright 2023-latest the httpland authors. All rights reserved. MIT license. +// This module is browser compatible. + +export type { Middleware } from "./types.ts"; +export type { Handler } from "./deps.ts"; diff --git a/types.ts b/types.ts new file mode 100644 index 0000000..495eee9 --- /dev/null +++ b/types.ts @@ -0,0 +1,9 @@ +// Copyright 2023-latest the httpland authors. All rights reserved. MIT license. +// This module is browser compatible. + +import type { Handler } from "./deps.ts"; + +/** HTTP middleware API. */ +export interface Middleware { + (request: Request, next: Handler): Response | Promise; +} From bc8430707423ad663706cbff832afde515fcdf79 Mon Sep 17 00:00:00 2001 From: Tomoki Miyauchi Date: Mon, 13 Feb 2023 19:40:01 +0900 Subject: [PATCH 2/9] ci: add release workflow --- .github/workflows/codeql-analysis.yaml | 40 +++++++++++++ .github/workflows/release-npm.yaml | 57 +++++++++++++++++++ .github/workflows/release.yaml | 79 ++++++++++++++++++++++++++ .github/workflows/test.yaml | 43 ++++++++++++++ 4 files changed, 219 insertions(+) create mode 100644 .github/workflows/codeql-analysis.yaml create mode 100644 .github/workflows/release-npm.yaml create mode 100644 .github/workflows/release.yaml create mode 100644 .github/workflows/test.yaml diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml new file mode 100644 index 0000000..49ea8ba --- /dev/null +++ b/.github/workflows/codeql-analysis.yaml @@ -0,0 +1,40 @@ +name: "CodeQL" + +on: + push: + branches: [ main ] + + pull_request: + branches: [ main ] + + schedule: + - cron: '18 15 * * 2' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'typescript' ] + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/release-npm.yaml b/.github/workflows/release-npm.yaml new file mode 100644 index 0000000..eb82e86 --- /dev/null +++ b/.github/workflows/release-npm.yaml @@ -0,0 +1,57 @@ +name: release-npm + +on: + release: + types: [published] + +jobs: + release: + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [ubuntu-latest] + deno: [v1.x] + node: [16.x] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - uses: denoland/setup-deno@v1 + with: + deno-version: ${{ matrix.deno }} + + - name: Cache node_modules + uses: actions/cache@v2 + with: + path: ~/.pnpm-store + key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}- + + - uses: pnpm/action-setup@v2.0.1 + with: + version: 7.16.0 + run_install: | + - recursive: true + args: [--frozen-lockfile, --prefer-offline, --ignore-scripts] + + - name: Get tag version + if: startsWith(github.ref, 'refs/tags/') + id: get_tag_version + run: echo ::set-output name=TAG_VERSION::${GITHUB_REF/refs\/tags\//} + + - uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node }} + registry-url: 'https://registry.npmjs.org' + + - name: build + run: deno run -A ./_tools/build_npm.ts ${{steps.get_tag_version.outputs.TAG_VERSION}} + + - name: publish + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: deno run -A ./_tools/publish_npm.ts ${{steps.get_tag_version.outputs.TAG_VERSION}} + diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..12158d0 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,79 @@ +name: release + +on: + push: + branches: + - beta + - main + +jobs: + lint: + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [ubuntu-latest] + deno: [v1.x] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - uses: denoland/setup-deno@v1 + with: + deno-version: ${{ matrix.deno }} + + - name: Lint + run: | + deno fmt --check + deno lint + + test: + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [ubuntu-latest] + deno: [v1.x] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - uses: denoland/setup-deno@v1 + with: + deno-version: ${{ matrix.deno }} + + - name: Test + run: deno task test --coverage=coverage + + - name: Generate coverage + if: ${{ matrix.deno == 'v1.x' }} + run: deno task coverage coverage --output=cov_profile.lcov --lcov + + - uses: codecov/codecov-action@v3 + if: ${{ matrix.deno == 'v1.x' }} + with: + files: cov_profile.lcov + + release: + needs: [lint, test] + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [ubuntu-latest] + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + token: ${{ secrets.GH_TOKEN }} + + - uses: cycjimmy/semantic-release-action@v3 + with: + extra_plugins: | + @semantic-release/changelog + @semantic-release/git + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..89347c2 --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,43 @@ +name: test + +on: push +jobs: + lint: + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [ubuntu-latest, ubuntu-22.04, macos-latest, windows-latest] + deno: [v1.x] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - uses: denoland/setup-deno@v1 + with: + deno-version: ${{ matrix.deno }} + + - name: Lint + run: | + deno fmt --check + deno lint + + test: + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [ubuntu-latest, ubuntu-22.04, macos-latest, windows-latest] + deno: [v1.x] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - uses: denoland/setup-deno@v1 + with: + deno-version: ${{ matrix.deno }} + + - name: Test + run: deno task test From b67962baedb0e080b6adae4c46c9c5616c70a032 Mon Sep 17 00:00:00 2001 From: Tomoki Miyauchi Date: Mon, 13 Feb 2023 19:40:35 +0900 Subject: [PATCH 3/9] chore(_tools): add npm build script --- _tools/build_npm.ts | 23 +++++++++++++++++++++++ _tools/meta.ts | 38 ++++++++++++++++++++++++++++++++++++++ _tools/publish_npm.ts | 26 ++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 _tools/build_npm.ts create mode 100644 _tools/meta.ts create mode 100644 _tools/publish_npm.ts diff --git a/_tools/build_npm.ts b/_tools/build_npm.ts new file mode 100644 index 0000000..ba36b84 --- /dev/null +++ b/_tools/build_npm.ts @@ -0,0 +1,23 @@ +import { build, emptyDir } from "https://deno.land/x/dnt@0.33.1/mod.ts"; +import { join } from "https://deno.land/std@0.177.0/path/mod.ts"; +import { makeOptions } from "./meta.ts"; + +async function buildPkg(version: string): Promise { + await emptyDir("./npm"); + const pkg = makeOptions(version); + await Deno.copyFile("LICENSE", join(pkg.outDir, "LICENSE")); + Deno.copyFile( + join(".", "README.md"), + join(pkg.outDir, "README.md"), + ); + await build(pkg); +} + +if (import.meta.main) { + const version = Deno.args[0]; + if (!version) { + console.error("argument is required"); + Deno.exit(1); + } + await buildPkg(version); +} diff --git a/_tools/meta.ts b/_tools/meta.ts new file mode 100644 index 0000000..b156fd2 --- /dev/null +++ b/_tools/meta.ts @@ -0,0 +1,38 @@ +import { BuildOptions } from "https://deno.land/x/dnt@0.33.1/mod.ts"; + +export const makeOptions = (version: string): BuildOptions => ({ + test: false, + shims: {}, + compilerOptions: { lib: ["esnext", "dom"] }, + typeCheck: true, + entryPoints: ["./mod.ts"], + outDir: "./npm", + package: { + name: "@httpland/http-middleware", + version, + description: "HTTP middleware specification", + keywords: [ + "http", + "middleware", + "http-middleware", + "handler", + "http-handler", + "next", + "request", + "response", + ], + license: "MIT", + homepage: "https://github.com/httpland/http-middleware", + repository: { + type: "git", + url: "git+https://github.com/httpland/http-middleware.git", + }, + bugs: { + url: "https://github.com/httpland/http-middleware/issues", + }, + sideEffects: false, + type: "module", + publishConfig: { access: "public" }, + }, + packageManager: "pnpm", +}); diff --git a/_tools/publish_npm.ts b/_tools/publish_npm.ts new file mode 100644 index 0000000..b8d7ec7 --- /dev/null +++ b/_tools/publish_npm.ts @@ -0,0 +1,26 @@ +import { prerelease, valid } from "https://deno.land/x/semver@v1.4.1/mod.ts"; +import { makeOptions } from "./meta.ts"; + +if (import.meta.main) { + const version = Deno.args[0]; + if (!version) { + console.error("arg of version is required"); + Deno.exit(1); + } + if (!valid(version)) { + console.error("The argument of version is invalid"); + Deno.exit(1); + } + + const isPrerelease = prerelease(version); + const tag = isPrerelease?.[0] ?? "latest"; + + const pkg = makeOptions(version); + const result = await Deno.run({ + cmd: ["npm", "publish", pkg.outDir, "--tag", String(tag)], + stdout: "piped", + }) + .output(); + + console.log(new TextDecoder().decode(result)); +} From 846e4e28641a125e458885388286e91708d4a3ae Mon Sep 17 00:00:00 2001 From: Tomoki Miyauchi Date: Mon, 13 Feb 2023 19:41:25 +0900 Subject: [PATCH 4/9] chore: add config --- .releaserc | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .releaserc diff --git a/.releaserc b/.releaserc new file mode 100644 index 0000000..e7eb04b --- /dev/null +++ b/.releaserc @@ -0,0 +1,25 @@ +{ + "branches": [ + "main", + { + "name": "beta", + "prerelease": true + } + ], + "plugins": [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + "@semantic-release/changelog", + "@semantic-release/github", + [ + "@semantic-release/git", + { + "assets": [ + "CHANGELOG.md" + ], + "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" + } + ] + ], + "tagFormat": "${version}" +} From b9d518b30dfa5526e708707ef49fe5a652421a64 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 13 Feb 2023 10:42:39 +0000 Subject: [PATCH 5/9] chore(release): 1.0.0-beta.1 [skip ci] # 1.0.0-beta.1 (2023-02-13) ### Features * **types:** add middleware interface ([936af7b](https://github.com/httpland/http-middleware/commit/936af7bdf9229243e3256ac0397f39e1071110c1)) --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..56722d9 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,6 @@ +# 1.0.0-beta.1 (2023-02-13) + + +### Features + +* **types:** add middleware interface ([936af7b](https://github.com/httpland/http-middleware/commit/936af7bdf9229243e3256ac0397f39e1071110c1)) From 7d3ecb77b838d24769de274a08de44a37672e310 Mon Sep 17 00:00:00 2001 From: Tomoki Miyauchi Date: Tue, 14 Feb 2023 17:05:07 +0900 Subject: [PATCH 6/9] docs: add middleware list --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index e6fbde8..7a80868 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,12 @@ interface Handler { - It can access the next handler's return value (`Response`). - It can return `Response`. +## Middleware + +- [http-cors](https://github.com/httpland/http-cors) - Enable CORS +- [http-log](https://github.com/httpland/http-log) - Log for request and + response + ## License Copyright © 2023-present [httpland](https://github.com/httpland). From e9a5f75d893174d6f9d904dde672742209f6d950 Mon Sep 17 00:00:00 2001 From: Tomoki Miyauchi Date: Wed, 15 Feb 2023 01:57:41 +0900 Subject: [PATCH 7/9] docs: update middleware list --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 7a80868..0dc9ac8 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,8 @@ interface Handler { - [http-cors](https://github.com/httpland/http-cors) - Enable CORS - [http-log](https://github.com/httpland/http-log) - Log for request and response +- [http-etag](https://github.com/httpland/http-etag) - ETag calculate and + validate ## License From b80b02e0015bb684d7a089a90c3d26d3cc161adf Mon Sep 17 00:00:00 2001 From: Tomoki Miyauchi Date: Thu, 16 Mar 2023 16:20:09 +0900 Subject: [PATCH 8/9] refactor: remove external module --- deps.ts | 6 ------ mod.ts | 3 +-- types.ts | 5 ++++- 3 files changed, 5 insertions(+), 9 deletions(-) delete mode 100644 deps.ts diff --git a/deps.ts b/deps.ts deleted file mode 100644 index 5f69a73..0000000 --- a/deps.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2023-latest the httpland authors. All rights reserved. MIT license. -// This module is browser compatible. - -export { - type HttpHandler as Handler, -} from "https://deno.land/x/http_utils@1.0.0-beta.6/handlers.ts"; diff --git a/mod.ts b/mod.ts index 8fb374f..56d7dbe 100644 --- a/mod.ts +++ b/mod.ts @@ -1,5 +1,4 @@ // Copyright 2023-latest the httpland authors. All rights reserved. MIT license. // This module is browser compatible. -export type { Middleware } from "./types.ts"; -export type { Handler } from "./deps.ts"; +export type { Handler, Middleware } from "./types.ts"; diff --git a/types.ts b/types.ts index 495eee9..63edfda 100644 --- a/types.ts +++ b/types.ts @@ -1,7 +1,10 @@ // Copyright 2023-latest the httpland authors. All rights reserved. MIT license. // This module is browser compatible. -import type { Handler } from "./deps.ts"; +/** HTTP handler API. */ +export interface Handler { + (request: Request): Promise | Response; +} /** HTTP middleware API. */ export interface Middleware { From 85559367ee5ada75ae6ae351f59c6b838d77507d Mon Sep 17 00:00:00 2001 From: Tomoki Miyauchi Date: Thu, 16 Mar 2023 16:22:58 +0900 Subject: [PATCH 9/9] docs: add definition of terms --- README.md | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 0dc9ac8..0d273fc 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,17 @@ Define standard HTTP middleware specifications. This is intended to increase the interoperability of the HTTP library's own middleware. It consists only of the web standards stack and is compatible with many -Browsers. +browsers. + +## Terms + +
+
Upstream
+
Refers to HTTP requests forwarded from the client to the server.
+ +
Downstream
+
Refers to the HTTP response forwarded from the server to the client.
+
## Interface @@ -28,25 +38,25 @@ interface Handler { `Middleware` has the following features: -- Compatible with `Handler`. +- Compliant with [Fetch API](https://fetch.spec.whatwg.org/). +- Compliant with `Handler`. `Handler` is a powerful interface for handling HTTP requests. The `Middleware` is purely an extension and compatibility with `Handler`. -- It can access to the `Request`. -- It can access the next handler. -- It can call the next handler. -- It can choose not to call the next handler. -- It can access the next handler's return value (`Response`). -- It can return `Response`. +- It is a pure function. + + `Middleware` is a pure function that returns a value. Implementations are + expected to have no side effects. +- It is self-contained. +- It can handle upstream. +- It can handle downstream. +- It can handle next handler. -## Middleware +## Implementation -- [http-cors](https://github.com/httpland/http-cors) - Enable CORS -- [http-log](https://github.com/httpland/http-log) - Log for request and - response -- [http-etag](https://github.com/httpland/http-etag) - ETag calculate and - validate +See [chain-handler](https://github.com/httpland/chain-handler) for a concrete +implementation that can handle middleware ## License