@@ -139,8 +139,17 @@ func (bri *bucketReqImpl) manageKeyRewrite(ctx context.Context, key string) (str
139139 return key , nil
140140}
141141
142- // Get proxy GET requests.
142+ // Proxy GET requests.
143143func (bri * bucketReqImpl ) Get (ctx context.Context , input * GetInput ) {
144+ bri .internalGetOrHead (ctx , input , false )
145+ }
146+
147+ // Proxy HEAD requests.
148+ func (bri * bucketReqImpl ) Head (ctx context.Context , input * GetInput ) {
149+ bri .internalGetOrHead (ctx , input , true )
150+ }
151+
152+ func (bri * bucketReqImpl ) internalGetOrHead (ctx context.Context , input * GetInput , isHeadReq bool ) {
144153 // Get response handler
145154 resHan := responsehandler .GetResponseHandlerFromContext (ctx )
146155
@@ -157,31 +166,36 @@ func (bri *bucketReqImpl) Get(ctx context.Context, input *GetInput) {
157166
158167 // Check that the path ends with a / for a directory listing or the main path special case (empty path)
159168 if strings .HasSuffix (input .RequestPath , "/" ) || input .RequestPath == "" {
160- bri .manageGetFolder (ctx , key , input )
169+ bri .manageGetFolder (ctx , key , input , isHeadReq )
161170 // Stop
162171 return
163172 }
164173
165- // Get object case
174+ // Get or Head object case
166175
167- // Check if it is asked to redirect to signed url
168- if bri .targetCfg .Actions != nil &&
176+ // Check if it is a HEAD request or if it is asked to redirect to signed url
177+ if isHeadReq || bri .targetCfg .Actions != nil &&
169178 bri .targetCfg .Actions .GET != nil &&
170179 bri .targetCfg .Actions .GET .Config != nil &&
171180 bri .targetCfg .Actions .GET .Config .RedirectToSignedURL {
172181 // Get S3 client
173182 s3cl := bri .s3ClientManager .
174183 GetClientForTarget (bri .targetCfg .Name )
175184 // Head file in bucket
176- headOutput , err2 := s3cl .HeadObject (ctx , key )
185+ headOutput , hInfo , err2 := s3cl .HeadObject (ctx , key )
177186 // Check if there is an error
178187 if err2 != nil {
179188 // Save error
180189 err = err2
181190 } else if headOutput != nil {
182191 // File found
183- // Redirect to signed url
184- err = bri .redirectToSignedURL (ctx , key , input )
192+ // Check head request
193+ if isHeadReq {
194+ err = bri .answerHead (ctx , input , headOutput , hInfo )
195+ } else {
196+ // Redirect to signed url
197+ err = bri .redirectToSignedURL (ctx , key , input )
198+ }
185199 }
186200 } else {
187201 // Stream object
@@ -225,7 +239,7 @@ func (bri *bucketReqImpl) Get(ctx context.Context, input *GetInput) {
225239 }
226240}
227241
228- func (bri * bucketReqImpl ) manageGetFolder (ctx context.Context , key string , input * GetInput ) {
242+ func (bri * bucketReqImpl ) manageGetFolder (ctx context.Context , key string , input * GetInput , isHeadReq bool ) {
229243 // Get response handler
230244 resHan := responsehandler .GetResponseHandlerFromContext (ctx )
231245
@@ -236,7 +250,7 @@ func (bri *bucketReqImpl) manageGetFolder(ctx context.Context, key string, input
236250 // Create index key path
237251 indexKey := path .Join (key , bri .targetCfg .Actions .GET .Config .IndexDocument )
238252 // Head index file in bucket
239- headOutput , err := bri .s3ClientManager .
253+ headOutput , hInfo , err := bri .s3ClientManager .
240254 GetClientForTarget (bri .targetCfg .Name ).
241255 HeadObject (ctx , indexKey )
242256 // Check if error exists and not a not found error
@@ -248,8 +262,11 @@ func (bri *bucketReqImpl) manageGetFolder(ctx context.Context, key string, input
248262 }
249263 // Check that we found the file
250264 if headOutput != nil {
251- // Check if it is asked to redirect to signed url
252- if bri .targetCfg .Actions .GET .Config .RedirectToSignedURL {
265+ // Check if it is head request
266+ if isHeadReq { //nolint:gocritic // Ignore this
267+ // Answer with head
268+ err = bri .answerHead (ctx , input , headOutput , hInfo )
269+ } else if bri .targetCfg .Actions .GET .Config .RedirectToSignedURL { // Check if it is asked to redirect to signed url
253270 // Redirect to signed url
254271 err = bri .redirectToSignedURL (ctx , indexKey , input )
255272 } else {
@@ -311,25 +328,46 @@ func (bri *bucketReqImpl) manageGetFolder(ctx context.Context, key string, input
311328 return
312329 }
313330
314- // Send hook
315- bri .webhookManager .ManageGETHooks (
316- ctx ,
317- bri .targetCfg .Name ,
318- input .RequestPath ,
319- & webhook.GetInputMetadata {
320- IfModifiedSince : input .IfModifiedSince ,
321- IfMatch : input .IfMatch ,
322- IfNoneMatch : input .IfNoneMatch ,
323- IfUnmodifiedSince : input .IfUnmodifiedSince ,
324- Range : input .Range ,
325- },
326- & webhook.S3Metadata {
327- Bucket : info .Bucket ,
328- Region : info .Region ,
329- S3Endpoint : info .S3Endpoint ,
330- Key : info .Key ,
331- },
332- )
331+ if isHeadReq {
332+ // Send hook
333+ bri .webhookManager .ManageHEADHooks (
334+ ctx ,
335+ bri .targetCfg .Name ,
336+ input .RequestPath ,
337+ & webhook.HeadInputMetadata {
338+ IfModifiedSince : input .IfModifiedSince ,
339+ IfMatch : input .IfMatch ,
340+ IfNoneMatch : input .IfNoneMatch ,
341+ IfUnmodifiedSince : input .IfUnmodifiedSince ,
342+ },
343+ & webhook.S3Metadata {
344+ Bucket : info .Bucket ,
345+ Region : info .Region ,
346+ S3Endpoint : info .S3Endpoint ,
347+ Key : info .Key ,
348+ },
349+ )
350+ } else {
351+ // Send hook
352+ bri .webhookManager .ManageGETHooks (
353+ ctx ,
354+ bri .targetCfg .Name ,
355+ input .RequestPath ,
356+ & webhook.GetInputMetadata {
357+ IfModifiedSince : input .IfModifiedSince ,
358+ IfMatch : input .IfMatch ,
359+ IfNoneMatch : input .IfNoneMatch ,
360+ IfUnmodifiedSince : input .IfUnmodifiedSince ,
361+ Range : input .Range ,
362+ },
363+ & webhook.S3Metadata {
364+ Bucket : info .Bucket ,
365+ Region : info .Region ,
366+ S3Endpoint : info .S3Endpoint ,
367+ Key : info .Key ,
368+ },
369+ )
370+ }
333371
334372 // Transform entries in entry with path objects
335373 bucketRootPrefixKey := bri .targetCfg .Bucket .GetRootPrefix ()
@@ -513,7 +551,7 @@ func (bri *bucketReqImpl) Put(ctx context.Context, inp *PutInput) {
513551 // Check if allow override is enabled
514552 if ! bri .targetCfg .Actions .PUT .Config .AllowOverride {
515553 // Need to check if file already exists
516- headOutput , err2 := bri .s3ClientManager .
554+ headOutput , _ , err2 := bri .s3ClientManager .
517555 GetClientForTarget (bri .targetCfg .Name ).
518556 HeadObject (ctx , key )
519557 // Check if error is not found if exists
@@ -740,6 +778,52 @@ func (bri *bucketReqImpl) redirectToSignedURL(ctx context.Context, key string, i
740778 return nil
741779}
742780
781+ func (bri * bucketReqImpl ) answerHead (
782+ ctx context.Context ,
783+ input * GetInput ,
784+ hOutput * s3client.HeadOutput ,
785+ info * s3client.ResultInfo ,
786+ ) error {
787+ // Get response handler from context
788+ resHan := responsehandler .GetResponseHandlerFromContext (ctx )
789+
790+ // Send hook
791+ bri .webhookManager .ManageHEADHooks (
792+ ctx ,
793+ bri .targetCfg .Name ,
794+ input .RequestPath ,
795+ & webhook.HeadInputMetadata {
796+ IfModifiedSince : input .IfModifiedSince ,
797+ IfMatch : input .IfMatch ,
798+ IfNoneMatch : input .IfNoneMatch ,
799+ IfUnmodifiedSince : input .IfUnmodifiedSince ,
800+ },
801+ & webhook.S3Metadata {
802+ Bucket : info .Bucket ,
803+ Region : info .Region ,
804+ S3Endpoint : info .S3Endpoint ,
805+ Key : info .Key ,
806+ },
807+ )
808+
809+ // Transform input
810+ inp := & responsehandler.StreamInput {
811+ CacheControl : hOutput .CacheControl ,
812+ Expires : hOutput .Expires ,
813+ ContentDisposition : hOutput .ContentDisposition ,
814+ ContentEncoding : hOutput .ContentEncoding ,
815+ ContentLanguage : hOutput .ContentLanguage ,
816+ ContentLength : hOutput .ContentLength ,
817+ ContentType : hOutput .ContentType ,
818+ ETag : hOutput .ETag ,
819+ LastModified : hOutput .LastModified ,
820+ Metadata : hOutput .Metadata ,
821+ }
822+
823+ // Stream
824+ return resHan .StreamFile (bri .LoadFileContent , inp )
825+ }
826+
743827func (bri * bucketReqImpl ) streamFileForResponse (ctx context.Context , key string , input * GetInput ) error {
744828 // Get response handler from context
745829 resHan := responsehandler .GetResponseHandlerFromContext (ctx )
0 commit comments