api_request.go
package http_api
import (
"crypto/tls"
"encoding/json"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/url"
"strconv"
"strings"
"time"
)
type deadlinedConn struct {
Timeout time.Duration
net.Conn
}
func (c *deadlinedConn) Read(b []byte) (n int, err error) {
return c.Conn.Read(b)
}
func (c *deadlinedConn) Write(b []byte) (n int, err error) {
return c.Conn.Write(b)
}
// A custom http.Transport with support for deadline timeouts
func NewDeadlineTransport(connectTimeout time.Duration, requestTimeout time.Duration) *http.Transport {
transport := &http.Transport{
Dial: func(netw, addr string) (net.Conn, error) {
c, err := net.DialTimeout(netw, addr, connectTimeout)
if err != nil {
return nil, err
}
return &deadlinedConn{connectTimeout, c}, nil
},
ResponseHeaderTimeout: requestTimeout,
}
return transport
}
type Client struct {
c *http.Client
}
func NewClient(tlsConfig *tls.Config, connectTimeout time.Duration, requestTimeout time.Duration) *Client {
transport := NewDeadlineTransport(connectTimeout, requestTimeout)
transport.TLSClientConfig = tlsConfig
return &Client{
c: &http.Client{
Transport: transport,
Timeout: requestTimeout,
},
}
}
// NegotiateV1 is a helper function to perform a v1 HTTP request
// and fallback to parsing the old backwards-compatible response format
// storing the result in the value pointed to by v.
//
// TODO: deprecated, remove in 1.0 (replace calls with GETV1)
func (c *Client) NegotiateV1(endpoint string, v interface{}) error {
retry:
req, err := http.NewRequest("GET", endpoint, nil)
if err != nil {
return err
}
req.Header.Add("Accept", "application/vnd.nsq; version=1.0")
resp, err := c.c.Do(req)
if err != nil {
return err
}
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return err
}
if resp.StatusCode != 200 {
if resp.StatusCode == 403 && !strings.HasPrefix(endpoint, "https") {
endpoint, err = httpsEndpoint(endpoint, body)
if err != nil {
return err
}
goto retry
}
return fmt.Errorf("got response %s %q", resp.Status, body)
}
if len(body) == 0 {
body = []byte("{}")
}
// unwrap pre-1.0 api response
if resp.Header.Get("X-NSQ-Content-Type") != "nsq; version=1.0" {
var u struct {
StatusCode int64 `json:"status_code"`
Data json.RawMessage `json:"data"`
}
err := json.Unmarshal(body, u)
if err != nil {
return err
}
if u.StatusCode != 200 {
return fmt.Errorf("got 200 response, but api status code of %d", u.StatusCode)
}
body = u.Data
}
return json.Unmarshal(body, v)
}
// GETV1 is a helper function to perform a V1 HTTP request
// and parse our NSQ daemon's expected response format, with deadlines.
func (c *Client) GETV1(endpoint string, v interface{}) error {
retry:
req, err := http.NewRequest("GET", endpoint, nil)
if err != nil {
return err
}
req.Header.Add("Accept", "application/vnd.nsq; version=1.0")
resp, err := c.c.Do(req)
if err != nil {
return err
}
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return err
}
if resp.StatusCode != 200 {
if resp.StatusCode == 403 && !strings.HasPrefix(endpoint, "https") {
endpoint, err = httpsEndpoint(endpoint, body)
if err != nil {
return err
}
goto retry
}
return fmt.Errorf("got response %s %q", resp.Status, body)
}
err = json.Unmarshal(body, &v)
if err != nil {
return err
}
return nil
}
// PostV1 is a helper function to perform a V1 HTTP request
// and parse our NSQ daemon's expected response format, with deadlines.
func (c *Client) POSTV1(endpoint string) error {
retry:
req, err := http.NewRequest("POST", endpoint, nil)
if err != nil {
return err
}
req.Header.Add("Accept", "application/vnd.nsq; version=1.0")
resp, err := c.c.Do(req)
if err != nil {
return err
}
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return err
}
if resp.StatusCode != 200 {
if resp.StatusCode == 403 && !strings.HasPrefix(endpoint, "https") {
endpoint, err = httpsEndpoint(endpoint, body)
if err != nil {
return err
}
goto retry
}
return fmt.Errorf("got response %s %q", resp.Status, body)
}
return nil
}
func httpsEndpoint(endpoint string, body []byte) (string, error) {
var forbiddenResp struct {
HTTPSPort int `json:"https_port"`
}
err := json.Unmarshal(body, &forbiddenResp)
if err != nil {
return "", err
}
u, err := url.Parse(endpoint)
if err != nil {
return "", err
}
host, _, err := net.SplitHostPort(u.Host)
if err != nil {
return "", err
}
u.Scheme = "https"
u.Host = net.JoinHostPort(host, strconv.Itoa(forbiddenResp.HTTPSPort))
return u.String(), nil
}
api_request.go的更多相关文章
- 储物柜soket通信协议和中间件实现技术细节
一.中间件程序的职责: 1)对柜机提供soket长连接的服务器端,就是soket server.可提供上万的客户端同时连接.用来实时响应控制请求,中间件必须随时知道某个柜机的在线状态,外部请求时才能判 ...
- 突破短板,传统桌面程序 使用webapi 扩展迎合web和移动端融合的需求
传统桌面程序不能完全被web和移动端替代,但是需要改造.这里要说的是巧用webapi把以前用dll和com组件,ocx等方式做接口,做分布式开发的方式,改成restful 风格api的方式实现跨平台, ...
- PHP API 框架开发的学习
基于互联网的应用正变得越来越普及,在这个过程中,有更多的站点将自身的资源开放给开发者来调用.对外提供的API 调用使得站点之间的内容关联性更强,同时这些开放的平台也为用户.开发者和中小网站带来了更大的 ...
- jQuery里面ajax请求的封装
为了避免ajax漫天飞,我们需要对jQuery的代码进行封装,封装代码: function api_request(name, params, cb, scope, async, el) { if ( ...
- Python 基于request库的get,post,delete,封装
# coding=utf-8 import json import requests class TestApi(object): """ /* @param: @ses ...
- 听说PHP的生成器yield处理大量数据杠杠的
官方解释yield yield生成器是php5.5之后出现的,官方文档这样解释:yield提供了一种更容易的方法来实现简单的迭代对象,相比较定义类实现 Iterator 接口的方式,性能开销和复杂性大 ...
- 如何使用PHP的生成器yield处理大量数据业务
官方解释yield yield生成器是php5.5之后出现的,官方文档这样解释:yield提供了一种更容易的方法来实现简单的迭代对象,相比较定义类实现 Iterator 接口的方式,性能开销和复杂性大 ...
- 20191011-构建我们公司自己的自动化接口测试框架-testrun最重要的模块
testrun模块呢就是最终自动化测试入口,调用前面封装的各个模块主要流程是: 1. 获取测试集种待执行的测试用例 2. 处理测试用例获取的数据,包括转换数据格式,处理数据的中的关联等 3. 处理完数 ...
- 20191011-构建我们公司自己的自动化接口测试框架-Util的getTestSuite模块
getTestSuite主要是用于在testData里面获取测试集以及对应的测试数据,包括2个主要的方法,一个是获取测试集,一个是获取测试集里面要执行的测试用例 获取测试集方法: from Util. ...
随机推荐
- 我应该跟libuv说声对不起,我错怪了libuv(转)
一开始,我得向Libuv库和Libuv库开发者以及相关粉丝们道一个歉,对不起,我错怪你们了.深深感到自己的无知,是多么羞愧的事情!! 事情的经过是这样的. 原先按照公司要求,我在开发Win ...
- MOOS学习笔记3——命令行
MOOS学习笔记3--命令行 例程 /** * @code A simple example showing how to use a comms client问问怎么样 */ #include &q ...
- VueJs(8)---组件(注册组件)
组件(注册组件) 一.介绍 组件系统是Vue.js其中一个重要的概念,它提供了一种抽象,让我们可以使用独立可复用的小组件来构建大型应用,任意类型的应用界面都可以抽象为一个组件树 那么什么是组件呢? 组 ...
- List非0连续片段的索引
import pandas as pd import numpy as np l = [0, 11, 23, 33, 0, 0, 0, 76, 0, 41, 68] df = pd.DataFrame ...
- jjava Date格式是 May 07 17:44:06 CST 2018,怎么插入数据库中的timestamp格式中
首先 我来记录下错误 死在时间格式转换错误手里了 大致就是时间格式转化失败 java代码中的May 07 17:44:06 CST 2018 是这个格式转换为 数据库的 yyyy-MM-dd HH: ...
- 8人/天,小记一次 JAVA(APP后台) 项目改造 .NET 过程(后台代码已完整开源于 Github)
Github: https://github.com/iccb1013/Jade.Net 我们只消耗了8人/天的时间,完成了全部工作,基于我们 Jade.Net 的开源后台代码,任何小规模的后台管理系 ...
- 代码审计之SQL注入:BlueCMSv1.6 sp1
Preface 这是一篇纪录关于BlueCMSv1.6 sp1两个SQL注入的审计过程,原文来自代码审计之SQL注入:BlueCMSv1.6 sp1 ,主要纪录一下个人在参考博文复现这两个漏洞经过. ...
- JBOSSAS 5.x/6.x 反序列化命令执行漏洞(CVE-2017-12149)
本文主要记录一下JBOSSAS 5.x/6.x 反序列化命令执行漏洞的测试过程 仅供学习 文中利用到漏洞环境由phith0n维护: JBoss 5.x/6.x 反序列化漏洞(CVE-2017-1214 ...
- centos/linux 禁止root用户远程登录
注意:在禁止root等前要建立一个用户用来远程登录,否则退出后无法通过远程登录服务器. 编辑 /etc/ssh/sshd_config 文件 更改参数 PermitRootLogin yes 为 Pe ...
- Linux 命令行输入
这几天刚刚接触到Linux,在windows上安装的VMWare虚拟机,Centos7.安装什么都是贾爷和办公室的同事帮忙搞定的. 在虚拟机界面,按快捷键Ctrl+Alt+Enter,可以全屏显示Li ...