diff --git a/README.md b/README.md index d730fa6..1e850d5 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ AWS_ACCESS_KEY_ID | AWS `access key` for API access. | AWS_SECRET_ACCESS_KEY | AWS `secret key` for API access. | | EC2 Instance Role AWS_API_ENDPOINT | The endpoint for AWS API for local development. | | - INDEX_DOCUMENT | Name of your index document. | | index.html +INDEX_ON_404 | Serve index document on 404 error | | false DIRECTORY_LISTINGS | List files when a specified URL ends with /. | | false DIRECTORY_LISTINGS_FORMAT | Configures directory listing to be `html` (spider parsable) | | - HTTP_CACHE_CONTROL | Overrides S3's HTTP `Cache-Control` header. | | S3 Object metadata diff --git a/docker-compose.yml b/docker-compose.yml index daed992..463ef0a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,6 +17,7 @@ services: - AWS_S3_BUCKET - AWS_S3_KEY_PREFIX - INDEX_DOCUMENT + - INDEX_ON_404 - DIRECTORY_LISTINGS - DIRECTORY_LISTINGS_FORMAT - HTTP_CACHE_CONTROL diff --git a/internal/config/config.go b/internal/config/config.go index 6e80c32..612c340 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -22,6 +22,7 @@ type config struct { // nolint S3Bucket string // AWS_S3_BUCKET S3KeyPrefix string // AWS_S3_KEY_PREFIX IndexDocument string // INDEX_DOCUMENT + IndexOn404 bool // INDEX_ON_404 DirectoryListing bool // DIRECTORY_LISTINGS DirListingFormat string // DIRECTORY_LISTINGS_FORMAT HTTPCacheControl string // HTTP_CACHE_CONTROL (max-age=86400, no-cache ...) @@ -62,6 +63,10 @@ func Setup() { if len(indexDocument) == 0 { indexDocument = "index.html" } + indexOn404 := false + if b, err := strconv.ParseBool(os.Getenv("INDEX_ON_404")); err == nil { + indexOn404 = b + } directoryListings := false if b, err := strconv.ParseBool(os.Getenv("DIRECTORY_LISTINGS")); err == nil { directoryListings = b @@ -104,6 +109,7 @@ func Setup() { S3Bucket: os.Getenv("AWS_S3_BUCKET"), S3KeyPrefix: os.Getenv("AWS_S3_KEY_PREFIX"), IndexDocument: indexDocument, + IndexOn404: indexOn404, DirectoryListing: directoryListings, DirListingFormat: os.Getenv("DIRECTORY_LISTINGS_FORMAT"), HTTPCacheControl: os.Getenv("HTTP_CACHE_CONTROL"), diff --git a/internal/config/config_test.go b/internal/config/config_test.go index c1cd509..d3aafe8 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -15,6 +15,7 @@ func defaultConfig() *config { S3Bucket: "", S3KeyPrefix: "", IndexDocument: "index.html", + IndexOn404: false, DirectoryListing: false, DirListingFormat: "", HTTPCacheControl: "", @@ -49,6 +50,7 @@ func TestConfigDefaults(t *testing.T) { func TestChangeDefaults(t *testing.T) { os.Setenv("DIRECTORY_LISTINGS", "1") os.Setenv("ACCESS_LOG", "True") + os.Setenv("INDEX_ON_404", "True") os.Setenv("CONTENT_ENCODING", "f") os.Setenv("CORS_MAX_AGE", "0") os.Setenv("GET_ALL_PAGES_IN_DIR", "TRUE") @@ -62,6 +64,7 @@ func TestChangeDefaults(t *testing.T) { expected := defaultConfig() expected.DirectoryListing = true expected.AccessLog = true + expected.IndexOn404 = true expected.ContentEncoding = false expected.CorsMaxAge = 0 expected.AllPagesInDir = true diff --git a/internal/controllers/s3.go b/internal/controllers/s3.go index 7243e7c..a613623 100644 --- a/internal/controllers/s3.go +++ b/internal/controllers/s3.go @@ -67,8 +67,17 @@ func AwsS3(w http.ResponseWriter, r *http.Request) { obj, err := client.S3get(c.S3Bucket, c.S3KeyPrefix+path, rangeHeader) if err != nil { code, message := toHTTPError(err) - http.Error(w, message, code) - return + if code == 404 && c.IndexOn404 { + obj, err = client.S3get(c.S3Bucket, c.S3KeyPrefix+c.IndexDocument, rangeHeader) + if err != nil { + code, message = toHTTPError(err) + http.Error(w, message, code) + return + } + } else { + http.Error(w, message, code) + return + } } setHeadersFromAwsResponse(w, obj, c.HTTPCacheControl, c.HTTPExpires)