1 Star 3 Fork 0

简单的机械键盘 / gohttp

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
MulanPSL-2.0

gohttp

针对HTTP/1.1和HTTP/2封装的客户端请求库,从4.0版本开始,支持HTTP/2,之前的版本只支持http1。除了客户端请求,也提供了一个基于http2连接池的反向代理。

基于Promise实现,可以通过then接收返回结果,或者配合async/await使用。

安装

npm i gohttp

以下是3.x版本的http1请求过程,从4.0开始,接口不变,但是导出方式发生了变化。因为包含http1和http2的客户端请求,这两个协议在不使用ALPN支持,并且没有兼容接口的时候,是无法自动适应的。这里给出的封装就是基于http/https模块封装了HTTP/1.1的请求,基于http2模块封装了HTTP/2的请求。

4.2.0版本开始,httpcli提供了一个兼容http2cli的接口层。在接口层面,可以实现一致的请求方式。具体参考后面的文档描述。

HTTP/1.1协议的请求

从4.0开始,导出方式: const {httpcli} = require('gohttp')

接口使用方式不变

GET请求


const {httpcli} = require('gohttp');

//使用query选项设置查询字符串。
httpcli.get('http://localhost:2020/', { timeout: 3000, query: {key:45091, x: 32} })
        .then(res => {
            console.log(res.headers, res.status);
            return res.text();
        })
        .then(result => {
            console.log(result);
        });

POST请求


const {httpcli} = require('gohttp');

httpcli.post('http://localhost:2020/p', {
            body : {
                user: 'wang'
            }
        })
        .then(res => {
            return res.text();
        })
        .then(result => {
            console.log(result);
        });

PUT请求

const {httpcli} = require('gohttp');

httpcli.put('http://localhost:2020/p', {
            body : {
                user: 'wang'
            }
        })
        .then(res => {
            return res.text();
        })
        .then(result => {
            console.log(result);
        });

DELETE请求


const {httpcli} = require('gohttp');

httpcli.delete('http://localhost:2020/p/123')
        .then(res => {
            return res.text();
        })
        .then(result => {
            console.log(result);
        });

上传文件


const {httpcli} = require('gohttp');

httpcli.upload('http://localhost:2020/upload', {
            files: {
                image: [
                    'pictures/a.jpg',
                    'pictures/b.png'
                ],
                video: [
                    'videos/a.mp4',
                    'videos/b.mp4'
                ]
            },
            //要携带表单数据需要form选项
            //form : {}
        })
        .then(res => {
            return res.text();
        })
        .then(result => {
            console.log(result);
        });

简单上传

基于httpcli.upload封装的up函数参数更加简单:


httpcli.up('http://localhost:1234/upload', {
    name : 'image'
    file : 'images/123.jpg'
}).then(res => {
    return res.text();
}).then(d => {
    console.log(d);
});

下载文件


const {httpcli} = require('gohttp');

httpcli.download('https://localhost:2021/download', {
  dir: process.env.HOME + '/download/',
  //输出进度提示
  progress: true
}).then(d => {
    console.log(d || '');
}).catch(err => {
    console.error(err);
});

通过rawBody传递请求体数据

有时候,你可能需要转发请求数据。此时,若在服务端收到请求以后,再次通过body选项传递数据,需要再一次构造HTTP协议的请求体数据,会比较耗费性能。这时候可以通过rawBody把服务端的原始请求数据传递过去,实现转发。


'use strict'

//使用titbit框架作为服务端服务进行示例
const Titbit = require('titbit')

const {httpcli} = require('gohttp')

//初始化HTTP服务端应用
const app = new Titbit()

app.post('/transmit', async ctx => {
    /*
     * 把前端应用提交的数据转发给后台服务http://localhost:1200/data
     * ctx中的rawBody保存了原始HTTP协议格式的请求体数据。
    */
    let ret = await httpcli.post('http://localhost:1200/data', {
        headers: ctx.headers,
        rawBody: ctx.rawBody
    })

    c.send(ret)
})

app.run(1234)

请求返回值(res)

请求的返回值包括以下属性:

ok true或false,表示请求是否成功。

status 状态码,若是请求连接都没有成功则为0。

error 初始值为null,若是出错则为具体的Error实例。

headers 响应头信息。

timeout 初始值为false,若是为true则表示请求超时。

blob 函数,返回响应数据的原始Buffer。

text 函数,以字符串的形式返回响应数据。

json 函数,以JS对象的形式返回响应数据。就是对text返回的值做一次JSON.parse。

length 返回数据的总长度,单位是字节。

HTTP/2客户端返回的res也包括这些属性。

注意事项

http/1.1请求,可能需要通过选项family指定使用IPv4还是IPv6。

HTTP/2 请求

连接


const {http2cli} = require('gohttp')

//返回值是包装了http2Session实例的一个对象,并提供了常用请求和request方法。
hsession = http2cli.connect('http://localhost:1234')

连接选项


const {http2cli} = require('gohttp')

//返回值是包装了http2Session实例的一个对象,并提供了常用请求和request方法。
let hsession = http2cli.connect('http://localhost:1234', {
    //请求空闲10秒则超时。
    timeout: 10000,
    //此时,断开连接会自动重新连接。
    keepalive: true
})

连接池


const {http2cli} = require('gohttp')

//此时连接选项keepalive自动被设置为true。
let hs = http2cli.connectPool('http://localhost:1234', {
    //最大连接数量
    max: 5
})

//hs能使用的接口和connect返回的hsession一致。
//自动从连接池选择一个进行请求。
hs.get({
    path : '/'
})
.then(res => {
    console.log(res.text())
})

请求


const {http2cli} = require('gohttp')

let hs = http2cli.connect('http://localhost:1234')

//针对GET、POST、DELETE、PUT、OPTIONS提供了快速调用的同名小写方法。
//本质上都是调用了request。

hs.get({
    path : '/test',
})
.then(ret => {
    //ret是包含了headers, ok, status, error, data, text, json, blob属性的对象。
    console.log(ret.headers, ret.text())
})

//如果body是
hs.post({
    path : '/data',
    body : {
        name : 'Wang',
        id : '1001'
    }
})
.then(ret => {
    console.log(ret.headers, ret.text())
})

hs.request({
    method : 'PUT',
    path : '/content',
    headers : {
        'content-type' : 'text/plain'
    },
    body : {
        id : '1001',
        nickname : 'unix-great'
    }
})
.then(ret => {
    console.log(ret.headers, ret.text())
})

上传文件


const {http2cli} = require('gohttp')

//返回值是包装了http2Session实例的一个对象,并提供了常用请求和request方法。
let hs = http2cli.connect('http://localhost:1234', {
    //此时,断开连接会自动重新连接。
    keepalive: true
})

hs.upload({
    path : '/upload',
    files : {
        //键值 即为 上传名
      image : [
        process.env.HOME + '/tmp/images/123.jpg',
        process.env.HOME + '/tmp/images/space2.jpg',
      ],
      video : [
          process.env.HOME + '/tmp/images/a.mp4',
      ]
    },
    //可以使用form携带其他表单项
    form : {
        id : '1001'
    }
})
.then(ret => {
    console.log(ret.error)
    console.log(ret.status, ret.text())
})

简易上传

简易上传仅支持单个上传名,是对upload的封装。


const {http2cli} = require('gohttp')

//返回值是包装了http2Session实例的一个对象,并提供了常用请求和request方法。
let hs = http2cli.connect('http://localhost:1234')

hs.up({
    path : '/upload',
    name : 'image',
    file : [
        process.env.HOME + '/tmp/images/123.jpg',
        process.env.HOME + '/tmp/images/space2.jpg',
    ]
})
.then(ret => {
    console.log(ret.error)
    console.log(ret.status, ret.text())
})

持久连接

使用http2作为持久连接,一个连接可以发送多个请求,可以使用HTTP/2协议作为查询服务,基于协议的强大特性,可以完成比较复杂的功能。并且方便实现RPC,这方面其实已经有先例。HTTP/2协议本身并不要求一定要使用HTTPS,但是浏览器在实现上,要求必须启用HTTPS。在Node.js中,使用http2可以不启用https完成通信,在内网通信时,可以处理更快。

close 和 destroy

提供了close和destroy接口,不过没有参数,就是在内部调用了http2Session的close和destroy。

完整选项

选项 说明
debug 调式模式,true或false,开启会输出错误信息。
keepalive 是否保持连接,开启后,断开会自动重连。
max 使用connectPool指定最大多少个连接。
reconnDelay 重连延迟,毫秒值,默认为500毫秒。
headers 初始化连接,默认的消息头。

反向代理

基于对http2的封装以及连接池的处理,实现了基于http2连接池模式的反向代理。这可能是目前唯一一个支持HTTP/2协议以及连接池和自动重连并且支持负载均衡的反向代理。

使用示例:


'use strict'

const {http2proxy} = require('gohttp')
const titbit = require('titbit')

const app = new titbit({
  debug: true,
  http2: true,
  //这里应该换成你自己的证书和密钥文件路径
  key : './rsa/localhost.key',
  cert : './rsa/localhost.cert'
})

let hxy = new http2proxy({
  config: {
    'a.com' : [
      {
        url: 'http://localhost:2022',
        weight: 10,
        path : '/',
        reconnDelay: 5000,
        //请求后端服务时,附加的头部信息。
        headers : {
          'x-test-key' : `${Date.now()}-${Math.random()}`
        }
      },
      {
        url: 'http://localhost:2023',
        weight: 5,
        path : '/',
        reconnDelay: 1000
      }
    ]
  },
  //调式模式输出错误信息。
  debug: true
})

hxy.init(app)

app.run(1234)

配置中,host对应的数组中每一项元素都对应一个后端服务,相同的path存在多个就表示自然地启用负载均衡功能。

对应后端服务:

'use strict'

const titbit = require('titbit')

/**
 * 基于Node.js实现的http2服务端和客户端请求可以不使用https模式。
*/

const app = new titbit({
  debug: true,
  http2: true,
  loadInfoFile: '/tmp/loadinfo.log',
  globalLog: true,
  monitorTimeSlice: 512,
  timeout: 0
})

app.use(async (c, next) => {
  c.setHeader('x-set-key', `${Math.random()}|${Date.now()}`)
  await next()
})

app.get('/header', async c => {
  c.send(c.headers)
})

app.get('/', async c => {
  c.send(Math.random())
})

app.get('/:name/:age/:mobile/:info', async c => {
  c.send(c.param)
})

app.post('/p', async c => {
  c.send(c.body)
})

let port = 2022
let port_ind = process.argv.indexOf('--port')

if (port_ind > 0 && port_ind < process.argv.length - 1) {
  port = parseInt(process.argv[port_ind + 1])

  if (typeof port !== 'number') port = 2022
}

app.run(port)

兼容http2cli的接口层

这个接口层不会从协议层面兼容,Node.js层面也仅仅提供了http2服务端的兼容层。此兼容层接口设计目的是,当你需要切换协议时,不必更改代码。而在这之前,你需要知道服务端使用了什么协议。如果服务端兼容HTTP/2和HTTP/1.1,那么客户端使用哪个协议都是可以的。

兼容层接口的使用方式和HTTP/2的封装使用一致(http2cli),可以直接参考 ‘HTTP/2请求’ 部分。

示例:


const {httpcli} = require('gohttp');

// /api自动作为所有请求的路径前缀。
let hs = httpcli.connect('http://localhost:1234/api', {
      headers: {
        'access-token': '123456'
      }
    });

hs.post({
    //实际请求为 /api/p
    path: '/p',
    body: {
        a: 123,
        b: 234
    },

    //发送消息头会带上access-token
    headers: {
        'content-type': 'application/x-www-form-urlencoded'
    }
})
.then(res => {
    console.log(res.text(), res.headers);
})

//取消路径前缀
hs.prefix = ''
//取消默认消息头
hs.headers = null

在兼容层接口部分,url路径部分会自动作为prefix,用于所有请求的路径前缀。可以通过prefix设置。

木兰宽松许可证, 第2版 木兰宽松许可证, 第2版 2020年1月 http://license.coscl.org.cn/MulanPSL2 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束: 0. 定义 “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 “法人实体”是指提交贡献的机构及其“关联实体”。 “关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 1. 授予版权许可 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 2. 授予专利许可 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 3. 无商标许可 “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 4. 分发限制 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 5. 免责声明与责任限制 “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 6. 语言 “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。 条款结束 如何将木兰宽松许可证,第2版,应用到您的软件 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; 3, 请将如下声明文本放入每个源文件的头部注释中。 Copyright (c) [Year] [name of copyright holder] [Software Name] is licensed under Mulan PSL v2. You can use this software according to the terms and conditions of the Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2 THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details. Mulan Permissive Software License,Version 2 Mulan Permissive Software License,Version 2 (Mulan PSL v2) January 2020 http://license.coscl.org.cn/MulanPSL2 Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions: 0. Definition Software means the program and related documents which are licensed under this License and comprise all Contribution(s). Contribution means the copyrightable work licensed by a particular Contributor under this License. Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License. Legal Entity means the entity making a Contribution and all its Affiliates. Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity. 1. Grant of Copyright License Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not. 2. Grant of Patent License Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken. 3. No Trademark License No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4. 4. Distribution Restriction You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software. 5. Disclaimer of Warranty and Limitation of Liability THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 6. Language THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL. END OF THE TERMS AND CONDITIONS How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps: i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner; ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package; iii Attach the statement to the appropriate annotated syntax at the beginning of each source file. Copyright (c) [Year] [name of copyright holder] [Software Name] is licensed under Mulan PSL v2. You can use this software according to the terms and conditions of the Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2 THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details.

简介

Node.js环境的HTTP/HTTPS/HTTP2请求客户端。实现了http2的连接池、自动重连。基于连接池实现了HTTP/2协议的反向代理。 展开 收起
JavaScript
MulanPSL-2.0
取消

发行版 (20)

全部

贡献者

全部

近期动态

加载更多
不能加载更多了
JavaScript
1
https://gitee.com/daoio/gohttp.git
git@gitee.com:daoio/gohttp.git
daoio
gohttp
gohttp
master

搜索帮助