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:
commit
20bf0e00e8
5 changed files with 119 additions and 10 deletions
38
api.go
38
api.go
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
67
api_test.go
67
api_test.go
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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** | | |
|
||||||
+----------------------+----------------+--------------------------------------------+
|
+----------------------+----------------+--------------------------------------------+
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue