119 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			119 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
| package requests
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| 	"io/ioutil"
 | |
| 	"net/http"
 | |
| )
 | |
| 
 | |
| // Builder allows users to construct a request and then execute the
 | |
| // request via Do().
 | |
| // Do returns a Result which allows the user to get the body,
 | |
| // unmarshal the body into an interface, or into a simplejson.Json.
 | |
| type Builder interface {
 | |
| 	WithContext(context.Context) Builder
 | |
| 	WithBody(io.Reader) Builder
 | |
| 	WithMethod(string) Builder
 | |
| 	WithHeaders(http.Header) Builder
 | |
| 	SetHeader(key, value string) Builder
 | |
| 	Do() Result
 | |
| }
 | |
| 
 | |
| type builder struct {
 | |
| 	context  context.Context
 | |
| 	method   string
 | |
| 	endpoint string
 | |
| 	body     io.Reader
 | |
| 	header   http.Header
 | |
| 	result   *result
 | |
| }
 | |
| 
 | |
| // New provides a new Builder for the given endpoint.
 | |
| func New(endpoint string) Builder {
 | |
| 	return &builder{
 | |
| 		endpoint: endpoint,
 | |
| 		method:   "GET",
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // WithContext adds a context to the request.
 | |
| // If no context is provided, context.Background() is used instead.
 | |
| func (r *builder) WithContext(ctx context.Context) Builder {
 | |
| 	r.context = ctx
 | |
| 	return r
 | |
| }
 | |
| 
 | |
| // WithBody adds a body to the request.
 | |
| func (r *builder) WithBody(body io.Reader) Builder {
 | |
| 	r.body = body
 | |
| 	return r
 | |
| }
 | |
| 
 | |
| // WithMethod sets the request method. Defaults to "GET".
 | |
| func (r *builder) WithMethod(method string) Builder {
 | |
| 	r.method = method
 | |
| 	return r
 | |
| }
 | |
| 
 | |
| // WithHeaders replaces the request header map with the given header map.
 | |
| func (r *builder) WithHeaders(header http.Header) Builder {
 | |
| 	r.header = header
 | |
| 	return r
 | |
| }
 | |
| 
 | |
| // SetHeader sets a single header to the given value.
 | |
| // May be used to add multiple headers.
 | |
| func (r *builder) SetHeader(key, value string) Builder {
 | |
| 	if r.header == nil {
 | |
| 		r.header = make(http.Header)
 | |
| 	}
 | |
| 	r.header.Set(key, value)
 | |
| 	return r
 | |
| }
 | |
| 
 | |
| // Do performs the request and returns the response in its raw form.
 | |
| // If the request has already been performed, returns the previous result.
 | |
| // This will not allow you to repeat a request.
 | |
| func (r *builder) Do() Result {
 | |
| 	if r.result != nil {
 | |
| 		// Request has already been done
 | |
| 		return r.result
 | |
| 	}
 | |
| 
 | |
| 	// Must provide a non-nil context to NewRequestWithContext
 | |
| 	if r.context == nil {
 | |
| 		r.context = context.Background()
 | |
| 	}
 | |
| 
 | |
| 	return r.do()
 | |
| }
 | |
| 
 | |
| // do creates the request, executes it with the default client and extracts the
 | |
| // the body into the response
 | |
| func (r *builder) do() Result {
 | |
| 	req, err := http.NewRequestWithContext(r.context, r.method, r.endpoint, r.body)
 | |
| 	if err != nil {
 | |
| 		r.result = &result{err: fmt.Errorf("error creating request: %v", err)}
 | |
| 		return r.result
 | |
| 	}
 | |
| 	req.Header = r.header
 | |
| 
 | |
| 	resp, err := http.DefaultClient.Do(req)
 | |
| 	if err != nil {
 | |
| 		r.result = &result{err: fmt.Errorf("error performing request: %v", err)}
 | |
| 		return r.result
 | |
| 	}
 | |
| 
 | |
| 	defer resp.Body.Close()
 | |
| 	body, err := ioutil.ReadAll(resp.Body)
 | |
| 	if err != nil {
 | |
| 		r.result = &result{err: fmt.Errorf("error reading response body: %v", err)}
 | |
| 		return r.result
 | |
| 	}
 | |
| 
 | |
| 	r.result = &result{response: resp, body: body}
 | |
| 	return r.result
 | |
| }
 |