conversation

package
v0.4.4 Latest Latest
Warning

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

Go to latest
Published: Nov 17, 2021 License: MIT Imports: 9 Imported by: 2

Documentation

Overview

Package conversation deals with requests and responses while having an HTTP conversation. It provides convenience functions for dealing with common REST conversations.

Index

Examples

Constants

View Source
const DefaultTimeout = time.Second * 10

DefaultTimeout used by clients if no client is defined on a Request.

Variables

View Source
var ErrNilResponse = errors.New("nil response")

ErrNilResponse is returned if an attempted is made to unmarshal a nil response.

Functions

func Reply

func Reply(w http.ResponseWriter, body interface{}) error

Reply to the conversation with an HTTP OK and the given body. Bodies that are not of type []byte or string will be marshalled into JSON. If the marshall failed a 500 error is sent and an error returned. Zero length bodies will simply result in the default 200 status text.

Example
package main

import (
	"bytes"
	"fmt"
	"net/http/httptest"

	"bitbucket.org/idomdavis/gohttp/conversation"
)

func main() {
	w := httptest.ResponseRecorder{Body: &bytes.Buffer{}}

	if err := conversation.Reply(&w, []byte("body")); err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(w.Body.String())
	}

	w = httptest.ResponseRecorder{Body: &bytes.Buffer{}}

	if err := conversation.Reply(&w, "body"); err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(w.Body.String())
	}

	w = httptest.ResponseRecorder{Body: &bytes.Buffer{}}
	payload := struct{ Data string }{Data: "body"}

	if err := conversation.Reply(&w, payload); err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(w.Body.String())
	}

}
Output:

body
body
{"Data":"body"}

func Respond

func Respond(w http.ResponseWriter, code int) error

Respond using the default HTTP status text.

func Success

func Success(r *http.Response) bool

Success returns true if the HTTP Response type contains a success code (200, 201, 202).

Example
package main

import (
	"fmt"
	"net/http"

	"bitbucket.org/idomdavis/gohttp/conversation"
)

func main() {
	fmt.Println(conversation.Success(&http.Response{StatusCode: 200}))
	fmt.Println(conversation.Success(&http.Response{StatusCode: 400}))
	fmt.Println(conversation.Success(nil))

}
Output:

true
false
false

func Unmarshal

func Unmarshal(r io.Reader, in interface{}) error

Unmarshal a JSON request or response into the given interface. The interface should be a pointer.

Example
package main

import (
	"bytes"
	"fmt"

	"bitbucket.org/idomdavis/gohttp/conversation"
)

func main() {
	var body string

	err := conversation.Unmarshal(bytes.NewReader([]byte(`"body"`)), &body)

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println(body)

}
Output:

body

func Write

func Write(w http.ResponseWriter, code int, body []byte) error

Write an HTTP response, adding some extra headers along the way. If no body is set then the default HTTP status text for that code will be used.

Example
package main

import (
	"bytes"
	"fmt"
	"net/http"
	"net/http/httptest"

	"bitbucket.org/idomdavis/gohttp/conversation"
)

func main() {
	header := "X-Content-Type-Options"
	w := httptest.ResponseRecorder{Body: &bytes.Buffer{}}
	err := conversation.Write(&w, http.StatusOK, []byte("body"))

	if err != nil {
		fmt.Println(err)
	}

	fmt.Printf("%s: %s\n", header, w.Header().Get(header))
	fmt.Printf("%d - %s\n", w.Code, w.Body.String())

}
Output:

X-Content-Type-Options: nosniff
200 - body

Types

type Error added in v0.3.0

type Error struct {
	// Channel can receive 0-n errors.
	Channel chan<- error
}

Error allows handling of multiple errors during a conversation by passing the errors onto a channel to be handled asynchronously. This allows conversations to be completed even if an action during the conversation fails.

func (Error) Handle added in v0.3.0

func (e Error) Handle(err error)

Handle an error. If the errors is non-nil and a channel is registered with the handler then that error will be put onto the channel.

Example
package main

import (
	"errors"
	"fmt"

	"bitbucket.org/idomdavis/gohttp/conversation"
)

func main() {
	c := make(chan error)
	e := conversation.Error{Channel: c}

	go e.Handle(nil)
	go e.Handle(errors.New("error"))

	fmt.Println(<-c)

}
Output:

error

type Request

type Request struct {
	// Username if Basic Auth is being used. Password must also be set.
	Username string

	// Password is Basic Auth is being used. Username must also be set.
	Password string

	// Headers to use on the request. If Basic Auth is being used then the
	// Authorisation header is set before the headers are applied.
	Headers map[string]string

	// Client used for the request. If no client is set then a default client
	// will be constructed.
	Client *http.Client
}

Request allows for simple HTTP requests to be made to a URL. If a Username and Password is set then Basic Auth will be used. If no client is set then a default client is constructed using the DefaultTimeout.

func (Request) Get

func (r Request) Get(url string) (*http.Response, error)

Get the response from the given url. Get is a convenience method around Make which uses MethodGet and a nil body.

Example
package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"bitbucket.org/idomdavis/gohttp/conversation"
)

func main() {
	server := httptest.NewServer(http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			_ = conversation.Respond(w, http.StatusOK)
		}))

	response, err := http.Get(server.URL)

	if err != nil {
		fmt.Println(err)
	}

	_ = response.Body.Close()

	fmt.Println(conversation.Success(response))

}
Output:

true

func (Request) Make

func (r Request) Make(method, url string, payload []byte) (*http.Response, error)

Make a request, using Basic Auth if Username and Password are set. A client will be constructed for the request is none is set.

Example
package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"bitbucket.org/idomdavis/gohttp/conversation"
)

func main() {
	var body string

	server := httptest.NewServer(http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			u, p, _ := r.BasicAuth()
			h := r.Header.Get("header")
			_ = conversation.Reply(w, "\""+h+u+p+"\"")
		}))

	response, err := conversation.Request{
		Username: "u",
		Password: "p",
		Headers:  map[string]string{"header": "h"},
	}.Make(http.MethodGet, server.URL, nil)

	if err != nil {
		fmt.Println(err)
	}

	_ = conversation.Unmarshal(response.Body, &body)
	_ = response.Body.Close()

	fmt.Println(body)

}
Output:

hup

func (Request) Post

func (r Request) Post(url string, payload interface{}) (*http.Response, error)

Post the payload to the given url. The payload will be marshalled into JSON. Post is a convenience method around Make which uses MethodPost and the output of json.Marshal for the body.

Example
package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"bitbucket.org/idomdavis/gohttp/conversation"
)

func main() {
	var body string

	server := httptest.NewServer(http.HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			var reply string
			_ = conversation.Unmarshal(r.Body, &reply)
			_ = conversation.Reply(w, reply)
		}))

	response, err := conversation.Request{}.Post(server.URL, `"body"`)

	if err != nil {
		fmt.Println(err)
	}

	_ = conversation.Unmarshal(response.Body, &body)
	_ = response.Body.Close()

	fmt.Println(body)

}
Output:

body

Jump to

Keyboard shortcuts

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