Skip to content

Commit

Permalink
Merge 791628a into f9096bb
Browse files Browse the repository at this point in the history
  • Loading branch information
darklynx committed Aug 15, 2018
2 parents f9096bb + 791628a commit 1dbe332
Show file tree
Hide file tree
Showing 78 changed files with 3,127 additions and 364 deletions.
30 changes: 27 additions & 3 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 18 additions & 13 deletions handlers.go
Expand Up @@ -57,10 +57,12 @@ func getPage(values url.Values) (int, int) {
return max, skip
}

// getAndAuthBasket retrieves basket by name from HTTP request path and authorize access to the basket object
func getAndAuthBasket(w http.ResponseWriter, r *http.Request, ps httprouter.Params) (string, Basket) {
// getAuthenticatedBasket fetches basket details by name and authenticates the access to this basket, returns nil in case of failure
func getAuthenticatedBasket(w http.ResponseWriter, r *http.Request, ps httprouter.Params) (string, Basket) {
name := ps.ByName("basket")
if basket := basketsDb.Get(name); basket != nil {
if !validBasketName.MatchString(name) {
http.Error(w, "Invalid basket name; ["+name+"] does not match pattern: "+validBasketName.String(), http.StatusBadRequest)
} else if basket := basketsDb.Get(name); basket != nil {
// maybe custom header, e.g. basket_key, basket_token
if token := r.Header.Get("Authorization"); basket.Authorize(token) || token == serverConfig.MasterToken {
return name, basket
Expand Down Expand Up @@ -153,7 +155,7 @@ func GetBaskets(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {

// GetBasket handles HTTP request to get basket configuration
func GetBasket(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
if _, basket := getAndAuthBasket(w, r, ps); basket != nil {
if _, basket := getAuthenticatedBasket(w, r, ps); basket != nil {
json, err := json.Marshal(basket.Config())
writeJSON(w, http.StatusOK, json, err)
}
Expand All @@ -163,11 +165,11 @@ func GetBasket(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
func CreateBasket(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
name := ps.ByName("basket")
if name == serviceAPIPath || name == serviceUIPath {
http.Error(w, "Basket name may not clash with system path: "+name, http.StatusForbidden)
http.Error(w, "This basket name conflicts with reserved system path: "+name, http.StatusForbidden)
return
}
if !validBasketName.MatchString(name) {
http.Error(w, "Basket name does not match pattern: "+validBasketName.String(), http.StatusBadRequest)
http.Error(w, "Invalid basket name; ["+name+"] does not match pattern: "+validBasketName.String(), http.StatusBadRequest)
return
}

Expand Down Expand Up @@ -205,7 +207,7 @@ func CreateBasket(w http.ResponseWriter, r *http.Request, ps httprouter.Params)

// UpdateBasket handles HTTP request to update basket configuration
func UpdateBasket(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
if _, basket := getAndAuthBasket(w, r, ps); basket != nil {
if _, basket := getAuthenticatedBasket(w, r, ps); basket != nil {
// read config (max 2 kB)
body, err := ioutil.ReadAll(io.LimitReader(r.Body, 2048))
r.Body.Close()
Expand Down Expand Up @@ -234,7 +236,7 @@ func UpdateBasket(w http.ResponseWriter, r *http.Request, ps httprouter.Params)

// DeleteBasket handles HTTP request to delete basket
func DeleteBasket(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
if name, basket := getAndAuthBasket(w, r, ps); basket != nil {
if name, basket := getAuthenticatedBasket(w, r, ps); basket != nil {
log.Printf("[info] deleting basket: %s", name)

basketsDb.Delete(name)
Expand All @@ -244,7 +246,7 @@ func DeleteBasket(w http.ResponseWriter, r *http.Request, ps httprouter.Params)

// GetBasketResponse handles HTTP request to get basket response configuration
func GetBasketResponse(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
if _, basket := getAndAuthBasket(w, r, ps); basket != nil {
if _, basket := getAuthenticatedBasket(w, r, ps); basket != nil {
method, errm := getValidMethod(ps)
if errm != nil {
http.Error(w, errm.Error(), http.StatusBadRequest)
Expand All @@ -262,7 +264,7 @@ func GetBasketResponse(w http.ResponseWriter, r *http.Request, ps httprouter.Par

// UpdateBasketResponse handles HTTP request to update basket response configuration
func UpdateBasketResponse(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
if _, basket := getAndAuthBasket(w, r, ps); basket != nil {
if _, basket := getAuthenticatedBasket(w, r, ps); basket != nil {
method, errm := getValidMethod(ps)
if errm != nil {
http.Error(w, errm.Error(), http.StatusBadRequest)
Expand Down Expand Up @@ -295,7 +297,7 @@ func UpdateBasketResponse(w http.ResponseWriter, r *http.Request, ps httprouter.

// GetBasketRequests handles HTTP request to get requests collected by basket
func GetBasketRequests(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
if _, basket := getAndAuthBasket(w, r, ps); basket != nil {
if _, basket := getAuthenticatedBasket(w, r, ps); basket != nil {
values := r.URL.Query()
if query := values.Get("q"); len(query) > 0 {
// Find requests
Expand All @@ -312,7 +314,7 @@ func GetBasketRequests(w http.ResponseWriter, r *http.Request, ps httprouter.Par

// ClearBasket handles HTTP request to delete all requests collected by basket
func ClearBasket(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
if _, basket := getAndAuthBasket(w, r, ps); basket != nil {
if _, basket := getAuthenticatedBasket(w, r, ps); basket != nil {
basket.Clear()
w.WriteHeader(http.StatusNoContent)
}
Expand Down Expand Up @@ -348,7 +350,10 @@ func WebBasketPage(w http.ResponseWriter, r *http.Request, ps httprouter.Params)
// AcceptBasketRequests accepts and handles HTTP requests passed to different baskets
func AcceptBasketRequests(w http.ResponseWriter, r *http.Request) {
name := strings.Split(r.URL.Path, "/")[1]
if basket := basketsDb.Get(name); basket != nil {

if !validBasketName.MatchString(name) {
http.Error(w, "Invalid basket name; ["+name+"] does not match pattern: "+validBasketName.String(), http.StatusBadRequest)
} else if basket := basketsDb.Get(name); basket != nil {
request := basket.Add(r)

// forward request if configured and it's a first forwarding
Expand Down
32 changes: 30 additions & 2 deletions handlers_test.go
Expand Up @@ -107,7 +107,7 @@ func TestCreateBasket_Forbidden(t *testing.T) {

// validate response: 403 - forbidden
assert.Equal(t, 403, w.Code, "wrong HTTP result code")
assert.Equal(t, "Basket name may not clash with system path: "+basket+"\n", w.Body.String(), "wrong error message")
assert.Equal(t, "This basket name conflicts with reserved system path: "+basket+"\n", w.Body.String(), "wrong error message")
// validate database
assert.Nil(t, basketsDb.Get(basket), "basket '%v' should not be created", basket)
}
Expand All @@ -124,7 +124,7 @@ func TestCreateBasket_InvalidName(t *testing.T) {

// validate response: 400 - Bad Request
assert.Equal(t, 400, w.Code, "wrong HTTP result code")
assert.Equal(t, "Basket name does not match pattern: "+validBasketName.String()+"\n", w.Body.String(),
assert.Equal(t, "Invalid basket name; ["+basket+"] does not match pattern: "+validBasketName.String()+"\n", w.Body.String(),
"wrong error message")
// validate database
assert.Nil(t, basketsDb.Get(basket), "basket '%v' should not be created", basket)
Expand Down Expand Up @@ -379,6 +379,23 @@ func TestGetBasket_NotFound(t *testing.T) {
}
}

func TestGetBasket_BadRequest(t *testing.T) {
basket := "get05~"

r, err := http.NewRequest("GET", "http://localhost:55555/baskets/"+basket, strings.NewReader(""))
if assert.NoError(t, err) {
r.Header.Add("Authorization", "abcd12345")
w := httptest.NewRecorder()
ps := append(make(httprouter.Params, 0), httprouter.Param{Key: "basket", Value: basket})
GetBasket(w, r, ps)

// validate response: 400 - Bad Request
assert.Equal(t, 400, w.Code, "wrong HTTP result code")
assert.Equal(t, "Invalid basket name; ["+basket+"] does not match pattern: "+validBasketName.String()+"\n", w.Body.String(),
"wrong error message")
}
}

func TestUpdateBasket(t *testing.T) {
basket := "update01"

Expand Down Expand Up @@ -963,6 +980,17 @@ func TestAcceptBasketRequests_NotFound(t *testing.T) {
assert.Equal(t, 404, w.Code, "wrong HTTP result code")
}

func TestAcceptBasketRequests_BadRequest(t *testing.T) {
basket := "accept03%20"
req := createTestPOSTRequest("http://localhost:55555/"+basket, "my data", "text/plain")
w := httptest.NewRecorder()
AcceptBasketRequests(w, req)
// HTTP 400 - Bad Request
assert.Equal(t, 400, w.Code, "wrong HTTP result code")
assert.Equal(t, "Invalid basket name; [accept03 ] does not match pattern: "+validBasketName.String()+"\n", w.Body.String(),
"wrong error message")
}

func TestForwardToWeb(t *testing.T) {
r, err := http.NewRequest("GET", "http://localhost:55555/", strings.NewReader(""))
if assert.NoError(t, err) {
Expand Down
14 changes: 14 additions & 0 deletions vendor/golang.org/x/sys/unix/aliases.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions vendor/golang.org/x/sys/unix/mkerrors.sh

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 1dbe332

Please sign in to comment.