Skip to content

Commit f218c24

Browse files
oskarhurstOskar Hurst
andauthored
update cleanfilepath and use global env variables (#618)
Co-authored-by: Oskar Hurst <oskar.a.hurst@usace.army.mil>
1 parent eeabda1 commit f218c24

4 files changed

Lines changed: 22 additions & 23 deletions

File tree

api/handlers/media.go

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"context"
55
"net/http"
66
"net/url"
7-
"path/filepath"
7+
"path"
88
"strings"
99

1010
"github.com/aws/aws-sdk-go-v2/aws"
@@ -14,29 +14,30 @@ import (
1414

1515
func cleanFilepath(rawPath string) (string, error) {
1616
p, err := url.PathUnescape(rawPath)
17-
// Replace /api with /
18-
p = strings.Replace(p, "/api", "/", 1)
1917
if err != nil {
2018
return "", err
2119
}
22-
return filepath.Clean("/" + p), nil
20+
// The download route is mounted under the /api group; strip that prefix to
21+
// recover the S3 key.
22+
p = strings.TrimPrefix(p, "/api")
23+
// S3 keys are exact, literal strings under the aws-sdk-go-v2 client: a leading
24+
// slash makes "/cumulus/..." a different key than the stored "cumulus/..." and
25+
// real S3 returns NoSuchKey (the v1 SDK and MinIO normalize it, hiding this).
26+
// path.Clean still resolves any ".." for traversal safety.
27+
return strings.TrimPrefix(path.Clean("/"+p), "/"), nil
2328
}
2429

25-
func ServeMedia(awsCfg *aws.Config, bucket *string, endpoint string, forcePathStyle, disableSSL bool) echo.HandlerFunc {
30+
func ServeMedia(awsCfg *aws.Config, bucket *string, forcePathStyle bool) echo.HandlerFunc {
2631
return func(c echo.Context) error {
2732
path, err := cleanFilepath(c.Request().RequestURI)
2833
if err != nil {
2934
return c.String(http.StatusBadRequest, err.Error())
3035
}
3136

37+
// Endpoint/scheme come from the environment (AWS_ENDPOINT_URL_S3) via
38+
// awsCfg; only path-style addressing still needs to be set per-client.
3239
_client := s3.NewFromConfig(*awsCfg, func(o *s3.Options) {
33-
o.UsePathStyle = forcePathStyle // was a.WithS3ForcePathStyle(...)
34-
if endpoint != "" { // was: if cfg.AWSS3Endpoint != "" { a.WithEndpoint(...) }
35-
o.BaseEndpoint = aws.String(endpoint)
36-
}
37-
if disableSSL { // was a.WithDisableSSL(...)
38-
o.EndpointOptions.DisableHTTPS = true
39-
}
40+
o.UsePathStyle = forcePathStyle
4041
})
4142
output, err := _client.GetObject(context.Background(), &s3.GetObjectInput{Bucket: bucket, Key: aws.String(path)})
4243
if err != nil {

api/handlers/productfile_cog.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func ListProductfilesCOG(db *pgxpool.Pool) echo.HandlerFunc {
5959
// Content-Range/Accept-Ranges so a GDAL /vsicurl/ client can read tiles directly
6060
// (no full download). HEAD returns size + range support for /vsicurl/ probing.
6161
// Every request is authenticated (private route) and logged for metering.
62-
func StreamProductfileCOG(db *pgxpool.Pool, awsCfg *aws.Config, endpoint string, forcePathStyle, disableSSL bool) echo.HandlerFunc {
62+
func StreamProductfileCOG(db *pgxpool.Pool, awsCfg *aws.Config, forcePathStyle bool) echo.HandlerFunc {
6363
return func(c echo.Context) error {
6464
pfID, err := uuid.Parse(c.Param("productfile_id"))
6565
if err != nil {
@@ -72,14 +72,10 @@ func StreamProductfileCOG(db *pgxpool.Pool, awsCfg *aws.Config, endpoint string,
7272
}
7373

7474
ctx := c.Request().Context()
75+
// Endpoint/scheme come from the environment (AWS_ENDPOINT_URL_S3) via
76+
// awsCfg; only path-style addressing still needs to be set per-client.
7577
client := s3.NewFromConfig(*awsCfg, func(o *s3.Options) {
7678
o.UsePathStyle = forcePathStyle
77-
if endpoint != "" {
78-
o.BaseEndpoint = aws.String(endpoint)
79-
}
80-
if disableSSL {
81-
o.EndpointOptions.DisableHTTPS = true
82-
}
8379
})
8480

8581
// HEAD: metadata only (size + range support) for /vsicurl/ probing.

api/main.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ func main() {
162162
public.GET("/products/:product_id/files", handlers.ListProductfiles(db))
163163
// Direct, Range-capable COG access (authenticated + metered) for desktop clients
164164
private.GET("/products/:product_id/cog-files", handlers.ListProductfilesCOG(db))
165-
private.GET("/products/:product_id/cog/:productfile_id", handlers.StreamProductfileCOG(db, &cfg.AwsConfig, cfg.AWSS3Endpoint, cfg.AWSS3ForcePathStyle, cfg.AWSS3DisableSSL))
166-
private.HEAD("/products/:product_id/cog/:productfile_id", handlers.StreamProductfileCOG(db, &cfg.AwsConfig, cfg.AWSS3Endpoint, cfg.AWSS3ForcePathStyle, cfg.AWSS3DisableSSL))
165+
private.GET("/products/:product_id/cog/:productfile_id", handlers.StreamProductfileCOG(db, &cfg.AwsConfig, cfg.AWSS3ForcePathStyle))
166+
private.HEAD("/products/:product_id/cog/:productfile_id", handlers.StreamProductfileCOG(db, &cfg.AwsConfig, cfg.AWSS3ForcePathStyle))
167167

168168
// Productfiles
169169
private.POST("/productfiles", handlers.CreateProductfiles(db),
@@ -234,8 +234,7 @@ func main() {
234234

235235
// Serve Downloads
236236
public.GET("/cumulus/download/*", handlers.ServeMedia(
237-
&cfg.AwsConfig, &cfg.AWSS3Bucket,
238-
cfg.AWSS3Endpoint, cfg.AWSS3ForcePathStyle, cfg.AWSS3DisableSSL,
237+
&cfg.AwsConfig, &cfg.AWSS3Bucket, cfg.AWSS3ForcePathStyle,
239238
))
240239

241240
// List Downloads

docker-compose.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ services:
165165
- CUMULUS_AWS_S3_ENDPOINT=http://minio:9000
166166
- CUMULUS_AWS_S3_DISABLE_SSL=True
167167
- CUMULUS_AWS_S3_FORCE_PATH_STYLE=True
168+
# Global (S3-scoped) endpoint picked up by aws-sdk-go-v2 LoadDefaultConfig.
169+
# Unset in prod so the SDK uses real S3. http:// disables TLS for MinIO.
170+
- AWS_ENDPOINT_URL_S3=http://minio:9000
168171
- PG_FEATURESERV_URL=http://featureserv:8080
169172
volumes:
170173
- ./api/:/go/src/app/:rw

0 commit comments

Comments
 (0)