aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing/transport/http/common.go
diff options
context:
space:
mode:
authorSantiago M. Mola <santi@mola.io>2016-11-23 15:30:34 +0100
committerMáximo Cuadros <mcuadros@gmail.com>2016-11-23 15:38:12 +0100
commit08e08d771ef03df80248c80d81475fe7c5ea6fe7 (patch)
treed12e9befa22409e8cf50c5bbc4895e69fd8a5f48 /plumbing/transport/http/common.go
parent844169a739fb8bf1f252d416f10d8c7034db9fe2 (diff)
downloadgo-git-08e08d771ef03df80248c80d81475fe7c5ea6fe7.tar.gz
transport: create Client interface (#132)
* plumbing: move plumbing/client package to plumbing/transport. * transport: create Client interface. * A Client can instantiate any client transport service. * InstallProtocol installs a Client for a given protocol, instead of just a UploadPackService. * A Client can open a session for fetch-pack or send-pack for a specific Endpoint. * Adapt ssh and http clients to the new client interface. * updated doc
Diffstat (limited to 'plumbing/transport/http/common.go')
-rw-r--r--plumbing/transport/http/common.go155
1 files changed, 155 insertions, 0 deletions
diff --git a/plumbing/transport/http/common.go b/plumbing/transport/http/common.go
new file mode 100644
index 0000000..038c469
--- /dev/null
+++ b/plumbing/transport/http/common.go
@@ -0,0 +1,155 @@
+// Package http implements a HTTP client for go-git.
+package http
+
+import (
+ "fmt"
+ "net/http"
+
+ "gopkg.in/src-d/go-git.v4/plumbing"
+ "gopkg.in/src-d/go-git.v4/plumbing/transport"
+)
+
+type Client struct {
+ c *http.Client
+}
+
+var DefaultClient = NewClient(nil)
+
+// NewClient creates a new client with a custom net/http client.
+// See `InstallProtocol` to install and override default http client.
+// Unless a properly initialized client is given, it will fall back into
+// `http.DefaultClient`.
+func NewClient(c *http.Client) transport.Client {
+ if c == nil {
+ return &Client{http.DefaultClient}
+ }
+
+ return &Client{
+ c: c,
+ }
+}
+
+func (c *Client) NewFetchPackSession(ep transport.Endpoint) (
+ transport.FetchPackSession, error) {
+
+ return newFetchPackSession(c.c, ep), nil
+}
+
+func (c *Client) NewSendPackSession(ep transport.Endpoint) (
+ transport.SendPackSession, error) {
+
+ return newSendPackSession(c.c, ep), nil
+}
+
+type session struct {
+ auth AuthMethod
+ client *http.Client
+ endpoint transport.Endpoint
+}
+
+func (s *session) SetAuth(auth transport.AuthMethod) error {
+ a, ok := auth.(AuthMethod)
+ if !ok {
+ return transport.ErrInvalidAuthMethod
+ }
+
+ s.auth = a
+ return nil
+}
+
+func (*session) Close() error {
+ return nil
+}
+
+func (s *session) applyAuthToRequest(req *http.Request) {
+ if s.auth == nil {
+ return
+ }
+
+ s.auth.setAuth(req)
+}
+
+// AuthMethod is concrete implementation of common.AuthMethod for HTTP services
+type AuthMethod interface {
+ transport.AuthMethod
+ setAuth(r *http.Request)
+}
+
+func basicAuthFromEndpoint(ep transport.Endpoint) *BasicAuth {
+ info := ep.User
+ if info == nil {
+ return nil
+ }
+
+ p, ok := info.Password()
+ if !ok {
+ return nil
+ }
+
+ u := info.Username()
+ return NewBasicAuth(u, p)
+}
+
+// BasicAuth represent a HTTP basic auth
+type BasicAuth struct {
+ username, password string
+}
+
+// NewBasicAuth returns a basicAuth base on the given user and password
+func NewBasicAuth(username, password string) *BasicAuth {
+ return &BasicAuth{username, password}
+}
+
+func (a *BasicAuth) setAuth(r *http.Request) {
+ if a == nil {
+ return
+ }
+
+ r.SetBasicAuth(a.username, a.password)
+}
+
+// Name is name of the auth
+func (a *BasicAuth) Name() string {
+ return "http-basic-auth"
+}
+
+func (a *BasicAuth) String() string {
+ masked := "*******"
+ if a.password == "" {
+ masked = "<empty>"
+ }
+
+ return fmt.Sprintf("%s - %s:%s", a.Name(), a.username, masked)
+}
+
+// Err is a dedicated error to return errors based on status code
+type Err struct {
+ Response *http.Response
+}
+
+// NewErr returns a new Err based on a http response
+func NewErr(r *http.Response) error {
+ if r.StatusCode >= http.StatusOK && r.StatusCode < http.StatusMultipleChoices {
+ return nil
+ }
+
+ switch r.StatusCode {
+ case http.StatusUnauthorized:
+ return transport.ErrAuthorizationRequired
+ case http.StatusNotFound:
+ return transport.ErrRepositoryNotFound
+ }
+
+ return plumbing.NewUnexpectedError(&Err{r})
+}
+
+// StatusCode returns the status code of the response
+func (e *Err) StatusCode() int {
+ return e.Response.StatusCode
+}
+
+func (e *Err) Error() string {
+ return fmt.Sprintf("unexpected requesting %q status code: %d",
+ e.Response.Request.URL, e.Response.StatusCode,
+ )
+}