mirror of
https://github.com/minio/minio.git
synced 2025-01-11 15:03:22 -05:00
handler: simplify parsing valid location constraint. (#4040)
Separate out validating v/s parsing logic in isValidLocationConstraint() into parseLocationConstraint() and isValidLocation() Additionally also set `X-Amz-Bucket-Region` as part of the common headers for the clients to fallback on in-case of any region related errors.
This commit is contained in:
parent
4041e5f20d
commit
3fe33e7b15
@ -1346,6 +1346,11 @@ func TestToAdminAPIErr(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWriteSetConfigResponse(t *testing.T) {
|
||||
rootPath, err := newTestConfig(globalMinioDefaultRegion)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer removeAll(rootPath)
|
||||
testCases := []struct {
|
||||
status bool
|
||||
errs []error
|
||||
|
@ -36,6 +36,7 @@ func setCommonHeaders(w http.ResponseWriter) {
|
||||
// Set unique request ID for each reply.
|
||||
w.Header().Set(responseRequestIDKey, mustGetRequestID(UTCNow()))
|
||||
w.Header().Set("Server", globalServerUserAgent)
|
||||
w.Header().Set("X-Amz-Bucket-Region", serverConfig.GetRegion())
|
||||
w.Header().Set("Accept-Ranges", "bytes")
|
||||
}
|
||||
|
||||
|
@ -370,13 +370,20 @@ func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Req
|
||||
vars := mux.Vars(r)
|
||||
bucket := vars["bucket"]
|
||||
|
||||
// Validate if incoming location constraint is valid, reject
|
||||
// requests which do not follow valid region requirements.
|
||||
if s3Error := isValidLocationConstraint(r); s3Error != ErrNone {
|
||||
// Parse incoming location constraint.
|
||||
location, s3Error := parseLocationConstraint(r)
|
||||
if s3Error != ErrNone {
|
||||
writeErrorResponse(w, s3Error, r.URL)
|
||||
return
|
||||
}
|
||||
|
||||
// Validate if location sent by the client is valid, reject
|
||||
// requests which do not follow valid region requirements.
|
||||
if !isValidLocation(location) {
|
||||
writeErrorResponse(w, ErrInvalidRegion, r.URL)
|
||||
return
|
||||
}
|
||||
|
||||
bucketLock := globalNSMutex.NewNSLock(bucket, "")
|
||||
bucketLock.Lock()
|
||||
defer bucketLock.Unlock()
|
||||
|
@ -24,36 +24,29 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Validates location constraint in PutBucket request body.
|
||||
// The location value in the request body should match the
|
||||
// region configured at serverConfig, otherwise error is returned.
|
||||
func isValidLocationConstraint(r *http.Request) (s3Error APIErrorCode) {
|
||||
serverRegion := serverConfig.GetRegion()
|
||||
// Parses location constraint from the incoming reader.
|
||||
func parseLocationConstraint(r *http.Request) (location string, s3Error APIErrorCode) {
|
||||
// If the request has no body with content-length set to 0,
|
||||
// we do not have to validate location constraint. Bucket will
|
||||
// be created at default region.
|
||||
locationConstraint := createBucketLocationConfiguration{}
|
||||
err := xmlDecoder(r.Body, &locationConstraint, r.ContentLength)
|
||||
if err == nil || err == io.EOF {
|
||||
// Successfully decoded, proceed to verify the region.
|
||||
// Once region has been obtained we proceed to verify it.
|
||||
incomingRegion := locationConstraint.Location
|
||||
if incomingRegion == "" {
|
||||
// Location constraint is empty for region globalMinioDefaultRegion,
|
||||
// in accordance with protocol.
|
||||
incomingRegion = globalMinioDefaultRegion
|
||||
}
|
||||
// Return errInvalidRegion if location constraint does not match
|
||||
// with configured region.
|
||||
s3Error = ErrNone
|
||||
if serverRegion != incomingRegion {
|
||||
s3Error = ErrInvalidRegion
|
||||
}
|
||||
return s3Error
|
||||
if err != nil && err != io.EOF {
|
||||
errorIf(err, "Unable to xml decode location constraint")
|
||||
// Treat all other failures as XML parsing errors.
|
||||
return "", ErrMalformedXML
|
||||
} // else for both err as nil or io.EOF
|
||||
location = locationConstraint.Location
|
||||
if location == "" {
|
||||
location = globalMinioDefaultRegion
|
||||
}
|
||||
errorIf(err, "Unable to xml decode location constraint")
|
||||
// Treat all other failures as XML parsing errors.
|
||||
return ErrMalformedXML
|
||||
return location, ErrNone
|
||||
}
|
||||
|
||||
// Validates input location is same as configured region
|
||||
// of Minio server.
|
||||
func isValidLocation(location string) bool {
|
||||
return serverConfig.GetRegion() == location
|
||||
}
|
||||
|
||||
// Supported headers that needs to be extracted.
|
||||
|
@ -39,7 +39,7 @@ func TestIsValidLocationContraint(t *testing.T) {
|
||||
Body: ioutil.NopCloser(bytes.NewBuffer([]byte("<>"))),
|
||||
ContentLength: int64(len("<>")),
|
||||
}
|
||||
if err := isValidLocationConstraint(malformedReq); err != ErrMalformedXML {
|
||||
if _, err := parseLocationConstraint(malformedReq); err != ErrMalformedXML {
|
||||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
|
||||
@ -68,8 +68,6 @@ func TestIsValidLocationContraint(t *testing.T) {
|
||||
// Test case - 2.
|
||||
// In case of empty request body ErrNone is returned.
|
||||
{"", globalMinioDefaultRegion, ErrNone},
|
||||
// Test case - 3.
|
||||
{"eu-central-1", globalMinioDefaultRegion, ErrInvalidRegion},
|
||||
}
|
||||
for i, testCase := range testCases {
|
||||
inputRequest, e := createExpectedRequest(&http.Request{}, testCase.locationForInputRequest)
|
||||
@ -77,7 +75,7 @@ func TestIsValidLocationContraint(t *testing.T) {
|
||||
t.Fatalf("Test %d: Failed to Marshal bucket configuration", i+1)
|
||||
}
|
||||
serverConfig.SetRegion(testCase.serverConfigRegion)
|
||||
actualCode := isValidLocationConstraint(inputRequest)
|
||||
_, actualCode := parseLocationConstraint(inputRequest)
|
||||
if testCase.expectedCode != actualCode {
|
||||
t.Errorf("Test %d: Expected the APIErrCode to be %d, but instead found %d", i+1, testCase.expectedCode, actualCode)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user