sling

package module
v0.0.0-...-7bcba7e Latest Latest
Warning

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

Go to latest
Published: Apr 27, 2015 License: MIT Imports: 7 Imported by: 0

README

Sling Build Status Coverage GoDoc

Sling is a Go REST client library for creating and sending API requests.

Slings store http Request properties to simplify sending requests and decoding responses. Check usage or the examples to learn how to compose a Sling into your API client.

Features
  • Base/Path - path extend a Sling for different endpoints
  • Method Setters: Get/Post/Put/Patch/Delete/Head
  • Add and Set Request Headers
  • Encode url structs into URL query parameters
  • Encode url structs or json into the Request Body
  • Decode received JSON success responses

Install

go get github.com/dghubble/sling

Documentation

Read GoDoc

Usage

Use a simple Sling to set request properties (Path, QueryParams, etc.) and then create a new http.Request by calling Request().

req, err := sling.New().Get("https://example.com").Request()
client.Do(req)

Slings are much more powerful though. Use them to create REST clients which wrap complex API endpoints. Copy a base Sling with New() to avoid repeating common configuration.

const twitterApi = "https://api.twitter.com/1.1/"
base := sling.New().Base(twitterApi).Client(httpAuthClient)

users := base.New().Path("users/")
statuses := base.New().Path("statuses/")

Choose an http method, set query parameters, and send the request.

statuses.New().Get("show.json").QueryStruct(params).Receive(tweet)

The sections below provide more details about setting headers, query parameters, body data, and decoding a typed response after sending.

Headers

Add or Set headers which should be applied to all Requests created by a Sling.

base := sling.New().Base(baseUrl).Set("User-Agent", "Gophergram API Client")
req, err := base.New().Get("gophergram/list").Request()
QueryStruct

Define url parameter structs and use QueryStruct to encode query parameters.

// Github Issue Parameters
type IssueParams struct {
    Filter    string `url:"filter,omitempty"`
    State     string `url:"state,omitempty"`
    Labels    string `url:"labels,omitempty"`
    Sort      string `url:"sort,omitempty"`
    Direction string `url:"direction,omitempty"`
    Since     string `url:"since,omitempty"`
}
githubBase := sling.New().Base("https://api.github.com/").Client(httpClient)
path := fmt.Sprintf("repos/%s/%s/issues", owner, repo)

params := &IssueParams{Sort: "updated", State: "open"}
req, err := githubBase.New().Get(path).QueryStruct(params).Request()
Body
JsonBody

Make a Sling include JSON in the Body of its Requests using JsonBody.

type IssueRequest struct {
    Title     string   `json:"title,omitempty"`
    Body      string   `json:"body,omitempty"`
    Assignee  string   `json:"assignee,omitempty"`
    Milestone int      `json:"milestone,omitempty"`
    Labels    []string `json:"labels,omitempty"`
}
githubBase := sling.New().Base("https://api.github.com/").Client(httpClient)
path := fmt.Sprintf("repos/%s/%s/issues", owner, repo)

body := &IssueRequest{
    Title: "Test title",
    Body:  "Some issue",
}
req, err := githubBase.New().Post(path).JsonBody(body).Request()

Requests will include an application/json Content-Type header.

BodyStruct

Make a Sling include a url-tagged struct as a url-encoded form in the Body of its Requests using BodyStruct.

type StatusUpdateParams struct {
    Status             string   `url:"status,omitempty"`
    InReplyToStatusId  int64    `url:"in_reply_to_status_id,omitempty"`
    MediaIds           []int64  `url:"media_ids,omitempty,comma"`
}
tweetParams := &StatusUpdateParams{Status: "writing some Go"}
req, err := twitterBase.New().Post(path).BodyStruct(tweetParams).Request()

Requests will include an application/x-www-form-urlencoded Content-Type header.

Receive

Define expected value structs. Use Receive(v interface{}) to send a new Request that will automatically decode the response into the value.

// Github Issue (abbreviated)
type Issue struct {
    Id     int    `json:"id"`
    Url    string `json:"url"`
    Number int    `json:"number"`
    State  string `json:"state"`
    Title  string `json:"title"`
    Body   string `json:"body"`
}
issues := new([]Issue)
resp, err := githubBase.New().Get(path).QueryStruct(params).Receive(issues)
fmt.Println(issues, resp, err)
Build an API

APIs typically define an endpoint (also called a service) for each type of resource. For example, here is a tiny Github IssueService which creates and lists repository issues.

type IssueService struct {
    sling *sling.Sling
}

func NewIssueService(httpClient *http.Client) *IssueService {
    return &IssueService{
        sling: sling.New().Client(httpClient).Base(baseUrl),
    }
}

func (s *IssueService) Create(owner, repo string, issueBody *IssueRequest) (*Issue, *http.Response, error) {
    issue := new(Issue)
    path := fmt.Sprintf("repos/%s/%s/issues", owner, repo)
    resp, err := s.sling.New().Post(path).JsonBody(issueBody).Receive(issue)
    return issue, resp, err
}

func (srvc IssueService) List(owner, repo string, params *IssueParams) ([]Issue, *http.Response, error) {
    var issues []Issue
    path := fmt.Sprintf("repos/%s/%s/issues", owner, repo)
    resp, err := srvc.sling.New().Get(path).QueryStruct(params).Receive(&issues)
    return *issues, resp, err
}

APIs using Sling

Create a Pull Request to add a link to your own API.

Roadmap

  • Receive custom error structs

Motivation

Many client libraries follow the lead of google/go-github (our inspiration!), but do so by reimplementing logic common to all clients.

This project borrows and abstracts those ideas into a Sling, an agnostic component any API client can use for creating and sending requests.

License

MIT License

Documentation

Overview

Package sling is a Go REST client library for creating and sending requests.

Slings store http Request properties to simplify sending requests and decoding responses. Check the examples to learn how to compose a Sling into your API client.

Use a simple Sling to set request properties (Path, QueryParams, etc.) and then create a new http.Request by calling Request().

req, err := sling.New().Get("https://example.com").Request()
client.Do(req)

Slings are much more powerful though. Use them to create REST clients which wrap complex API endpoints. Copy a base Sling with New() to avoid repeating common configuration.

const twitterApi = "https://https://api.twitter.com/1.1/"
base := sling.New().Base(twitterApi).Client(httpAuthClient)

users := base.New().Path("users/")
statuses := base.New().Path("statuses/")

Choose an http method, set query parameters, and send the request.

statuses.New().Get("show.json").QueryStruct(params).Receive(tweet)

The usage README provides more details about setting headers, query parameters, body data, and decoding a typed response after sending.

Index

Constants

View Source
const (
	HEAD   = "HEAD"
	GET    = "GET"
	POST   = "POST"
	PUT    = "PUT"
	PATCH  = "PATCH"
	DELETE = "DELETE"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Sling

type Sling struct {
	// http Client for doing requests
	HttpClient *http.Client
	// HTTP method (GET, POST, etc.)
	Method string
	// raw url string for requests
	RawUrl string
	// stores key-values pairs to add to request's Headers
	Header http.Header
	// contains filtered or unexported fields
}

Sling is an HTTP Request builder and sender.

func New

func New() *Sling

New returns a new Sling with an http DefaultClient.

func (*Sling) Add

func (s *Sling) Add(key, value string) *Sling

Add adds the key, value pair in Headers, appending values for existing keys to the key's values. Header keys are canonicalized.

func (*Sling) Base

func (s *Sling) Base(rawURL string) *Sling

Base sets the RawUrl. If you intend to extend the url with Path, baseUrl should be specified with a trailing slash.

func (*Sling) BodyStruct

func (s *Sling) BodyStruct(bodyStruct interface{}) *Sling

BodyStruct sets the Sling's bodyStruct. The value pointed to by the bodyStruct will be url encoded to set the Body on new requests. The bodyStruct argument should be a pointer to a url tagged struct. See https://godoc.org/github.com/google/go-querystring/query for details.

func (*Sling) Client

func (s *Sling) Client(httpClient *http.Client) *Sling

Client sets the http Client used to do requests. If a nil client is given, the http.DefaultClient will be used.

func (*Sling) Delete

func (s *Sling) Delete(pathURL string) *Sling

Delete sets the Sling method to DELETE and sets the given pathURL.

func (*Sling) Do

func (s *Sling) Do(req *http.Request, v interface{}) (*http.Response, error)

Do sends the HTTP request and decodes the response into the value pointed to by v. It wraps http.Client.Do, but handles closing the Response Body. The Response and any error doing the request are returned.

Note that non-2xx StatusCodes are valid responses, not errors.

func (*Sling) Get

func (s *Sling) Get(pathURL string) *Sling

Get sets the Sling method to GET and sets the given pathURL.

func (*Sling) Head

func (s *Sling) Head(pathURL string) *Sling

Head sets the Sling method to HEAD and sets the given pathURL.

func (*Sling) JsonBody

func (s *Sling) JsonBody(jsonBody interface{}) *Sling

JsonBody sets the Sling's jsonBody. The value pointed to by the jsonBody will be JSON encoded to set the Body on new requests (see Request()). The jsonBody argument should be a pointer to a json tagged struct. See https://golang.org/pkg/encoding/json/#MarshalIndent for details.

func (*Sling) New

func (s *Sling) New() *Sling

New returns a copy of a Sling for creating a new Sling with properties from a base Sling. For example,

baseSling := sling.New().Client(client).Base("https://api.io/")
fooSling := baseSling.New().Get("foo/")
barSling := baseSling.New().Get("bar/")

fooSling and barSling will both use the same client, but send requests to https://api.io/foo/ and https://api.io/bar/ respectively.

Note that jsonBody and queryStructs item values are copied so if pointer values are used, mutating the original value will mutate the value within the child Sling.

func (*Sling) Patch

func (s *Sling) Patch(pathURL string) *Sling

Patch sets the Sling method to PATCH and sets the given pathURL.

func (*Sling) Path

func (s *Sling) Path(path string) *Sling

Path extends the RawUrl with the given path by resolving the reference to an absolute URL. If parsing errors occur, the RawUrl is left unmodified.

func (*Sling) Post

func (s *Sling) Post(pathURL string) *Sling

Post sets the Sling method to POST and sets the given pathURL.

func (*Sling) Put

func (s *Sling) Put(pathURL string) *Sling

Put sets the Sling method to PUT and sets the given pathURL.

func (*Sling) QueryStruct

func (s *Sling) QueryStruct(queryStruct interface{}) *Sling

QueryStruct appends the queryStruct to the Sling's queryStructs. The value pointed to by each queryStruct will be encoded as url query parameters on new requests (see Request()). The queryStruct argument should be a pointer to a url tagged struct. See https://godoc.org/github.com/google/go-querystring/query for details.

func (*Sling) Receive

func (s *Sling) Receive(v interface{}) (*http.Response, error)

Receive creates a new HTTP request, sends it, and decodes the response into the value pointed to by v. Receive is shorthand for calling Request and Do.

func (*Sling) Request

func (s *Sling) Request() (*http.Request, error)

Request returns a new http.Request created with the Sling properties. Returns any errors parsing the RawUrl, encoding query structs, encoding the body, or creating the http.Request.

func (*Sling) Set

func (s *Sling) Set(key, value string) *Sling

Set sets the key, value pair in Headers, replacing existing values associated with key. Header keys are canonicalized.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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