1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/guonaihong-gout

Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

Gout — это HTTP-клиент, написанный на языке Go. Он разработан для повышения эффективности работы.

Архитектура:

Иконка: изображение gout-ad.png, расположенное по адресу https://github.com/guonaihong/images/blob/master/gout/gout-v0.0.8.png?raw=true.

Функции:

  • Поддержка настройки GET/PUT/DELETE/PATH/HEAD/OPTIONS.
  • Настройка HTTP-заголовка (можно передавать struct, map, array, slice и другие типы).
  • Настройка параметров URL-запроса (можно передавать struct, map, array, slice, string и другие типы).
  • Кодирование JSON в тело запроса (можно передавать struct, map, string, []byte и другие типы).
  • Кодирование XML в тело запроса (можно передавать struct, string, []byte и другие типы).
  • Кодирование YAML в тело запроса (можно передавать struct, map, string, []byte и другие типы).
  • Кодирование protobuf в тело запроса (можно передавать только struct).
  • Поддержка form-data (можно передавать struct, map, array, slice и другие типы).
  • Поддержка x-www-form-urlencoded (можно передавать struct, map, array, slice и другие типы).
  • Поддержка io.Reader, uint/uint8/uint16...int/int8...string...[]byte...float32,float64 в теле запроса.
  • Разбор тела ответа JSON, XML, YAML в структуру (BindJSON/BindXML/BindYAML).
  • Разбор содержимого тела ответа в io.Writer, uint/uint8...int/int8...string...[]byte...float32,float64.
  • Анализ заголовка ответа в структуре.
  • Тестирование производительности интерфейса, возможность контролировать количество или время тестов, а также частоту тестирования.
  • Возможность повторных попыток с отсрочкой (retry-backoff), можно задать условия повторной попытки.
  • Отправка «голых» HTTP-пакетов данных.
  • Экспорт команды curl.
  • Передача пользовательского *http.Client.
  • Поддержка промежуточных программ запросов (https://github.com/antlabs/gout-middleware).
  • Поддержка промежуточных программ ответов ResponseUse.
  • Установка формата передачи данных chunked.
  • Проверка данных в заголовке и теле.
  • И многое другое.

Демонстрация:

Изображение: gif-файл gout-example.gif, расположенный по адресу https://raw.githubusercontent.com/guonaihong/images/master/gout/gout-example.gif.

Содержание:

  • Installation.
  • Example.
  • Quick start.
  • API Examples:
    • GET POST PUT DELETE PATH HEAD OPTIONS.
    • Query Parameters.
    • HTTP header:
      • установка заголовка запроса;
      • анализ заголовка ответа;
      • получение всех заголовков.
    • Data valid.
    • ResponseUse.
    • HTTP body:
      • body:
        • установка данных в тело HTTP-запроса;
        • анализ тела ответа в переменную.
      • JSON:
        • сериализация JSON в тело запроса;
        • разбор тела ответа HTTP в формате JSON.
      • YAML.
      • XML.
      • Form-data.
      • X-www-form-urlencoded.
      • Protobuf.
      • Callback.
      • Получение *http.Response.
      • Несколько функций привязки.
    • Установка времени ожидания запроса.
    • Proxy.
    • Socks5.
    • Cookie.
    • Basic auth.
    • Context:
      • отмена отправки запроса.
    • Unix socket.
    • HTTP2 doc.
    • Debug mode:
      • включение режима отладки;
      • отключение выделения цветом в режиме отладки;
      • пользовательский режим отладки;
      • информация трассировки;
      • сохранение в Writer;
      • сохранение в файл.
    • Benchmark:
      • тестирование определённое количество раз;
      • тестирование в течение определённого времени;
      • тестирование с фиксированной частотой;
      • настраиваемые функции тестирования.
    • Retry backoff:
      • указание условий повторной попытки, когда код HTTP равен определённому значению;
      • определение условий повторной попытки по умолчанию, если доступ к URL невозможен. Использование резервной копии. Установка
go get github.com/guonaihong/gout

Пример

В каталоге _example находятся примеры, которые можно запустить напрямую. Если вы не понимаете, как использовать пример, вы можете описать то, что вызывает у вас затруднения, и создать issue.

Запуск команды:

cd _example
# GOPROXY — это открытие go module прокси, можно быстрее загрузить модуль
# При первом запуске нужно добавить GOPROXY для загрузки модуля, если модули уже установлены, просто запустите go run 01-color-json.go
env GOPROXY=https://goproxy.cn go run 01-color-json.go

Быстрый старт

package main

import (
    "fmt"
    "github.com/guonaihong/gout"
    "time"
)

// Используется для анализа тела ответа сервера
type RspBody struct {
    ErrMsg  string `json:"errmsg"`
    ErrCode int    `json:"errcode"`
    Data    string `json:"data"`
}

// Используется для анализа заголовка ответа сервера
type RspHeader struct {
    Sid  string `header:"sid"`
    Time int    `header:"time"`
}

func main() {
    rsp := RspBody{}
    header := RspHeader{}

    //code := 0
    err := gout.

        // POST запрос
        POST("127.0.0.1:8080").

        // Открыть режим отладки
        Debug(true).

        // Установить строку запроса
        SetQuery(gout.H{"page": 10, "size": 10}).

        // Установить заголовок HTTP
        SetHeader(gout.H{"X-IP": "127.0.0.1", "sid": fmt.Sprintf("%x", time.Now().UnixNano())}).

        // SetJSON устанавливает тело HTTP в формате JSON
        // Есть аналогичные функции: BindJSON, BindYAML, BindXML, BindForm, BindWWWForm
        SetJSON(gout.H{"text": "gout"}).

        // BindJSON анализирует содержимое тела ответа
        // Аналогичные функции: BindBody, BindYAML, BindXML
        BindJSON(&rsp).

        // Анализировать заголовок ответа
        BindHeader(&header).
        // код HTTP
        // Code(&code).

        // Завершить функцию
        Do()

        // Проверить ошибку
    if err != nil {
        fmt.Printf("send fail:%s\n", err)
    }
}
/*
> POST /?page=10&size=10 HTTP/1.1
> Sid: 15d9b742ef32c130
> X-Ip: 127.0.0.1
> Content-Type: application/json
>

{
    "text": "gout"
}
*/

Примеры API

GET, POST, PUT, DELETE, PATH, HEAD, OPTIONS

package main

import (
    "github.com/guonaihong/gout"
)

func main() {
    url := "https://github.com"
    // Отправить GET запрос
    gout.GET(url).Do()

    // Отправить POST запрос
    gout.POST(url).Do()

    // Отправить PUT запрос
    gout.PUT(url).Do()

    // Отправить DELETE запрос
    gout.DELETE(url).Do()

    // Отправить PATH запрос
    gout.PATCH(url).Do()

    // Отправить HEAD запрос
    gout.HEAD(url).Do()

    // Отправить OPTIONS запрос
    gout.OPTIONS(url).Do()
}

Параметры запроса

SetQuery

package main

import (
    "fmt"
    "github.com/guonaihong/gout"
    "time"
)

func main() {
    err := gout.
        // Устанавливаем GET запрос и url, :8080/test.query — это 127.0.0.1:8080/test.query в сокращённом виде
        GET(":8080/test.query").
        // Включаем режим отладки
        Debug(true).
        // Устанавливаем строку запроса
        SetQuery(gout.H{
            "q1": "v1",
            "q2": 2,
            "q3": float32(3.14),
            "q4": 4.56,
            "q5": time.Now().Unix(),
            "q6": time.Now().UnixNano(),
            "q7": time.Now().Format("2006-01-02")}).
        // Заканчиваем функцию
        Do()
    if err != nil {
        fmt.Printf("%s\n", err)
        return
    }

}
/*
> GET /test.query?q1=v1&q2=2&q3=3.14&q4=4.56&q5=1574081600&q6=1574081600258009213&q7=2019-11-18 HTTP/1.1
>
< HTTP/1.1 200 OK
< Content-Length: 0
*/

SetQuery поддерживает больше типов данных

package main

import (
    "github.com/guonaihong/gout"
)

func main() {

    code := 0

    err := gout. ```
// Отправляем GET запрос :8080/testquery на 127.0.0.1:8080/testquery в краткой форме
GET(":8080/testquery").

// Устанавливаем строку запроса
SetQuery( /*см. ниже поддерживаемые случаи*/ ).

// Анализируем код HTTP, если не интересует ответ сервера, то эту функцию можно не устанавливать
Code(&code).
Do()
if err != nil {

}
}

/*
Поддерживаются следующие типы для SetQuery:
* string
* map[string]interface{} (можно использовать gout.H как псевдоним)
* struct
* array, slice (длина должна быть чётной)
*/

// 1. string
SetQuery("check_in=2019-06-18&check_out=2018-06-18")

// 2. gout.H или map[string]interface{}
SetQuery(gout.H{
    "check_in":"2019-06-18",
    "check_out":"2019-06-18",
})

// 3. struct
type testQuery struct {
    CheckIn string `query:checkin`
    CheckOut string `query:checkout`
}

SetQuery(&testQuery{CheckIn:2019-06-18, CheckOut:2019-06-18})

// 4. array or slice
// ?active=enable&action=drop
SetQuery([]string{"active", "enable", "action", "drop"})```

HTTP header

Установка заголовка GET запроса

package main

import (
    "fmt"
    "github.com/guonaihong/gout"
    "time"
)

func main() {
    err := gout.
        // Устанавливаем GET запрос и url, :8080/test.header — это 127.0.0.1:8080/test.header в краткой записи
        GET(":8080/test.header").
        // Включаем режим отладки
        Debug(true).
        // Устанавливаем заголовок HTTP
        SetHeader(gout.H{
            "h1": "v1",
            "h2": 2,
            "h3": float32(3.14),
            "h4": 4.56,
            "h5": time.Now().Unix(),
            "h6": time.Now().UnixNano(),
            "h7": time.Now().Format("2006-01-02")}).
        Do()
    if err != nil {
        fmt.Printf("%s\n", err)
        return
    }

}

/*
> GET /test.header HTTP/1.1
> H2: 2
> H3: 3.14
> H4: 4.56
> H5: 1574081686
> H6: 1574081686471347098
> H7: 2019-11-18
> H1: v1
>


< HTTP/1.1 200 OK
< Content-Length: 0
*/

Анализ заголовка ответа

package main

import (
    "fmt"
    "github.com/guonaihong/gout"
    "time"
)

// Аналогично анализу JSON, для анализа HTTP заголовка необходимо установить тег header
type rspHeader struct {
    Total int       `header:"total"`
    Sid   string    `header:"sid"`
    Time  time.Time `header:"time" time_format:"2006-01-02"`
}

func main() {

    rsp := rspHeader{}
    err := gout.
        // :8080/test.header — http://127.0.0.1:8080/test.header в краткой записи
        GET(":8080/test.header").
        // Включить режим отладки
        Debug(true).
        // Привязать заголовок запроса к структуре
        BindHeader(&rsp). 
        // Завершить функцию
        Do()
    if err != nil {
        fmt.Printf("%s\n", err)
        return
    }

    fmt.Printf("rsp header:\n%#v \nTime:%s\n", rsp, rsp.Time)
}

/*
> GET /test.header HTTP/1.1
>



< HTTP/1.1 200 OK
< Content-Length: 0
< Sid: 1234
< Time: 2019-11-18
< Total: 2048
*/
### SetHeader и BindHeader поддерживают больше типов
<details>
```go
package main

import (
    "fmt"
    "github.com/guonaihong/gout"
)

type testHeader struct {
    CheckIn  string `header:checkin`
    CheckOut string `header:checkout`
}

func main() {

    t := testHeader{}

    code := 0

    err := gout.
        GET(":8080/testquery").
        Code(&code).
        SetHeader( /*см. ниже поддерживаемый тип*/ ).
        BindHeader(&t).
        Do()
    if err != nil {
        fmt.Printf("fail:%s\n", err)
    }   
}
  • BindHeader поддерживает следующие типы: структура
// struct
type testHeader struct {
    CheckIn string `header:checkin`
    CheckOut string `header:checkout`
}
  • SetHeader поддерживает следующие типы:
/*
map[string]interface{}, можно использовать gout.H как псевдоним
struct
array, slice (длины должны быть чётными)
*/

// gout.H либо map[string]interface{}
SetHeader(gout.H{
    "check_in":"2019-06-18",
    "check_out":"2019-06-18",
})

// struct
type testHeader struct {
    CheckIn string `header:checkin`
    CheckOut string `header:checkout`
}

SetHeader(&testHeader{CheckIn:2019-06-18, CheckOut:2019-06-18})

// array или slice
// -H active:enable -H action:drop
SetHeader([]string{"active", "enable", "action", "drop"})
## Проверка данных Для проверки данных используется библиотека https://github.com/go-playground/validator, подробнее о синтаксисе можно узнать из документации. ```go import ( "fmt" "github.com/guonaihong/gout" )

type testValid struct {
Val string valid:"required"
}

func main() { tv := testValid{} err := gout. // Установить POST метод и URL POST(":8080/req/body"). // Включить режим отладки Debug(true). // Разобрать JSON

并且当需要的字段没有值时, 返回错误 BindJSON(&tv). //结�ончание функции Do()

if err != nil {
    fmt.Printf("%s\n", err)
    return
}

}


## responseUse 
response中间件,在Bind()之前执行。可以对response进行通用逻辑处理。
Если только нужна логика замыкания, можно использовать WithResponseMiddlerFunc, и не нужно создавать структуру, в следующем примере используются оба метода.
```go


import (
    "bytes"
    "encoding/json"
    "errors"
    "fmt"
    "github.com/gin-gonic/gin"
    middler "github.com/guonaihong/gout/interface"
    "io/ioutil"
    "log"
    "net/http"
    "time"
)

// response拦截器修改示例
type demoResponseMiddler struct{}

func (d *demoResponseMiddler) ModifyResponse(response *http.Response) error {
    // 修改responseBody。 Потому что возвращаемое значение, вероятно, будет иметь поля { code, data,msg}, надеемся провести унифицированную обработку
    //здесь хотим проверить код. Если не подходит, то возвращаем ошибку. В противном случае записываем содержимое data в body, чтобы при последующем BindJson можно было напрямую обработать бизнес
    all, err := ioutil.ReadAll(response.Body)
    если err != nil, {
        вернуть err
    }
    obj := make(map[string]interface{})
    err = json.Unmarshal(all, &obj)
    если err != nil, {
        вернуть err
    }
    code := obj["code"]
    msg := obj["msg"]
    data := obj["data"]

    // Go中json中的数字 после десериализации станут типом float64
    если float64(200) != code, {
        вернуть errors.New(fmt.Sprintf("запрос не удался, code %d msg %s", code, msg))
    } иначе {
        byt, _ := json.Marshal(&data)
        response.Body = ioutil.NopCloser(bytes.NewReader(byt))
        вернуть nil
    }
}
func demoResponse() *demoResponseMiddler {
    вернуть &demoResponseMiddler{}
}

func main() {
    go server()                        //запустить тестовый сервис
    time.Sleep(time.Millisecond * 500) //использовать время для ожидания синхронизации
    responseUseExample()
}

func responseUseExample() {
    //успешный запрос
    successRes := new(map[string]interface{})
    err := gout.GET(":8080/success").ResponseUse(
        demoResponse(),
        // обратите внимание на использование WithResponseMiddlerFunc здесь
        middler.WithResponseMiddlerFunc(func(response *http.Response) error {
            // Do your magic
            вернуть nil
        }),
    ).BindJSON(&successRes).Do()
    log.Printf("успешный запрос  -->   ответ %s  \n  err  %s \n ", successRes, err)

    //неудачный запрос
    failRes := new(map[string]interface{})
    err = gout.GET(":8080/fail").ResponseUse(demoResponse()).BindJSON(&failRes).Do()
    log.Printf("неудачный запрос  -->  ответ %s  \n  err  %s \n ", successRes, err)
}

type Result struct {
    Code int         `json:"code"`
    Msg  string      `json:"msg"`
    Data interface{} `json:"data"`
}
type Item struct {
    Id   string `json:"id"`
    Name string `json:"name"`
}

func server() {
    router := gin.New()
    router.GET("/success", func(c *gin.Context) {
        c.JSON(200, Result{200, "запрос выполнен успешно", Item{"001", "Чжан Сань"}})
    })
    router.GET("/fail", func(c *gin.Context) {
        c.JSON(200, Result{500, "ошибка запроса к базе данных", nil})
    })
    router.Run()
}

Перевод:

И далее, когда требуется значение поля, возвращается ошибка: BindJSON(&tv). //Завершение функции. Do().

Если err не равно nil, то: fmt.Printf("%s\n", err); return.

ResponseUse

Response — это промежуточное ПО, которое выполняется перед Bind(). Оно позволяет выполнять общую логику обработки ответа. Если вам нужна только логика закрытия, вы можете использовать WithResponseMiddlerFunc и не создавать структуру. В следующем примере используется оба метода.

Импорт:

"bytes",
"encoding/json",
"errors",
"fmt",
"github.com/gin-gonic/gin",
middler "github.com/guonaihong/gout/interface",
"io/ioutil",
"log",
"net/http",
"time",
```

**Пример модификации response-перехватчика:**

Тип demoResponseMiddler представляет собой пустую структуру.

Функция (d * demoResponseMiddler) ModifyResponse принимает ответ * http.Response в качестве аргумента и возвращает ошибку. Она изменяет responseBody, потому что возвращаемое значение может содержать поля {code, data, msg}. Мы надеемся выполнить унифицированную обработку. Здесь мы хотим проверить код, если он не подходит, мы возвращаем ошибку, иначе мы записываем содержимое данных в тело, чтобы мы могли напрямую обрабатывать бизнес при последующем BindJSON.

Все, err: = ioutil.ReadAll (response.Body), если err! = nil, вернуть err.
Obj: = make (map [string] interface {}), err = json.Unmarshal (all, & obj), если err! = nil, вернуть err.
Код: = obj ["код"], msg: = obj ["msg"], данные: = obj ["данные"].

В Go числа после десериализации становятся типом float64. Если float64 (200)! = код, верните errors.New (fmt.Sprintf ("запрос не выполнен, код % d msg % s", код, msg)). Иначе byt, _: = json.Marshal (& data), response.Body = ioutil.NopCloser (bytes.NewReader (byt)), вернуть nil.

DemoResponse: = & demoResponseMiddler возвращает * demoResponseMiddler.

Основная функция запускает тестовый сервер с помощью go server (), ждёт синхронизации с time.Sleep (time.Millisecond * 500), затем вызывает responseUseExample ().

ResponseUseExample выполняет успешный и неудачный запросы.

Успешный запрос: successRes: = new (map [строка] интерфейс {}), err: = gout.GET (": 8080 / успех"). ResponseUse (demoResponse (), middler.WithResponseMiddlerFunc (func (ответ * http.Response) ошибка {Do your magic, return nil}), BindJSON (& successRes), Do ()). Log.Printf ("успешный запрос -> ответ % s \n err % s \n", successRes, err).

Неудачный запрос: failRes: = new (map [строка] интерфейс {}), err: = gout.GET (": 8080 / сбой"). ResponseUse (demoResponse ()), BindJSON (& failRes), Do (). Log.Printf («неудачный запрос -> ответ % s \n err % s \n», successRes, err).

Структура результата содержит код int Msg string Data interface {}, структура элемента содержит Id string Name string.

Серверная функция создаёт маршрутизатор gin.New (), добавляет маршруты GET / success и GET / fail, которые возвращают результаты успешного и неудачного запросов соответственно. Затем запускается маршрутизатор с помощью router.Run (). **Текст запроса на русском языке:**

Использование различных методов отправки данных в запросах:
* использование структуры;
* x-www-form-urlencoded;
* protobuf;
* callback;
* get .Response;
* multiple binding functions;
* set request timeout;
* proxy;
* socks5.

**Основной язык текста запроса:** язык Go.

В запросе присутствуют фрагменты кода, которые не удалось перевести. Это связано с тем, что некоторые конструкции специфичны для языка программирования Go и не имеют прямых аналогов в русском языке. **benchConcurrent = 30**)

func main() {
    err := gout.
        POST(":8080").                     //давление на локальный порт 8080
        SetJSON(gout.H{"hello": "world"}). //установка содержимого запроса body
        Filter().                          //открытие фильтра
        Bench().                           //выбор функции bench
        Concurrent(benchConcurrent).       //количество одновременных запросов
        Durations(benchTime).              //время тестирования
        Do()

    if err != nil {
        fmt.Printf("%v\n", err)
    }
}

**benchmark-rate**

Следующий пример запускает 20 одновременных запросов. Для сервиса порта :8080 проводится тестирование с общим количеством запросов 3000, при этом каждую секунду отправляется 1000 запросов. Содержимое представляет собой структуру json:
```go
package main

import (
    "fmt"
    "github.com/guonaihong/gout"
)

const (
    benchNumber     = 3000
    benchConcurrent = 20
)

func main() {
    err := gout.
        POST(":8080").                     //давление на локальный порт 8080
        SetJSON(gout.H{"hello": "world"}). //установка содержимого запроса body
        Filter().                          //открытие фильтра
        Bench().                           //выбор функции bench
        Rate(1000).                        //1000 запросов в секунду
        Concurrent(benchConcurrent).       //количество одновременных запросов
        Number(benchNumber).               //количество запросов
        Do()

    if err != nil {
        fmt.Printf("%v\n", err)
    }
}

```

**Custom benchmark functions**

Пользовательские функции тестирования, создающие разные данные http-запроса для каждого теста:
```go
package main

import (
    "fmt"
    "github.com/google/uuid"
    "github.com/guonaihong/gout"
    "github.com/guonaihong/gout/filter"
    "sync/atomic"
)

func main() {
    i := int32(0)

    err := filter.NewBench().
        Concurrent(30). //запуск 30 горутин
        Number(30000).  //тестирование 30 000 раз
        Loop(func(c *gout.Context) error {

            // следующий код генерирует разные данные HTTP-запросов для каждого теста
            uid := uuid.New()  //создание uuid
            id := atomic.AddInt32(&i, 1) //генерация id, можно понять как ++i, потокобезопасная версия

            c.POST(":1234").SetJSON(gout.H{
                "sid": uid.String(),
                "appkey": fmt.Sprintf("ak:%d", id),
                "text":   fmt.Sprintf("test text :%d", id)})
            return nil

        }).Do()

    if err != nil {
        fmt.Printf("err = %v\n", err)
    }
}

```

**retry-backoff**

Функция retry использует алгоритм с колебаниями и экспоненциальным откатом [backoff](http://www.awsarchitectureblog.com/2015/03/backoff.html):
```go
package main

import (
    "fmt"
    "github.com/guonaihong/gout"
    "time"
)

func main() {
    err := gout.HEAD("127.0.0.1:8080").
        Debug(true).                      //включение режима отладки
        Filter().                         //открытие фильтра
        Retry().                          //включение функции повтора
        Attempt(5).                       //максимум 5 попыток
        WaitTime(500 * time.Millisecond). //основное время ожидания
        MaxWaitTime(3 * time.Second).     //максимальное время ожидания
        Do()

    if err != nil {
        fmt.Printf("err = %v\n", err)
    }
}

```

**retry conditions httpcode**

Указаны условия повтора, в этом примере сервер возвращает статус 209, после чего происходит повтор:
[полный код](_example/19c-retry-httpcode.go)
``` go
package main

import (
    "fmt"
    "github.com/guonaihong/gout"
    "github.com/guonaihong/gout/filter"
    "time"
)

func useRetryFuncCode() {
    s := ""
    err := gout.GET(":8080/code").Debug(true).BindBody(&s).F().
        Retry().Attempt(3).WaitTime(time.Millisecond * 10).MaxWaitTime(time.Millisecond * 50).
        Func(func(c *gout.Context) error {
            if c.Error != nil || c.Code == 209 {
                return filter.ErrRetry
            }

            return nil

        }).Do()

    fmt.Printf("err = %v\n", err)
}
```

**retry conditions backupurl**

Заданы условия повтора, здесь по умолчанию URL недоступен, используется резервный URL для доступа:
[полный код](_example/19b-retry-customize-backup.go)
```go
package main

import (
    "fmt"
    "github.com/guonaihong/gout"
    "github.com/guonaihong/gout/core"
    "github.com/guonaihong/gout/filter"
    "time"
)
func useRetryFunc() {
    // получение неиспользуемого порта
    port := core.GetNoPortExists()
    s := ""

    err := gout.GET(":" + port).Debug(true).BindBody(&s).F().
        Retry().Attempt(3).WaitTime(time.Millisecond * 10).MaxWaitTime(time.Millisecond * 50).
        Func(func(c *gout.Context) error {
            if c.Error != nil {
                c.SetHost(":1234") //должен быть существующий порт
                return filter.ErrRetry
            }
            return nil

        }).Do()
    fmt.Printf("err = %v\n", err)
}
``` ```
package main

import (
    "fmt"
    "github.com/guonaihong/gout"
)

func main() {
    s := `POST /colorjson HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Go-http-client/1.1
Content-Length: 97
Content-Type: application/json
Accept-Encoding: gzip

{"array":["foo","bar","baz"],"bool":false,"null":null,"num":100,"obj":{"a":1,"b":2},"str":"foo"}`
    err := gout.NewImport().RawText(s).Debug(true).SetHost(":1234").Do()
    if err != nil {
        fmt.Printf("err = %s\n", err)
        return
    }
}
```

```
package main

import (
    "fmt"
    "github.com/guonaihong/gout"
)

func main() {
    // 1.formdata
    err := gout.GET(":1234").
        SetForm(gout.A{"text", "good", "mode", "A", "voice", gout.FormFile("./t8.go")}).
        Export().Curl().Do()
    // output:
    // curl -X GET -F "text=good" -F "mode=A" -F "voice=@./voice" "http://127.0.0.1:1234"

    // 2.json body
    err = gout.GET(":1234").
        SetJSON(gout.H{"key1": "val1", "key2": "val2"}).
        Export().Curl().Do()
    // output:
    // curl -X GET -H "Content-Type:application/json" -d "{\"key1\":\"val1\",\"key2\":\"val2\"}" "http://127.0.0.1:1234"

    fmt.Printf("%v\n", err)
}
```

```
package main

import (
    "fmt"
    "github.com/guonaihong/gout"
)

func main() {
    // 1.formdata
    err := gout.GET(":1234").
        SetForm(gout.A{"text", "good", "mode", "A", "voice", gout.FormFile("./t8.go")}).
        Export().Curl().GenAndSend().Do()
    // output:
    // curl -X GET -F "text=good" -F "mode=A" -F "voice=@./voice" "http://127.0.0.1:1234"

    // 2.json body
    err = gout.GET(":1234").
        SetJSON(gout.H{"key1": "val1", "key2": "val2"}).
        Export().Curl().GenAndSend().Do()
    // output:
    // curl -X GET -H "Content-Type:application/json" -d "{\"key1\":\"val1\",\"key2\":\"val2\"}" "http://127.0.0.1:1234"

    fmt.Printf("%v\n", err)
}
```

```
package main

import (
    "fmt"
    "net/http"

    "github.com/guonaihong/gout"
)

func main() {

    c := &http.Client{} //http.Client里面有fd连接池,如果对这块优化不是太了解,只使用一个实例就行
    err := gout.New(c). // New接口可传入http.Client对象
                GET("www.qq.com").
                Debug(true).
                Do()

    if err != nil {
        fmt.Printf("err = %s\n", err)
        return
    }
}
```

```
package main

import (
        "fmt"

        "github.com/guonaihong/gout"
)

func main() {
        err := gout.POST(":8080").
                Chunked().
                SetBody("11111111111").
                Do()
        if err != nil {
                fmt.Printf("err :%v\n", err)
        }   
}
// 使用nc 起一个tcp服务, 使用上面的代码发起数据观察下结果
// nc -l 8080
```

```
package main

import (
    "fmt"

    "github.com/guonaihong/gout"
)

func main() {
    err := gout.POST("/colorjson").
            Chunked().
            SetBody(`{"array":["foo","bar","baz"],"bool":false,"null":null,"num":100,"obj":{"a":1,"b":2},"str":"foo"}`).
            Do()
    if err != nil {
        fmt.Printf("err :%v\n", err)
        return
    }
}
```

```
import (
    "github.com/guonaihong/gout"
)

func main() {
    globalWithOpt := gout.NewWithOpt(gout.WithInsecureSkipVerify())
    err := globalWithOpt.GET("url").Do()
    if err != nil {
        fmt.Printf("err = %v\n" ,err)
        return
    }
}
```

```
import (
    "github.com/guonaihong/gout"
)

func main() {
    globalWithOpt := gout.NewWithOpt(gout.WithClose3xxJump())
    err := globalWithOpt.GET("url").Do()
    if err != nil {
        fmt.Printf("err = %v\n" ,err)
        return
    }
}
```

```
import (
    "github.com/guonaihong/gout"
)

func main() {
    globalWithOpt := gout.NewWithOpt(gout.WithTimeout())
    err := globalWithOpt.GET("url").Do()
    if err != nil {
        fmt.Printf("err = %v\n" ,err)
        return
    }
}
``` **err := globalWithOpt.GET("url").Do()**

    if err != nil {
        fmt.Printf("err = %v\n", err)
        return
    }
}  

# Глобальная конфигурация  
## Установка таймаута  

Устанавливает глобальное время ожидания. Это может упростить некоторый код. При использовании глобальной конфигурации по умолчанию вы уже знаете о некоторых недостатках, которые она может вызвать.  
```go  

package main  

import (  
    "fmt"  
    "github.com/guonaihong/gout"  
    "time"  
)  

func main() {  
    gout.SetTimeout(time.Second * 1)  
    err := gout.GET("www.baidu.com").Do()  
    if err != nil {  
        fmt.Printf("ошибка: %v\n")  
    }  
}  
```  
## Включение отладки  

Включает глобальный переключатель отладки.  
```go  
package main  

import (  
    "fmt"  

    "github.com/guonaihong/gout"  
)  

func main() {  
    gout.SetDebug(true)  
    err := gout.GET(":8080/colorjson").Do()  
    if err != nil {  
        fmt.Printf("ошибка: %v\n")  
    }  
}  
```

# Уникальные функции  
## Пересылка данных gin  

Gout был разработан с учётом возможности совместной работы с gin. Ниже показано, как легко использовать gout для пересылки данных, связанных с gin.  
```go  
package main  

import (  
    "github.com/gin-gonic/gin"  
    "github.com/guonaihong/gout"  
)  

type testQuery struct {  
    Size int    `query:"size" form:"size"` // tag запроса — это то, что нужно gout для установки строки запроса  
    Page int    `query:"page" form:"page"`  
    Ak   string `query:"ak" form:"ak"`  
}  

// Следующий узел сервера  
func nextSever() {  
    r := gin.Default()  

    r.GET("/query", func(c *gin.Context) {  
        q := testQuery{}  
        err := c.ShouldBindQuery(&q)  
        if err != nil {  
            return  
        }  
        c.JSON(200, q)  
    })  
    r.Run(":1234")  
}  

func main() {  
    go nextSever()  
    r := gin.Default()  

    // Демонстрация привязки строки запроса gin к узлу nextServer  
    r.GET("/query", func(c *gin.Context) {  
        q := testQuery{}  
        // Привязка строки запроса  
        err := c.ShouldBindQuery(&q)  
        if err != nil {  
            return  
        }  

        // Разработка пересылки, повторное использование переменной q структуры gin  
        code := 0 // код HTTP  
        err = gout.  
            // Отправка запроса GET  
            GET("127.0.0.1:1234/query").  
            // Установка строки запроса  
            SetQuery(q).  
            // Интересуемся возвращаемым статусом HTTP-сервера, устанавливаем эту функцию  
            Code(&code).  
            Do()  
        if err != nil || code != 200 { /* todo Need to handle errors here */  
        }  
        c.JSON(200, q)  
    })  

    r.Run()  
}  

// HTTP-клиент  
// curl '127.0.0.1:8080/query?size=10&page=20&ak=test'  
```

# Часто задаваемые вопросы  

## Как обстоят дела с производительностью gout benchmark?  

Ниже приведён сравнительный анализ производительности с apache ab [_example/16d-benchmark-vs-ab.go_](_example/16d-benchmark-vs-ab.go).

Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

Создание самой удобной HTTP-клиентской библиотеки для GitHub, чтобы вы почувствовали, что жизнь уже удалась, и было ещё веселее. https://github.com/guonaihong/gout Развернуть Свернуть
Apache-2.0
Отмена

Обновления

Пока нет обновлений

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/guonaihong-gout.git
git@api.gitlife.ru:oschina-mirror/guonaihong-gout.git
oschina-mirror
guonaihong-gout
guonaihong-gout
master