1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00
moby--moby/utils/http.go

171 lines
4.1 KiB
Go
Raw Normal View History

2013-08-02 02:47:58 -04:00
package utils
import (
"bytes"
"io"
"net/http"
"strings"
)
// VersionInfo is used to model entities which has a version.
// It is basically a tupple with name and version.
type VersionInfo interface {
Name() string
Version() string
}
func validVersion(version VersionInfo) bool {
stopChars := " \t\r\n/"
if strings.ContainsAny(version.Name(), stopChars) {
return false
}
if strings.ContainsAny(version.Version(), stopChars) {
return false
}
return true
}
// Convert versions to a string and append the string to the string base.
//
// Each VersionInfo will be converted to a string in the format of
// "product/version", where the "product" is get from the Name() method, while
// version is get from the Version() method. Several pieces of verson information
// will be concatinated and separated by space.
func appendVersions(base string, versions ...VersionInfo) string {
if len(versions) == 0 {
return base
}
var buf bytes.Buffer
if len(base) > 0 {
buf.Write([]byte(base))
}
for _, v := range versions {
name := []byte(v.Name())
version := []byte(v.Version())
if len(name) == 0 || len(version) == 0 {
continue
}
if !validVersion(v) {
continue
}
buf.Write([]byte(v.Name()))
buf.Write([]byte("/"))
buf.Write([]byte(v.Version()))
buf.Write([]byte(" "))
}
return buf.String()
}
// HTTPRequestDecorator is used to change an instance of
// http.Request. It could be used to add more header fields,
// change body, etc.
type HTTPRequestDecorator interface {
// ChangeRequest() changes the request accordingly.
// The changed request will be returned or err will be non-nil
// if an error occur.
ChangeRequest(req *http.Request) (newReq *http.Request, err error)
}
// HTTPUserAgentDecorator appends the product/version to the user agent field
// of a request.
type HTTPUserAgentDecorator struct {
versions []VersionInfo
}
func NewHTTPUserAgentDecorator(versions ...VersionInfo) HTTPRequestDecorator {
ret := new(HTTPUserAgentDecorator)
ret.versions = versions
return ret
}
2013-11-18 18:35:56 -05:00
func (h *HTTPUserAgentDecorator) ChangeRequest(req *http.Request) (newReq *http.Request, err error) {
2013-08-02 02:47:58 -04:00
if req == nil {
return req, nil
}
2013-11-18 18:35:56 -05:00
userAgent := appendVersions(req.UserAgent(), h.versions...)
2013-08-02 02:47:58 -04:00
if len(userAgent) > 0 {
req.Header.Set("User-Agent", userAgent)
}
return req, nil
}
type HTTPMetaHeadersDecorator struct {
Headers map[string][]string
}
2013-11-18 18:35:56 -05:00
func (h *HTTPMetaHeadersDecorator) ChangeRequest(req *http.Request) (newReq *http.Request, err error) {
if h.Headers == nil {
return req, nil
}
2013-11-18 18:35:56 -05:00
for k, v := range h.Headers {
req.Header[k] = v
}
return req, nil
}
2013-10-22 14:48:29 -04:00
type HTTPAuthDecorator struct {
login string
password string
}
func NewHTTPAuthDecorator(login, password string) HTTPRequestDecorator {
ret := new(HTTPAuthDecorator)
ret.login = login
ret.password = password
return ret
}
func (self *HTTPAuthDecorator) ChangeRequest(req *http.Request) (*http.Request, error) {
req.SetBasicAuth(self.login, self.password)
return req, nil
}
2013-08-02 02:47:58 -04:00
// HTTPRequestFactory creates an HTTP request
// and applies a list of decorators on the request.
type HTTPRequestFactory struct {
decorators []HTTPRequestDecorator
}
func NewHTTPRequestFactory(d ...HTTPRequestDecorator) *HTTPRequestFactory {
2013-11-18 18:35:56 -05:00
return &HTTPRequestFactory{
decorators: d,
}
2013-08-02 02:47:58 -04:00
}
2013-10-22 14:48:29 -04:00
func (self *HTTPRequestFactory) AddDecorator(d... HTTPRequestDecorator) {
self.decorators = append(self.decorators, d...)
}
2013-08-02 02:47:58 -04:00
// NewRequest() creates a new *http.Request,
// applies all decorators in the HTTPRequestFactory on the request,
// then applies decorators provided by d on the request.
2013-11-18 18:35:56 -05:00
func (h *HTTPRequestFactory) NewRequest(method, urlStr string, body io.Reader, d ...HTTPRequestDecorator) (*http.Request, error) {
2013-08-02 02:47:58 -04:00
req, err := http.NewRequest(method, urlStr, body)
if err != nil {
return nil, err
}
2013-08-02 03:23:46 -04:00
// By default, a nil factory should work.
2013-11-18 18:35:56 -05:00
if h == nil {
2013-08-02 03:23:46 -04:00
return req, nil
}
2013-11-18 18:35:56 -05:00
for _, dec := range h.decorators {
2013-08-02 02:47:58 -04:00
req, err = dec.ChangeRequest(req)
if err != nil {
return nil, err
}
}
for _, dec := range d {
req, err = dec.ChangeRequest(req)
if err != nil {
return nil, err
}
}
2013-10-22 14:48:29 -04:00
Debugf("%v -- HEADERS: %v", req.URL, req.Header)
2013-08-02 02:47:58 -04:00
return req, err
}