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"]
// 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() {
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.
@ -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 matchedImages == len(names) {
proxy(c.tlsConfig, engine, w, r)
proxy(engine, w, r)
return
}
}
@ -462,7 +462,11 @@ func getContainerJSON(c *context, w http.ResponseWriter, r *http.Request) {
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")
container.Engine.CheckConnectionErr(err)
@ -767,7 +771,11 @@ func postContainersExec(c *context, w http.ResponseWriter, r *http.Request) {
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)
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
err := proxyAsync(c.tlsConfig, engine.Addr, w, r, cb)
err := proxyAsync(engine, w, r, cb)
engine.CheckConnectionErr(err)
if err != nil {
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
err := proxyAsync(c.tlsConfig, container.Engine.Addr, w, r, cb)
err := proxyAsync(container.Engine, w, r, cb)
container.Engine.CheckConnectionErr(err)
if err != nil {
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)
}
err = proxy(c.tlsConfig, container.Engine.Addr, w, r)
err = proxy(container.Engine, w, r)
container.Engine.CheckConnectionErr(err)
if err != nil {
httpError(w, err.Error(), http.StatusInternalServerError)
@ -1025,7 +1033,7 @@ func proxyContainerAndForceRefresh(c *context, w http.ResponseWriter, r *http.Re
container.Refresh()
}
err = proxyAsync(c.tlsConfig, container.Engine.Addr, w, r, cb)
err = proxyAsync(container.Engine, w, r, cb)
container.Engine.CheckConnectionErr(err)
if err != nil {
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"]
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)
return
}
@ -1051,7 +1059,7 @@ func proxyImageGet(c *context, w http.ResponseWriter, r *http.Request) {
for _, image := range c.cluster.Images() {
if len(strings.SplitN(name, ":", 2)) == 2 && image.Match(name, true) ||
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)
return
}
@ -1075,7 +1083,7 @@ func proxyImagePush(c *context, w http.ResponseWriter, r *http.Request) {
for _, image := range c.cluster.Images() {
if tag != "" && image.Match(name, true) ||
tag == "" && image.Match(name, false) {
err := proxy(c.tlsConfig, image.Engine.Addr, w, r)
err := proxy(image.Engine, w, r)
image.Engine.CheckConnectionErr(err)
return
}
@ -1120,7 +1128,7 @@ func proxyRandom(c *context, w http.ResponseWriter, r *http.Request) {
return
}
err = proxy(c.tlsConfig, engine.Addr, w, r)
err = proxy(engine, w, r)
engine.CheckConnectionErr(err)
if err != nil {
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
err = proxyAsync(c.tlsConfig, container.Engine.Addr, w, r, cb)
err = proxyAsync(container.Engine, w, r, cb)
container.Engine.CheckConnectionErr(err)
if err != nil {
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)
}
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) {
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 {
// Use a new client for each request
client, scheme := newClientAndScheme(tlsConfig)
func proxyAsync(engine *cluster.Engine, w http.ResponseWriter, r *http.Request, callback func(*http.Response)) error {
// RequestURI may not be sent to client
r.RequestURI = ""
client, scheme := engine.HTTPClientAndScheme()
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")
resp, err := client.Do(r)
@ -132,8 +126,8 @@ func proxyAsync(tlsConfig *tls.Config, addr string, w http.ResponseWriter, r *ht
return nil
}
func proxy(tlsConfig *tls.Config, addr string, w http.ResponseWriter, r *http.Request) error {
return proxyAsync(tlsConfig, addr, w, r, nil)
func proxy(engine *cluster.Engine, w http.ResponseWriter, r *http.Request) error {
return proxyAsync(engine, w, r, nil)
}
type tlsClientConn struct {

View File

@ -8,6 +8,7 @@ import (
"math"
"math/rand"
"net"
"net/http"
"strings"
"sync"
"time"
@ -131,6 +132,14 @@ func NewEngine(addr string, overcommitRatio float64, opts *EngineOpts) *Engine {
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
// host, gather machine specs (memory, cpu, ...) and monitor state changes.
func (e *Engine) Connect(config *tls.Config) error {