git-lfs/lfs/http.go

154 lines
3.3 KiB
Go
Raw Normal View History

2015-03-19 19:30:55 +00:00
package lfs
import (
"crypto/tls"
2015-03-05 19:49:15 +00:00
"fmt"
2015-03-05 18:39:37 +00:00
"github.com/rubyist/tracerx"
2015-03-05 19:49:15 +00:00
"io"
"net/http"
"os"
2015-03-05 19:49:15 +00:00
"strings"
)
func DoHTTP(c *Configuration, req *http.Request) (*http.Response, error) {
2015-03-05 18:39:37 +00:00
var res *http.Response
var err error
2015-03-05 21:18:02 +00:00
if req.Body != nil {
req.Body = newCountedRequest(req)
2015-03-05 21:18:02 +00:00
}
2015-03-05 19:49:15 +00:00
traceHttpRequest(c, req)
2015-03-05 18:39:37 +00:00
switch req.Method {
case "GET", "HEAD":
2015-03-05 18:39:37 +00:00
res, err = c.RedirectingHttpClient().Do(req)
default:
2015-03-05 18:39:37 +00:00
res, err = c.HttpClient().Do(req)
}
2015-03-05 18:39:37 +00:00
traceHttpResponse(c, res)
2015-03-05 18:39:37 +00:00
return res, err
}
func (c *Configuration) HttpClient() *http.Client {
if c.httpClient == nil {
c.httpClient = &http.Client{
Transport: c.RedirectingHttpClient().Transport,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return RedirectError
},
}
}
return c.httpClient
}
func (c *Configuration) RedirectingHttpClient() *http.Client {
if c.redirectingHttpClient == nil {
2015-03-05 18:49:21 +00:00
tr := &http.Transport{}
sslVerify, _ := c.GitConfig("http.sslverify")
if sslVerify == "false" || len(os.Getenv("GIT_SSL_NO_VERIFY")) > 0 {
tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
}
2015-03-05 18:49:21 +00:00
c.redirectingHttpClient = &http.Client{Transport: tr}
}
return c.redirectingHttpClient
}
2015-03-05 19:49:15 +00:00
var tracedTypes = []string{"json", "text", "xml", "html"}
func traceHttpRequest(c *Configuration, req *http.Request) {
tracerx.Printf("HTTP: %s %s", req.Method, req.URL.String())
if c.isTracingHttp == false {
return
}
fmt.Fprintf(os.Stderr, "> %s %s %s\n", req.Method, req.URL.RequestURI(), req.Proto)
2015-03-05 19:49:15 +00:00
for key, _ := range req.Header {
fmt.Fprintf(os.Stderr, "> %s: %s\n", key, req.Header.Get(key))
2015-03-05 19:49:15 +00:00
}
}
func traceHttpResponse(c *Configuration, res *http.Response) {
2015-03-05 19:49:15 +00:00
tracerx.Printf("HTTP: %d", res.StatusCode)
if c.isTracingHttp == false {
return
}
2015-03-05 21:18:02 +00:00
fmt.Fprintf(os.Stderr, "\n")
fmt.Fprintf(os.Stderr, "< %s %s\n", res.Proto, res.Status)
2015-03-05 19:49:15 +00:00
for key, _ := range res.Header {
fmt.Fprintf(os.Stderr, "< %s: %s\n", key, res.Header.Get(key))
2015-03-05 19:49:15 +00:00
}
traceBody := false
ctype := strings.ToLower(strings.SplitN(res.Header.Get("Content-Type"), ";", 2)[0])
for _, tracedType := range tracedTypes {
if strings.Contains(ctype, tracedType) {
traceBody = true
}
}
res.Body = newCountedResponse(res)
2015-03-05 19:49:15 +00:00
if traceBody {
res.Body = newTracedBody(res.Body)
2015-03-05 19:49:15 +00:00
}
2015-03-05 21:19:53 +00:00
fmt.Fprintf(os.Stderr, "\n")
2015-03-05 19:49:15 +00:00
}
const (
countingUpload = iota
countingDownload
)
2015-03-05 21:18:02 +00:00
type countingBody struct {
Direction int
Size int64
2015-03-22 18:12:04 +00:00
io.ReadCloser
2015-03-05 21:18:02 +00:00
}
func (r *countingBody) Read(p []byte) (int, error) {
2015-03-22 18:12:04 +00:00
n, err := r.ReadCloser.Read(p)
2015-03-05 21:18:02 +00:00
r.Size += int64(n)
return n, err
}
func (r *countingBody) Close() error {
if r.Direction == countingUpload {
fmt.Fprintf(os.Stderr, "* uploaded %d bytes\n", r.Size)
} else {
fmt.Fprintf(os.Stderr, "* downloaded %d bytes\n", r.Size)
}
2015-03-22 18:12:04 +00:00
return r.ReadCloser.Close()
2015-03-05 21:18:02 +00:00
}
func newCountedResponse(res *http.Response) *countingBody {
return &countingBody{countingDownload, 0, res.Body}
}
func newCountedRequest(req *http.Request) *countingBody {
return &countingBody{countingUpload, 0, req.Body}
2015-03-05 21:18:02 +00:00
}
2015-03-05 19:49:15 +00:00
type tracedBody struct {
2015-03-22 18:12:04 +00:00
io.ReadCloser
2015-03-05 19:49:15 +00:00
}
func (r *tracedBody) Read(p []byte) (int, error) {
2015-03-22 18:12:04 +00:00
n, err := r.ReadCloser.Read(p)
fmt.Fprintf(os.Stderr, "%s\n", string(p[0:n]))
2015-03-05 19:49:15 +00:00
return n, err
}
func (r *tracedBody) Close() error {
2015-03-22 18:12:04 +00:00
return r.ReadCloser.Close()
2015-03-05 19:49:15 +00:00
}
func newTracedBody(body io.ReadCloser) *tracedBody {
return &tracedBody{body}
2015-03-05 19:49:15 +00:00
}