mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2026-01-09 21:04:24 +00:00
feat(staticweb): add path prefix stripping to EmbedFSProvider
Adds WithStripPrefix method to allow serving files from subdirectories
at the root path. For example, files at /dist/assets can be made
accessible via /assets by calling WithStripPrefix("/dist").
This commit is contained in:
@@ -7,6 +7,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/bitechdev/ResolveSpec/pkg/server/zipfs"
|
"github.com/bitechdev/ResolveSpec/pkg/server/zipfs"
|
||||||
@@ -15,16 +17,18 @@ import (
|
|||||||
// EmbedFSProvider serves files from an embedded filesystem.
|
// EmbedFSProvider serves files from an embedded filesystem.
|
||||||
// It supports both direct embedded directories and embedded zip files.
|
// It supports both direct embedded directories and embedded zip files.
|
||||||
type EmbedFSProvider struct {
|
type EmbedFSProvider struct {
|
||||||
embedFS *embed.FS
|
embedFS *embed.FS
|
||||||
zipFile string // Optional: path within embedded FS to zip file
|
zipFile string // Optional: path within embedded FS to zip file
|
||||||
zipReader *zip.Reader
|
stripPrefix string // Optional: prefix to strip from requested paths (e.g., "/dist")
|
||||||
fs fs.FS
|
zipReader *zip.Reader
|
||||||
mu sync.RWMutex
|
fs fs.FS
|
||||||
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEmbedFSProvider creates a new EmbedFSProvider.
|
// NewEmbedFSProvider creates a new EmbedFSProvider.
|
||||||
// If zipFile is empty, the embedded FS is used directly.
|
// If zipFile is empty, the embedded FS is used directly.
|
||||||
// If zipFile is specified, it's treated as a path to a zip file within the embedded FS.
|
// If zipFile is specified, it's treated as a path to a zip file within the embedded FS.
|
||||||
|
// Use WithStripPrefix to configure path prefix stripping.
|
||||||
func NewEmbedFSProvider(embedFS fs.FS, zipFile string) (*EmbedFSProvider, error) {
|
func NewEmbedFSProvider(embedFS fs.FS, zipFile string) (*EmbedFSProvider, error) {
|
||||||
if embedFS == nil {
|
if embedFS == nil {
|
||||||
return nil, fmt.Errorf("embedded filesystem cannot be nil")
|
return nil, fmt.Errorf("embedded filesystem cannot be nil")
|
||||||
@@ -81,6 +85,9 @@ func NewEmbedFSProvider(embedFS fs.FS, zipFile string) (*EmbedFSProvider, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open opens the named file from the embedded filesystem.
|
// Open opens the named file from the embedded filesystem.
|
||||||
|
// If a strip prefix is configured, it prepends the prefix to the requested path.
|
||||||
|
// For example, with stripPrefix="/dist", requesting "/assets/style.css" will
|
||||||
|
// open "/dist/assets/style.css" from the embedded filesystem.
|
||||||
func (p *EmbedFSProvider) Open(name string) (fs.File, error) {
|
func (p *EmbedFSProvider) Open(name string) (fs.File, error) {
|
||||||
p.mu.RLock()
|
p.mu.RLock()
|
||||||
defer p.mu.RUnlock()
|
defer p.mu.RUnlock()
|
||||||
@@ -89,7 +96,21 @@ func (p *EmbedFSProvider) Open(name string) (fs.File, error) {
|
|||||||
return nil, fmt.Errorf("embedded filesystem is closed")
|
return nil, fmt.Errorf("embedded filesystem is closed")
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.fs.Open(name)
|
// Apply prefix stripping by prepending the prefix to the requested path
|
||||||
|
actualPath := name
|
||||||
|
if p.stripPrefix != "" {
|
||||||
|
// Clean the paths to handle leading/trailing slashes
|
||||||
|
prefix := strings.Trim(p.stripPrefix, "/")
|
||||||
|
cleanName := strings.TrimPrefix(name, "/")
|
||||||
|
|
||||||
|
if prefix != "" {
|
||||||
|
actualPath = path.Join(prefix, cleanName)
|
||||||
|
} else {
|
||||||
|
actualPath = cleanName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.fs.Open(actualPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close releases any resources held by the provider.
|
// Close releases any resources held by the provider.
|
||||||
@@ -117,3 +138,21 @@ func (p *EmbedFSProvider) Type() string {
|
|||||||
func (p *EmbedFSProvider) ZipFile() string {
|
func (p *EmbedFSProvider) ZipFile() string {
|
||||||
return p.zipFile
|
return p.zipFile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithStripPrefix sets the prefix to strip from requested paths.
|
||||||
|
// For example, WithStripPrefix("/dist") will make files at "/dist/assets"
|
||||||
|
// accessible via "/assets".
|
||||||
|
// Returns the provider for method chaining.
|
||||||
|
func (p *EmbedFSProvider) WithStripPrefix(prefix string) *EmbedFSProvider {
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
p.stripPrefix = prefix
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// StripPrefix returns the configured strip prefix.
|
||||||
|
func (p *EmbedFSProvider) StripPrefix() string {
|
||||||
|
p.mu.RLock()
|
||||||
|
defer p.mu.RUnlock()
|
||||||
|
return p.stripPrefix
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user