From 0f471cb50484a059c1e5cfca99b017a52575a00b Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Fri, 11 Dec 2020 12:56:21 +0300 Subject: [PATCH 1/2] Single page application feature - if true server will return index document content on 404 error --- README.md | 1 + docker-compose.yml | 1 + internal/config/config.go | 6 ++++++ internal/config/config_test.go | 3 +++ internal/controllers/s3.go | 23 +++++++++++++++++++++-- 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d730fa6..accf75f 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ MAX_IDLE_CONNECTIONS | Allowed number of idle connections to the S3 storage IDLE_CONNECTION_TIMEOUT | Allowed timeout to the S3 storage. | | 10 DISABLE_COMPRESSION | If true will pass encoded content through as-is. | | true INSECURE_TLS | If true it will skip cert checks | | false +SPA | Signle Page Application - If true server will return index document content on 404 error (like `try_files $uri $uri/ /index.html;` in nginx) | | false ### 2. Run the application diff --git a/docker-compose.yml b/docker-compose.yml index daed992..a8948bf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -33,4 +33,5 @@ services: - CONTENT_ENCODING - HEALTHCHECK_PATH - GET_ALL_PAGES_IN_DIR=true + - SPA container_name: app diff --git a/internal/config/config.go b/internal/config/config.go index 6e80c32..aa4d02f 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -46,6 +46,7 @@ type config struct { // nolint DisableCompression bool // DISABLE_COMPRESSION InsecureTLS bool // Disables TLS validation on request endpoints. JwtSecretKey string // JWT_SECRET_KEY + SPA bool // SPA } // Setup configurations with environment variables @@ -98,6 +99,10 @@ func Setup() { if b, err := strconv.ParseBool(os.Getenv("INSECURE_TLS")); err == nil { insecureTLS = b } + SPA := false + if b, err := strconv.ParseBool(os.Getenv("SPA")); err == nil { + SPA = b + } Config = &config{ AwsRegion: region, AwsAPIEndpoint: os.Getenv("AWS_API_ENDPOINT"), @@ -128,6 +133,7 @@ func Setup() { DisableCompression: disableCompression, InsecureTLS: insecureTLS, JwtSecretKey: os.Getenv("JWT_SECRET_KEY"), + SPA: SPA, } // Proxy log.Printf("[config] Proxy to %v", Config.S3Bucket) diff --git a/internal/config/config_test.go b/internal/config/config_test.go index c1cd509..f9d3317 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -38,6 +38,7 @@ func defaultConfig() *config { IdleConnTimeout: time.Duration(10) * time.Second, DisableCompression: true, InsecureTLS: false, + SPA: false, } } @@ -56,6 +57,7 @@ func TestChangeDefaults(t *testing.T) { os.Setenv("IDLE_CONNECTION_TIMEOUT", "60") os.Setenv("DISABLE_COMPRESSION", "FALSE") os.Setenv("INSECURE_TLS", "t") + os.Setenv("SPA", "TRUE") Setup() @@ -69,6 +71,7 @@ func TestChangeDefaults(t *testing.T) { expected.IdleConnTimeout = time.Duration(60) * time.Second expected.DisableCompression = false expected.InsecureTLS = true + expected.SPA = true assert.Equal(t, expected, Config) } diff --git a/internal/controllers/s3.go b/internal/controllers/s3.go index 7243e7c..61a07de 100644 --- a/internal/controllers/s3.go +++ b/internal/controllers/s3.go @@ -67,8 +67,27 @@ 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.SPA && strings.Index(path, c.IndexDocument) == -1 { + + idx := strings.LastIndex(path, "/") + + if idx > -1 { + indexPath := c.S3KeyPrefix + path[:idx+1] + c.IndexDocument + + var indexError error + obj, indexError = client.S3get(c.S3Bucket, indexPath, rangeHeader) + + if indexError != nil { + code, message = toHTTPError(indexError) + http.Error(w, message, code) + return + } + } + } else { + http.Error(w, message, code) + return + } } setHeadersFromAwsResponse(w, obj, c.HTTPCacheControl, c.HTTPExpires) From 70c580719738c5e52ccc7649ca1133ef4fda4777 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Wed, 18 Aug 2021 23:22:15 +0300 Subject: [PATCH 2/2] implement 403 errors --- internal/controllers/s3-error.go | 2 ++ internal/controllers/s3.go | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/controllers/s3-error.go b/internal/controllers/s3-error.go index 9fda7fe..8a2c88f 100644 --- a/internal/controllers/s3-error.go +++ b/internal/controllers/s3-error.go @@ -12,6 +12,8 @@ func toHTTPError(err error) (int, string) { switch aerr.Code() { case s3.ErrCodeNoSuchBucket, s3.ErrCodeNoSuchKey: return http.StatusNotFound, aerr.Error() + case "AccessDenied": + return http.StatusForbidden, aerr.Error() } return http.StatusInternalServerError, aerr.Error() } diff --git a/internal/controllers/s3.go b/internal/controllers/s3.go index 61a07de..c624c46 100644 --- a/internal/controllers/s3.go +++ b/internal/controllers/s3.go @@ -68,7 +68,7 @@ func AwsS3(w http.ResponseWriter, r *http.Request) { if err != nil { code, message := toHTTPError(err) - if code == 404 && c.SPA && strings.Index(path, c.IndexDocument) == -1 { + if (code == 404 || code == 403) && c.SPA && strings.Index(path, c.IndexDocument) == -1 { idx := strings.LastIndex(path, "/")