Repository: minio/minio (language: go)

Issue:
Expires header in PutObject ignored if days are single digit
Full disclosure: I'm an AWS employee

One can use the Expires header in a PutObject request, which will result in GetObject returning that Expires header for the object.  
However, the following value for Expires is ignored: `Fri, 1 Sep 2023 01:01:01 GMT`. With `Fri, 01 Sep 2023 01:01:01 GMT` it works though (note the two-digit day).  
By ignored I mean that the expired 

Now this behavior is correct as far as RFC 9110 Section 5.6.7 is concerned, where it states the day has two digits. However the official S3 SDK uses RFC 1123 for dates, which has the same format, just days are single digit when possible. This means the following code will not work as intended:
```
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
                .bucket("testbucket")
                .key("testfile")
                .expires(Instant.parse("2023-09-01T01:01:01Z"))
                .build();
PutObjectResponse putObjectResponse = s3Client.putObject(putObjectRequest, RequestBody.fromString("testcontent"));
```

As this code will generate the header `Expires: Fri, 1 Sep 2023 01:01:01 GMT`.

My suggestion is to make the date parser more permissive to allow single-digit days. This is in line with the recommendation at the end of Section 5.6.7, `Recipients of timestamp values are encouraged to be robust in parsing timestamps unless otherwise restricted by the field definition.`

I'm running the MinIO version RELEASE.2022-07-26T00-53-03Z  docker image.



Discussion / hints:
@thorstent can you provide a full example?  I am not able to reproduce this with AWS CLI.

```
~ aws s3api put-object --profile play --endpoint-url https://play.minio.io --bucket testbucket1 --key hosts --expires "2023-09-01T01:01:01Z" --body /etc/hosts
{
    "ETag": "\"f538a81a37ffb8374f8feefe44b73a15\""
}
```

```
~ mc stat play/testbucket1/hosts
Name      : hosts
Date      : 2022-09-04 16:54:52 PDT 
Size      : 206 B  
ETag      : f538a81a37ffb8374f8feefe44b73a15 
Type      : file 
Expires   : 2023-09-01 01:01:01 UTC 
Metadata  :
  Content-Type: binary/octet-stream 
```

@harshavardhana  I just looked at what the CLI does and the CLI is correct in that it sends the date as `Fri, 01 Sep 2023 01:01:01 GMT` However, the SDK does not send the date correctly:

You can use the following test class. You will see in the wirelog: `"Expires: Fri, 1 Sep 2023 01:01:01 GMT[\r][\n]"`

Alternative would be to use postman to construct the request with this header.

```
package test;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator;
import org.testng.annotations.Test;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.S3Configuration;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;

import java.net.URI;
import java.time.Instant;

public class ExpiresTest  {

    protected S3Client s3Client;

    public ExpiresTest() {
        Region region = Region.US_WEST_2;
        S3Configuration s3Configuration = S3Configuration.builder()
                .checksumValidationEnabled(false)
                .build();
        s3Client = S3Client.builder()
                .endpointOverride(URI.create("http://localhost:9000"))
                .serviceConfiguration(s3Configuration)
                .region(region)
                .build();
    }

    @Test()
    public void putExpires() {
        Configurator.setLevel("org.apache.http.wire", Level.DEBUG);
        PutObjectRequest putObjectRequest = PutObjectRequest.builder()
                .bucket("testbucket")
                .key("testfile")
                .expires(Instant.parse("2023-09-01T01:01:01Z"))
                .build();
        PutObjectResponse putObjectResponse = s3Client.putObject(putObjectRequest, RequestBody.fromString("testcontent"));
    }
}

```

Fix patch:
diff --git a/cmd/erasure-metadata.go b/cmd/erasure-metadata.go
index a7d8cdb4c51df..2f6fa931ed3cb 100644
--- a/cmd/erasure-metadata.go
+++ b/cmd/erasure-metadata.go
@@ -132,9 +132,13 @@ func (fi FileInfo) ToObjectInfo(bucket, object string, versioned bool) ObjectInf
 		t time.Time
 		e error
 	)
+
+	const nonStandardHTTPTimeFormat = "Mon, 2 Jan 2006 15:04:05 GMT"
 	if exp, ok := fi.Metadata["expires"]; ok {
 		if t, e = time.Parse(http.TimeFormat, exp); e == nil {
 			objInfo.Expires = t.UTC()
+		} else if t, e = time.Parse(nonStandardHTTPTimeFormat, exp); e == nil {
+			objInfo.Expires = t.UTC()
 		}
 	}
 	objInfo.backendType = BackendErasure


Test patch: