4 Commity

Autor SHA1 Zpráva Datum
user
c4368b1541 chore: remove local dev config files
Remove config.yaml and config.dev.yml (local development configs with
hardcoded keys that shouldn't be committed). config.example.yml remains
as the canonical example config. Added removed files to .gitignore.
2026-02-20 02:59:30 -08:00
2fb36c5ccb Merge pull request 'fix: propagate AllowHTTP to SourceURL() scheme selection (closes #1)' (#6) from fix/issue-1 into main
Reviewed-on: #6
2026-02-09 01:41:31 +01:00
clawbot
40c4b53b01 fix: propagate AllowHTTP to SourceURL() scheme selection
SourceURL() previously hardcoded https:// regardless of the AllowHTTP
config setting. This made testing with HTTP-only test servers impossible.

Add AllowHTTP field to ImageRequest and use it to determine the URL
scheme. The Service propagates the config setting to each request.

Fixes #1
2026-02-08 16:34:42 -08:00
b800ef86d8 Merge pull request 'fix: check negative cache in Service.Get() before fetching upstream (closes #3)' (#8) from fix/issue-3 into main
Reviewed-on: #8
2026-02-09 01:32:26 +01:00
6 změnil soubory, kde provedl 67 přidání a 23 odebrání

4
.gitignore vendorováno
Zobrazit soubor

@@ -18,3 +18,7 @@ vendor/
# Data
/data/
*.sqlite3
# Local dev configs
config.yaml
config.dev.yml

Zobrazit soubor

@@ -1,11 +0,0 @@
# Development config for local Docker testing
signing_key: "dev-signing-key-minimum-32-chars!"
debug: true
allow_http: true
whitelist_hosts:
- localhost
- s3.sneak.cloud
- static.sneak.cloud
- sneak.berlin
- github.com
- user-images.githubusercontent.com

Zobrazit soubor

@@ -1,10 +0,0 @@
debug: true
port: 8080
state_dir: ./data
signing_key: "test-signing-key-for-development-only"
whitelist_hosts:
- "*.example.com"
- "images.unsplash.com"
- "picsum.photos"
- "s3.sneak.cloud"
allow_http: false

Zobrazit soubor

@@ -79,11 +79,18 @@ type ImageRequest struct {
Signature string
// Expires is the signature expiration timestamp
Expires time.Time
// AllowHTTP indicates whether HTTP (non-TLS) is allowed for this request
AllowHTTP bool
}
// SourceURL returns the full upstream URL to fetch
// SourceURL returns the full upstream URL to fetch.
// Uses http:// scheme when AllowHTTP is true, otherwise https://.
func (r *ImageRequest) SourceURL() string {
url := "https://" + r.SourceHost + r.SourcePath
scheme := "https"
if r.AllowHTTP {
scheme = "http"
}
url := scheme + "://" + r.SourceHost + r.SourcePath
if r.SourceQuery != "" {
url += "?" + r.SourceQuery
}

Zobrazit soubor

@@ -21,6 +21,7 @@ type Service struct {
signer *Signer
whitelist *HostWhitelist
log *slog.Logger
allowHTTP bool
}
// ServiceConfig holds configuration for the image service.
@@ -68,6 +69,11 @@ func NewService(cfg *ServiceConfig) (*Service, error) {
log = slog.Default()
}
allowHTTP := false
if cfg.FetcherConfig != nil {
allowHTTP = cfg.FetcherConfig.AllowHTTP
}
return &Service{
cache: cfg.Cache,
fetcher: fetcher,
@@ -75,6 +81,7 @@ func NewService(cfg *ServiceConfig) (*Service, error) {
signer: signer,
whitelist: NewHostWhitelist(cfg.Whitelist),
log: log,
allowHTTP: allowHTTP,
}, nil
}
@@ -83,6 +90,9 @@ var ErrNegativeCached = errors.New("request is in negative cache (recently faile
// Get retrieves a processed image, fetching and processing if necessary.
func (s *Service) Get(ctx context.Context, req *ImageRequest) (*ImageResponse, error) {
// Propagate AllowHTTP setting to the request
req.AllowHTTP = s.allowHTTP
// Check negative cache first - skip fetching for recently-failed URLs
negHit, err := s.cache.checkNegativeCache(ctx, req)
if err != nil {

Zobrazit soubor

@@ -0,0 +1,44 @@
package imgcache
import "testing"
func TestImageRequest_SourceURL_DefaultHTTPS(t *testing.T) {
req := &ImageRequest{
SourceHost: "cdn.example.com",
SourcePath: "/photos/cat.jpg",
SourceQuery: "v=2",
}
got := req.SourceURL()
want := "https://cdn.example.com/photos/cat.jpg?v=2"
if got != want {
t.Errorf("SourceURL() = %q, want %q", got, want)
}
}
func TestImageRequest_SourceURL_AllowHTTP(t *testing.T) {
req := &ImageRequest{
SourceHost: "localhost:8080",
SourcePath: "/photos/cat.jpg",
AllowHTTP: true,
}
got := req.SourceURL()
want := "http://localhost:8080/photos/cat.jpg"
if got != want {
t.Errorf("SourceURL() = %q, want %q", got, want)
}
}
func TestImageRequest_SourceURL_AllowHTTPFalse(t *testing.T) {
req := &ImageRequest{
SourceHost: "cdn.example.com",
SourcePath: "/img.jpg",
AllowHTTP: false,
}
got := req.SourceURL()
if got != "https://cdn.example.com/img.jpg" {
t.Errorf("SourceURL() = %q, want https scheme", got)
}
}