use same HTTP client as dockerengine

Signed-off-by: Victor Vieux <vieux@docker.com>
This commit is contained in:
Victor Vieux 2016-02-10 00:02:34 -08:00
parent d9914ffa59
commit 64b9c50b69
3 changed files with 37 additions and 26 deletions

View File

@ -124,9 +124,9 @@ func getImages(c *context, w http.ResponseWriter, r *http.Request) {
names := r.Form["names"] names := r.Form["names"]
// Create a map of engine address to the list of images it holds. // Create a map of engine address to the list of images it holds.
engineImages := make(map[string][]*cluster.Image) engineImages := make(map[*cluster.Engine][]*cluster.Image)
for _, image := range c.cluster.Images() { for _, image := range c.cluster.Images() {
engineImages[image.Engine.Addr] = append(engineImages[image.Engine.Addr], image) engineImages[image.Engine] = append(engineImages[image.Engine], image)
} }
// Look for an engine that has all the images we need. // Look for an engine that has all the images we need.
@ -146,7 +146,7 @@ func getImages(c *context, w http.ResponseWriter, r *http.Request) {
// If the engine has all images, stop our search here. // If the engine has all images, stop our search here.
if matchedImages == len(names) { if matchedImages == len(names) {
proxy(c.tlsConfig, engine, w, r) proxy(engine, w, r)
return return
} }
} }
@ -462,7 +462,11 @@ func getContainerJSON(c *context, w http.ResponseWriter, r *http.Request) {
return return
} }
client, scheme := newClientAndScheme(c.tlsConfig) client, scheme := container.Engine.HTTPClientAndScheme()
if client == nil {
httpError(w, "Cannot connect to docker engine", http.StatusInternalServerError)
return
}
resp, err := client.Get(scheme + "://" + container.Engine.Addr + "/containers/" + container.Id + "/json") resp, err := client.Get(scheme + "://" + container.Engine.Addr + "/containers/" + container.Id + "/json")
container.Engine.CheckConnectionErr(err) container.Engine.CheckConnectionErr(err)
@ -767,7 +771,11 @@ func postContainersExec(c *context, w http.ResponseWriter, r *http.Request) {
return return
} }
client, scheme := newClientAndScheme(c.tlsConfig) client, scheme := container.Engine.HTTPClientAndScheme()
if client == nil {
httpError(w, "Cannot connect to docker engine", http.StatusInternalServerError)
return
}
resp, err := client.Post(scheme+"://"+container.Engine.Addr+"/containers/"+container.Id+"/exec", "application/json", r.Body) resp, err := client.Post(scheme+"://"+container.Engine.Addr+"/containers/"+container.Id+"/exec", "application/json", r.Body)
container.Engine.CheckConnectionErr(err) container.Engine.CheckConnectionErr(err)
@ -931,7 +939,7 @@ func proxyNetworkDisconnect(c *context, w http.ResponseWriter, r *http.Request)
} }
// request is forwarded to the container's address // request is forwarded to the container's address
err := proxyAsync(c.tlsConfig, engine.Addr, w, r, cb) err := proxyAsync(engine, w, r, cb)
engine.CheckConnectionErr(err) engine.CheckConnectionErr(err)
if err != nil { if err != nil {
httpError(w, err.Error(), http.StatusNotFound) httpError(w, err.Error(), http.StatusNotFound)
@ -974,7 +982,7 @@ func proxyNetworkConnect(c *context, w http.ResponseWriter, r *http.Request) {
} }
// request is forwarded to the container's address // request is forwarded to the container's address
err := proxyAsync(c.tlsConfig, container.Engine.Addr, w, r, cb) err := proxyAsync(container.Engine, w, r, cb)
container.Engine.CheckConnectionErr(err) container.Engine.CheckConnectionErr(err)
if err != nil { if err != nil {
httpError(w, err.Error(), http.StatusNotFound) httpError(w, err.Error(), http.StatusNotFound)
@ -997,7 +1005,7 @@ func proxyContainer(c *context, w http.ResponseWriter, r *http.Request) {
r.URL.Path = strings.Replace(r.URL.Path, name, container.Id, 1) r.URL.Path = strings.Replace(r.URL.Path, name, container.Id, 1)
} }
err = proxy(c.tlsConfig, container.Engine.Addr, w, r) err = proxy(container.Engine, w, r)
container.Engine.CheckConnectionErr(err) container.Engine.CheckConnectionErr(err)
if err != nil { if err != nil {
httpError(w, err.Error(), http.StatusInternalServerError) httpError(w, err.Error(), http.StatusInternalServerError)
@ -1025,7 +1033,7 @@ func proxyContainerAndForceRefresh(c *context, w http.ResponseWriter, r *http.Re
container.Refresh() container.Refresh()
} }
err = proxyAsync(c.tlsConfig, container.Engine.Addr, w, r, cb) err = proxyAsync(container.Engine, w, r, cb)
container.Engine.CheckConnectionErr(err) container.Engine.CheckConnectionErr(err)
if err != nil { if err != nil {
httpError(w, err.Error(), http.StatusInternalServerError) httpError(w, err.Error(), http.StatusInternalServerError)
@ -1037,7 +1045,7 @@ func proxyImage(c *context, w http.ResponseWriter, r *http.Request) {
name := mux.Vars(r)["name"] name := mux.Vars(r)["name"]
if image := c.cluster.Image(name); image != nil { if image := c.cluster.Image(name); image != nil {
err := proxy(c.tlsConfig, image.Engine.Addr, w, r) err := proxy(image.Engine, w, r)
image.Engine.CheckConnectionErr(err) image.Engine.CheckConnectionErr(err)
return return
} }
@ -1051,7 +1059,7 @@ func proxyImageGet(c *context, w http.ResponseWriter, r *http.Request) {
for _, image := range c.cluster.Images() { for _, image := range c.cluster.Images() {
if len(strings.SplitN(name, ":", 2)) == 2 && image.Match(name, true) || if len(strings.SplitN(name, ":", 2)) == 2 && image.Match(name, true) ||
len(strings.SplitN(name, ":", 2)) == 1 && image.Match(name, false) { len(strings.SplitN(name, ":", 2)) == 1 && image.Match(name, false) {
err := proxy(c.tlsConfig, image.Engine.Addr, w, r) err := proxy(image.Engine, w, r)
image.Engine.CheckConnectionErr(err) image.Engine.CheckConnectionErr(err)
return return
} }
@ -1075,7 +1083,7 @@ func proxyImagePush(c *context, w http.ResponseWriter, r *http.Request) {
for _, image := range c.cluster.Images() { for _, image := range c.cluster.Images() {
if tag != "" && image.Match(name, true) || if tag != "" && image.Match(name, true) ||
tag == "" && image.Match(name, false) { tag == "" && image.Match(name, false) {
err := proxy(c.tlsConfig, image.Engine.Addr, w, r) err := proxy(image.Engine, w, r)
image.Engine.CheckConnectionErr(err) image.Engine.CheckConnectionErr(err)
return return
} }
@ -1120,7 +1128,7 @@ func proxyRandom(c *context, w http.ResponseWriter, r *http.Request) {
return return
} }
err = proxy(c.tlsConfig, engine.Addr, w, r) err = proxy(engine, w, r)
engine.CheckConnectionErr(err) engine.CheckConnectionErr(err)
if err != nil { if err != nil {
httpError(w, err.Error(), http.StatusInternalServerError) httpError(w, err.Error(), http.StatusInternalServerError)
@ -1159,7 +1167,7 @@ func postCommit(c *context, w http.ResponseWriter, r *http.Request) {
} }
// proxy commit request to the right node // proxy commit request to the right node
err = proxyAsync(c.tlsConfig, container.Engine.Addr, w, r, cb) err = proxyAsync(container.Engine, w, r, cb)
container.Engine.CheckConnectionErr(err) container.Engine.CheckConnectionErr(err)
if err != nil { if err != nil {
httpError(w, err.Error(), http.StatusInternalServerError) httpError(w, err.Error(), http.StatusInternalServerError)

View File

@ -54,12 +54,6 @@ func sendErrorJSONMessage(w io.Writer, errorCode int, errorMessage string) {
json.NewEncoder(w).Encode(message) json.NewEncoder(w).Encode(message)
} }
func newClientAndScheme(tlsConfig *tls.Config) (*http.Client, string) {
if tlsConfig != nil {
return &http.Client{Transport: &http.Transport{TLSClientConfig: tlsConfig}}, "https"
}
return &http.Client{}, "http"
}
func getContainerFromVars(c *context, vars map[string]string) (string, *cluster.Container, error) { func getContainerFromVars(c *context, vars map[string]string) (string, *cluster.Container, error) {
if name, ok := vars["name"]; ok { if name, ok := vars["name"]; ok {
@ -102,14 +96,14 @@ func closeIdleConnections(client *http.Client) {
} }
} }
func proxyAsync(tlsConfig *tls.Config, addr string, w http.ResponseWriter, r *http.Request, callback func(*http.Response)) error { func proxyAsync(engine *cluster.Engine, w http.ResponseWriter, r *http.Request, callback func(*http.Response)) error {
// Use a new client for each request
client, scheme := newClientAndScheme(tlsConfig)
// RequestURI may not be sent to client // RequestURI may not be sent to client
r.RequestURI = "" r.RequestURI = ""
client, scheme := engine.HTTPClientAndScheme()
r.URL.Scheme = scheme r.URL.Scheme = scheme
r.URL.Host = addr r.URL.Host = engine.Addr
log.WithFields(log.Fields{"method": r.Method, "url": r.URL}).Debug("Proxy request") log.WithFields(log.Fields{"method": r.Method, "url": r.URL}).Debug("Proxy request")
resp, err := client.Do(r) resp, err := client.Do(r)
@ -132,8 +126,8 @@ func proxyAsync(tlsConfig *tls.Config, addr string, w http.ResponseWriter, r *ht
return nil return nil
} }
func proxy(tlsConfig *tls.Config, addr string, w http.ResponseWriter, r *http.Request) error { func proxy(engine *cluster.Engine, w http.ResponseWriter, r *http.Request) error {
return proxyAsync(tlsConfig, addr, w, r, nil) return proxyAsync(engine, w, r, nil)
} }
type tlsClientConn struct { type tlsClientConn struct {

View File

@ -8,6 +8,7 @@ import (
"math" "math"
"math/rand" "math/rand"
"net" "net"
"net/http"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -131,6 +132,14 @@ func NewEngine(addr string, overcommitRatio float64, opts *EngineOpts) *Engine {
return e return e
} }
// HTTPClientAndScheme returns the underlying HTTPClient and the scheme used by the engine
func (e *Engine) HTTPClientAndScheme() (*http.Client, string) {
if dc, ok := e.client.(*dockerclient.DockerClient); ok {
return dc.HTTPClient, dc.URL.Scheme
}
return nil, ""
}
// Connect will initialize a connection to the Docker daemon running on the // Connect will initialize a connection to the Docker daemon running on the
// host, gather machine specs (memory, cpu, ...) and monitor state changes. // host, gather machine specs (memory, cpu, ...) and monitor state changes.
func (e *Engine) Connect(config *tls.Config) error { func (e *Engine) Connect(config *tls.Config) error {