request

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 2, 2019 License: MIT Imports: 8 Imported by: 0

README

Request Build Status Go Report Card GoDoc

An opinionated but extremely easy to use HTTP request client for Go to make JSON request and retrieve the results

Description

With this request package you just need to define the structs that correspond to the JSON request and response body. Together with the parameters like URL, method and headers you can directly execute a request with Do. If the request body is not of type io.Reader already it will be encoded as JSON. Also the response will be decoded back into the struct you provided for the result. Request and response body are optional which means they can be nil.
If the request could be made but the response status code was not 2xx an error of the type HTTPError from the package httperrors will be returned.

Example

import "github.com/fastbill/go-request"

type Input struct {
	RequestValue string `json:"requestValue"`
}

type Output struct {
	ResponseValue string `json:"responseValue"`
}

params := request.Params{
    URL:    "https://example.com",
    Method: "POST",
    Headers: map[string]string{"my-header":"value", "another-header":"value2"},
    Body:   Input{RequestValue: "someValueIn"},
    Query: map[string]string{"key": "value"},
}

result := &Output{}
err := request.Do(params, result)

Convenience wrappers

err := request.Get("http://example.com", result)

err := request.Post("http://example.com", Input{RequestValue: "someValueIn"}, result)

Defaults

  • All 2xx response codes are treated as success, all other codes lead to an error being returned
  • If an HTTPError is returned it contains the response body as message if there was one
  • The request package takes care of closing the response body after sending the request
  • The http client does not follow redirects
  • The http client timeout is set to 30 seconds
  • Accept and Content-Type request header are set to application/json and can be overwritten via the Headers parameter

Streaming

The package allows the request body (Body property of Params) to be of type io.Reader. That way you can pass on request bodies to other services without parsing them.

Why?

To understand why this package was created have a look at the code that would be the native equivalent of the code shown in the example above.

import (
	"bytes"
	"encoding/json"
	"net/http"
	"time"
)

type Input struct {
	RequestValue string `json:"requestValue"`
}

type Output struct {
	ResponseValue string `json:"responseValue"`
}

buf := &bytes.Buffer{}
err := json.NewEncoder(buf).Encode(&Input{RequestValue: "someValueIn"})
if err != nil {
    return err
}

req, err := http.NewRequest("POST", url, buf)
if err != nil {
    return err
}

req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
req.Header.Set("my-header", "value")
req.Header.Set("another-header", "value2")

q := req.URL.Query()
q.Add("key", "value")
req.URL.RawQuery = q.Encode()

client := &http.Client{
    Timeout: 30 * time.Second,
    CheckRedirect: func(req *http.Request, via []*http.Request) error {
        return http.ErrUseLastResponse
    },
}

res, err := client.Do(req)
if err != nil {
    return err
}
defer func() {
    res.Body.Close()
}()

result := &Output{}
err = json.NewDecoder(res.Body).Decode(result)

This shows the request package saves a lot of boilerplate code. instead of around 35 lines we just write the 9 lines shown in the example. That way the code is much easier to read and maintain.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Do

func Do(params Params, responseBody interface{}) (returnErr error)

Do executes the request as specified in the request params The response body will be parsed into the provided struct

Example
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	body, _ := ioutil.ReadAll(r.Body)
	fmt.Println(string(body))
	w.Write([]byte(`{"responseValue":"someValueOut"}`))
}))
defer ts.Close()

params := Params{
	URL:    ts.URL,
	Method: "POST",
	Body:   Input{RequestValue: "someValueIn"},
}

result := &Output{}
err := Do(params, result)

fmt.Println(result.ResponseValue, err)
Output:

{"requestValue":"someValueIn"}

someValueOut <nil>

func Get

func Get(url string, responseBody interface{}) error

Get is a convience wrapper for "Do" to execute GET requests

func GetClient

func GetClient() *http.Client

GetClient returns an http client that does not follow redirects and has a timeout of defaultTimeout.

func Post

func Post(url string, requestBody interface{}, responseBody interface{}) error

Post is a convience wrapper for "Do" to execute POST requests

Types

type Params

type Params struct {
	Method  string
	URL     string
	Headers map[string]string
	Body    interface{}
	Query   map[string]string
	Timeout time.Duration
}

Params holds all information necessary to set up the request instance.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL