Skip to content

Instantly share code, notes, and snippets.

@quells
Last active November 22, 2019 06:42
Show Gist options
  • Save quells/cde33b128b0d1555641b322acca583b4 to your computer and use it in GitHub Desktop.
Save quells/cde33b128b0d1555641b322acca583b4 to your computer and use it in GitHub Desktop.
Basic Go HTTP helper
package rex
import (
"bytes"
"net/http"
"strings"
"time"
)
type Request struct {
method, baseURL, path string
headers map[string][]string
params map[string]string
body []byte
}
func newRequest(method, baseURL, path string) *Request {
return &Request{
method: method,
baseURL: baseURL,
path: path,
headers: make(map[string][]string),
params: make(map[string]string),
}
}
func Get(baseURL, path string) *Request {
return newRequest(http.MethodGet, baseURL, path)
}
func Post(baseURL, path string) *Request {
return newRequest(http.MethodPost, baseURL, path)
}
func Put(baseURL, path string) *Request {
return newRequest(http.MethodPut, baseURL, path)
}
func Delete(baseURL, path string) *Request {
return newRequest(http.MethodDelete, baseURL, path)
}
func (r *Request) Header(header string, values ...string) *Request {
r.headers[header] = append(r.headers[header], values...)
return r
}
func (r *Request) BasicAuth(username, password string) *Request {
value := base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
return r.Header("Authorization", "Basic "+value)
}
func (r *Request) Param(key, value string) *Request {
r.params[key] = value
return r
}
func (r *Request) Params(params map[string]string) *Request {
for k, v := range params {
r.params[k] = v
}
return r
}
func (r *Request) Body(body []byte) *Request {
r.body = body
return r
}
func (r Request) buildRequest() (req *http.Request, err error) {
baseURL := r.baseURL + r.path
queryParams := make([]string, len(r.params))
var i int
for k, v := range r.params {
queryParams[i] = k + "=" + v
i++
}
u := baseURL + "?" + strings.Join(queryParams, "&")
if len(r.body) > 0 {
buf := bytes.NewBuffer(r.body)
req, err = http.NewRequest(r.method, u, buf)
} else {
req, err = http.NewRequest(r.method, u, nil)
}
if err != nil {
return
}
for header, values := range r.headers {
for _, value := range values {
req.Header.Add(header, value)
}
}
return
}
func (r Request) Send() (resp *http.Response, stats *Stats, err error) {
var req *http.Request
req, err = r.buildRequest()
if err != nil {
return
}
stats = NewStats()
resp, err = http.DefaultClient.Do(req)
stats.done()
if err == nil {
stats.StatusCode = resp.StatusCode
}
return
}
func (r Request) IntoJSON(v interface{}) (stats *Stats, err error) {
var resp *http.Response
resp, stats, err = r.Send()
if err != nil {
return
}
var respData []byte
respData, err = ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return
}
err = json.Unmarshal(respData, v)
return
}
func (r Request) JSON() (respBody map[string]interface{}, stats *Stats, err error) {
stats, err = r.IntoJSON(&respBody)
return
}
// Stats about a Request.
type Stats struct {
StatusCode int
Start time.Time
Duration time.Duration
}
func NewStats() *Stats {
return &Stats{
Start: time.Now(),
}
}
func (s *Stats) done() {
s.Duration = time.Since(s.Start)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment