mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
http utils
This commit is contained in:
parent
ea2486d631
commit
793fd983ef
1 changed files with 129 additions and 0 deletions
129
utils/http.go
Normal file
129
utils/http.go
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *HTTPUserAgentDecorator) ChangeRequest(req *http.Request) (newReq *http.Request, err error) {
|
||||||
|
if req == nil {
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
userAgent := appendVersions(req.UserAgent(), self.versions...)
|
||||||
|
if len(userAgent) > 0 {
|
||||||
|
req.Header.Set("User-Agent", userAgent)
|
||||||
|
}
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPRequestFactory creates an HTTP request
|
||||||
|
// and applies a list of decorators on the request.
|
||||||
|
type HTTPRequestFactory struct {
|
||||||
|
decorators []HTTPRequestDecorator
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHTTPRequestFactory(d ...HTTPRequestDecorator) *HTTPRequestFactory {
|
||||||
|
ret := new(HTTPRequestFactory)
|
||||||
|
ret.decorators = d
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRequest() creates a new *http.Request,
|
||||||
|
// applies all decorators in the HTTPRequestFactory on the request,
|
||||||
|
// then applies decorators provided by d on the request.
|
||||||
|
func (self *HTTPRequestFactory) NewRequest(method, urlStr string, body io.Reader, d ...HTTPRequestDecorator) (*http.Request, error) {
|
||||||
|
req, err := http.NewRequest(method, urlStr, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, dec := range self.decorators {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return req, err
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue