mirror of
https://github.com/minio/minio.git
synced 2024-12-24 06:05:55 -05:00
use ParseForm() to allow query param lookups once (#12900)
``` cpu: Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz BenchmarkURLQueryForm BenchmarkURLQueryForm-4 247099363 4.809 ns/op 0 B/op 0 allocs/op BenchmarkURLQuery BenchmarkURLQuery-4 2517624 462.1 ns/op 432 B/op 4 allocs/op PASS ok github.com/minio/minio/cmd 3.848s ```
This commit is contained in:
parent
7b0b0f9101
commit
a2cd3c9a1d
@ -122,7 +122,7 @@ func (a adminAPIHandlers) SetRemoteTargetHandler(w http.ResponseWriter, r *http.
|
||||
defer logger.AuditLog(ctx, w, r, mustGetClaimsFromToken(r))
|
||||
vars := mux.Vars(r)
|
||||
bucket := pathClean(vars["bucket"])
|
||||
update := r.URL.Query().Get("update") == "true"
|
||||
update := r.Form.Get("update") == "true"
|
||||
|
||||
if !globalIsErasure {
|
||||
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL)
|
||||
@ -169,7 +169,7 @@ func (a adminAPIHandlers) SetRemoteTargetHandler(w http.ResponseWriter, r *http.
|
||||
target.SourceBucket = bucket
|
||||
var ops []madmin.TargetUpdateType
|
||||
if update {
|
||||
ops = madmin.GetTargetUpdateOps(r.URL.Query())
|
||||
ops = madmin.GetTargetUpdateOps(r.Form)
|
||||
} else {
|
||||
target.Arn = globalBucketTargetSys.getRemoteARN(bucket, &target)
|
||||
}
|
||||
|
@ -337,7 +337,7 @@ func (a adminAPIHandlers) HelpConfigKVHandler(w http.ResponseWriter, r *http.Req
|
||||
subSys := vars["subSys"]
|
||||
key := vars["key"]
|
||||
|
||||
_, envOnly := r.URL.Query()["env"]
|
||||
_, envOnly := r.Form["env"]
|
||||
|
||||
rd, err := GetHelp(subSys, key, envOnly)
|
||||
if err != nil {
|
||||
|
@ -851,7 +851,7 @@ func (a adminAPIHandlers) ListServiceAccounts(w http.ResponseWriter, r *http.Req
|
||||
|
||||
var targetAccount string
|
||||
|
||||
user := r.URL.Query().Get("user")
|
||||
user := r.Form.Get("user")
|
||||
if user != "" {
|
||||
if !globalIAMSys.IsAllowed(iampolicy.Args{
|
||||
AccountName: cred.AccessKey,
|
||||
@ -997,7 +997,7 @@ func (a adminAPIHandlers) AccountInfoHandler(w http.ResponseWriter, r *http.Requ
|
||||
r.Header.Set("delimiter", SlashSeparator)
|
||||
|
||||
// Check if we are asked to return prefix usage
|
||||
enablePrefixUsage := r.URL.Query().Get("prefix-usage") == "true"
|
||||
enablePrefixUsage := r.Form.Get("prefix-usage") == "true"
|
||||
|
||||
isAllowedAccess := func(bucketName string) (rd, wr bool) {
|
||||
if globalIAMSys.IsAllowed(iampolicy.Args{
|
||||
|
@ -450,7 +450,7 @@ func (a adminAPIHandlers) TopLocksHandler(w http.ResponseWriter, r *http.Request
|
||||
}
|
||||
|
||||
count := 10 // by default list only top 10 entries
|
||||
if countStr := r.URL.Query().Get("count"); countStr != "" {
|
||||
if countStr := r.Form.Get("count"); countStr != "" {
|
||||
var err error
|
||||
count, err = strconv.Atoi(countStr)
|
||||
if err != nil {
|
||||
@ -458,7 +458,7 @@ func (a adminAPIHandlers) TopLocksHandler(w http.ResponseWriter, r *http.Request
|
||||
return
|
||||
}
|
||||
}
|
||||
stale := r.URL.Query().Get("stale") == "true" // list also stale locks
|
||||
stale := r.Form.Get("stale") == "true" // list also stale locks
|
||||
|
||||
peerLocks := globalNotificationSys.GetLocks(ctx, r)
|
||||
|
||||
@ -713,7 +713,7 @@ func (a adminAPIHandlers) HealHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
hip, errCode := extractHealInitParams(mux.Vars(r), r.URL.Query(), r.Body)
|
||||
hip, errCode := extractHealInitParams(mux.Vars(r), r.Form, r.Body)
|
||||
if errCode != ErrNone {
|
||||
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(errCode), r.URL)
|
||||
return
|
||||
@ -926,9 +926,9 @@ func (a adminAPIHandlers) SpeedtestHandler(w http.ResponseWriter, r *http.Reques
|
||||
return
|
||||
}
|
||||
|
||||
sizeStr := r.URL.Query().Get(peerRESTSize)
|
||||
durationStr := r.URL.Query().Get(peerRESTDuration)
|
||||
concurrentStr := r.URL.Query().Get(peerRESTConcurrent)
|
||||
sizeStr := r.Form.Get(peerRESTSize)
|
||||
durationStr := r.Form.Get(peerRESTDuration)
|
||||
concurrentStr := r.Form.Get(peerRESTConcurrent)
|
||||
|
||||
size, err := strconv.Atoi(sizeStr)
|
||||
if err != nil {
|
||||
@ -1157,7 +1157,7 @@ func mustTrace(entry interface{}, opts madmin.ServiceTraceOpts) (shouldTrace boo
|
||||
}
|
||||
|
||||
func extractTraceOptions(r *http.Request) (opts madmin.ServiceTraceOpts, err error) {
|
||||
q := r.URL.Query()
|
||||
q := r.Form
|
||||
|
||||
opts.OnlyErrors = q.Get("err") == "true"
|
||||
opts.S3 = q.Get("s3") == "true"
|
||||
@ -1259,15 +1259,15 @@ func (a adminAPIHandlers) ConsoleLogHandler(w http.ResponseWriter, r *http.Reque
|
||||
if objectAPI == nil {
|
||||
return
|
||||
}
|
||||
node := r.URL.Query().Get("node")
|
||||
node := r.Form.Get("node")
|
||||
// limit buffered console entries if client requested it.
|
||||
limitStr := r.URL.Query().Get("limit")
|
||||
limitStr := r.Form.Get("limit")
|
||||
limitLines, err := strconv.Atoi(limitStr)
|
||||
if err != nil {
|
||||
limitLines = 10
|
||||
}
|
||||
|
||||
logKind := r.URL.Query().Get("logType")
|
||||
logKind := r.Form.Get("logType")
|
||||
if logKind == "" {
|
||||
logKind = string(logger.All)
|
||||
}
|
||||
@ -1342,7 +1342,7 @@ func (a adminAPIHandlers) KMSCreateKeyHandler(w http.ResponseWriter, r *http.Req
|
||||
return
|
||||
}
|
||||
|
||||
if err := GlobalKMS.CreateKey(r.URL.Query().Get("key-id")); err != nil {
|
||||
if err := GlobalKMS.CreateKey(r.Form.Get("key-id")); err != nil {
|
||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||
return
|
||||
}
|
||||
@ -1409,7 +1409,7 @@ func (a adminAPIHandlers) KMSKeyStatusHandler(w http.ResponseWriter, r *http.Req
|
||||
return
|
||||
}
|
||||
|
||||
keyID := r.URL.Query().Get("key-id")
|
||||
keyID := r.Form.Get("key-id")
|
||||
if keyID == "" {
|
||||
keyID = stat.DefaultKey
|
||||
}
|
||||
@ -1576,7 +1576,7 @@ func (a adminAPIHandlers) HealthInfoHandler(w http.ResponseWriter, r *http.Reque
|
||||
return
|
||||
}
|
||||
|
||||
query := r.URL.Query()
|
||||
query := r.Form
|
||||
healthInfo := madmin.HealthInfo{Version: madmin.HealthInfoVersion}
|
||||
healthInfoCh := make(chan madmin.HealthInfo)
|
||||
|
||||
@ -1600,7 +1600,7 @@ func (a adminAPIHandlers) HealthInfoHandler(w http.ResponseWriter, r *http.Reque
|
||||
}
|
||||
|
||||
deadline := 1 * time.Hour
|
||||
if dstr := r.URL.Query().Get("deadline"); dstr != "" {
|
||||
if dstr := r.Form.Get("deadline"); dstr != "" {
|
||||
var err error
|
||||
deadline, err = time.ParseDuration(dstr)
|
||||
if err != nil {
|
||||
@ -1975,7 +1975,7 @@ func (a adminAPIHandlers) BandwidthMonitorHandler(w http.ResponseWriter, r *http
|
||||
reportCh := make(chan madmin.BucketBandwidthReport)
|
||||
keepAliveTicker := time.NewTicker(500 * time.Millisecond)
|
||||
defer keepAliveTicker.Stop()
|
||||
bucketsRequestedString := r.URL.Query().Get("buckets")
|
||||
bucketsRequestedString := r.Form.Get("buckets")
|
||||
bucketsRequested := strings.Split(bucketsRequestedString, ",")
|
||||
go func() {
|
||||
defer close(reportCh)
|
||||
@ -2233,8 +2233,8 @@ func (a adminAPIHandlers) InspectDataHandler(w http.ResponseWriter, r *http.Requ
|
||||
return
|
||||
}
|
||||
|
||||
volume := r.URL.Query().Get("volume")
|
||||
file := r.URL.Query().Get("file")
|
||||
volume := r.Form.Get("volume")
|
||||
file := r.Form.Get("file")
|
||||
if len(volume) == 0 {
|
||||
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrInvalidBucketName), r.URL)
|
||||
return
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
@ -61,13 +62,13 @@ func isRequestSignatureV2(r *http.Request) bool {
|
||||
|
||||
// Verify if request has AWS PreSign Version '4'.
|
||||
func isRequestPresignedSignatureV4(r *http.Request) bool {
|
||||
_, ok := r.URL.Query()[xhttp.AmzCredential]
|
||||
_, ok := r.Form[xhttp.AmzCredential]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Verify request has AWS PreSign Version '2'.
|
||||
func isRequestPresignedSignatureV2(r *http.Request) bool {
|
||||
_, ok := r.URL.Query()[xhttp.AmzAccessKeyID]
|
||||
_, ok := r.Form[xhttp.AmzAccessKeyID]
|
||||
return ok
|
||||
}
|
||||
|
||||
@ -102,6 +103,14 @@ const (
|
||||
|
||||
// Get request authentication type.
|
||||
func getRequestAuthType(r *http.Request) authType {
|
||||
if r.URL != nil {
|
||||
var err error
|
||||
r.Form, err = url.ParseQuery(r.URL.RawQuery)
|
||||
if err != nil {
|
||||
logger.LogIf(r.Context(), err)
|
||||
return authTypeUnknown
|
||||
}
|
||||
}
|
||||
if isRequestSignatureV2(r) {
|
||||
return authTypeSignedV2
|
||||
} else if isRequestPresignedSignatureV2(r) {
|
||||
@ -116,7 +125,7 @@ func getRequestAuthType(r *http.Request) authType {
|
||||
return authTypeJWT
|
||||
} else if isRequestPostPolicySignatureV4(r) {
|
||||
return authTypePostPolicy
|
||||
} else if _, ok := r.URL.Query()[xhttp.Action]; ok {
|
||||
} else if _, ok := r.Form[xhttp.Action]; ok {
|
||||
return authTypeSTS
|
||||
} else if _, ok := r.Header[xhttp.Authorization]; !ok {
|
||||
return authTypeAnonymous
|
||||
@ -183,7 +192,7 @@ func getSessionToken(r *http.Request) (token string) {
|
||||
if token != "" {
|
||||
return token
|
||||
}
|
||||
return r.URL.Query().Get(xhttp.AmzSecurityToken)
|
||||
return r.Form.Get(xhttp.AmzSecurityToken)
|
||||
}
|
||||
|
||||
// Fetch claims in the security token returned by the client, doesn't return
|
||||
@ -444,7 +453,7 @@ func isReqAuthenticated(ctx context.Context, r *http.Request, region string, sty
|
||||
// Do not verify 'X-Amz-Content-Sha256' if skipSHA256.
|
||||
var contentSHA256 []byte
|
||||
if skipSHA256 := skipContentSha256Cksum(r); !skipSHA256 && isRequestPresignedSignatureV4(r) {
|
||||
if sha256Sum, ok := r.URL.Query()[xhttp.AmzContentSha256]; ok && len(sha256Sum) > 0 {
|
||||
if sha256Sum, ok := r.Form[xhttp.AmzContentSha256]; ok && len(sha256Sum) > 0 {
|
||||
contentSHA256, err = hex.DecodeString(sha256Sum[0])
|
||||
if err != nil {
|
||||
return ErrContentSHA256Mismatch
|
||||
|
@ -38,6 +38,7 @@ func TestGetRequestAuthType(t *testing.T) {
|
||||
req *http.Request
|
||||
authT authType
|
||||
}
|
||||
nopCloser := ioutil.NopCloser(io.LimitReader(&nullReader{}, 1024))
|
||||
testCases := []testCase{
|
||||
// Test case - 1
|
||||
// Check for generic signature v4 header.
|
||||
@ -54,6 +55,7 @@ func TestGetRequestAuthType(t *testing.T) {
|
||||
"Content-Encoding": []string{streamingContentEncoding},
|
||||
},
|
||||
Method: http.MethodPut,
|
||||
Body: nopCloser,
|
||||
},
|
||||
authT: authTypeStreamingSigned,
|
||||
},
|
||||
@ -113,6 +115,7 @@ func TestGetRequestAuthType(t *testing.T) {
|
||||
"Content-Type": []string{"multipart/form-data"},
|
||||
},
|
||||
Method: http.MethodPost,
|
||||
Body: nopCloser,
|
||||
},
|
||||
authT: authTypePostPolicy,
|
||||
},
|
||||
@ -220,6 +223,7 @@ func TestIsRequestPresignedSignatureV2(t *testing.T) {
|
||||
q := inputReq.URL.Query()
|
||||
q.Add(testCase.inputQueryKey, testCase.inputQueryValue)
|
||||
inputReq.URL.RawQuery = q.Encode()
|
||||
inputReq.ParseForm()
|
||||
|
||||
actualResult := isRequestPresignedSignatureV2(inputReq)
|
||||
if testCase.expectedResult != actualResult {
|
||||
@ -254,6 +258,7 @@ func TestIsRequestPresignedSignatureV4(t *testing.T) {
|
||||
q := inputReq.URL.Query()
|
||||
q.Add(testCase.inputQueryKey, testCase.inputQueryValue)
|
||||
inputReq.URL.RawQuery = q.Encode()
|
||||
inputReq.ParseForm()
|
||||
|
||||
actualResult := isRequestPresignedSignatureV4(inputReq)
|
||||
if testCase.expectedResult != actualResult {
|
||||
|
@ -246,7 +246,7 @@ func (api objectAPIHandlers) ListMultipartUploadsHandler(w http.ResponseWriter,
|
||||
return
|
||||
}
|
||||
|
||||
prefix, keyMarker, uploadIDMarker, delimiter, maxUploads, encodingType, errCode := getBucketMultipartResources(r.URL.Query())
|
||||
prefix, keyMarker, uploadIDMarker, delimiter, maxUploads, encodingType, errCode := getBucketMultipartResources(r.Form)
|
||||
if errCode != ErrNone {
|
||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(errCode), r.URL)
|
||||
return
|
||||
@ -1699,7 +1699,7 @@ func (api objectAPIHandlers) ResetBucketReplicationStateHandler(w http.ResponseW
|
||||
|
||||
vars := mux.Vars(r)
|
||||
bucket := vars["bucket"]
|
||||
durationStr := r.URL.Query().Get("older-than")
|
||||
durationStr := r.Form.Get("older-than")
|
||||
var (
|
||||
days time.Duration
|
||||
err error
|
||||
|
@ -458,7 +458,7 @@ func (r *RestoreObjectRequest) validate(ctx context.Context, objAPI ObjectLayer)
|
||||
func postRestoreOpts(ctx context.Context, r *http.Request, bucket, object string) (opts ObjectOptions, err error) {
|
||||
versioned := globalBucketVersioningSys.Enabled(bucket)
|
||||
versionSuspended := globalBucketVersioningSys.Suspended(bucket)
|
||||
vid := strings.TrimSpace(r.URL.Query().Get(xhttp.VersionID))
|
||||
vid := strings.TrimSpace(r.Form.Get(xhttp.VersionID))
|
||||
if vid != "" && vid != nullVersionID {
|
||||
_, err := uuid.Parse(vid)
|
||||
if err != nil {
|
||||
|
@ -92,7 +92,7 @@ func (api objectAPIHandlers) ListObjectVersionsHandler(w http.ResponseWriter, r
|
||||
return
|
||||
}
|
||||
|
||||
urlValues := r.URL.Query()
|
||||
urlValues := r.Form
|
||||
|
||||
// Extract all the listBucketVersions query params to their native values.
|
||||
prefix, marker, delimiter, maxkeys, encodingType, versionIDMarker, errCode := getListBucketObjectVersionsArgs(urlValues)
|
||||
@ -153,7 +153,7 @@ func (api objectAPIHandlers) ListObjectsV2MHandler(w http.ResponseWriter, r *htt
|
||||
return
|
||||
}
|
||||
|
||||
urlValues := r.URL.Query()
|
||||
urlValues := r.Form
|
||||
|
||||
// Extract all the listObjectsV2 query params to their native values.
|
||||
prefix, token, startAfter, delimiter, fetchOwner, maxKeys, encodingType, errCode := getListObjectsV2Args(urlValues)
|
||||
@ -220,7 +220,7 @@ func (api objectAPIHandlers) ListObjectsV2Handler(w http.ResponseWriter, r *http
|
||||
return
|
||||
}
|
||||
|
||||
urlValues := r.URL.Query()
|
||||
urlValues := r.Form
|
||||
|
||||
// Extract all the listObjectsV2 query params to their native values.
|
||||
prefix, token, startAfter, delimiter, fetchOwner, maxKeys, encodingType, errCode := getListObjectsV2Args(urlValues)
|
||||
@ -329,7 +329,7 @@ func (api objectAPIHandlers) ListObjectsV1Handler(w http.ResponseWriter, r *http
|
||||
}
|
||||
|
||||
// Extract all the litsObjectsV1 query params to their native values.
|
||||
prefix, marker, delimiter, maxKeys, encodingType, s3Error := getListObjectsV1Args(r.URL.Query())
|
||||
prefix, marker, delimiter, maxKeys, encodingType, s3Error := getListObjectsV1Args(r.Form)
|
||||
if s3Error != ErrNone {
|
||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL)
|
||||
return
|
||||
|
@ -77,10 +77,10 @@ func getConditionValues(r *http.Request, lc string, username string, claims map[
|
||||
}
|
||||
}
|
||||
|
||||
vid := r.URL.Query().Get("versionId")
|
||||
vid := r.Form.Get(xhttp.VersionID)
|
||||
if vid == "" {
|
||||
if u, err := url.Parse(r.Header.Get(xhttp.AmzCopySource)); err == nil {
|
||||
vid = u.Query().Get("versionId")
|
||||
vid = u.Query().Get(xhttp.VersionID)
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,8 +143,8 @@ func getConditionValues(r *http.Request, lc string, username string, claims map[
|
||||
}
|
||||
}
|
||||
|
||||
var cloneURLValues = url.Values{}
|
||||
for k, v := range r.URL.Query() {
|
||||
cloneURLValues := make(url.Values, len(r.Form))
|
||||
for k, v := range r.Form {
|
||||
cloneURLValues[k] = v
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ import (
|
||||
// Test cross domain xml handler.
|
||||
func TestCrossXMLHandler(t *testing.T) {
|
||||
// Server initialization.
|
||||
router := mux.NewRouter().SkipClean(true)
|
||||
router := mux.NewRouter().SkipClean(true).UseEncodedPath()
|
||||
handler := setCrossDomainPolicy(router)
|
||||
srv := httptest.NewServer(handler)
|
||||
|
||||
|
@ -406,7 +406,7 @@ func setRequestValidityHandler(h http.Handler) http.Handler {
|
||||
return
|
||||
}
|
||||
// Check for bad components in URL query values.
|
||||
for _, vv := range r.URL.Query() {
|
||||
for _, vv := range r.Form {
|
||||
for _, v := range vv {
|
||||
if hasBadPathComponent(v) {
|
||||
writeErrorResponse(r.Context(), w, errorCodes.ToAPIErr(ErrInvalidResourceName), r.URL)
|
||||
@ -436,55 +436,6 @@ func setBucketForwardingHandler(h http.Handler) http.Handler {
|
||||
return
|
||||
}
|
||||
|
||||
// For browser requests, when federation is setup we need to
|
||||
// specifically handle download and upload for browser requests.
|
||||
if guessIsBrowserReq(r) {
|
||||
var bucket, _ string
|
||||
switch r.Method {
|
||||
case http.MethodPut:
|
||||
if getRequestAuthType(r) == authTypeJWT {
|
||||
bucket, _ = path2BucketObjectWithBasePath(minioReservedBucketPath+"/upload", r.URL.Path)
|
||||
}
|
||||
case http.MethodGet:
|
||||
if t := r.URL.Query().Get("token"); t != "" {
|
||||
bucket, _ = path2BucketObjectWithBasePath(minioReservedBucketPath+"/download", r.URL.Path)
|
||||
} else if getRequestAuthType(r) != authTypeJWT && !strings.HasPrefix(r.URL.Path, minioReservedBucketPath) {
|
||||
bucket, _ = request2BucketObjectName(r)
|
||||
}
|
||||
}
|
||||
if bucket == "" {
|
||||
h.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
sr, err := globalDNSConfig.Get(bucket)
|
||||
if err != nil {
|
||||
if err == dns.ErrNoEntriesFound {
|
||||
writeErrorResponse(r.Context(), w, errorCodes.ToAPIErr(ErrNoSuchBucket),
|
||||
r.URL)
|
||||
} else {
|
||||
writeErrorResponse(r.Context(), w, toAPIError(r.Context(), err),
|
||||
r.URL)
|
||||
}
|
||||
return
|
||||
}
|
||||
if globalDomainIPs.Intersection(set.CreateStringSet(getHostsSlice(sr)...)).IsEmpty() {
|
||||
r.URL.Scheme = "http"
|
||||
if globalIsTLS {
|
||||
r.URL.Scheme = "https"
|
||||
}
|
||||
r.URL.Host = getHostFromSrv(sr)
|
||||
// Make sure we remove any existing headers before
|
||||
// proxying the request to another node.
|
||||
for k := range w.Header() {
|
||||
w.Header().Del(k)
|
||||
}
|
||||
globalForwarder.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
h.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
bucket, object := request2BucketObjectName(r)
|
||||
|
||||
// Requests in federated setups for STS type calls which are
|
||||
|
@ -112,7 +112,7 @@ var userMetadataKeyPrefixes = []string{
|
||||
|
||||
// extractMetadata extracts metadata from HTTP header and HTTP queryString.
|
||||
func extractMetadata(ctx context.Context, r *http.Request) (metadata map[string]string, err error) {
|
||||
query := r.URL.Query()
|
||||
query := r.Form
|
||||
header := r.Header
|
||||
metadata = make(map[string]string)
|
||||
// Extract all query values.
|
||||
|
@ -42,7 +42,7 @@ func ClusterCheckHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(ctx, globalAPIConfig.getClusterDeadline())
|
||||
defer cancel()
|
||||
|
||||
opts := HealthOptions{Maintenance: r.URL.Query().Get("maintenance") == "true"}
|
||||
opts := HealthOptions{Maintenance: r.Form.Get("maintenance") == "true"}
|
||||
result := objLayer.Health(ctx, opts)
|
||||
if result.WriteQuorum > 0 {
|
||||
w.Header().Set(xhttp.MinIOWriteQuorum, strconv.Itoa(result.WriteQuorum))
|
||||
|
@ -65,7 +65,7 @@ func (api objectAPIHandlers) ListenNotificationHandler(w http.ResponseWriter, r
|
||||
}
|
||||
}
|
||||
|
||||
values := r.URL.Query()
|
||||
values := r.Form
|
||||
|
||||
var prefix string
|
||||
if len(values[peerRESTListenPrefix]) > 1 {
|
||||
|
@ -63,15 +63,16 @@ func (l *lockRESTServer) IsValid(w http.ResponseWriter, r *http.Request) bool {
|
||||
}
|
||||
|
||||
func getLockArgs(r *http.Request) (args dsync.LockArgs, err error) {
|
||||
quorum, err := strconv.Atoi(r.URL.Query().Get(lockRESTQuorum))
|
||||
values := r.Form
|
||||
quorum, err := strconv.Atoi(values.Get(lockRESTQuorum))
|
||||
if err != nil {
|
||||
return args, err
|
||||
}
|
||||
|
||||
args = dsync.LockArgs{
|
||||
Owner: r.URL.Query().Get(lockRESTOwner),
|
||||
UID: r.URL.Query().Get(lockRESTUID),
|
||||
Source: r.URL.Query().Get(lockRESTSource),
|
||||
Owner: values.Get(lockRESTOwner),
|
||||
UID: values.Get(lockRESTUID),
|
||||
Source: values.Get(lockRESTSource),
|
||||
Quorum: quorum,
|
||||
}
|
||||
|
||||
|
@ -332,8 +332,8 @@ func (s *storageRESTServer) WalkDirHandler(w http.ResponseWriter, r *http.Reques
|
||||
}
|
||||
}
|
||||
|
||||
prefix := r.URL.Query().Get(storageRESTPrefixFilter)
|
||||
forward := r.URL.Query().Get(storageRESTForwardFilter)
|
||||
prefix := r.Form.Get(storageRESTPrefixFilter)
|
||||
forward := r.Form.Get(storageRESTForwardFilter)
|
||||
writer := streamHTTPResponse(w)
|
||||
writer.CloseWithError(s.storage.WalkDir(r.Context(), WalkDirOptions{
|
||||
Bucket: volume,
|
||||
|
@ -83,7 +83,7 @@ func getOpts(ctx context.Context, r *http.Request, bucket, object string) (Objec
|
||||
|
||||
var partNumber int
|
||||
var err error
|
||||
if pn := r.URL.Query().Get(xhttp.PartNumber); pn != "" {
|
||||
if pn := r.Form.Get(xhttp.PartNumber); pn != "" {
|
||||
partNumber, err = strconv.Atoi(pn)
|
||||
if err != nil {
|
||||
return opts, err
|
||||
@ -93,7 +93,7 @@ func getOpts(ctx context.Context, r *http.Request, bucket, object string) (Objec
|
||||
}
|
||||
}
|
||||
|
||||
vid := strings.TrimSpace(r.URL.Query().Get(xhttp.VersionID))
|
||||
vid := strings.TrimSpace(r.Form.Get(xhttp.VersionID))
|
||||
if vid != "" && vid != nullVersionID {
|
||||
_, err := uuid.Parse(vid)
|
||||
if err != nil {
|
||||
@ -219,7 +219,7 @@ func delOpts(ctx context.Context, r *http.Request, bucket, object string) (opts
|
||||
// get ObjectOptions for PUT calls from encryption headers and metadata
|
||||
func putOpts(ctx context.Context, r *http.Request, bucket, object string, metadata map[string]string) (opts ObjectOptions, err error) {
|
||||
versioned := globalBucketVersioningSys.Enabled(bucket)
|
||||
vid := strings.TrimSpace(r.URL.Query().Get(xhttp.VersionID))
|
||||
vid := strings.TrimSpace(r.Form.Get(xhttp.VersionID))
|
||||
if vid != "" && vid != nullVersionID {
|
||||
_, err := uuid.Parse(vid)
|
||||
if err != nil {
|
||||
|
@ -491,7 +491,7 @@ func (api objectAPIHandlers) getObjectHandler(ctx context.Context, objectAPI Obj
|
||||
setPartsCountHeaders(w, objInfo)
|
||||
}
|
||||
|
||||
setHeadGetRespHeaders(w, r.URL.Query())
|
||||
setHeadGetRespHeaders(w, r.Form)
|
||||
|
||||
statusCodeWritten := false
|
||||
httpWriter := ioutil.WriteOnClose(w)
|
||||
@ -739,7 +739,7 @@ func (api objectAPIHandlers) headObjectHandler(ctx context.Context, objectAPI Ob
|
||||
}
|
||||
|
||||
// Set any additional requested response headers.
|
||||
setHeadGetRespHeaders(w, r.URL.Query())
|
||||
setHeadGetRespHeaders(w, r.Form)
|
||||
|
||||
// Successful response.
|
||||
if rs != nil || opts.PartNumber > 0 {
|
||||
@ -806,7 +806,7 @@ func getCpObjMetadataFromHeader(ctx context.Context, r *http.Request, userMeta m
|
||||
// to the destination metadata.
|
||||
sc := r.Header.Get(xhttp.AmzStorageClass)
|
||||
if sc == "" {
|
||||
sc = r.URL.Query().Get(xhttp.AmzStorageClass)
|
||||
sc = r.Form.Get(xhttp.AmzStorageClass)
|
||||
}
|
||||
|
||||
// if x-amz-metadata-directive says REPLACE then
|
||||
@ -2264,8 +2264,8 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
|
||||
return
|
||||
}
|
||||
|
||||
uploadID := r.URL.Query().Get(xhttp.UploadID)
|
||||
partIDString := r.URL.Query().Get(xhttp.PartNumber)
|
||||
uploadID := r.Form.Get(xhttp.UploadID)
|
||||
partIDString := r.Form.Get(xhttp.PartNumber)
|
||||
|
||||
partID, err := strconv.Atoi(partIDString)
|
||||
if err != nil {
|
||||
@ -2591,8 +2591,8 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http
|
||||
return
|
||||
}
|
||||
|
||||
uploadID := r.URL.Query().Get(xhttp.UploadID)
|
||||
partIDString := r.URL.Query().Get(xhttp.PartNumber)
|
||||
uploadID := r.Form.Get(xhttp.UploadID)
|
||||
partIDString := r.Form.Get(xhttp.PartNumber)
|
||||
|
||||
partID, err := strconv.Atoi(partIDString)
|
||||
if err != nil {
|
||||
@ -2812,7 +2812,7 @@ func (api objectAPIHandlers) AbortMultipartUploadHandler(w http.ResponseWriter,
|
||||
return
|
||||
}
|
||||
|
||||
uploadID, _, _, _, s3Error := getObjectResources(r.URL.Query())
|
||||
uploadID, _, _, _, s3Error := getObjectResources(r.Form)
|
||||
if s3Error != ErrNone {
|
||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL)
|
||||
return
|
||||
@ -2851,7 +2851,7 @@ func (api objectAPIHandlers) ListObjectPartsHandler(w http.ResponseWriter, r *ht
|
||||
return
|
||||
}
|
||||
|
||||
uploadID, partNumberMarker, maxParts, encodingType, s3Error := getObjectResources(r.URL.Query())
|
||||
uploadID, partNumberMarker, maxParts, encodingType, s3Error := getObjectResources(r.Form)
|
||||
if s3Error != ErrNone {
|
||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL)
|
||||
return
|
||||
@ -2997,7 +2997,7 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite
|
||||
}
|
||||
|
||||
// Get upload id.
|
||||
uploadID, _, _, _, s3Error := getObjectResources(r.URL.Query())
|
||||
uploadID, _, _, _, s3Error := getObjectResources(r.Form)
|
||||
if s3Error != ErrNone {
|
||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL)
|
||||
return
|
||||
|
@ -26,6 +26,7 @@ import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"path"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
@ -557,12 +558,8 @@ func testAPIGetObjectHandler(obj ObjectLayer, instanceType, bucketName string, a
|
||||
t.Fatalf("Test %d: %s: Failed parsing response body: <ERROR> %v", i+1, instanceType, err)
|
||||
}
|
||||
|
||||
if actualError.BucketName != testCase.bucketName {
|
||||
t.Fatalf("Test %d: %s: Unexpected bucket name, expected %s, got %s", i+1, instanceType, testCase.bucketName, actualError.BucketName)
|
||||
}
|
||||
|
||||
if actualError.Key != testCase.objectName {
|
||||
t.Fatalf("Test %d: %s: Unexpected object name, expected %s, got %s", i+1, instanceType, testCase.objectName, actualError.Key)
|
||||
if path.Clean(actualError.Resource) != pathJoin(SlashSeparator, testCase.bucketName, testCase.objectName) {
|
||||
t.Fatalf("Test %d: %s: Unexpected resource, expected %s, got %s", i+1, instanceType, pathJoin(SlashSeparator, testCase.bucketName, testCase.objectName), actualError.Resource)
|
||||
}
|
||||
|
||||
// Verify response of the V2 signed HTTP request.
|
||||
@ -606,12 +603,8 @@ func testAPIGetObjectHandler(obj ObjectLayer, instanceType, bucketName string, a
|
||||
t.Fatalf("Test %d: %s: Failed parsing response body: <ERROR> %v", i+1, instanceType, err)
|
||||
}
|
||||
|
||||
if actualError.BucketName != testCase.bucketName {
|
||||
t.Fatalf("Test %d: %s: Unexpected bucket name, expected %s, got %s", i+1, instanceType, testCase.bucketName, actualError.BucketName)
|
||||
}
|
||||
|
||||
if actualError.Key != testCase.objectName {
|
||||
t.Fatalf("Test %d: %s: Unexpected object name, expected %s, got %s", i+1, instanceType, testCase.objectName, actualError.Key)
|
||||
if path.Clean(actualError.Resource) != pathJoin(SlashSeparator, testCase.bucketName, testCase.objectName) {
|
||||
t.Fatalf("Test %d: %s: Unexpected resource, expected %s, got %s", i+1, instanceType, pathJoin(SlashSeparator, testCase.bucketName, testCase.objectName), actualError.Resource)
|
||||
}
|
||||
}
|
||||
|
||||
@ -918,7 +911,6 @@ func testAPIGetObjectWithPartNumberHandler(obj ObjectLayer, instanceType, bucket
|
||||
|
||||
mkGetReqWithPartNumber := func(oindex int, oi ObjectInput, partNumber int) {
|
||||
object := oi.objectName
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
queries := url.Values{}
|
||||
queries.Add("partNumber", strconv.Itoa(partNumber))
|
||||
@ -930,6 +922,7 @@ func testAPIGetObjectWithPartNumberHandler(obj ObjectLayer, instanceType, bucket
|
||||
object, oindex, partNumber, err)
|
||||
}
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
apiRouter.ServeHTTP(rec, req)
|
||||
|
||||
// Check response code (we make only valid requests in this test)
|
||||
|
@ -136,7 +136,7 @@ func (s *peerRESTServer) LoadPolicyMappingHandler(w http.ResponseWriter, r *http
|
||||
return
|
||||
}
|
||||
|
||||
_, isGroup := r.URL.Query()[peerRESTIsGroup]
|
||||
_, isGroup := r.Form[peerRESTIsGroup]
|
||||
if err := globalIAMSys.LoadPolicyMapping(objAPI, userOrGroup, isGroup); err != nil {
|
||||
s.writeErrorResponse(w, err)
|
||||
return
|
||||
@ -841,7 +841,7 @@ func (s *peerRESTServer) ListenHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
values := r.URL.Query()
|
||||
values := r.Form
|
||||
|
||||
var prefix string
|
||||
if len(values[peerRESTListenPrefix]) > 1 {
|
||||
@ -932,15 +932,13 @@ func (s *peerRESTServer) ListenHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func extractTraceOptsFromPeerRequest(r *http.Request) (opts madmin.ServiceTraceOpts, err error) {
|
||||
opts.S3 = r.Form.Get(peerRESTTraceS3) == "true"
|
||||
opts.OS = r.Form.Get(peerRESTTraceOS) == "true"
|
||||
opts.Storage = r.Form.Get(peerRESTTraceStorage) == "true"
|
||||
opts.Internal = r.Form.Get(peerRESTTraceInternal) == "true"
|
||||
opts.OnlyErrors = r.Form.Get(peerRESTTraceErr) == "true"
|
||||
|
||||
q := r.URL.Query()
|
||||
opts.OnlyErrors = q.Get(peerRESTTraceErr) == "true"
|
||||
opts.Storage = q.Get(peerRESTTraceStorage) == "true"
|
||||
opts.Internal = q.Get(peerRESTTraceInternal) == "true"
|
||||
opts.S3 = q.Get(peerRESTTraceS3) == "true"
|
||||
opts.OS = q.Get(peerRESTTraceOS) == "true"
|
||||
|
||||
if t := q.Get(peerRESTTraceThreshold); t != "" {
|
||||
if t := r.Form.Get(peerRESTTraceThreshold); t != "" {
|
||||
d, err := time.ParseDuration(t)
|
||||
if err != nil {
|
||||
return opts, err
|
||||
@ -1078,7 +1076,8 @@ func (s *peerRESTServer) GetBandwidth(w http.ResponseWriter, r *http.Request) {
|
||||
s.writeErrorResponse(w, errors.New("invalid request"))
|
||||
return
|
||||
}
|
||||
bucketsString := r.URL.Query().Get("buckets")
|
||||
|
||||
bucketsString := r.Form.Get("buckets")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.(http.Flusher).Flush()
|
||||
|
||||
@ -1259,9 +1258,9 @@ func (s *peerRESTServer) SpeedtestHandler(w http.ResponseWriter, r *http.Request
|
||||
return
|
||||
}
|
||||
|
||||
sizeStr := r.URL.Query().Get(peerRESTSize)
|
||||
durationStr := r.URL.Query().Get(peerRESTDuration)
|
||||
concurrentStr := r.URL.Query().Get(peerRESTConcurrent)
|
||||
sizeStr := r.Form.Get(peerRESTSize)
|
||||
durationStr := r.Form.Get(peerRESTDuration)
|
||||
concurrentStr := r.Form.Get(peerRESTConcurrent)
|
||||
|
||||
size, err := strconv.Atoi(sizeStr)
|
||||
if err != nil {
|
||||
|
@ -196,7 +196,7 @@ func (api objectAPIHandlers) getObjectInArchiveFileHandler(ctx context.Context,
|
||||
return
|
||||
}
|
||||
|
||||
setHeadGetRespHeaders(w, r.URL.Query())
|
||||
setHeadGetRespHeaders(w, r.Form)
|
||||
|
||||
httpWriter := ioutil.WriteOnClose(w)
|
||||
|
||||
@ -467,7 +467,7 @@ func (api objectAPIHandlers) headObjectInArchiveFileHandler(ctx context.Context,
|
||||
}
|
||||
|
||||
// Set any additional requested response headers.
|
||||
setHeadGetRespHeaders(w, r.URL.Query())
|
||||
setHeadGetRespHeaders(w, r.Form)
|
||||
|
||||
// Successful response.
|
||||
if rs != nil {
|
||||
|
@ -183,7 +183,7 @@ func doesPresignV2SignatureMatch(r *http.Request) APIErrorCode {
|
||||
}
|
||||
|
||||
func getReqAccessKeyV2(r *http.Request) (auth.Credentials, bool, APIErrorCode) {
|
||||
if accessKey := r.URL.Query().Get(xhttp.AmzAccessKeyID); accessKey != "" {
|
||||
if accessKey := r.Form.Get(xhttp.AmzAccessKeyID); accessKey != "" {
|
||||
return checkKeyValid(accessKey)
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ func (c credentialHeader) getScope() string {
|
||||
}
|
||||
|
||||
func getReqAccessKeyV4(r *http.Request, region string, stype serviceType) (auth.Credentials, bool, APIErrorCode) {
|
||||
ch, s3Err := parseCredentialHeader("Credential="+r.URL.Query().Get(xhttp.AmzCredential), region, stype)
|
||||
ch, s3Err := parseCredentialHeader("Credential="+r.Form.Get(xhttp.AmzCredential), region, stype)
|
||||
if s3Err != ErrNone {
|
||||
// Strip off the Algorithm prefix.
|
||||
v4Auth := strings.TrimPrefix(r.Header.Get("Authorization"), signV4Algorithm)
|
||||
|
@ -46,7 +46,7 @@ func skipContentSha256Cksum(r *http.Request) bool {
|
||||
)
|
||||
|
||||
if isRequestPresignedSignatureV4(r) {
|
||||
v, ok = r.URL.Query()[xhttp.AmzContentSha256]
|
||||
v, ok = r.Form[xhttp.AmzContentSha256]
|
||||
if !ok {
|
||||
v, ok = r.Header[xhttp.AmzContentSha256]
|
||||
}
|
||||
@ -82,7 +82,7 @@ func getContentSha256Cksum(r *http.Request, stype serviceType) string {
|
||||
// X-Amz-Content-Sha256, if not set in presigned requests, checksum
|
||||
// will default to 'UNSIGNED-PAYLOAD'.
|
||||
defaultSha256Cksum = unsignedPayload
|
||||
v, ok = r.URL.Query()[xhttp.AmzContentSha256]
|
||||
v, ok = r.Form[xhttp.AmzContentSha256]
|
||||
if !ok {
|
||||
v, ok = r.Header[xhttp.AmzContentSha256]
|
||||
}
|
||||
@ -151,7 +151,7 @@ func sumHMAC(key []byte, data []byte) []byte {
|
||||
// extractSignedHeaders extract signed headers from Authorization header
|
||||
func extractSignedHeaders(signedHeaders []string, r *http.Request) (http.Header, APIErrorCode) {
|
||||
reqHeaders := r.Header
|
||||
reqQueries := r.URL.Query()
|
||||
reqQueries := r.Form
|
||||
// find whether "host" is part of list of signed headers.
|
||||
// if not return ErrUnsignedHeaders. "host" is mandatory.
|
||||
if !contains(signedHeaders, "host") {
|
||||
|
@ -89,6 +89,7 @@ func TestSkipContentSha256Cksum(t *testing.T) {
|
||||
inputReq.Header.Set(testCase.inputHeaderKey, testCase.inputHeaderValue)
|
||||
}
|
||||
}
|
||||
inputReq.ParseForm()
|
||||
|
||||
actualResult := skipContentSha256Cksum(inputReq)
|
||||
if testCase.expectedResult != actualResult {
|
||||
@ -163,6 +164,7 @@ func TestExtractSignedHeaders(t *testing.T) {
|
||||
// set headers value through Get parameter
|
||||
inputQuery.Add("x-amz-server-side-encryption", xhttp.AmzEncryptionAES)
|
||||
r.URL.RawQuery = inputQuery.Encode()
|
||||
r.ParseForm()
|
||||
_, errCode = extractSignedHeaders(signedHeaders, r)
|
||||
if errCode != ErrNone {
|
||||
t.Fatalf("Expected the APIErrorCode to be %d, but got %d", ErrNone, errCode)
|
||||
@ -267,6 +269,7 @@ func TestGetContentSha256Cksum(t *testing.T) {
|
||||
if testCase.h != "" {
|
||||
r.Header.Set("x-amz-content-sha256", testCase.h)
|
||||
}
|
||||
r.ParseForm()
|
||||
got := getContentSha256Cksum(r, serviceS3)
|
||||
if got != testCase.expected {
|
||||
t.Errorf("Test %d: got:%s expected:%s", i+1, got, testCase.expected)
|
||||
|
@ -209,7 +209,7 @@ func doesPresignedSignatureMatch(hashedPayload string, r *http.Request, region s
|
||||
req := *r
|
||||
|
||||
// Parse request query string.
|
||||
pSignValues, err := parsePreSignV4(req.URL.Query(), region, stype)
|
||||
pSignValues, err := parsePreSignV4(req.Form, region, stype)
|
||||
if err != ErrNone {
|
||||
return err
|
||||
}
|
||||
@ -241,12 +241,12 @@ func doesPresignedSignatureMatch(hashedPayload string, r *http.Request, region s
|
||||
|
||||
// Construct new query.
|
||||
query := make(url.Values)
|
||||
clntHashedPayload := req.URL.Query().Get(xhttp.AmzContentSha256)
|
||||
clntHashedPayload := req.Form.Get(xhttp.AmzContentSha256)
|
||||
if clntHashedPayload != "" {
|
||||
query.Set(xhttp.AmzContentSha256, hashedPayload)
|
||||
}
|
||||
|
||||
token := req.URL.Query().Get(xhttp.AmzSecurityToken)
|
||||
token := req.Form.Get(xhttp.AmzSecurityToken)
|
||||
if token != "" {
|
||||
query.Set(xhttp.AmzSecurityToken, cred.SessionToken)
|
||||
}
|
||||
@ -271,7 +271,7 @@ func doesPresignedSignatureMatch(hashedPayload string, r *http.Request, region s
|
||||
)
|
||||
|
||||
// Add missing query parameters if any provided in the request URL
|
||||
for k, v := range req.URL.Query() {
|
||||
for k, v := range req.Form {
|
||||
if !defaultSigParams.Contains(k) {
|
||||
query[k] = v
|
||||
}
|
||||
@ -281,19 +281,19 @@ func doesPresignedSignatureMatch(hashedPayload string, r *http.Request, region s
|
||||
encodedQuery := query.Encode()
|
||||
|
||||
// Verify if date query is same.
|
||||
if req.URL.Query().Get(xhttp.AmzDate) != query.Get(xhttp.AmzDate) {
|
||||
if req.Form.Get(xhttp.AmzDate) != query.Get(xhttp.AmzDate) {
|
||||
return ErrSignatureDoesNotMatch
|
||||
}
|
||||
// Verify if expires query is same.
|
||||
if req.URL.Query().Get(xhttp.AmzExpires) != query.Get(xhttp.AmzExpires) {
|
||||
if req.Form.Get(xhttp.AmzExpires) != query.Get(xhttp.AmzExpires) {
|
||||
return ErrSignatureDoesNotMatch
|
||||
}
|
||||
// Verify if signed headers query is same.
|
||||
if req.URL.Query().Get(xhttp.AmzSignedHeaders) != query.Get(xhttp.AmzSignedHeaders) {
|
||||
if req.Form.Get(xhttp.AmzSignedHeaders) != query.Get(xhttp.AmzSignedHeaders) {
|
||||
return ErrSignatureDoesNotMatch
|
||||
}
|
||||
// Verify if credential query is same.
|
||||
if req.URL.Query().Get(xhttp.AmzCredential) != query.Get(xhttp.AmzCredential) {
|
||||
if req.Form.Get(xhttp.AmzCredential) != query.Get(xhttp.AmzCredential) {
|
||||
return ErrSignatureDoesNotMatch
|
||||
}
|
||||
// Verify if sha256 payload query is same.
|
||||
@ -321,7 +321,7 @@ func doesPresignedSignatureMatch(hashedPayload string, r *http.Request, region s
|
||||
newSignature := getSignature(presignedSigningKey, presignedStringToSign)
|
||||
|
||||
// Verify signature.
|
||||
if !compareSignatureV4(req.URL.Query().Get(xhttp.AmzSignature), newSignature) {
|
||||
if !compareSignatureV4(req.Form.Get(xhttp.AmzSignature), newSignature) {
|
||||
return ErrSignatureDoesNotMatch
|
||||
}
|
||||
return ErrNone
|
||||
@ -369,7 +369,7 @@ func doesSignatureMatch(hashedPayload string, r *http.Request, region string, st
|
||||
}
|
||||
|
||||
// Query string.
|
||||
queryStr := req.URL.Query().Encode()
|
||||
queryStr := req.Form.Encode()
|
||||
|
||||
// Get canonical request.
|
||||
canonicalRequest := getCanonicalRequest(extractedSignedHeaders, hashedPayload, queryStr, req.URL.Path, req.Method)
|
||||
|
@ -293,6 +293,9 @@ func TestDoesPresignedSignatureMatch(t *testing.T) {
|
||||
req.Header.Set(key, value)
|
||||
}
|
||||
|
||||
// parse form.
|
||||
req.ParseForm()
|
||||
|
||||
// Check if it matches!
|
||||
err := doesPresignedSignatureMatch(payloadSHA256, req, testCase.region, serviceS3)
|
||||
if err != testCase.expected {
|
||||
|
@ -119,7 +119,7 @@ func (s *storageRESTServer) IsValid(w http.ResponseWriter, r *http.Request) bool
|
||||
return false
|
||||
}
|
||||
|
||||
diskID := r.URL.Query().Get(storageRESTDiskID)
|
||||
diskID := r.Form.Get(storageRESTDiskID)
|
||||
if diskID == "" {
|
||||
// Request sent empty disk-id, we allow the request
|
||||
// as the peer might be coming up and trying to read format.json
|
||||
@ -282,7 +282,7 @@ func (s *storageRESTServer) DeleteVolHandler(w http.ResponseWriter, r *http.Requ
|
||||
}
|
||||
vars := mux.Vars(r)
|
||||
volume := vars[storageRESTVolume]
|
||||
forceDelete := r.URL.Query().Get(storageRESTForceDelete) == "true"
|
||||
forceDelete := r.Form.Get(storageRESTForceDelete) == "true"
|
||||
err := s.storage.DeleteVol(r.Context(), volume, forceDelete)
|
||||
if err != nil {
|
||||
s.writeErrorResponse(w, err)
|
||||
@ -641,10 +641,8 @@ func (s *storageRESTServer) DeleteVersionsHandler(w http.ResponseWriter, r *http
|
||||
return
|
||||
}
|
||||
|
||||
vars := r.URL.Query()
|
||||
volume := vars.Get(storageRESTVolume)
|
||||
|
||||
totalVersions, err := strconv.Atoi(vars.Get(storageRESTTotalVersions))
|
||||
volume := r.Form.Get(storageRESTVolume)
|
||||
totalVersions, err := strconv.Atoi(r.Form.Get(storageRESTTotalVersions))
|
||||
if err != nil {
|
||||
s.writeErrorResponse(w, err)
|
||||
return
|
||||
|
@ -117,7 +117,7 @@ func calculateSeedSignature(r *http.Request) (cred auth.Credentials, signature s
|
||||
}
|
||||
|
||||
// Query string.
|
||||
queryStr := req.URL.Query().Encode()
|
||||
queryStr := req.Form.Encode()
|
||||
|
||||
// Get canonical request.
|
||||
canonicalRequest := getCanonicalRequest(extractedSignedHeaders, payload, queryStr, req.URL.Path, req.Method)
|
||||
|
@ -95,14 +95,14 @@ func registerSTSRouter(router *mux.Router) {
|
||||
stsRouter.Methods(http.MethodPost).MatcherFunc(func(r *http.Request, rm *mux.RouteMatch) bool {
|
||||
ctypeOk := wildcard.MatchSimple("application/x-www-form-urlencoded*", r.Header.Get(xhttp.ContentType))
|
||||
authOk := wildcard.MatchSimple(signV4Algorithm+"*", r.Header.Get(xhttp.Authorization))
|
||||
noQueries := len(r.URL.Query()) == 0
|
||||
noQueries := len(r.URL.RawQuery) == 0
|
||||
return ctypeOk && authOk && noQueries
|
||||
}).HandlerFunc(httpTraceAll(sts.AssumeRole))
|
||||
|
||||
// Assume roles with JWT handler, handles both ClientGrants and WebIdentity.
|
||||
stsRouter.Methods(http.MethodPost).MatcherFunc(func(r *http.Request, rm *mux.RouteMatch) bool {
|
||||
ctypeOk := wildcard.MatchSimple("application/x-www-form-urlencoded*", r.Header.Get(xhttp.ContentType))
|
||||
noQueries := len(r.URL.Query()) == 0
|
||||
noQueries := len(r.URL.RawQuery) == 0
|
||||
return ctypeOk && noQueries
|
||||
}).HandlerFunc(httpTraceAll(sts.AssumeRoleWithSSO))
|
||||
|
||||
@ -155,6 +155,18 @@ func checkAssumeRoleAuth(ctx context.Context, r *http.Request) (user auth.Creden
|
||||
return user, true, ErrSTSNone
|
||||
}
|
||||
|
||||
func parseForm(r *http.Request) error {
|
||||
if err := r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
for k, v := range r.PostForm {
|
||||
if _, ok := r.Form[k]; !ok {
|
||||
r.Form[k] = v
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AssumeRole - implementation of AWS STS API AssumeRole to get temporary
|
||||
// credentials for regular users on Minio.
|
||||
// https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html
|
||||
@ -167,7 +179,7 @@ func (sts *stsAPIHandlers) AssumeRole(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := r.ParseForm(); err != nil {
|
||||
if err := parseForm(r); err != nil {
|
||||
writeSTSErrorResponse(ctx, w, true, ErrSTSInvalidParameterValue, err)
|
||||
return
|
||||
}
|
||||
@ -275,7 +287,7 @@ func (sts *stsAPIHandlers) AssumeRoleWithSSO(w http.ResponseWriter, r *http.Requ
|
||||
ctx := newContext(r, w, "AssumeRoleSSOCommon")
|
||||
|
||||
// Parse the incoming form data.
|
||||
if err := r.ParseForm(); err != nil {
|
||||
if err := parseForm(r); err != nil {
|
||||
writeSTSErrorResponse(ctx, w, true, ErrSTSInvalidParameterValue, err)
|
||||
return
|
||||
}
|
||||
@ -514,7 +526,7 @@ func (sts *stsAPIHandlers) AssumeRoleWithLDAPIdentity(w http.ResponseWriter, r *
|
||||
defer logger.AuditLog(ctx, w, r, nil, stsLDAPPassword)
|
||||
|
||||
// Parse the incoming form data.
|
||||
if err := r.ParseForm(); err != nil {
|
||||
if err := parseForm(r); err != nil {
|
||||
writeSTSErrorResponse(ctx, w, true, ErrSTSInvalidParameterValue, err)
|
||||
return
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
@ -1648,12 +1649,8 @@ func ExecObjectLayerAPIAnonTest(t *testing.T, obj ObjectLayer, testName, bucketN
|
||||
t.Fatal(failTestStr(unknownSignTestStr, "error response failed to parse error XML"))
|
||||
}
|
||||
|
||||
if actualError.BucketName != bucketName {
|
||||
t.Fatal(failTestStr(unknownSignTestStr, "error response bucket name differs from expected value"))
|
||||
}
|
||||
|
||||
if actualError.Key != objectName {
|
||||
t.Fatal(failTestStr(unknownSignTestStr, "error response object name differs from expected value"))
|
||||
if path.Clean(actualError.Resource) != pathJoin(SlashSeparator, bucketName, SlashSeparator, objectName) {
|
||||
t.Fatal(failTestStr(unknownSignTestStr, "error response resource differs from expected value"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -2035,13 +2032,15 @@ func registerAPIFunctions(muxRouter *mux.Router, objLayer ObjectLayer, apiFuncti
|
||||
func initTestAPIEndPoints(objLayer ObjectLayer, apiFunctions []string) http.Handler {
|
||||
// initialize a new mux router.
|
||||
// goriilla/mux is the library used to register all the routes and handle them.
|
||||
muxRouter := mux.NewRouter().SkipClean(true)
|
||||
muxRouter := mux.NewRouter().SkipClean(true).UseEncodedPath()
|
||||
if len(apiFunctions) > 0 {
|
||||
// Iterate the list of API functions requested for and register them in mux HTTP handler.
|
||||
registerAPIFunctions(muxRouter, objLayer, apiFunctions...)
|
||||
muxRouter.Use(globalHandlers...)
|
||||
return muxRouter
|
||||
}
|
||||
registerAPIRouter(muxRouter)
|
||||
muxRouter.Use(globalHandlers...)
|
||||
return muxRouter
|
||||
}
|
||||
|
||||
|
70
cmd/url_test.go
Normal file
70
cmd/url_test.go
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkURLQueryForm(b *testing.B) {
|
||||
req, err := http.NewRequest(http.MethodGet, "http://localhost:9000/bucket/name?uploadId=upload&partNumber=1", nil)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
// benchmark utility which helps obtain number of allocations and bytes allocated per ops.
|
||||
b.ReportAllocs()
|
||||
// the actual benchmark for PutObject starts here. Reset the benchmark timer.
|
||||
b.ResetTimer()
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
req.Form.Get("uploadId")
|
||||
}
|
||||
})
|
||||
|
||||
// Benchmark ends here. Stop timer.
|
||||
b.StopTimer()
|
||||
}
|
||||
|
||||
// BenchmarkURLQuery - benchmark URL memory allocations
|
||||
func BenchmarkURLQuery(b *testing.B) {
|
||||
req, err := http.NewRequest(http.MethodGet, "http://localhost:9000/bucket/name?uploadId=upload&partNumber=1", nil)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
// benchmark utility which helps obtain number of allocations and bytes allocated per ops.
|
||||
b.ReportAllocs()
|
||||
// the actual benchmark for PutObject starts here. Reset the benchmark timer.
|
||||
b.ResetTimer()
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
req.URL.Query().Get("uploadId")
|
||||
}
|
||||
})
|
||||
|
||||
// Benchmark ends here. Stop timer.
|
||||
b.StopTimer()
|
||||
}
|
Loading…
Reference in New Issue
Block a user