阿里云主机折上折
  • 微信号
Current Site:Index > Custom middleware encapsulation and publishing

Custom middleware encapsulation and publishing

Author:Chuan Chen 阅读数:47882人阅读 分类: Node.js

Basic Concepts of Middleware

Koa2 middleware is essentially a function that takes the context object and the next function as parameters. Middleware controls the execution flow through the next function, forming an onion model. Each middleware can process requests and responses, modify the context object, or terminate the request.

async function middleware(ctx, next) {
  // Request processing logic
  await next()
  // Response processing logic
}

Principles of Middleware Encapsulation

When encapsulating middleware, the Single Responsibility Principle should be considered, where each middleware handles only a specific functionality. Good middleware should be configurable, allowing custom behavior through an options parameter. Error handling mechanisms are essential, and internal errors should be caught and thrown via ctx.throw.

function createMiddleware(options = {}) {
  return async function(ctx, next) {
    try {
      // Middleware logic
      await next()
    } catch(err) {
      ctx.throw(500, 'Internal Server Error')
    }
  }
}

Common Middleware Encapsulation Patterns

Configurable Middleware

Return a middleware instance through a factory function, supporting parameter configuration. For example, a logging middleware can configure the log level:

function logger(options = { level: 'info' }) {
  return async (ctx, next) => {
    const start = Date.now()
    await next()
    const ms = Date.now() - start
    if(options.level === 'debug') {
      console.debug(`${ctx.method} ${ctx.url} - ${ms}ms`)
    } else {
      console.log(`${ctx.method} ${ctx.url}`)
    }
  }
}

Composite Middleware

Combine multiple functionalities into a composite middleware, such as integrating authentication and authorization:

function auth(options) {
  const authenticate = require('./authenticate')
  const authorize = require('./authorize')
  
  return async (ctx, next) => {
    await authenticate(options)(ctx, async () => {
      await authorize(options)(ctx, next)
    })
  }
}

Middleware Development Practices

Example of Request Processing Middleware

Developing a request parameter validation middleware:

function validate(schema) {
  return async (ctx, next) => {
    const { error } = schema.validate(ctx.request.body)
    if (error) {
      ctx.status = 400
      ctx.body = { error: error.details[0].message }
      return
    }
    await next()
  }
}

// Usage example
const Joi = require('joi')
const userSchema = Joi.object({
  username: Joi.string().required(),
  password: Joi.string().min(6).required()
})

app.use(validate(userSchema))

Example of Response Processing Middleware

A unified response formatting middleware:

function responseFormatter() {
  return async (ctx, next) => {
    await next()
    if (!ctx.body) return
    
    ctx.body = {
      code: ctx.status,
      data: ctx.body,
      timestamp: Date.now()
    }
  }
}

Middleware Testing Methods

Testing middleware using supertest and jest:

const request = require('supertest')
const Koa = require('koa')
const app = new Koa()

app.use(require('./middleware'))

test('should return 400 for invalid input', async () => {
  const response = await request(app.callback())
    .post('/api')
    .send({})
  
  expect(response.status).toBe(400)
})

Middleware Publishing Process

Package Structure Standards

Typical npm package directory structure for middleware:

/package-name
  /lib
    - index.js
  /test
    - middleware.test.js
  - package.json
  - README.md

package.json Configuration

Key fields configuration example:

{
  "name": "koa-validate",
  "version": "1.0.0",
  "main": "lib/index.js",
  "keywords": ["koa", "middleware", "validation"],
  "peerDependencies": {
    "koa": "^2.0.0"
  }
}

Documentation Writing Essentials

README.md should include:

  • Installation instructions
  • Basic usage examples
  • Configuration options explanation
  • Frequently asked questions
# koa-validate

## Installation

```bash
npm install koa-validate

Basic Usage

app.use(validate(schema))

## Version Management and Updates

Follow semantic versioning:
- Patch version (1.0.x): Backward-compatible bug fixes
- Minor version (1.x.0): Backward-compatible feature additions
- Major version (x.0.0): Incompatible API changes

Use npm version commands to manage versions:

```bash
npm version patch
npm version minor
npm version major

Performance Optimization Tips

Avoid blocking operations in middleware. For time-consuming operations, use asynchronous methods:

function cacheMiddleware(ttl) {
  const cache = new Map()
  
  return async (ctx, next) => {
    const key = ctx.url
    if (cache.has(key)) {
      const { value, expiry } = cache.get(key)
      if (Date.now() < expiry) {
        ctx.body = value
        return
      }
    }
    
    await next()
    
    if (ctx.status === 200) {
      cache.set(key, {
        value: ctx.body,
        expiry: Date.now() + ttl
      })
    }
  }
}

Error Handling Best Practices

Internal middleware errors should trigger application-level error events via ctx.app.emit:

function errorHandler() {
  return async (ctx, next) => {
    try {
      await next()
    } catch (err) {
      ctx.status = err.status || 500
      ctx.body = { message: err.message }
      ctx.app.emit('error', err, ctx)
    }
  }
}

Middleware Composition Techniques

Use koa-compose to combine multiple middleware:

const compose = require('koa-compose')

function middlewareA() { /* ... */ }
function middlewareB() { /* ... */ }

const combined = compose([middlewareA(), middlewareB()])

app.use(combined)

TypeScript Support

Add type declarations for middleware:

import { Middleware } from 'koa'

interface Options {
  prefix?: string
}

export function myMiddleware(options?: Options): Middleware {
  return async (ctx, next) => {
    // Implementation logic
    await next()
  }
}

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.