forked from minio/minio
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Pass on web-handler arguments properly to log entries (minio#7894)
- Loading branch information
1 parent
5c0acbc
commit ffd7b70
Showing
3 changed files
with
370 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
/* | ||
* MinIO Cloud Storage, (C) 2019 MinIO, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package cmd | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
|
||
"github.com/minio/minio/cmd/logger" | ||
"github.com/minio/minio/pkg/handlers" | ||
) | ||
|
||
const ( | ||
kmBucket = "BucketName" | ||
kmObject = "ObjectName" | ||
kmObjects = "Objects" | ||
kmPrefix = "Prefix" | ||
kmMarker = "Marker" | ||
kmUsername = "UserName" | ||
kmHostname = "HostName" | ||
kmPolicy = "Policy" | ||
) | ||
|
||
// KeyValueMap extends builtin map to support setting and getting | ||
// select fields like BucketName, ObjectName, Prefix, etc. | ||
type KeyValueMap map[string]string | ||
|
||
// Bucket returns the BucketName | ||
func (km KeyValueMap) Bucket() string { | ||
return km[kmBucket] | ||
} | ||
|
||
// Object returns the ObjectName | ||
func (km KeyValueMap) Object() string { | ||
return km[kmObject] | ||
} | ||
|
||
// Prefix returns the Prefix | ||
func (km KeyValueMap) Prefix() string { | ||
return km[kmPrefix] | ||
} | ||
|
||
// Username returns the Username | ||
func (km KeyValueMap) Username() string { | ||
return km[kmUsername] | ||
} | ||
|
||
// Hostname returns the Hostname | ||
func (km KeyValueMap) Hostname() string { | ||
return km[kmHostname] | ||
} | ||
|
||
// Policy returns the Policy | ||
func (km KeyValueMap) Policy() string { | ||
return km[kmPolicy] | ||
} | ||
|
||
// Objects returns the Objects | ||
func (km KeyValueMap) Objects() []string { | ||
var objects []string | ||
_ = json.Unmarshal([]byte(km[kmObjects]), &objects) | ||
return objects | ||
} | ||
|
||
// SetBucket sets the given bucket to the KeyValueMap | ||
func (km *KeyValueMap) SetBucket(bucket string) { | ||
(*km)[kmBucket] = bucket | ||
} | ||
|
||
// SetPrefix sets the given prefix to the KeyValueMap | ||
func (km *KeyValueMap) SetPrefix(prefix string) { | ||
(*km)[kmPrefix] = prefix | ||
} | ||
|
||
// SetObject sets the given object to the KeyValueMap | ||
func (km *KeyValueMap) SetObject(object string) { | ||
(*km)[kmObject] = object | ||
} | ||
|
||
// SetMarker sets the given marker to the KeyValueMap | ||
func (km *KeyValueMap) SetMarker(marker string) { | ||
(*km)[kmMarker] = marker | ||
} | ||
|
||
// SetPolicy sets the given policy to the KeyValueMap | ||
func (km *KeyValueMap) SetPolicy(policy string) { | ||
(*km)[kmPolicy] = policy | ||
} | ||
|
||
// SetExpiry sets the expiry to the KeyValueMap | ||
func (km *KeyValueMap) SetExpiry(expiry int64) { | ||
(*km)[kmPolicy] = fmt.Sprintf("%d", expiry) | ||
} | ||
|
||
// SetObjects sets the list of objects to the KeyValueMap | ||
func (km *KeyValueMap) SetObjects(objects []string) { | ||
objsVal, err := json.Marshal(objects) | ||
if err != nil { | ||
// NB this can only happen when we can't marshal a Go | ||
// slice to its json representation. | ||
objsVal = []byte("[]") | ||
} | ||
(*km)[kmObjects] = string(objsVal) | ||
} | ||
|
||
// SetUsername sets the username to the KeyValueMap | ||
func (km *KeyValueMap) SetUsername(username string) { | ||
(*km)[kmUsername] = username | ||
} | ||
|
||
// SetHostname sets the hostname to the KeyValueMap | ||
func (km *KeyValueMap) SetHostname(hostname string) { | ||
(*km)[kmHostname] = hostname | ||
} | ||
|
||
// ToKeyValuer interface wraps ToKeyValue method that allows types to | ||
// marshal their values as a map of structure member names to their | ||
// values, as strings | ||
type ToKeyValuer interface { | ||
ToKeyValue() KeyValueMap | ||
} | ||
|
||
// ToKeyValue implementation for WebGenericArgs | ||
func (args *WebGenericArgs) ToKeyValue() KeyValueMap { | ||
return KeyValueMap{} | ||
} | ||
|
||
// ToKeyValue implementation for MakeBucketArgs | ||
func (args *MakeBucketArgs) ToKeyValue() KeyValueMap { | ||
km := KeyValueMap{} | ||
km.SetBucket(args.BucketName) | ||
return km | ||
} | ||
|
||
// ToKeyValue implementation for RemoveBucketArgs | ||
func (args *RemoveBucketArgs) ToKeyValue() KeyValueMap { | ||
km := KeyValueMap{} | ||
km.SetBucket(args.BucketName) | ||
return km | ||
} | ||
|
||
// ToKeyValue implementation for ListObjectsArgs | ||
func (args *ListObjectsArgs) ToKeyValue() KeyValueMap { | ||
km := KeyValueMap{} | ||
km.SetBucket(args.BucketName) | ||
km.SetPrefix(args.Prefix) | ||
km.SetMarker(args.Marker) | ||
return km | ||
} | ||
|
||
// ToKeyValue implementation for RemoveObjectArgs | ||
func (args *RemoveObjectArgs) ToKeyValue() KeyValueMap { | ||
km := KeyValueMap{} | ||
km.SetBucket(args.BucketName) | ||
km.SetObjects(args.Objects) | ||
return km | ||
} | ||
|
||
// ToKeyValue implementation for LoginArgs | ||
func (args *LoginArgs) ToKeyValue() KeyValueMap { | ||
km := KeyValueMap{} | ||
km.SetUsername(args.Username) | ||
return km | ||
} | ||
|
||
// ToKeyValue implementation for GetBucketPolicyArgs | ||
func (args *GetBucketPolicyArgs) ToKeyValue() KeyValueMap { | ||
km := KeyValueMap{} | ||
km.SetBucket(args.BucketName) | ||
km.SetPrefix(args.Prefix) | ||
return km | ||
} | ||
|
||
// ToKeyValue implementation for ListAllBucketPoliciesArgs | ||
func (args *ListAllBucketPoliciesArgs) ToKeyValue() KeyValueMap { | ||
km := KeyValueMap{} | ||
km.SetBucket(args.BucketName) | ||
return km | ||
} | ||
|
||
// ToKeyValue implementation for SetBucketPolicyWebArgs | ||
func (args *SetBucketPolicyWebArgs) ToKeyValue() KeyValueMap { | ||
km := KeyValueMap{} | ||
km.SetBucket(args.BucketName) | ||
km.SetPrefix(args.Prefix) | ||
km.SetPolicy(args.Policy) | ||
return km | ||
} | ||
|
||
// ToKeyValue implementation for SetAuthArgs | ||
// SetAuthArgs doesn't implement the ToKeyValue interface that will be | ||
// used by logger subsystem down the line, to avoid leaking | ||
// credentials to an external log target | ||
func (args *SetAuthArgs) ToKeyValue() KeyValueMap { | ||
return KeyValueMap{} | ||
} | ||
|
||
// ToKeyValue implementation for PresignedGetArgs | ||
func (args *PresignedGetArgs) ToKeyValue() KeyValueMap { | ||
km := KeyValueMap{} | ||
km.SetHostname(args.HostName) | ||
km.SetBucket(args.BucketName) | ||
km.SetObject(args.ObjectName) | ||
km.SetExpiry(args.Expiry) | ||
return km | ||
} | ||
|
||
// newWebContext creates a context with ReqInfo values from the given | ||
// http request and api name. | ||
func newWebContext(r *http.Request, args ToKeyValuer, api string) context.Context { | ||
argsMap := args.ToKeyValue() | ||
bucket := argsMap.Bucket() | ||
object := argsMap.Object() | ||
prefix := argsMap.Prefix() | ||
|
||
if prefix != "" { | ||
object = prefix | ||
} | ||
reqInfo := &logger.ReqInfo{ | ||
DeploymentID: globalDeploymentID, | ||
RemoteHost: handlers.GetSourceIP(r), | ||
UserAgent: r.UserAgent(), | ||
API: api, | ||
BucketName: bucket, | ||
ObjectName: object, | ||
} | ||
return logger.SetReqInfo(context.Background(), reqInfo) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/* | ||
* MinIO Cloud Storage, (C) 2019 MinIO, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package cmd | ||
|
||
import ( | ||
"bytes" | ||
"net/http" | ||
"testing" | ||
|
||
"github.com/minio/minio/cmd/logger" | ||
) | ||
|
||
func TestKeyValueMap(t *testing.T) { | ||
bucket := "bucket" | ||
object := "object" | ||
prefix := "prefix" | ||
username := "username" | ||
policy := "policy" | ||
host := "min.io" | ||
objects := []string{object, object} | ||
|
||
km := KeyValueMap{} | ||
km.SetBucket(bucket) | ||
km.SetPrefix(prefix) | ||
km.SetUsername(username) | ||
km.SetHostname(host) | ||
km.SetObject(object) | ||
km.SetObjects(objects) | ||
km.SetPolicy(policy) | ||
|
||
if got := km.Bucket(); got != bucket { | ||
t.Errorf("Expected %s but got %s", bucket, got) | ||
} | ||
|
||
if got := km.Object(); got != object { | ||
t.Errorf("Expected %s but got %s", object, got) | ||
} | ||
|
||
areEqualObjects := func(as, bs []string) bool { | ||
if len(as) != len(bs) { | ||
return false | ||
} | ||
|
||
for i, a := range as { | ||
b := bs[i] | ||
if a != b { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
|
||
if got := km.Objects(); !areEqualObjects(got, objects) { | ||
t.Errorf("Expected %s but got %s", objects, got) | ||
} | ||
|
||
if got := km.Policy(); got != policy { | ||
t.Errorf("Expected %s but got %s", policy, got) | ||
} | ||
|
||
if got := km.Prefix(); got != prefix { | ||
t.Errorf("Expected %s but got %s", prefix, got) | ||
} | ||
|
||
if got := km.Username(); got != username { | ||
t.Errorf("Expected %s but got %s", username, got) | ||
} | ||
|
||
if got := km.Hostname(); got != host { | ||
t.Errorf("Expected %s but got %s", host, got) | ||
} | ||
} | ||
|
||
func TestNewWebContext(t *testing.T) { | ||
api := "Test API" | ||
args := ListObjectsArgs{ | ||
BucketName: "bucket", | ||
Prefix: "prefix", | ||
Marker: "marker", | ||
} | ||
|
||
req, err := http.NewRequest(http.MethodPost, "http://min.io", bytes.NewReader([]byte("nothing"))) | ||
if err != nil { | ||
t.Fatal("Unexpected failure while creating a test request") | ||
} | ||
|
||
ctx := newWebContext(req, &args, api) | ||
reqInfo := logger.GetReqInfo(ctx) | ||
|
||
if reqInfo.API != api { | ||
t.Errorf("Expected %s got %s", api, reqInfo.API) | ||
} | ||
|
||
if reqInfo.BucketName != args.BucketName { | ||
t.Errorf("Expected %s got %s", args.BucketName, reqInfo.BucketName) | ||
} | ||
} |
Oops, something went wrong.