rest

package
v0.0.0-...-3c4673a Latest Latest
Warning

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

Go to latest
Published: Nov 12, 2021 License: MIT Imports: 21 Imported by: 0

Documentation

Overview

Package rest is an extremely simple to use, lightweight, yet powerful REST Client.

Motivation

The Go http standard library is a great library, but it might sometimes be a bit too low level to use, and it doesn't offer features like fork-join requests for better performance, response caching based on headers, and the possibility to mockup responses.

Features and Roadmap

v0.1

  • GET, POST, PUT, PATCH, DELETE, HEAD & OPTIONS HTTP verbs
  • Dead simple, synchronous requests
  • Automatic caching of transport object and hosts connections
  • Response Caching, based on response headers (cache-control, last-modified, etag, expires)
  • Local caching strategies: TTL, LRU & Max Byte Size.
  • Mockups!
  • Fork-Join request pattern, for sending many requests concurrently, getting better client perfomance.
  • Async request pattern.
  • Request Body can be `string`, `[]byte`, `struct` & `map`
  • Automatic marshal and unmarshal for `JSON` and `XML` Content-Type. Default JSON.
  • Full access to http.Response object.

v0.2

  • Retries
  • BasicAuth
  • UserAgent

v0.3

v0.4

  • Custom Root Certificates and Client Certificates
  • Testing +95%

v0.5

  • Plugable external caches like Memcached

Caching

Caching is done by two strategies working together: Time To Live (TTL) and Least Recently Used (LRU). Objects are inserted in the cache based on Response Headers. You can establish a maximum Memory Size for the cache and objects are flushed based on time expiration (TTL) or by hitting the maximum memory limit. In the last case, least accessed objects will be removed first.

Examples

Installation

go get github.com/go-loco/restful/rest

Importing

import "github.com/go-loco/restful/rest"

Simple GET

resp := rest.Get("https://api.restfulsite.com/resource")

Simple POST

// Using a `string` as body
resp := rest.Post("https://api.restfulsite.com/resource", "Body")

Simple POST, with Struct Body

type User struct {
  Id   int    `json:"id"`
  Name string `json:"name"`
}

body := new(User)
body.Id = 1
body.Name = "Hernan"

// body will be marshall as JSON
resp := rest.Post("https://api.restfulsite.com/resource/1", body)
fmt.Println(resp)

Fork Join

ForkJoin let you **fork** requests, and **wait** until all of them have return.

Concurrent has methods for Get, Post, Put, Patch, Delete, Head & Options, with the almost the same API as the synchronous methods. The difference is that these methods return a FutureResponse, which holds a pointer to Response. Response inside FutureResponse is nil until request has finished.

var f [3]*rest.FutureResponse

// ForkJoin will send all requests concurrently
// and will wait until all requests have their correspondent responses
rest.ForkJoin(func(c *rest.Concurrent) {
  f[0] = c.Get("https://api.restfulsite.com/resource/1")
  f[1] = c.Get("https://api.restfulsite.com/resource/2")
  f[2] = c.Get("https://api.restfulsite.com/resource/3")
 })

for i := range f {
  if f[i].Response().StatusCode == http.StatusOK {
    fmt.Println(f[i].Response())
  }
}

Async

Async let you make Restful requests in an **asynchronous** way, without blocking the go routine calling the Async function.

Whenever the Response is ready, the **f** function will be called back.

// This won't be blocked.
rest.AsyncGet("https://api.restfulsite.com/user", func(r *rest.Response) {
  if r.StatusCode == http.StatusOK {
    fmt.Println(r)
  }
})

// This will be printed first.
fmt.Println("print first")

Defaults * Headers: keep-alive, Cache-Control: no-cache * Timeout: 2 seconds * ContentType: JSON (for body requests in POST, PUT and PATCH) * Cache: enable * Cache Size: 1GB * Idle Connections Per Host: 2 (the default of http.net package) * HTTP/2: automatic with Go 1.6 * Gzip: automatic support for gzip responses

RequestBuilder

RequestBuilder gives you the power to go beyond defaults. It is possible to set up headers, timeout, baseURL, proxy, contentType, not to use cache, directly disabling timeout (in an explicit way), and setting max idle connections.

headers := make(http.Header)
headers.Add("myHeader", "myValue")

var rb = rest.RequestBuilder{
  Headers:             headers,
  Timeout:             200 * time.Millisecond,
  BaseURL:             "https://baseURL",
  Proxy:               "http://myproxy",
  ContentType:         rest.JSON,
  DisableCache:        false,
  DisableTimeout:      false,
  MaxIdleConnsPerHost: 10,
}

resp := rb.Get("/mypath")

Mockups

When using mockups, all requests will be sent to the mockup server. To activate the mockup *environment* you have two ways: using the flag -mock

go test -mock

Or by programmatically starting the mockup server

StartMockupServer()

An example

myURL := "http://mytest.com/foo"

myHeaders := make(http.Header)
myHeaders.Add("Hello", "world")

mock := rest.Mock{
  URL:          myURL,
	HTTPMethod:   http.MethodGet,
	ReqHeaders:   myHeaders,
	RespHTTPCode: http.StatusOK,
	RespBody:     "foo",
}

rest.AddMockups(&mock)

v := rest.Get(myURL)

Index

Constants

View Source
const MOCK_NOT_FOUND_ERROR string = "MockUp nil!"

Variables

View Source
var DefaultConnectTimeout = 1500 * time.Millisecond
View Source
var DefaultMaxIdleConnsPerHost = 2

DefaultMaxIdleConnsPerHost is the default maxium idle connections to have per Host for all clients, that use *any* RequestBuilder that don't set a CustomPool

View Source
var DefaultTimeout = 500 * time.Millisecond

DefaultTimeout is the default timeout for all clients. DefaultConnectTimeout is the time it takes to make a connection Type: time.Duration

View Source
var MaxCacheSize = 1 * GB

MaxCacheSize is the Maxium Byte Size to be hold by the ResourceCache Default is 1 GigaByte Type: rest.ByteSize

Functions

func AddMockups

func AddMockups(mocks ...*Mock) error

AddMockups ...

func AsyncDelete

func AsyncDelete(url string, f func(*Response))

AsyncDelete is the *asynchronous* option for DELETE. The go routine calling AsyncDelete(), will not be blocked.

Whenever the Response is ready, the *f* function will be called back.

AsyncDelete uses the DefaultBuilder

func AsyncGet

func AsyncGet(url string, f func(*Response))

AsyncGet is the *asynchronous* option for GET. The go routine calling AsyncGet(), will not be blocked.

Whenever the Response is ready, the *f* function will be called back.

AsyncGet uses the DefaultBuilder

func AsyncHead

func AsyncHead(url string, f func(*Response))

AsyncHead is the *asynchronous* option for HEAD. The go routine calling AsyncHead(), will not be blocked.

Whenever the Response is ready, the *f* function will be called back.

AsyncHead uses the DefaultBuilder

func AsyncOptions

func AsyncOptions(url string, f func(*Response))

AsyncOptions is the *asynchronous* option for OPTIONS. The go routine calling AsyncOptions(), will not be blocked.

Whenever the Response is ready, the *f* function will be called back.

AsyncOptions uses the DefaultBuilder

func AsyncPatch

func AsyncPatch(url string, body interface{}, f func(*Response))

AsyncPatch is the *asynchronous* option for PATCH. The go routine calling AsyncPatch(), will not be blocked.

Whenever the Response is ready, the *f* function will be called back.

AsyncPatch uses the DefaultBuilder

func AsyncPost

func AsyncPost(url string, body interface{}, f func(*Response))

AsyncPost is the *asynchronous* option for POST. The go routine calling AsyncPost(), will not be blocked.

Whenever the Response is ready, the *f* function will be called back.

AsyncPost uses the DefaultBuilder

func AsyncPut

func AsyncPut(url string, body interface{}, f func(*Response))

AsyncPut is the *asynchronous* option for PUT. The go routine calling AsyncPut(), will not be blocked.

Whenever the Response is ready, the *f* function will be called back.

AsyncPut uses the DefaultBuilder

func FlushMockups

func FlushMockups()

FlushMockups ...

func ForkJoin

func ForkJoin(f func(*Concurrent))

ForkJoin let you *fork* requests, and *wait* until all of them have return.

Concurrent has methods for Get, Post, Put, Patch, Delete, Head & Options, with the almost the same API as the synchronous methods. The difference is that these methods return a FutureResponse, which holds a pointer to Response. Response inside FutureResponse is nil until request has finished.

var futureA, futureB *rest.FutureResponse

rest.ForkJoin(func(c *rest.Concurrent){
	futureA = c.Get("/url/1")
	futureB = c.Get("/url/2")
})

fmt.Println(futureA.Response())
fmt.Println(futureB.Response())

AsyncOptions uses the DefaultBuilder

func StartMockupServer

func StartMockupServer()

StartMockupServer sets the enviroment to send all client requests to the mockup server.

func StopMockupServer

func StopMockupServer()

StopMockupServer stop sending requests to the mockup server

Types

type BasicAuth

type BasicAuth struct {
	UserName string
	Password string
}

BasicAuth gives the possibility to set UserName and Password for a given RequestBuilder. Basic Auth is used by some APIs

type ByteSize

type ByteSize int64

ByteSize is a helper for configuring MaxCacheSize

const (

	// KB = KiloBytes
	KB ByteSize = 1 << (10 * iota)

	// MB = MegaBytes
	MB

	// GB = GigaBytes
	GB
)

type Concurrent

type Concurrent struct {
	// contains filtered or unexported fields
}

Concurrent has methods for Get, Post, Put, Patch, Delete, Head & Options, with the almost the same API as the synchronous methods. The difference is that these methods return a FutureResponse, which holds a pointer to Response. Response inside FutureResponse is nil until the request has finished.

rest.ForkJoin(func(c *rest.Concurrent){
	futureA = c.Get("/url/1")
	futureB = c.Get("/url/2")
})

The difference is that Concurrent methods returns a FutureResponse, instead of a Resonse

func (*Concurrent) Delete

func (c *Concurrent) Delete(url string) *FutureResponse

Delete issues a DELETE HTTP verb to the specified URL, concurrently with any other concurrent requests that may be called.

In Restful, DELETE is used to "delete" a resource. Client should expect a response status code of of 200(OK), 404(Not Found), or 400(Bad Request).

func (*Concurrent) Get

func (c *Concurrent) Get(url string) *FutureResponse

Get issues a GET HTTP verb to the specified URL, concurrently with any other concurrent requests that may be called.

In Restful, GET is used for "reading" or retrieving a resource. Client should expect a response status code of 200(OK) if resource exists, 404(Not Found) if it doesn't, or 400(Bad Request).

func (*Concurrent) Head

func (c *Concurrent) Head(url string) *FutureResponse

Head issues a HEAD HTTP verb to the specified URL, concurrently with any other concurrent requests that may be called.

In Restful, HEAD is used to "read" a resource headers only. Client should expect a response status code of 200(OK) if resource exists, 404(Not Found) if it doesn't, or 400(Bad Request).

func (*Concurrent) Options

func (c *Concurrent) Options(url string) *FutureResponse

Options issues a OPTIONS HTTP verb to the specified URL, concurrently with any other concurrent requests that may be called.

In Restful, OPTIONS is used to get information about the resource and supported HTTP verbs. Client should expect a response status code of 200(OK) if resource exists, 404(Not Found) if it doesn't, or 400(Bad Request).

func (*Concurrent) Patch

func (c *Concurrent) Patch(url string, body interface{}) *FutureResponse

Patch issues a PATCH HTTP verb to the specified URL, concurrently with any other concurrent requests that may be called.

In Restful, PATCH is used for "partially updating" a resource. Client should expect a response status code of of 200(OK), 404(Not Found), or 400(Bad Request). 200(OK) could be also 204(No Content)

Body could be any of the form: string, []byte, struct & map.

func (*Concurrent) Post

func (c *Concurrent) Post(url string, body interface{}) *FutureResponse

Post issues a POST HTTP verb to the specified URL, concurrently with any other concurrent requests that may be called.

In Restful, POST is used for "creating" a resource. Client should expect a response status code of 201(Created), 400(Bad Request), 404(Not Found), or 409(Conflict) if resource already exist.

Body could be any of the form: string, []byte, struct & map.

func (*Concurrent) Put

func (c *Concurrent) Put(url string, body interface{}) *FutureResponse

Put issues a PUT HTTP verb to the specified URL, concurrently with any other concurrent requests that may be called.

In Restful, PUT is used for "updating" a resource. Client should expect a response status code of of 200(OK), 404(Not Found), or 400(Bad Request). 200(OK) could be also 204(No Content)

Body could be any of the form: string, []byte, struct & map.

type ContentType

type ContentType int

ContentType represents the Content Type for the Body of HTTP Verbs like POST, PUT, and PATCH

const (
	// JSON represents a JSON Content Type
	JSON ContentType = iota

	// XML represents an XML Content Type
	XML

	// BYTES represents a plain Content Type
	BYTES
)

type CustomPool

type CustomPool struct {
	MaxIdleConnsPerHost int
	Proxy               string

	// Public for custom fine tuning
	Transport http.RoundTripper
}

CustomPool defines a separate internal *transport* and connection pooling.

type FutureResponse

type FutureResponse struct {
	// contains filtered or unexported fields
}

FutureResponse represents a response to be completed after a ForkJoin operation is done.

FutureResponse will never be nil, and has a Response function for getting the Response, that will be nil after the ForkJoin operation is completed

func (*FutureResponse) Response

func (fr *FutureResponse) Response() *Response

Response gives you the Response of a Request,after the ForkJoin operation is completed.

Response will be nil if the ForkJoin operation is not completed.

type Mock

type Mock struct {

	// Request URL
	URL string

	// Request HTTP Method (GET, POST, PUT, PATCH, HEAD, DELETE, OPTIONS)
	// As a good practice use the constants in http package (http.MethodGet, etc.)
	HTTPMethod string

	// Request array Headers
	ReqHeaders http.Header

	// Request Body, used with POST, PUT & PATCH
	ReqBody string

	// Response HTTP Code
	RespHTTPCode int

	// Response Array Headers
	RespHeaders http.Header

	// Response Body
	RespBody string
}

Mock serves the purpose of creating Mockups. All requests will be sent to the mockup server if mockup is activated. Or by programmatically starting the mockup server

StartMockupServer()

type RequestBuilder

type RequestBuilder struct {

	// Headers to be send in the request
	Headers http.Header

	// Complete request time out.
	Timeout time.Duration

	//Connection timeout, it bounds the time spent obtaining a successful connection
	ConnectTimeout time.Duration

	// Base URL to be used for each Request. The final URL will be BaseURL + URL.
	BaseURL string

	// ContentType
	ContentType ContentType

	// Disable internal caching of Responses
	DisableCache bool

	// Disable timeout and default timeout = no timeout
	DisableTimeout bool

	// Set the http client to follow a redirect if we get a 3xx response
	FollowRedirect bool

	// Create a CustomPool if you don't want to share the *transport*, with others
	// RequestBuilder
	CustomPool *CustomPool

	// Set Basic Auth for this RequestBuilder
	BasicAuth *BasicAuth

	// Set an specific User Agent for this RequestBuilder
	UserAgent string

	// Public for custom fine tuning
	Client *http.Client
	// contains filtered or unexported fields
}

RequestBuilder is the baseline for creating requests There's a Default Builder that you may use for simple requests RequestBuilder si thread-safe, and you should store it for later re-used.

func (*RequestBuilder) AsyncDelete

func (rb *RequestBuilder) AsyncDelete(url string, f func(*Response))

AsyncDelete is the *asynchronous* option for DELETE. The go routine calling AsyncDelete(), will not be blocked.

Whenever the Response is ready, the *f* function will be called back.

func (*RequestBuilder) AsyncGet

func (rb *RequestBuilder) AsyncGet(url string, f func(*Response))

AsyncGet is the *asynchronous* option for GET. The go routine calling AsyncGet(), will not be blocked.

Whenever the Response is ready, the *f* function will be called back.

func (*RequestBuilder) AsyncHead

func (rb *RequestBuilder) AsyncHead(url string, f func(*Response))

AsyncHead is the *asynchronous* option for HEAD. The go routine calling AsyncHead(), will not be blocked.

Whenever the Response is ready, the *f* function will be called back.

func (*RequestBuilder) AsyncOptions

func (rb *RequestBuilder) AsyncOptions(url string, f func(*Response))

AsyncOptions is the *asynchronous* option for OPTIONS. The go routine calling AsyncOptions(), will not be blocked.

Whenever the Response is ready, the *f* function will be called back.

func (*RequestBuilder) AsyncPatch

func (rb *RequestBuilder) AsyncPatch(url string, body interface{}, f func(*Response))

AsyncPatch is the *asynchronous* option for PATCH. The go routine calling AsyncPatch(), will not be blocked.

Whenever the Response is ready, the *f* function will be called back.

func (*RequestBuilder) AsyncPost

func (rb *RequestBuilder) AsyncPost(url string, body interface{}, f func(*Response))

AsyncPost is the *asynchronous* option for POST. The go routine calling AsyncPost(), will not be blocked.

Whenever the Response is ready, the *f* function will be called back.

func (*RequestBuilder) AsyncPut

func (rb *RequestBuilder) AsyncPut(url string, body interface{}, f func(*Response))

AsyncPut is the *asynchronous* option for PUT. The go routine calling AsyncPut(), will not be blocked.

Whenever the Response is ready, the *f* function will be called back.

func (*RequestBuilder) Delete

func (rb *RequestBuilder) Delete(url string) *Response

Delete issues a DELETE HTTP verb to the specified URL

In Restful, DELETE is used to "delete" a resource. Client should expect a response status code of of 200(OK), 404(Not Found), or 400(Bad Request).

func (*RequestBuilder) ForkJoin

func (rb *RequestBuilder) ForkJoin(f func(*Concurrent))

ForkJoin let you *fork* requests, and *wait* until all of them have return.

Concurrent has methods for Get, Post, Put, Patch, Delete, Head & Options, with the almost the same API as the synchronous methods. The difference is that these methods return a FutureResponse, which holds a pointer to Response. Response inside FutureResponse is nil until the request has finished.

var futureA, futureB *rest.FutureResponse

rest.ForkJoin(func(c *rest.Concurrent){
	futureA = c.Get("/url/1")
	futureB = c.Get("/url/2")
})

fmt.Println(futureA.Response())
fmt.Println(futureB.Response())

func (*RequestBuilder) Get

func (rb *RequestBuilder) Get(url string) *Response

Get issues a GET HTTP verb to the specified URL.

In Restful, GET is used for "reading" or retrieving a resource. Client should expect a response status code of 200(OK) if resource exists, 404(Not Found) if it doesn't, or 400(Bad Request).

func (*RequestBuilder) Head

func (rb *RequestBuilder) Head(url string) *Response

Head issues a HEAD HTTP verb to the specified URL

In Restful, HEAD is used to "read" a resource headers only. Client should expect a response status code of 200(OK) if resource exists, 404(Not Found) if it doesn't, or 400(Bad Request).

func (*RequestBuilder) Options

func (rb *RequestBuilder) Options(url string) *Response

Options issues a OPTIONS HTTP verb to the specified URL

In Restful, OPTIONS is used to get information about the resource and supported HTTP verbs. Client should expect a response status code of 200(OK) if resource exists, 404(Not Found) if it doesn't, or 400(Bad Request).

func (*RequestBuilder) Patch

func (rb *RequestBuilder) Patch(url string, body interface{}) *Response

Patch issues a PATCH HTTP verb to the specified URL.

In Restful, PATCH is used for "partially updating" a resource. Client should expect a response status code of of 200(OK), 404(Not Found), or 400(Bad Request). 200(OK) could be also 204(No Content)

Body could be any of the form: string, []byte, struct & map.

func (*RequestBuilder) Post

func (rb *RequestBuilder) Post(url string, body interface{}) *Response

Post issues a POST HTTP verb to the specified URL.

In Restful, POST is used for "creating" a resource. Client should expect a response status code of 201(Created), 400(Bad Request), 404(Not Found), or 409(Conflict) if resource already exist.

Body could be any of the form: string, []byte, struct & map.

func (*RequestBuilder) Put

func (rb *RequestBuilder) Put(url string, body interface{}) *Response

Put issues a PUT HTTP verb to the specified URL.

In Restful, PUT is used for "updating" a resource. Client should expect a response status code of of 200(OK), 404(Not Found), or 400(Bad Request). 200(OK) could be also 204(No Content)

Body could be any of the form: string, []byte, struct & map.

type Response

type Response struct {
	*http.Response
	Err error
	// contains filtered or unexported fields
}

Response ...

func Delete

func Delete(url string) *Response

Delete issues a DELETE HTTP verb to the specified URL

In Restful, DELETE is used to "delete" a resource. Client should expect a response status code of of 200(OK), 404(Not Found), or 400(Bad Request).

Delete uses the DefaultBuilder.

func Get

func Get(url string) *Response

Get issues a GET HTTP verb to the specified URL.

In Restful, GET is used for "reading" or retrieving a resource. Client should expect a response status code of 200(OK) if resource exists, 404(Not Found) if it doesn't, or 400(Bad Request).

Get uses the DefaultBuilder.

func Head(url string) *Response

Head issues a HEAD HTTP verb to the specified URL

In Restful, HEAD is used to "read" a resource headers only. Client should expect a response status code of 200(OK) if resource exists, 404(Not Found) if it doesn't, or 400(Bad Request).

Head uses the DefaultBuilder.

func Options

func Options(url string) *Response

Options issues a OPTIONS HTTP verb to the specified URL

In Restful, OPTIONS is used to get information about the resource and supported HTTP verbs. Client should expect a response status code of 200(OK) if resource exists, 404(Not Found) if it doesn't, or 400(Bad Request).

Options uses the DefaultBuilder.

func Patch

func Patch(url string, body interface{}) *Response

Patch issues a PATCH HTTP verb to the specified URL

In Restful, PATCH is used for "partially updating" a resource. Client should expect a response status code of of 200(OK), 404(Not Found), or 400(Bad Request). 200(OK) could be also 204(No Content)

Body could be any of the form: string, []byte, struct & map.

Patch uses the DefaultBuilder.

func Post

func Post(url string, body interface{}) *Response

Post issues a POST HTTP verb to the specified URL.

In Restful, POST is used for "creating" a resource. Client should expect a response status code of 201(Created), 400(Bad Request), 404(Not Found), or 409(Conflict) if resource already exist.

Body could be any of the form: string, []byte, struct & map.

Post uses the DefaultBuilder.

func Put

func Put(url string, body interface{}) *Response

Put issues a PUT HTTP verb to the specified URL.

In Restful, PUT is used for "updating" a resource. Client should expect a response status code of of 200(OK), 404(Not Found), or 400(Bad Request). 200(OK) could be also 204(No Content)

Body could be any of the form: string, []byte, struct & map.

Put uses the DefaultBuilder.

func (*Response) Bytes

func (r *Response) Bytes() []byte

Bytes return the Response Body as bytes.

func (*Response) CacheHit

func (r *Response) CacheHit() bool

CacheHit shows if a response was get from the cache.

func (*Response) Debug

func (r *Response) Debug() string

Debug let any request/response to be dumped, showing how the request/response went through the wire, only if debug mode is *on* on RequestBuilder.

func (*Response) FillUp

func (r *Response) FillUp(fill interface{}) error

FillUp set the *fill* parameter with the corresponding JSON or XML response. fill could be `struct` or `map[string]interface{}`

func (*Response) String

func (r *Response) String() string

String return the Respnse Body as a String.

Jump to

Keyboard shortcuts

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