fix: some apis bypassed authentication (#1373)

diff --git a/api/go.mod b/api/go.mod
index a30e7a2..d1681ff 100644
--- a/api/go.mod
+++ b/api/go.mod
@@ -29,7 +29,7 @@
 	github.com/jonboulle/clockwork v0.2.2 // indirect
 	github.com/prometheus/client_golang v1.8.0 // indirect
 	github.com/satori/go.uuid v1.2.0
-	github.com/shiningrush/droplet v0.2.4
+	github.com/shiningrush/droplet v0.2.6-0.20210126131015-cbf9557974f7
 	github.com/shiningrush/droplet/wrapper/gin v0.2.1
 	github.com/sirupsen/logrus v1.7.0 // indirect
 	github.com/sony/sonyflake v1.0.0
diff --git a/api/go.sum b/api/go.sum
index 503d19b..541e882 100644
--- a/api/go.sum
+++ b/api/go.sum
@@ -339,6 +339,8 @@
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
 github.com/shiningrush/droplet v0.2.4 h1:OW4Pp+dXs9O61QKTiYSRWCdQeOyzO1n9h+i2PDJ5DK0=
 github.com/shiningrush/droplet v0.2.4/go.mod h1:akW2vIeamvMD6zj6wIBfzYn6StGXBxwlW3gA+hcHu5M=
+github.com/shiningrush/droplet v0.2.6-0.20210126131015-cbf9557974f7 h1:E0+CduActvXFpdvUXu7wxfw+trl5MKRkY4IZ1uQYsvc=
+github.com/shiningrush/droplet v0.2.6-0.20210126131015-cbf9557974f7/go.mod h1:akW2vIeamvMD6zj6wIBfzYn6StGXBxwlW3gA+hcHu5M=
 github.com/shiningrush/droplet/wrapper/gin v0.2.1 h1:1o+5KUF2sKsdZ7SkmOC5ahAP1qaZKqnm0c5hOYFV6YQ=
 github.com/shiningrush/droplet/wrapper/gin v0.2.1/go.mod h1:cx5BfLuStFDFIKuEOc1zBTpiT3B4Ezkg3MdlP6rW51I=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
diff --git a/api/internal/handler/global_rule/global_rule.go b/api/internal/handler/global_rule/global_rule.go
index cb7630a..cc83e93 100644
--- a/api/internal/handler/global_rule/global_rule.go
+++ b/api/internal/handler/global_rule/global_rule.go
@@ -31,7 +31,6 @@
 	"github.com/apisix/manager-api/internal/core/store"
 	"github.com/apisix/manager-api/internal/handler"
 	"github.com/apisix/manager-api/internal/utils"
-	"github.com/apisix/manager-api/internal/utils/consts"
 )
 
 type Handler struct {
@@ -55,8 +54,10 @@
 	r.PUT("/apisix/admin/global_rules", wgin.Wraps(h.Set,
 		wrapper.InputType(reflect.TypeOf(SetInput{}))))
 
-	r.PATCH("/apisix/admin/global_rules/:id", consts.ErrorWrapper(Patch))
-	r.PATCH("/apisix/admin/global_rules/:id/*path", consts.ErrorWrapper(Patch))
+	r.PATCH("/apisix/admin/global_rules/:id", wgin.Wraps(h.Patch,
+		wrapper.InputType(reflect.TypeOf(PatchInput{}))))
+	r.PATCH("/apisix/admin/global_rules/:id/*path", wgin.Wraps(h.Patch,
+		wrapper.InputType(reflect.TypeOf(PatchInput{}))))
 
 	r.DELETE("/apisix/admin/global_rules/:id", wgin.Wraps(h.BatchDelete,
 		wrapper.InputType(reflect.TypeOf(BatchDeleteInput{}))))
@@ -149,13 +150,20 @@
 	return ret, nil
 }
 
-func Patch(c *gin.Context) (interface{}, error) {
-	reqBody, _ := c.GetRawData()
-	ID := c.Param("id")
-	subPath := c.Param("path")
+type PatchInput struct {
+	ID      string `auto_read:"id,path"`
+	SubPath string `auto_read:"path,path"`
+	Body    []byte `auto_read:"@body"`
+}
+
+func (h *Handler) Patch(c droplet.Context) (interface{}, error) {
+	input := c.Input().(*PatchInput)
+	reqBody := input.Body
+	ID := input.ID
+	subPath := input.SubPath
 
 	routeStore := store.GetStore(store.HubKeyGlobalRule)
-	stored, err := routeStore.Get(c, ID)
+	stored, err := routeStore.Get(c.Context(), ID)
 	if err != nil {
 		return handler.SpecCodeResponse(err), err
 	}
@@ -171,7 +179,7 @@
 		return handler.SpecCodeResponse(err), err
 	}
 
-	ret, err := routeStore.Update(c, &globalRule, false)
+	ret, err := routeStore.Update(c.Context(), &globalRule, false)
 	if err != nil {
 		return handler.SpecCodeResponse(err), err
 	}
diff --git a/api/internal/handler/route/route.go b/api/internal/handler/route/route.go
index 764bf7a..2e3f15e 100644
--- a/api/internal/handler/route/route.go
+++ b/api/internal/handler/route/route.go
@@ -73,19 +73,29 @@
 	r.DELETE("/apisix/admin/routes/:ids", wgin.Wraps(h.BatchDelete,
 		wrapper.InputType(reflect.TypeOf(BatchDelete{}))))
 
-	r.PATCH("/apisix/admin/routes/:id", consts.ErrorWrapper(Patch))
-	r.PATCH("/apisix/admin/routes/:id/*path", consts.ErrorWrapper(Patch))
+	r.PATCH("/apisix/admin/routes/:id", wgin.Wraps(h.Patch,
+		wrapper.InputType(reflect.TypeOf(PatchInput{}))))
+	r.PATCH("/apisix/admin/routes/:id/*path", wgin.Wraps(h.Patch,
+		wrapper.InputType(reflect.TypeOf(PatchInput{}))))
 
-	r.GET("/apisix/admin/notexist/routes", consts.ErrorWrapper(Exist))
+	r.GET("/apisix/admin/notexist/routes", wgin.Wraps(h.Exist,
+		wrapper.InputType(reflect.TypeOf(ExistCheckInput{}))))
 }
 
-func Patch(c *gin.Context) (interface{}, error) {
-	reqBody, _ := c.GetRawData()
-	ID := c.Param("id")
-	subPath := c.Param("path")
+type PatchInput struct {
+	ID      string `auto_read:"id,path"`
+	SubPath string `auto_read:"path,path"`
+	Body    []byte `auto_read:"@body"`
+}
+
+func (h *Handler) Patch(c droplet.Context) (interface{}, error) {
+	input := c.Input().(*PatchInput)
+	reqBody := input.Body
+	ID := input.ID
+	subPath := input.SubPath
 
 	routeStore := store.GetStore(store.HubKeyRoute)
-	stored, err := routeStore.Get(c, ID)
+	stored, err := routeStore.Get(c.Context(), ID)
 	if err != nil {
 		return handler.SpecCodeResponse(err), err
 	}
@@ -101,7 +111,7 @@
 		return handler.SpecCodeResponse(err), err
 	}
 
-	ret, err := routeStore.Update(c, &route, false)
+	ret, err := routeStore.Update(c.Context(), &route, false)
 	if err != nil {
 		return handler.SpecCodeResponse(err), err
 	}
@@ -493,6 +503,11 @@
 	return rows
 }
 
+type ExistCheckInput struct {
+	Name    string `auto_read:"name,query"`
+	Exclude string `auto_read:"exclude,query"`
+}
+
 // swagger:operation GET /apisix/admin/notexist/routes checkRouteExist
 //
 // Return result of route exists checking by name and exclude id.
@@ -520,15 +535,13 @@
 //     description: unexpected error
 //     schema:
 //       "$ref": "#/definitions/ApiError"
-func Exist(c *gin.Context) (interface{}, error) {
-	//input := c.Input().(*ExistInput)
-
-	//temporary
-	name := c.Query("name")
-	exclude := c.Query("exclude")
+func (h *Handler) Exist(c droplet.Context) (interface{}, error) {
+	input := c.Input().(*ExistCheckInput)
+	name := input.Name
+	exclude := input.Exclude
 	routeStore := store.GetStore(store.HubKeyRoute)
 
-	ret, err := routeStore.List(c, store.ListInput{
+	ret, err := routeStore.List(c.Context(), store.ListInput{
 		Predicate:  nil,
 		PageSize:   0,
 		PageNumber: 0,
diff --git a/api/internal/handler/ssl/ssl.go b/api/internal/handler/ssl/ssl.go
index 89793a2..50b6e1b 100644
--- a/api/internal/handler/ssl/ssl.go
+++ b/api/internal/handler/ssl/ssl.go
@@ -67,10 +67,13 @@
 	r.POST("/apisix/admin/check_ssl_cert", wgin.Wraps(h.Validate,
 		wrapper.InputType(reflect.TypeOf(entity.SSL{}))))
 
-	r.PATCH("/apisix/admin/ssl/:id", consts.ErrorWrapper(Patch))
-	r.PATCH("/apisix/admin/ssl/:id/*path", consts.ErrorWrapper(Patch))
+	r.PATCH("/apisix/admin/ssl/:id", wgin.Wraps(h.Patch,
+		wrapper.InputType(reflect.TypeOf(PatchInput{}))))
+	r.PATCH("/apisix/admin/ssl/:id/*path", wgin.Wraps(h.Patch,
+		wrapper.InputType(reflect.TypeOf(PatchInput{}))))
 
-	r.POST("/apisix/admin/check_ssl_exists", consts.ErrorWrapper(Exist))
+	r.POST("/apisix/admin/check_ssl_exists", wgin.Wraps(h.Exist,
+		wrapper.InputType(reflect.TypeOf(ExistCheckInput{}))))
 }
 
 type GetInput struct {
@@ -234,13 +237,20 @@
 	return ret, nil
 }
 
-func Patch(c *gin.Context) (interface{}, error) {
-	reqBody, _ := c.GetRawData()
-	ID := c.Param("id")
-	subPath := c.Param("path")
+type PatchInput struct {
+	ID      string `auto_read:"id,path"`
+	SubPath string `auto_read:"path,path"`
+	Body    []byte `auto_read:"@body"`
+}
+
+func (h *Handler) Patch(c droplet.Context) (interface{}, error) {
+	input := c.Input().(*PatchInput)
+	reqBody := input.Body
+	ID := input.ID
+	subPath := input.SubPath
 
 	sslStore := store.GetStore(store.HubKeySsl)
-	stored, err := sslStore.Get(c, ID)
+	stored, err := sslStore.Get(c.Context(), ID)
 	if err != nil {
 		return handler.SpecCodeResponse(err), err
 	}
@@ -256,7 +266,7 @@
 		return handler.SpecCodeResponse(err), err
 	}
 
-	ret, err := sslStore.Update(c, &ssl, false)
+	ret, err := sslStore.Update(c.Context(), &ssl, false)
 	if err != nil {
 		return handler.SpecCodeResponse(err), err
 	}
@@ -423,6 +433,10 @@
 	return false
 }
 
+type ExistCheckInput struct {
+	Body []byte `auto_read:"@body"`
+}
+
 // swagger:operation POST /apisix/admin/check_ssl_exists checkSSLExist
 //
 // Check whether the SSL exists.
@@ -450,17 +464,17 @@
 //     description: unexpected error
 //     schema:
 //       "$ref": "#/definitions/ApiError"
-func Exist(c *gin.Context) (interface{}, error) {
-	//input := c.Input().(*ExistInput)
+func (h *Handler) Exist(c droplet.Context) (interface{}, error) {
+	input := c.Input().(*ExistCheckInput)
 	//temporary
-	reqBody, _ := c.GetRawData()
+	reqBody := input.Body
 	var hosts []string
 	if err := json.Unmarshal(reqBody, &hosts); err != nil {
 		return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest}, err
 	}
 
 	routeStore := store.GetStore(store.HubKeySsl)
-	ret, err := routeStore.List(c, store.ListInput{
+	ret, err := routeStore.List(c.Context(), store.ListInput{
 		Predicate:  nil,
 		PageSize:   0,
 		PageNumber: 0,
diff --git a/api/internal/handler/upstream/upstream.go b/api/internal/handler/upstream/upstream.go
index 54c3a6e..faab379 100644
--- a/api/internal/handler/upstream/upstream.go
+++ b/api/internal/handler/upstream/upstream.go
@@ -60,8 +60,10 @@
 	r.DELETE("/apisix/admin/upstreams/:ids", wgin.Wraps(h.BatchDelete,
 		wrapper.InputType(reflect.TypeOf(BatchDelete{}))))
 
-	r.GET("/apisix/admin/notexist/upstreams", consts.ErrorWrapper(Exist))
-	r.GET("/apisix/admin/names/upstreams", consts.ErrorWrapper(listUpstreamNames))
+	r.GET("/apisix/admin/notexist/upstreams", wgin.Wraps(h.Exist,
+		wrapper.InputType(reflect.TypeOf(ExistCheckInput{}))))
+
+	r.GET("/apisix/admin/names/upstreams", wgin.Wraps(h.listUpstreamNames))
 }
 
 type GetInput struct {
@@ -248,15 +250,18 @@
 	return rows
 }
 
-func Exist(c *gin.Context) (interface{}, error) {
-	//input := c.Input().(*ExistInput)
+type ExistCheckInput struct {
+	Name    string `auto_read:"name,query"`
+	Exclude string `auto_read:"exclude,query"`
+}
 
-	//temporary
-	name := c.Query("name")
-	exclude := c.Query("exclude")
+func (h *Handler) Exist(c droplet.Context) (interface{}, error) {
+	input := c.Input().(*ExistCheckInput)
+	name := input.Name
+	exclude := input.Exclude
 	routeStore := store.GetStore(store.HubKeyUpstream)
 
-	ret, err := routeStore.List(c, store.ListInput{
+	ret, err := routeStore.List(c.Context(), store.ListInput{
 		Predicate:  nil,
 		PageSize:   0,
 		PageNumber: 0,
@@ -275,17 +280,18 @@
 	if len(rows) > 0 {
 		r := rows[0].(*entity.Upstream)
 		if r.ID != exclude {
-			return nil, consts.InvalidParam("Upstream name is reduplicate")
+			return &data.SpecCodeResponse{StatusCode: http.StatusBadRequest},
+				consts.InvalidParam("Upstream name is reduplicate")
 		}
 	}
 
 	return nil, nil
 }
 
-func listUpstreamNames(c *gin.Context) (interface{}, error) {
+func (h *Handler) listUpstreamNames(c droplet.Context) (interface{}, error) {
 	routeStore := store.GetStore(store.HubKeyUpstream)
 
-	ret, err := routeStore.List(c, store.ListInput{
+	ret, err := routeStore.List(c.Context(), store.ListInput{
 		Predicate:  nil,
 		PageSize:   0,
 		PageNumber: 0,
diff --git a/api/internal/utils/consts/api_error.go b/api/internal/utils/consts/api_error.go
index 4e2a0c0..51e2efd 100644
--- a/api/internal/utils/consts/api_error.go
+++ b/api/internal/utils/consts/api_error.go
@@ -17,40 +17,11 @@
 package consts
 
 import (
-	"net/http"
-	"strings"
-
 	"github.com/gin-gonic/gin"
 )
 
 type WrapperHandle func(c *gin.Context) (interface{}, error)
 
-func ErrorWrapper(handle WrapperHandle) gin.HandlerFunc {
-	return func(c *gin.Context) {
-		data, err := handle(c)
-		if err != nil {
-			apiError, ok := err.(*ApiError)
-			if !ok {
-				errMsg := err.Error()
-				if strings.Contains(errMsg, "required") ||
-					strings.Contains(errMsg, "conflicted") ||
-					strings.Contains(errMsg, "invalid") ||
-					strings.Contains(errMsg, "missing") ||
-					strings.Contains(errMsg, "validate failed") {
-					apiError = InvalidParam(errMsg)
-				} else if strings.Contains(errMsg, "not found") {
-					apiError = NotFound(errMsg)
-				} else {
-					apiError = SystemError(errMsg)
-				}
-			}
-			c.JSON(apiError.Status, apiError)
-			return
-		}
-		c.JSON(http.StatusOK, gin.H{"data": data, "code": 0, "message": "success"})
-	}
-}
-
 // swagger:model ApiError
 type ApiError struct {
 	Status int `json:"-"`
diff --git a/api/internal/utils/consts/api_error_test.go b/api/internal/utils/consts/api_error_test.go
index 9be241e..3f5cae4 100644
--- a/api/internal/utils/consts/api_error_test.go
+++ b/api/internal/utils/consts/api_error_test.go
@@ -17,13 +17,8 @@
 package consts
 
 import (
-	"fmt"
 	"net/http"
 	"net/http/httptest"
-	"testing"
-
-	"github.com/gin-gonic/gin"
-	"github.com/stretchr/testify/assert"
 )
 
 func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
@@ -32,31 +27,3 @@
 	r.ServeHTTP(w, req)
 	return w
 }
-
-func TestRequestLogHandler(t *testing.T) {
-	r := gin.New()
-	r.GET("/", ErrorWrapper(func(c *gin.Context) (interface{}, error) {
-		return nil, nil
-	}))
-	r.GET("/notfound", ErrorWrapper(func(c *gin.Context) (interface{}, error) {
-		return nil, fmt.Errorf("data not found")
-	}))
-	r.GET("/invalid", ErrorWrapper(func(c *gin.Context) (interface{}, error) {
-		return nil, fmt.Errorf("schema validate failed")
-	}))
-	r.GET("/error", ErrorWrapper(func(c *gin.Context) (interface{}, error) {
-		return nil, fmt.Errorf("internal system error")
-	}))
-
-	w := performRequest(r, "GET", "/")
-	assert.Equal(t, 200, w.Code)
-
-	w = performRequest(r, "GET", "/notfound")
-	assert.Equal(t, 404, w.Code)
-
-	w = performRequest(r, "GET", "/invalid")
-	assert.Equal(t, 400, w.Code)
-
-	w = performRequest(r, "GET", "/error")
-	assert.Equal(t, 500, w.Code)
-}
diff --git a/api/test/docker/Dockerfile b/api/test/docker/Dockerfile
index 9f8a170..6374393 100644
--- a/api/test/docker/Dockerfile
+++ b/api/test/docker/Dockerfile
@@ -23,8 +23,6 @@
 
 RUN mkdir -p /go/manager-api/conf \
     && mkdir -p /go/manager-api/build-tools \
-    && go env -w GOPROXY=https://goproxy.io,direct \
-    && export GOPROXY=https://goproxy.io \
     && go test -c -cover -covermode=atomic -o /go/manager-api/manager-api -coverpkg "./..." ./cmd/manager \
     && mv /go/src/github.com/apisix/manager-api/entry.sh /go/manager-api/ \
     && mv /go/src/github.com/apisix/manager-api/build-tools/* /go/manager-api/build-tools/ \
diff --git a/api/test/e2e/base.go b/api/test/e2e/base.go
index 08fa71e..1cf59eb 100644
--- a/api/test/e2e/base.go
+++ b/api/test/e2e/base.go
@@ -54,6 +54,7 @@
 
 	url := ManagerAPIHost + "/apisix/admin/user/login"
 	req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(requestBody))
+	req.Header.Add("Content-Type", "application/json")
 	if err != nil {
 		panic(err)
 	}
@@ -217,8 +218,17 @@
 		}
 
 		// set header
+		setContentType := false
 		for key, val := range tc.Headers {
 			req.WithHeader(key, val)
+			if strings.ToLower(key) == "content-type" {
+				setContentType = true
+			}
+		}
+
+		// set default content-type
+		if !setContentType {
+			req.WithHeader("Content-Type", "application/json")
 		}
 
 		// set body
diff --git a/api/test/e2e/route_test.go b/api/test/e2e/route_test.go
index 0a606b2..307b65c 100644
--- a/api/test/e2e/route_test.go
+++ b/api/test/e2e/route_test.go
@@ -357,12 +357,15 @@
 			Sleep:        sleepTime,
 		},
 		{
-			Desc:         "route patch for update status (route online)",
-			Object:       ManagerApiExpect(t),
-			Method:       http.MethodPatch,
-			Path:         "/apisix/admin/routes/r1/status",
-			Body:         "1",
-			Headers:      map[string]string{"Authorization": token},
+			Desc:   "route patch for update status (route online)",
+			Object: ManagerApiExpect(t),
+			Method: http.MethodPatch,
+			Path:   "/apisix/admin/routes/r1/status",
+			Body:   "1",
+			Headers: map[string]string{
+				"Authorization": token,
+				"Content-Type":  "text/plain",
+			},
 			ExpectStatus: http.StatusOK,
 		},
 		{
diff --git a/api/test/e2e/route_with_management_fileds_test.go b/api/test/e2e/route_with_management_fileds_test.go
index 3c4bb3f..ab74ea7 100644
--- a/api/test/e2e/route_with_management_fileds_test.go
+++ b/api/test/e2e/route_with_management_fileds_test.go
@@ -50,6 +50,26 @@
 			ExpectStatus: http.StatusOK,
 		},
 		{
+			Desc:         "check route exists by name",
+			Object:       ManagerApiExpect(t),
+			Method:       http.MethodGet,
+			Path:         "/apisix/admin/notexist/routes",
+			Query:        "name=jack",
+			Headers:      map[string]string{"Authorization": token},
+			ExpectStatus: http.StatusBadRequest,
+			ExpectBody:   "Route name is reduplicate",
+			Sleep:        sleepTime,
+		},
+		{
+			Desc:         "check route exists by name (exclude it self)",
+			Object:       ManagerApiExpect(t),
+			Method:       http.MethodGet,
+			Path:         "/apisix/admin/notexist/routes",
+			Query:        "name=jack&exclude=r1",
+			Headers:      map[string]string{"Authorization": token},
+			ExpectStatus: http.StatusOK,
+		},
+		{
 			Desc:         "access the route's uri (r1)",
 			Object:       APISIXExpect(t),
 			Method:       http.MethodGet,
@@ -57,7 +77,6 @@
 			Headers:      map[string]string{"Authorization": token},
 			ExpectStatus: http.StatusOK,
 			ExpectBody:   "hello world",
-			Sleep:        sleepTime,
 		},
 		{
 			Desc:         "verify the route's content (r1)",
@@ -67,7 +86,6 @@
 			Headers:      map[string]string{"Authorization": token},
 			ExpectStatus: http.StatusOK,
 			ExpectBody:   "\"name\":\"jack\",\"desc\":\"config route with name and desc\"",
-			Sleep:        sleepTime,
 		},
 	}
 	for _, tc := range tests {
diff --git a/api/test/e2e/ssl_test.go b/api/test/e2e/ssl_test.go
index 8aafbcf..2c3096c 100644
--- a/api/test/e2e/ssl_test.go
+++ b/api/test/e2e/ssl_test.go
@@ -163,12 +163,15 @@
 	// enable SSL again
 	tests = []HttpTestCase{
 		{
-			Desc:         "enable SSL",
-			Object:       ManagerApiExpect(t),
-			Method:       http.MethodPatch,
-			Path:         "/apisix/admin/ssl/1/status",
-			Body:         `1`,
-			Headers:      map[string]string{"Authorization": token},
+			Desc:   "enable SSL",
+			Object: ManagerApiExpect(t),
+			Method: http.MethodPatch,
+			Path:   "/apisix/admin/ssl/1/status",
+			Body:   `1`,
+			Headers: map[string]string{
+				"Authorization": token,
+				"Content-Type":  "text/plain",
+			},
 			ExpectStatus: http.StatusOK,
 			ExpectBody:   "\"status\":1",
 		},
diff --git a/api/test/e2e/upstream_test.go b/api/test/e2e/upstream_test.go
index 5d8d247..3936c11 100644
--- a/api/test/e2e/upstream_test.go
+++ b/api/test/e2e/upstream_test.go
@@ -45,6 +45,7 @@
 			Method: http.MethodPut,
 			Path:   "/apisix/admin/upstreams/1",
 			Body: `{
+				"name": "upstream1",
 				"nodes": [{
 					"host": "172.16.238.20",
 					"port": 1980,
@@ -56,6 +57,37 @@
 			ExpectStatus: http.StatusOK,
 		},
 		{
+			Desc:         "check upstream exists by name",
+			Object:       ManagerApiExpect(t),
+			Method:       http.MethodGet,
+			Path:         "/apisix/admin/notexist/upstreams",
+			Query:        "name=upstream1",
+			Headers:      map[string]string{"Authorization": token},
+			ExpectStatus: http.StatusBadRequest,
+			ExpectBody:   "Upstream name is reduplicate",
+			Sleep:        sleepTime,
+		},
+		{
+			Desc:         "upstream name list",
+			Object:       ManagerApiExpect(t),
+			Method:       http.MethodGet,
+			Path:         "/apisix/admin/names/upstreams",
+			Headers:      map[string]string{"Authorization": token},
+			ExpectStatus: http.StatusOK,
+			ExpectBody:   `"name":"upstream1"`,
+			Sleep:        sleepTime,
+		},
+		{
+			Desc:         "check upstream exists by name (exclude it self)",
+			Object:       ManagerApiExpect(t),
+			Method:       http.MethodGet,
+			Path:         "/apisix/admin/notexist/upstreams",
+			Query:        "name=upstream1&exclude=1",
+			Headers:      map[string]string{"Authorization": token},
+			ExpectStatus: http.StatusOK,
+			Sleep:        sleepTime,
+		},
+		{
 			Desc:   "create route using the upstream just created",
 			Object: ManagerApiExpect(t),
 			Method: http.MethodPut,
diff --git a/api/test/shell/cli_test.sh b/api/test/shell/cli_test.sh
index 85acf47..c272c36 100755
--- a/api/test/shell/cli_test.sh
+++ b/api/test/shell/cli_test.sh
@@ -223,7 +223,7 @@
 ./manager-api &
 sleep 3
 
-curl http://127.0.0.1:9000/apisix/admin/user/login -d '{"username":"admin", "password": "admin"}'
+curl http://127.0.0.1:9000/apisix/admin/user/login -H "Content-Type: application/json" -d '{"username":"admin", "password": "admin"}'
 
 ./manager-api stop
 sleep 6
@@ -272,7 +272,7 @@
 sleep 3
 
 # validate process is right by requesting login api
-resp=$(curl http://127.0.0.1:9000/apisix/admin/user/login -d '{"username":"admin", "password": "admin"}')
+resp=$(curl http://127.0.0.1:9000/apisix/admin/user/login -H "Content-Type: application/json" -d '{"username":"admin", "password": "admin"}')
 token=$(echo "${resp}" | sed 's/{/\n/g' | sed 's/,/\n/g' | grep "token" | sed 's/:/\n/g' | sed '1d' | sed 's/}//g'  | sed 's/"//g')
 if [ -z "${token}" ]; then
     echo "login failed"
@@ -280,7 +280,7 @@
 fi
 
 # more validation to make sure it's ok to access etcd
-resp=$(curl -ig -XPUT http://127.0.0.1:9000/apisix/admin/consumers -i -H "Authorization: $token" -d '{"username":"etcd_basic_auth_test"}')
+resp=$(curl -ig -XPUT http://127.0.0.1:9000/apisix/admin/consumers -i -H "Content-Type: application/json" -H "Authorization: $token" -d '{"username":"etcd_basic_auth_test"}')
 respCode=$(echo "${resp}" | sed 's/{/\n/g'| sed 's/,/\n/g' | grep "code" | sed 's/:/\n/g' | sed '1d')
 respMessage=$(echo "${resp}" | sed 's/{/\n/g'| sed 's/,/\n/g' | grep "message" | sed 's/:/\n/g' | sed '1d')
 if [ "$respCode" != "0" ] || [ $respMessage != "\"\"" ]; then