mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge branch 'feature/attach_ws' into feature/attach_ws2
Conflicts: api.go
This commit is contained in:
commit
e2ca600fd8
1 changed files with 106 additions and 43 deletions
149
api.go
149
api.go
|
@ -1,6 +1,7 @@
|
||||||
package docker
|
package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"code.google.com/p/go.net/websocket"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dotcloud/docker/auth"
|
"github.com/dotcloud/docker/auth"
|
||||||
|
@ -22,6 +23,8 @@ const APIVERSION = 1.4
|
||||||
const DEFAULTHTTPHOST string = "127.0.0.1"
|
const DEFAULTHTTPHOST string = "127.0.0.1"
|
||||||
const DEFAULTHTTPPORT int = 4243
|
const DEFAULTHTTPPORT int = 4243
|
||||||
|
|
||||||
|
type HttpApiFunc func(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error
|
||||||
|
|
||||||
func hijackServer(w http.ResponseWriter) (io.ReadCloser, io.Writer, error) {
|
func hijackServer(w http.ResponseWriter) (io.ReadCloser, io.Writer, error) {
|
||||||
conn, _, err := w.(http.Hijacker).Hijack()
|
conn, _, err := w.(http.Hijacker).Hijack()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -741,6 +744,53 @@ func postContainersAttach(srv *Server, version float64, w http.ResponseWriter, r
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func wsContainersAttach(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
|
|
||||||
|
if err := parseForm(r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logs, err := getBoolParam(r.Form.Get("logs"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
stream, err := getBoolParam(r.Form.Get("stream"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
stdin, err := getBoolParam(r.Form.Get("stdin"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
stdout, err := getBoolParam(r.Form.Get("stdout"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
stderr, err := getBoolParam(r.Form.Get("stderr"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if vars == nil {
|
||||||
|
return fmt.Errorf("Missing parameter")
|
||||||
|
}
|
||||||
|
name := vars["name"]
|
||||||
|
|
||||||
|
if _, err := srv.ContainerInspect(name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
h := websocket.Handler(func(ws *websocket.Conn) {
|
||||||
|
defer ws.Close()
|
||||||
|
|
||||||
|
if err := srv.ContainerAttach(name, logs, stream, stdin, stdout, stderr, ws, ws); err != nil {
|
||||||
|
utils.Debugf("Error: %s", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
h.ServeHTTP(w, r)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func getContainersByName(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
func getContainersByName(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return fmt.Errorf("Missing parameter")
|
return fmt.Errorf("Missing parameter")
|
||||||
|
@ -911,25 +961,61 @@ func writeCorsHeaders(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS")
|
w.Header().Add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeHttpHandler(srv *Server, logging bool, localMethod string, localRoute string, handlerFunc HttpApiFunc) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// log the request
|
||||||
|
utils.Debugf("Calling %s %s", localMethod, localRoute)
|
||||||
|
|
||||||
|
if logging {
|
||||||
|
log.Println(r.Method, r.RequestURI)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(r.Header.Get("User-Agent"), "Docker-Client/") {
|
||||||
|
userAgent := strings.Split(r.Header.Get("User-Agent"), "/")
|
||||||
|
if len(userAgent) == 2 && userAgent[1] != VERSION {
|
||||||
|
utils.Debugf("Warning: client and server don't have the same version (client: %s, server: %s)", userAgent[1], VERSION)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
version, err := strconv.ParseFloat(mux.Vars(r)["version"], 64)
|
||||||
|
if err != nil {
|
||||||
|
version = APIVERSION
|
||||||
|
}
|
||||||
|
if srv.enableCors {
|
||||||
|
writeCorsHeaders(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
if version == 0 || version > APIVERSION {
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := handlerFunc(srv, version, w, r, mux.Vars(r)); err != nil {
|
||||||
|
utils.Debugf("Error: %s", err)
|
||||||
|
httpError(w, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func createRouter(srv *Server, logging bool) (*mux.Router, error) {
|
func createRouter(srv *Server, logging bool) (*mux.Router, error) {
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
|
|
||||||
m := map[string]map[string]func(*Server, float64, http.ResponseWriter, *http.Request, map[string]string) error{
|
m := map[string]map[string]HttpApiFunc{
|
||||||
"GET": {
|
"GET": {
|
||||||
"/events": getEvents,
|
"/events": getEvents,
|
||||||
"/info": getInfo,
|
"/info": getInfo,
|
||||||
"/version": getVersion,
|
"/version": getVersion,
|
||||||
"/images/json": getImagesJSON,
|
"/images/json": getImagesJSON,
|
||||||
"/images/viz": getImagesViz,
|
"/images/viz": getImagesViz,
|
||||||
"/images/search": getImagesSearch,
|
"/images/search": getImagesSearch,
|
||||||
"/images/{name:.*}/history": getImagesHistory,
|
"/images/{name:.*}/history": getImagesHistory,
|
||||||
"/images/{name:.*}/json": getImagesByName,
|
"/images/{name:.*}/json": getImagesByName,
|
||||||
"/containers/ps": getContainersJSON,
|
"/containers/ps": getContainersJSON,
|
||||||
"/containers/json": getContainersJSON,
|
"/containers/json": getContainersJSON,
|
||||||
"/containers/{name:.*}/export": getContainersExport,
|
"/containers/{name:.*}/export": getContainersExport,
|
||||||
"/containers/{name:.*}/changes": getContainersChanges,
|
"/containers/{name:.*}/changes": getContainersChanges,
|
||||||
"/containers/{name:.*}/json": getContainersByName,
|
"/containers/{name:.*}/json": getContainersByName,
|
||||||
"/containers/{name:.*}/top": getContainersTop,
|
"/containers/{name:.*}/top": getContainersTop,
|
||||||
|
"/containers/{name:.*}/attach/ws": wsContainersAttach,
|
||||||
},
|
},
|
||||||
"POST": {
|
"POST": {
|
||||||
"/auth": postAuth,
|
"/auth": postAuth,
|
||||||
|
@ -964,37 +1050,13 @@ func createRouter(srv *Server, logging bool) (*mux.Router, error) {
|
||||||
utils.Debugf("Registering %s, %s", method, route)
|
utils.Debugf("Registering %s, %s", method, route)
|
||||||
// NOTE: scope issue, make sure the variables are local and won't be changed
|
// NOTE: scope issue, make sure the variables are local and won't be changed
|
||||||
localRoute := route
|
localRoute := route
|
||||||
localMethod := method
|
|
||||||
localFct := fct
|
localFct := fct
|
||||||
f := func(w http.ResponseWriter, r *http.Request) {
|
localMethod := method
|
||||||
utils.Debugf("Calling %s %s from %s", localMethod, localRoute, r.RemoteAddr)
|
|
||||||
|
|
||||||
if logging {
|
// build the handler function
|
||||||
log.Println(r.Method, r.RequestURI)
|
f := makeHttpHandler(srv, logging, localMethod, localRoute, localFct)
|
||||||
}
|
|
||||||
if strings.Contains(r.Header.Get("User-Agent"), "Docker-Client/") {
|
|
||||||
userAgent := strings.Split(r.Header.Get("User-Agent"), "/")
|
|
||||||
if len(userAgent) == 2 && userAgent[1] != VERSION {
|
|
||||||
utils.Debugf("Warning: client and server don't have the same version (client: %s, server: %s)", userAgent[1], VERSION)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
version, err := strconv.ParseFloat(mux.Vars(r)["version"], 64)
|
|
||||||
if err != nil {
|
|
||||||
version = APIVERSION
|
|
||||||
}
|
|
||||||
if srv.enableCors {
|
|
||||||
writeCorsHeaders(w, r)
|
|
||||||
}
|
|
||||||
if version == 0 || version > APIVERSION {
|
|
||||||
w.WriteHeader(http.StatusNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := localFct(srv, version, w, r, mux.Vars(r)); err != nil {
|
|
||||||
httpError(w, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// add the new route
|
||||||
if localRoute == "" {
|
if localRoute == "" {
|
||||||
r.Methods(localMethod).HandlerFunc(f)
|
r.Methods(localMethod).HandlerFunc(f)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1003,6 +1065,7 @@ func createRouter(srv *Server, logging bool) (*mux.Router, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue