github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/cmd/generic-handlers_test.go (about) 1 // Copyright (c) 2015-2021 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package cmd 19 20 import ( 21 "net/http" 22 "net/http/httptest" 23 "net/url" 24 "strconv" 25 "testing" 26 27 "github.com/minio/minio/internal/crypto" 28 "github.com/minio/minio/internal/grid" 29 xhttp "github.com/minio/minio/internal/http" 30 ) 31 32 // Tests request guess function for net/rpc requests. 33 func TestGuessIsRPC(t *testing.T) { 34 if guessIsRPCReq(nil) { 35 t.Fatal("Unexpected return for nil request") 36 } 37 38 u, err := url.Parse("http://localhost:9000/minio/lock") 39 if err != nil { 40 t.Fatal(err) 41 } 42 43 r := &http.Request{ 44 Proto: "HTTP/1.0", 45 Method: http.MethodPost, 46 URL: u, 47 } 48 if !guessIsRPCReq(r) { 49 t.Fatal("Test shouldn't fail for a possible net/rpc request.") 50 } 51 r = &http.Request{ 52 Proto: "HTTP/1.1", 53 Method: http.MethodGet, 54 } 55 if guessIsRPCReq(r) { 56 t.Fatal("Test shouldn't report as net/rpc for a non net/rpc request.") 57 } 58 r = &http.Request{ 59 Proto: "HTTP/1.1", 60 Method: http.MethodGet, 61 URL: &url.URL{Path: grid.RoutePath}, 62 } 63 if !guessIsRPCReq(r) { 64 t.Fatal("Grid RPC path not detected") 65 } 66 } 67 68 var isHTTPHeaderSizeTooLargeTests = []struct { 69 header http.Header 70 shouldFail bool 71 }{ 72 {header: generateHeader(0, 0), shouldFail: false}, 73 {header: generateHeader(1024, 0), shouldFail: false}, 74 {header: generateHeader(2048, 0), shouldFail: false}, 75 {header: generateHeader(8*1024+1, 0), shouldFail: true}, 76 {header: generateHeader(0, 1024), shouldFail: false}, 77 {header: generateHeader(0, 2048), shouldFail: true}, 78 {header: generateHeader(0, 2048+1), shouldFail: true}, 79 } 80 81 func generateHeader(size, usersize int) http.Header { 82 header := http.Header{} 83 for i := 0; i < size; i++ { 84 header.Set(strconv.Itoa(i), "") 85 } 86 userlength := 0 87 for i := 0; userlength < usersize; i++ { 88 userlength += len(userMetadataKeyPrefixes[0] + strconv.Itoa(i)) 89 header.Set(userMetadataKeyPrefixes[0]+strconv.Itoa(i), "") 90 } 91 return header 92 } 93 94 func TestIsHTTPHeaderSizeTooLarge(t *testing.T) { 95 for i, test := range isHTTPHeaderSizeTooLargeTests { 96 if res := isHTTPHeaderSizeTooLarge(test.header); res != test.shouldFail { 97 t.Errorf("Test %d: Expected %v got %v", i, res, test.shouldFail) 98 } 99 } 100 } 101 102 var containsReservedMetadataTests = []struct { 103 header http.Header 104 shouldFail bool 105 }{ 106 { 107 header: http.Header{"X-Minio-Key": []string{"value"}}, 108 }, 109 { 110 header: http.Header{crypto.MetaIV: []string{"iv"}}, 111 shouldFail: false, 112 }, 113 { 114 header: http.Header{crypto.MetaAlgorithm: []string{crypto.InsecureSealAlgorithm}}, 115 shouldFail: false, 116 }, 117 { 118 header: http.Header{crypto.MetaSealedKeySSEC: []string{"mac"}}, 119 shouldFail: false, 120 }, 121 { 122 header: http.Header{ReservedMetadataPrefix + "Key": []string{"value"}}, 123 shouldFail: true, 124 }, 125 } 126 127 func TestContainsReservedMetadata(t *testing.T) { 128 for _, test := range containsReservedMetadataTests { 129 test := test 130 t.Run("", func(t *testing.T) { 131 contains := containsReservedMetadata(test.header) 132 if contains && !test.shouldFail { 133 t.Errorf("contains reserved header but should not fail") 134 } else if !contains && test.shouldFail { 135 t.Errorf("does not contain reserved header but failed") 136 } 137 }) 138 } 139 } 140 141 var sseTLSHandlerTests = []struct { 142 URL *url.URL 143 Header http.Header 144 IsTLS, ShouldFail bool 145 }{ 146 {URL: &url.URL{}, Header: http.Header{}, IsTLS: false, ShouldFail: false}, // 0 147 {URL: &url.URL{}, Header: http.Header{xhttp.AmzServerSideEncryptionCustomerAlgorithm: []string{"AES256"}}, IsTLS: false, ShouldFail: true}, // 1 148 {URL: &url.URL{}, Header: http.Header{xhttp.AmzServerSideEncryptionCustomerAlgorithm: []string{"AES256"}}, IsTLS: true, ShouldFail: false}, // 2 149 {URL: &url.URL{}, Header: http.Header{xhttp.AmzServerSideEncryptionCustomerKey: []string{""}}, IsTLS: true, ShouldFail: false}, // 3 150 {URL: &url.URL{}, Header: http.Header{xhttp.AmzServerSideEncryptionCopyCustomerAlgorithm: []string{""}}, IsTLS: false, ShouldFail: true}, // 4 151 } 152 153 func TestSSETLSHandler(t *testing.T) { 154 defer func(isSSL bool) { globalIsTLS = isSSL }(globalIsTLS) // reset globalIsTLS after test 155 156 var okHandler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) { 157 w.WriteHeader(http.StatusOK) 158 } 159 for i, test := range sseTLSHandlerTests { 160 globalIsTLS = test.IsTLS 161 162 w := httptest.NewRecorder() 163 r := new(http.Request) 164 r.Header = test.Header 165 r.URL = test.URL 166 167 h := setRequestValidityMiddleware(okHandler) 168 h.ServeHTTP(w, r) 169 170 switch { 171 case test.ShouldFail && w.Code == http.StatusOK: 172 t.Errorf("Test %d: should fail but status code is HTTP %d", i, w.Code) 173 case !test.ShouldFail && w.Code != http.StatusOK: 174 t.Errorf("Test %d: should not fail but status code is HTTP %d and not 200 OK", i, w.Code) 175 } 176 } 177 }