npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

hc-proxy-patch

v1.0.10

Published

honeycomb api proxy express middleware.

Downloads

5

Readme

service proxy

api代理模块,解决跨域、权限问题

场景案例

远程需要被代理转发的服务:

http://localhost:7001/api/aaa         // 视频服务接口
http://localhost:7001/api/c/*         // 视频服务接口
http://192.168.1.1:7001/api/bbb       // 音乐服务接口
http://localhost:7001/ws/*            // 聊天服务接口 (使用websocket)

以honeycomb项目为例进行配置

  1. 确定honeycomb项目的启动端口和prefix,比如: 项目的启动端口为8001,prefix为 'example'
  2. 整理远程调用的服务,给每个服务起个英文名称,比如: 上面的两个服务 视频服务(video) 音乐服务(music) 聊天服务(chat)
  3. 配置在router.js中,进行如下配置
// router.js
const app = require('./app');
const Proxy = require('hc-proxy');
const proxyInstance = new Proxy({
  service: {
    video: {
      endpoint: 'http://localhost:7001/',
      client: 'http',
      api: [
        '/api/aaa',
        '/api/c/*'
      ]
    },
    music: {
      endpoint: 'http://192.168.1.1:7001/',
      client: 'http',
      api: [
        '/api/bbb'
      ]
    }
  },
  headers: [
    'x-csrf-token',
    'X-Operator'
  ]
});

proxyInstance.setProxyPrefix('/api/proxy');

module.exports = function (router) {
  proxyInstance.mount(router, app);
};

配置完成后访问地址

访问地址为 ${honeycomb服务地址:honeycomb服务端口/honeycomb的prefix} + ${proxyPrefix} + ${被代理服务名} + ${具体api}

1. 视频服务:   curl http://localhost:8001/example/api/proxy/video/api/aaa => http://localhost:7001/api/aaa
2. 视频服务:   curl http://localhost:8001/example/api/proxy/video/api/c/somewhat?xxx=123 => http://localhost:7001/api/c/somewhat?xxx=123
3. 音乐服务:   curl http://localhost:8001/example/api/proxy/music/api/bbb => http://192.168.1.1:7001/api/bbb

代理websocket服务

// router.js
const app = require('./app');
const Proxy = require('hc-proxy');
const proxyInstance = new Proxy({
  service: {
    music: {
      endpoint: 'http://192.168.1.1:7001/',
      client: 'http',
      api: [
        '/api/bbb'
      ]
    },
    chat: {
      endpoint: 'http://localhost:7001/',
      client: 'websocket',
      api: [
        '/ws/*'
      ]
    }
  },
  headers: [
    'x-csrf-token',
    'X-Operator'
  ]
});

proxyInstance.setProxyPrefix('/api/proxy');

module.exports = function (router) {
  proxyInstance.mount(router, app);
};

websocket配置完成后访问地址

访问地址为 ${honeycomb服务地址:honeycomb服务端口/honeycomb的prefix} + ${proxyPrefix} + ${被代理服务名} + ${具体api}

1. 音乐服务:   curl http://localhost:8001/example/api/proxy/music/api/bbb => http://192.168.1.1:7001/api/bbb
2. 聊天服务:   curl http://localhost:8001/example/api/proxy/chat/ws/somewhat => http://localhost:7001/ws/somewhat      // 支持websocket

代理文件上传

// router.js
const app = require('./app');
const Proxy = require('hc-proxy');
const proxyInstance = new Proxy({
  service: {
    music: {
      endpoint: 'http://192.168.1.1:7001/',
      client: 'http',
      api: [
        {
          path: '/api/upload',
          file: true
        },
        {
          path: '/api/upload_limited',
          file: {
            maxFileSize: 100        // 100B
          }
        }
      ]
    }
  },
  headers: [
    'x-csrf-token',
    'X-Operator'
  ]
});

proxyInstance.setProxyPrefix('/api/proxy');

module.exports = function (router) {
  proxyInstance.mount(router, app);
};

文件上传代理效果

1. 上传文件1:   curl http://localhost:8001/example/api/proxy/music/api/upload => http://192.168.1.1:7001/api/upload
2. 上传文件2:   curl http://localhost:8001/example/api/proxy/music/api/upload_limited => http://192.168.1.1:7001/api/upload_limited

API document

约定:

  • proxy挂在的http服务称为 "代理服务"
  • 被proxy代理的远端服务称为 "远端服务"

new Proxy(options)

options Object

options.service 详情

{
  ${serviceCode}: {
    endpoint: ${endpoint},
    accessKeyId: ${accessKeyId},
    accessKeySecret: ${accessKeySecret},
    headerExtension: ${headerExtension},
    headers: ${headers},
    client: ${client},
    timeout: ${timeout},
    useQuerystringInDelete: ${useQuerystringInDelete},    // 只有 appClient / urllib 模式有效
    urllibOption: ${urllibOption},                        // 只有 appClient / urllib 模式有效
    api: [
      ${apiString},
      {
        path: ${path},
        route: ${route},
        method: ${method},
        timeout: ${apiTimeout},
        defaultQuery: ${defaultQuery},
        beforeRequest: ${beforeRequest}, // TODO
        useQuerystringInDelete: ${useQuerystringInDelete},
        urllibOption: ${urllibOption}
      }
    ]
  }
}

通用配置:

  • endpoint: 每个远端服务的服务地址,如: 'http://localhost:7001' 或 'http://localhost:7001/service'
  • client: 目前只支持'appClient' / 'http' / 'websocket',默认为'appClient',其中 appClient 带了honeycomb体系中的签名逻辑
  • timeout: 某个服务或接口的超时时间,毫秒计算,默认60000
  • apiString: 使用默认配置对某个api进行代理,设置的是Api的path,如: '/api/user' 会对 '/api/user' 进行 'GET', 'POST', 'PUT', 'DELETE' 代理
  • path: api的路径,如: '/api/user',支持 '/api/user' / '/api/user/:user' / '/api/user/*'
  • route: api在路由中出现的路径(会忽略proxyPrefix),如: '/remote_service/aaa' , 则调用 ${localService} + '/remote_service/aaa',会被走path对应的远端服务
  • method: 指定这个api支持的方法 'GET' / ['GET', 'POST'],不填时,默认为 ['GET', 'POST', 'PUT', 'DELETE']
  • apiTimeout: 覆盖整个服务的timeout
  • defaultQuery: String / Object,用于配置默认的query参数(代理请求时自动加上)
  • beforeRequest: 暂不支持
  • file: 配置上传文件,出现上传文件配置时,该接口支持上传文件,子配置使用默认值可以配置为 {... file: true}
    • maxFileSize: 上传文件的大小限制, 单位byte, default
  • useQuerystringInDelete: delete方法使用querystring代理, 默认为true
  • urllibOption: 用户覆盖的urllibOption,覆盖系统默认值,优先级: service.api.urllibOption > service.urllibOption > hc-proxy默认设置

client=[appClient/serviceClient]的专属配置

  • headers: 选填,同 hc-service-client 配置,见文档: https://www.npmjs.com/package/hc-service-client
  • accessKeyId: 选填,同 hc-service-client 配置,默认 'hc-proxy',详见 https://www.npmjs.com/package/hc-service-client
  • accessKeySecret: 同 hc-service-client 配置,必填,不填时取 app.config.systemToken,详见 https://www.npmjs.com/package/hc-service-client
  • headerExtension: 同 hc-service-client 配置,见文档: https://www.npmjs.com/package/hc-service-client

options.headers Array

options.headers 用于声明proxy需要转发的header。 默认情况下,proxy不转发客户端过来的header,只有在proxyHeaders中配置的header才会被转发。

proxy.setProxyPrefix(proxyPrefix)

  • proxyPrefix

setProxyPrefix方法用于指定 hc-proxy 挂载在代理服务上的总前缀

如: 默认 proxyPrefix = /api/proxy 则: 所有请求远端服务的请求,格式为 ${localHttpServer}/api/proxy/${serviceCode}/${remoteApi}

proxy.mount(router, app)

将proxy的配置挂在到代理服务。

  • router: Express Router instance
  • app: app.server 是一个 http.Server 的实例,honeycomb中,直接 require('./app') 能获得

更多例子

'use strict';

const app = require('./app');
const Proxy = require('hc-proxy');
const proxyInstance = new Proxy({
  service: {
    otm: {
      endpoint: 'http://dev.dtboost.biz.aliyun.test/otm_v2',                           // 自动截取最后的'/'
      client: 'appClient',                                                                // 默认appClient
      timeout: 10000,                                                                     // 默认60000
      api: [
        '/api/*',                                                                         // 支持 * 代理某个path下的所有api
        '/otm_v2/api/entities/list',                                                      // 代理这个 url 的 GET POST PUT DELETE 方法
        {path: '/otm_v2/api/entities/list', method: 'GET'},                                // 只代理 GET 方法
        {path: '/otm_v2/api/entities/list', client: 'appClient'},                          // 显式指定 method
        {path: '/otm_v2/api/schemas', method: ['GET', 'POST']},                            // 只支持 GET POST 方法
        {host: 'http://taobao.com/api', path: '/tag_factory_v2/api/:id', method: 'GET'},   // 不同域时,指定host
        {path: 'http://taobao.com/api', route: '/api/proxy/taobao_api'},                   // 指定route的代理,不指定route时,所有代理接口请求 /<-app_name->/api/proxy 获得代理
        '/otm_v2/api/tags/query_tags_entity_pagenum',                                     // 
        {path: '/otm_v2/api/schemas/:id', route: '/api/proxy/schemas/:id'}                 // 带参数的url,保证route和url中的param一致,也可以不填route
      ]
    },
    websocket: {
      endpoint: 'http://dev.dtboost.biz.aliyun.test/websocket',               // 远程的websocket地址
      client: 'websocket',                                                       // 选择websocket作为连接的client
      api: [
        '/ws'                                                                    // 配置连接路径,不在的路径返回404
      ]
    }
  },
  headers: [
    'x-csrf-token',
    'X-Operator'
  ]
});

proxyInstance.setProxyPrefix('/api/proxy');

module.exports = function (router) {
  proxyInstance.mount(router, app);
};

DEBUG [代理没生效?]

在命令行启动命令前加入DEBUG=hc-proxy

// 以启动命令为 honeycomb start 为例
DEBUG=hc-proxy honeycomb start

// ...
// hc-proxy [GET] /api/proxy/urllib_proxy/urllib -> http://localhost:58062/urllib +0ms
// hc-proxy [POST] /api/proxy/urllib_proxy/urllib -> http://localhost:58062/urllib +3ms
// hc-proxy [DELETE] /api/proxy/urllib_proxy/urllib -> http://localhost:58062/urllib +1ms
// hc-proxy [PUT] /api/proxy/urllib_proxy/urllib -> http://localhost:58062/urllib +0ms
// ...

作用

  • 本地开发时,可以使用这个代理访问远程其它服务(如otm)的问题;
  • 非本地开发环境时,可以不使用代理,而直接访问类似'/otm_v2/api/xxx',以减小内部调用开销,由前端自行控制;