Git Product home page Git Product logo

h3-proxy's Introduction


h3-proxy

A proxy event handler for h3, using proxyRequest.

Features

  • Powered by built-in proxyRequest of h3.
  • Support http(s) proxy via some simple configurations.
  • Support logs via consola.
  • Support Typescript.

Installation

# pnpm
$ pnpm add h3-proxy

# yarn
$ yarn add h3-proxy

# npm
$ npm i h3-proxy

Basic usage

import { createServer } from 'node:http'
import { createApp, eventHandler, toNodeListener } from 'h3'
import { createProxyEventHandler } from 'h3-proxy'

const app = createApp()

const port = process.env.PORT || 3000

// Define proxy event handler
const proxyEventHandler = createProxyEventHandler({
  target: `http://127.0.0.1:${port}`,
  pathRewrite: {
    '^/api': '',
  },
  pathFilter: ['/api/**'],
  // enableLogger: true
})

// Add proxy middlewares
app.use(eventHandler(proxyEventHandler))

// Define api routes
app.use(
  '/test',
  eventHandler(() => 'Hello world!')
)

createServer(toNodeListener(app)).listen(port)

Multiple proxy targets usage

Create multiple proxy h3 event handler middleware.

import { createServer } from 'node:http'
import { createApp, eventHandler, toNodeListener } from 'h3'
import { createProxyEventHandler } from 'h3-proxy'

const app = createApp()

const port = process.env.PORT || 3000

// proxy to `http://127.0.0.1:${port}`
const proxyEventHandler1 = createProxyEventHandler({
  target: `http://127.0.0.1:${port}`, // http://127.0.0.1:3000
  pathRewrite: {
    '^/api': '',
  },
  pathFilter: ['/api/**'],
})

// proxy to other target
const proxyEventHandler2 = createProxyEventHandler({
  target: `http://127.0.0.1:${port}/other-api-module`,
  pathRewrite: {
    '^/other-api': '',
  },
  pathFilter: ['/other-api/**'],
})

// Add proxy middlewares
app.use(eventHandler(proxyEventHandler1))
app.use(eventHandler(proxyEventHandler2))

// Define api routes
app.use(
  '/test',
  eventHandler(() => 'Hello world!')
)

app.use(
  '/other-api-module/some/path',
  eventHandler(() => 'Hello other API module!')
)

createServer(toNodeListener(app)).listen(port)
  • For proxyEventHandler1, The result of proxy request is as follows:

/api/test -> http://127.0.0.1:3000/test

  • For proxyEventHandler2, The result of proxy request is as follows:

/other-api/some/path -> http://127.0.0.1:3000/other-api-module/some/path

Or, using Array type options to define multiple proxy targets (added in v1.11.0).

const proxyEventHandler = createProxyEventHandler([
  {
    // options
  },
  {
    // other proxy target options
  }
])

APIs

createProxyEventHandler

Create a h3 event handler that can handle proxy requests.

const proxyEventHandler = createProxyEventHandler({
  // options
})

Options

Key Type Required Default value Description
target string true undefined Proxy target address, including protocol, host and port. url string to be parsed with the node:url module
pathFilter string, string[], glob, glob[], Function false undefined Narrow down which requests should be proxied.
pathRewrite object/Function false undefined Rewrite target's url path. Object-keys will be used as RegExp to match paths.
configureProxyRequest Function false undefined Configure options of proxyRequest. More details see built-in util proxyRequest of h3
proxyRequestMethod
(Added in v1.13.0)
Function false undefined Customize proxyRequest of h3 method.
enableLogger boolean false true Whether to enable logger which is created by consola.
loggerOptions ConsolaOptions false {} Configure the options of consola.
changeOrigin boolean false false Whether to changes the origin of the host header to the target URL

pathFilter

  • path matching

    • createProxyEventHandler({...}) - matches any path, all requests will be proxied when pathFilter is not configured.
    • createProxyEventHandler({ pathFilter: '/api', ...}) - matches paths starting with /api
  • multiple path matching

    • createProxyEventHandler({ pathFilter: ['/api', '/ajax', '/someotherpath'], ...})
  • wildcard path matching

    For fine-grained control you can use wildcard matching. Glob pattern matching is done by micromatch. Visit micromatch or glob for more globbing examples.

    • createProxyEventHandler({ pathFilter: '**', ...}) matches any path, all requests will be proxied.
    • createProxyEventHandler({ pathFilter: '**/*.html', ...}) matches any path which ends with .html
    • createProxyEventHandler({ pathFilter: '/*.html', ...}) matches paths directly under path-absolute
    • createProxyEventHandler({ pathFilter: '/api/**/*.html', ...}) matches requests ending with .html in the path of /api
    • createProxyEventHandler({ pathFilter: ['/api/**', '/ajax/**'], ...}) combine multiple patterns
    • createProxyEventHandler({ pathFilter: ['/api/**', '!**/bad.json'], ...}) exclusion

⚠️ TIPS, In multiple path matching, you cannot use string paths and wildcard paths together.

  • custom matching

    For full control you can provide a custom function to determine which requests should be proxied or not.

    /**
     * @return {Boolean}
     */
    const pathFilter = function (path, req) {
    
      return path.match(/^\/api/) && req.method === 'GET';
    
      // TIPS: if you are using it in nuxt-proxy-request
      // Pls use `new RegExp()` instead.
    
      // return path.match(new RegExp('^\/api')) && req.method === 'GET';
    };
    
    const apiProxy = createProxyEventHandler({
      target: 'http://www.example.org',
      pathFilter: pathFilter,
    });

pathRewrite

Rewrite target's url path. Object-keys will be used as RegExp to match paths.

// rewrite path
pathRewrite: {'^/old/api' : '/new/api'}

// remove path
pathRewrite: {'^/remove/api' : ''}

// add base path
pathRewrite: {'^/' : '/basepath/'}

// custom rewriting
pathRewrite: function (path, req) { return path.replace('/api', '/base/api') }

// custom rewriting, returning Promise
pathRewrite: async function (path, req) {
  const should_add_something = await httpRequestToDecideSomething(path);
  if (should_add_something) path += "something";
  return path;
}

configureProxyRequest

For the return value, Please refer to the source code of proxyRequest of h3.

createProxyEventHandler({
  // ...
  // the param `event` is H3Event
  configureProxyRequest(event) {
    // return your custom options of proxyRequest

    // eg: specify some request headers
    // return {
    //   headers: {}
    // }

    return {}
  }
})

Framework Supports

Nuxt

Add a server middleware.

// ~/server/middleware/proxy.ts

import { createProxyEventHandler } from 'h3-proxy'

export default defineEventHandler(createProxyEventHandler({
  // options...
}))

h3-proxy's People

Contributors

yisibell avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

h3-proxy's Issues

Feature Request: Support for Different Target Servers for Specific API Routes

I am currently using your package in my project.
The package works well for proxying API requests.
However, I have encountered a limitation that I believe could be a valuable addition to your package .

Current Behavior:

The component successfully proxies API requests made to /api. All requests to the /api endpoint are forwarded to a single specified server.

Desired Feature:

I would like the component to support routing requests to different servers based on the API route. Specifically, I want requests to /api/xxx1 to be proxied to one server, while all other /api requests (except /api/xxx1) are proxied to a different server. This feature is crucial for my project as it involves interacting with multiple backend services.

Example:

  • Requests to /api/xxx1 should be forwarded to Server A (Dev server).
  • Requests to any other /api routes (like /api/xxx2, /api/xxx3, etc.) should be forwarded to Server B (Service Gateway).

Use Case:

This feature is particularly useful in a microservices architecture where different microservices are hosted on separate servers. It allows for more flexibility and control over the routing of API requests.

I believe this feature could benefit other users who might be in a similar situation. I am looking forward to your thoughts on this and would greatly appreciate it if this feature could be considered for implementation in a future release.

Thank you for your time and effort in maintaining this component.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.