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

* Remote Api: Add flag to enable cross domain requests

This commit is contained in:
Victor Vieux 2013-06-11 10:12:36 +00:00
commit 20bf0e00e8
5 changed files with 119 additions and 10 deletions

38
api.go
View file

@ -703,9 +703,18 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
return nil return nil
} }
func ListenAndServe(addr string, srv *Server, logging bool) error { func optionsHandler(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
w.WriteHeader(http.StatusOK)
return nil
}
func writeCorsHeaders(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Access-Control-Allow-Origin", "*")
w.Header().Add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
w.Header().Add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS")
}
func createRouter(srv *Server, logging bool) (*mux.Router, error) {
r := mux.NewRouter() r := mux.NewRouter()
log.Printf("Listening for HTTP on %s\n", addr)
m := map[string]map[string]func(*Server, float64, http.ResponseWriter, *http.Request, map[string]string) error{ m := map[string]map[string]func(*Server, float64, http.ResponseWriter, *http.Request, map[string]string) error{
"GET": { "GET": {
@ -745,6 +754,9 @@ func ListenAndServe(addr string, srv *Server, logging bool) error {
"/containers/{name:.*}": deleteContainers, "/containers/{name:.*}": deleteContainers,
"/images/{name:.*}": deleteImages, "/images/{name:.*}": deleteImages,
}, },
"OPTIONS": {
"": optionsHandler,
},
} }
for method, routes := range m { for method, routes := range m {
@ -769,6 +781,9 @@ func ListenAndServe(addr string, srv *Server, logging bool) error {
if err != nil { if err != nil {
version = APIVERSION version = APIVERSION
} }
if srv.enableCors {
writeCorsHeaders(w, r)
}
if version == 0 || version > APIVERSION { if version == 0 || version > APIVERSION {
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
return return
@ -777,9 +792,24 @@ func ListenAndServe(addr string, srv *Server, logging bool) error {
httpError(w, err) httpError(w, err)
} }
} }
r.Path("/v{version:[0-9.]+}" + localRoute).Methods(localMethod).HandlerFunc(f)
r.Path(localRoute).Methods(localMethod).HandlerFunc(f) if localRoute == "" {
r.Methods(localMethod).HandlerFunc(f)
} else {
r.Path("/v{version:[0-9.]+}" + localRoute).Methods(localMethod).HandlerFunc(f)
r.Path(localRoute).Methods(localMethod).HandlerFunc(f)
}
} }
} }
return r, nil
}
func ListenAndServe(addr string, srv *Server, logging bool) error {
log.Printf("Listening for HTTP on %s\n", addr)
r, err := createRouter(srv, logging)
if err != nil {
return err
}
return http.ListenAndServe(addr, r) return http.ListenAndServe(addr, r)
} }

View file

@ -1239,6 +1239,73 @@ func TestDeleteContainers(t *testing.T) {
} }
} }
func TestOptionsRoute(t *testing.T) {
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{runtime: runtime, enableCors: true}
r := httptest.NewRecorder()
router, err := createRouter(srv, false)
if err != nil {
t.Fatal(err)
}
req, err := http.NewRequest("OPTIONS", "/", nil)
if err != nil {
t.Fatal(err)
}
router.ServeHTTP(r, req)
if r.Code != http.StatusOK {
t.Errorf("Expected response for OPTIONS request to be \"200\", %v found.", r.Code)
}
}
func TestGetEnabledCors(t *testing.T) {
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{runtime: runtime, enableCors: true}
r := httptest.NewRecorder()
router, err := createRouter(srv, false)
if err != nil {
t.Fatal(err)
}
req, err := http.NewRequest("GET", "/version", nil)
if err != nil {
t.Fatal(err)
}
router.ServeHTTP(r, req)
if r.Code != http.StatusOK {
t.Errorf("Expected response for OPTIONS request to be \"200\", %v found.", r.Code)
}
allowOrigin := r.Header().Get("Access-Control-Allow-Origin")
allowHeaders := r.Header().Get("Access-Control-Allow-Headers")
allowMethods := r.Header().Get("Access-Control-Allow-Methods")
if allowOrigin != "*" {
t.Errorf("Expected header Access-Control-Allow-Origin to be \"*\", %s found.", allowOrigin)
}
if allowHeaders != "Origin, X-Requested-With, Content-Type, Accept" {
t.Errorf("Expected header Access-Control-Allow-Headers to be \"Origin, X-Requested-With, Content-Type, Accept\", %s found.", allowHeaders)
}
if allowMethods != "GET, POST, DELETE, PUT, OPTIONS" {
t.Errorf("Expected hearder Access-Control-Allow-Methods to be \"GET, POST, DELETE, PUT, OPTIONS\", %s found.", allowMethods)
}
}
func TestDeleteImages(t *testing.T) { func TestDeleteImages(t *testing.T) {
//FIXME: Implement this test //FIXME: Implement this test
t.Log("Test not implemented") t.Log("Test not implemented")

View file

@ -33,6 +33,7 @@ func main() {
bridgeName := flag.String("b", "", "Attach containers to a pre-existing network bridge") bridgeName := flag.String("b", "", "Attach containers to a pre-existing network bridge")
pidfile := flag.String("p", "/var/run/docker.pid", "File containing process PID") pidfile := flag.String("p", "/var/run/docker.pid", "File containing process PID")
flHost := flag.String("H", fmt.Sprintf("%s:%d", host, port), "Host:port to bind/connect to") flHost := flag.String("H", fmt.Sprintf("%s:%d", host, port), "Host:port to bind/connect to")
flEnableCors := flag.Bool("api-enable-cors", false, "Enable CORS requests in the remote api.")
flag.Parse() flag.Parse()
if *bridgeName != "" { if *bridgeName != "" {
docker.NetworkBridgeIface = *bridgeName docker.NetworkBridgeIface = *bridgeName
@ -65,7 +66,7 @@ func main() {
flag.Usage() flag.Usage()
return return
} }
if err := daemon(*pidfile, host, port, *flAutoRestart); err != nil { if err := daemon(*pidfile, host, port, *flAutoRestart, *flEnableCors); err != nil {
log.Fatal(err) log.Fatal(err)
os.Exit(-1) os.Exit(-1)
} }
@ -104,7 +105,7 @@ func removePidFile(pidfile string) {
} }
} }
func daemon(pidfile, addr string, port int, autoRestart bool) error { func daemon(pidfile, addr string, port int, autoRestart, enableCors bool) error {
if addr != "127.0.0.1" { if addr != "127.0.0.1" {
log.Println("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\") log.Println("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
} }
@ -122,7 +123,7 @@ func daemon(pidfile, addr string, port int, autoRestart bool) error {
os.Exit(0) os.Exit(0)
}() }()
server, err := docker.NewServer(autoRestart) server, err := docker.NewServer(autoRestart, enableCors)
if err != nil { if err != nil {
return err return err
} }

View file

@ -1057,6 +1057,14 @@ Here are the steps of 'docker run' :
In this first version of the API, some of the endpoints, like /attach, /pull or /push uses hijacking to transport stdin, In this first version of the API, some of the endpoints, like /attach, /pull or /push uses hijacking to transport stdin,
stdout and stderr on the same socket. This might change in the future. stdout and stderr on the same socket. This might change in the future.
3.3 CORS Requests
-----------------
To enable cross origin requests to the remote api add the flag "-api-enable-cors" when running docker in daemon mode.
docker -d -H="192.168.1.9:4243" -api-enable-cors
================================== ==================================
Docker Remote API Client Libraries Docker Remote API Client Libraries
================================== ==================================
@ -1080,3 +1088,4 @@ and we will add the libraries here.
| Javascript (Angular) | dockerui | https://github.com/crosbymichael/dockerui | | Javascript (Angular) | dockerui | https://github.com/crosbymichael/dockerui |
| **WebUI** | | | | **WebUI** | | |
+----------------------+----------------+--------------------------------------------+ +----------------------+----------------+--------------------------------------------+

View file

@ -879,7 +879,7 @@ func (srv *Server) ImageInspect(name string) (*Image, error) {
return nil, fmt.Errorf("No such image: %s", name) return nil, fmt.Errorf("No such image: %s", name)
} }
func NewServer(autoRestart bool) (*Server, error) { func NewServer(autoRestart, enableCors bool) (*Server, error) {
if runtime.GOARCH != "amd64" { if runtime.GOARCH != "amd64" {
log.Fatalf("The docker runtime currently only supports amd64 (not %s). This will change in the future. Aborting.", runtime.GOARCH) log.Fatalf("The docker runtime currently only supports amd64 (not %s). This will change in the future. Aborting.", runtime.GOARCH)
} }
@ -888,12 +888,14 @@ func NewServer(autoRestart bool) (*Server, error) {
return nil, err return nil, err
} }
srv := &Server{ srv := &Server{
runtime: runtime, runtime: runtime,
enableCors: enableCors,
} }
runtime.srv = srv runtime.srv = srv
return srv, nil return srv, nil
} }
type Server struct { type Server struct {
runtime *Runtime runtime *Runtime
enableCors bool
} }