From d2e7de229b2700f8163920c5b8bd8636cc02a808 Mon Sep 17 00:00:00 2001 From: Tim Leguijt Date: Wed, 22 Jan 2025 14:50:04 +0100 Subject: [PATCH] set Content-Type correctly for javascript and css files (#12) --- .../unreleased/Added-20250121-150950.yaml | 3 +++ cmd/main.go | 2 +- internal/provider_azure.go | 2 +- internal/provider_gcp.go | 7 +++++- internal/provider_s3.go | 2 +- internal/utils.go | 23 +++++++++++++++++-- 6 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 .changes/unreleased/Added-20250121-150950.yaml diff --git a/.changes/unreleased/Added-20250121-150950.yaml b/.changes/unreleased/Added-20250121-150950.yaml new file mode 100644 index 0000000..01a76c1 --- /dev/null +++ b/.changes/unreleased/Added-20250121-150950.yaml @@ -0,0 +1,3 @@ +kind: Added +body: 'GCP: Detection of JS and CSS filetype and set ContentType' +time: 2025-01-21T15:09:50.953801+01:00 diff --git a/cmd/main.go b/cmd/main.go index dd5c60e..840ed7a 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -78,7 +78,7 @@ var syncCmd = &cobra.Command{ fmt.Println("Directory synchronized successfully; creating lock file") // Create the lockfile (empty file) - err = client.UploadFile(ctx, strings.NewReader(""), filepath.Join(remoteDir, lockFile)) + err = client.UploadFile(ctx, strings.NewReader(""), filepath.Join(remoteDir, lockFile), "") if err != nil { log.Fatalf("failed to create lock file: %v", err) } diff --git a/internal/provider_azure.go b/internal/provider_azure.go index 2b507bf..e864ba4 100644 --- a/internal/provider_azure.go +++ b/internal/provider_azure.go @@ -38,7 +38,7 @@ func NewAzureBlobClient(ctx context.Context, bucket string) (*AzureBlobClient, e return &AzureBlobClient{client: client, container: container}, nil } -func (c *AzureBlobClient) UploadFile(ctx context.Context, file io.Reader, remotePath string) error { +func (c *AzureBlobClient) UploadFile(ctx context.Context, file io.Reader, remotePath string, contentType string) error { var tempFile *os.File var err error diff --git a/internal/provider_gcp.go b/internal/provider_gcp.go index c8e7587..cdb27d6 100644 --- a/internal/provider_gcp.go +++ b/internal/provider_gcp.go @@ -22,11 +22,16 @@ func NewGCSClient(ctx context.Context, bucket string) (*GCSClient, error) { } // UploadFile to GCS -func (c *GCSClient) UploadFile(ctx context.Context, file io.Reader, remotePath string) error { +func (c *GCSClient) UploadFile(ctx context.Context, file io.Reader, remotePath string, contentType string) error { bucket := c.client.Bucket(c.bucket) obj := bucket.Object(remotePath) writer := obj.NewWriter(ctx) + + if contentType != "" { + writer.ContentType = contentType + } + defer writer.Close() _, err := io.Copy(writer, file) diff --git a/internal/provider_s3.go b/internal/provider_s3.go index 5bc2f00..77e0276 100644 --- a/internal/provider_s3.go +++ b/internal/provider_s3.go @@ -26,7 +26,7 @@ func NewS3Client(ctx context.Context, bucket string) (*S3Client, error) { } // UploadFile to S3 -func (c *S3Client) UploadFile(ctx context.Context, file io.Reader, remotePath string) error { +func (c *S3Client) UploadFile(ctx context.Context, file io.Reader, remotePath string, contentType string) error { _, err := c.client.PutObject(ctx, &s3.PutObjectInput{ Bucket: aws.String(c.bucket), Key: aws.String(remotePath), diff --git a/internal/utils.go b/internal/utils.go index 606b3aa..950667a 100644 --- a/internal/utils.go +++ b/internal/utils.go @@ -10,7 +10,7 @@ import ( ) type StorageClient interface { - UploadFile(ctx context.Context, file io.Reader, remotePath string) error + UploadFile(ctx context.Context, file io.Reader, remotePath string, contentType string) error FileExists(ctx context.Context, remotePath string) (bool, error) } @@ -45,7 +45,12 @@ func SyncDirectory(ctx context.Context, client StorageClient, localDir, remoteDi return } defer file.Close() - if err := client.UploadFile(ctx, file, remotePath); err != nil { + + // Get the content type based on file extension. + // We can't rely on auto-detection of mimetypes because + // of security implications. See https://stackoverflow.com/questions/70695214/net-http-does-detectcontenttype-support-javascript + contentType := GetContentType(path) + if err := client.UploadFile(ctx, file, remotePath, contentType); err != nil { errCh <- err } else { fmt.Printf("Uploaded %s to %s\n", path, remotePath) @@ -69,3 +74,17 @@ func SyncDirectory(ctx context.Context, client StorageClient, localDir, remoteDi } return nil } + +func GetContentType(file string) string { + ext := filepath.Ext(file) + switch ext { + case ".htm", ".html": + return "text/html; charset=UTF-8" + case ".css": + return "text/css; charset=UTF-8" + case ".js": + return "application/javascript; charset=UTF-8" + } + + return "" +}