c282983235
The initial thought here is to introduce a MethodTestCase type that encapsulates the behavior of testing a single method in a particular given service. To do so, a httptest.Server is created and the schema is turned into a request which is fired at that server. Thet MethodTestCase, of course, knows how to respond to different requests, and the behavior of those responses is tested. What I dislike is that we have to write three things which are mostly the same to test any endpoint in any case on the API: 1) a request type (Go struct) 2) an expected response type (Go type) 3) the actual response (a mutltline Go string, which is really just JSON) This seems redundant, so I may explore other options for implementing this sort of thing in the future.
86 lines
2.5 KiB
Go
86 lines
2.5 KiB
Go
// NOTE: Subject to change, do not rely on this package from outside git-lfs source
|
|
package api
|
|
|
|
import "net/url"
|
|
|
|
const (
|
|
MediaType = "application/vnd.git-lfs+json; charset=utf-8"
|
|
)
|
|
|
|
// Client exposes the LFS API to callers through a multitude of different
|
|
// services and transport mechanisms. Callers can make a *RequestSchema using
|
|
// any service that is attached to the Client, and then execute a request based
|
|
// on that schema using the `Do()` method.
|
|
//
|
|
// A prototypical example follows:
|
|
// ```
|
|
// apiResponse, schema := client.Locks.Lock(request)
|
|
// resp, err := client.Do(schema)
|
|
// if err != nil {
|
|
// handleErr(err)
|
|
// }
|
|
//
|
|
// fmt.Println(apiResponse.Lock)
|
|
// ```
|
|
type Client struct {
|
|
Locks LockService
|
|
|
|
// base is root URL that all requests will be made against. It is
|
|
// initialized when the client is constructed, and remains immutable
|
|
// throughout the duration of the *Client.
|
|
base *url.URL
|
|
// lifecycle is the lifecycle used by all requests through this client.
|
|
lifecycle Lifecycle
|
|
}
|
|
|
|
// NewClient instantiates and returns a new instance of *Client with a base path
|
|
// initialized to the given `root`. If `root` is unable to be parsed according
|
|
// to the rules of `url.Parse`, then a `nil` client will be returned, and the
|
|
// parse error will be returned instead.
|
|
//
|
|
// Assuming all goes well, a *Client is returned as expected, along with a `nil`
|
|
// error.
|
|
func NewClient(root string, lifecycle Lifecycle) (*Client, error) {
|
|
base, err := url.Parse(root)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if lifecycle == nil {
|
|
lifecycle = NewHttpLifecycle(base)
|
|
}
|
|
|
|
return &Client{
|
|
base: base,
|
|
lifecycle: lifecycle,
|
|
}, nil
|
|
}
|
|
|
|
// Do preforms the request assosicated with the given *RequestSchema by
|
|
// delegating into the Lifecycle in use.
|
|
//
|
|
// If any error was encountered while either building, executing or cleaning up
|
|
// the request, then it will be returned immediately, and the request can be
|
|
// treated as invalid.
|
|
//
|
|
// If no error occured, an some api.Response implementation will be returned,
|
|
// along with a `nil` error. At this point, the body of the response has been
|
|
// serialized into `schema.Into`, and the body is closed.
|
|
func (c *Client) Do(schema *RequestSchema) (Response, error) {
|
|
req, err := c.lifecycle.Build(schema)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
resp, err := c.lifecycle.Execute(req, schema.Into)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err = c.lifecycle.Cleanup(resp); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return resp, nil
|
|
}
|