Browse Source

Fix blossom blob list URLs missing file extensions and add MIME sniffing

- handleListBlobs now derives file extension from stored MIME type when
  building blob URLs, so browsers can identify file types correctly
- Added http.DetectContentType fallback in upload, mirror, and media
  handlers for when Content-Type header is missing or unhelpful

Files modified:
- pkg/blossom/handlers.go: Fix list URLs, add content sniffing fallback
- pkg/version/version: Bump to v0.58.8
- CLAUDE.md: Update git remotes documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
imwald-v0.58.10
woikos 4 months ago
parent
commit
e36c39e3f0
No known key found for this signature in database
  1. 6
      CLAUDE.md
  2. 28
      pkg/blossom/handlers.go
  3. 2
      pkg/version/version

6
CLAUDE.md

@ -322,10 +322,10 @@ ssh -i ~/.ssh/id_ed25519 -o IdentitiesOnly=yes root@69.164.249.71 \
## Git Remotes ## Git Remotes
Only one remote exists: - **origin**: `ssh://git@git.nostrdev.com:29418/mleku/next.orly.dev.git` (contract work)
- **origin**: `ssh://git@git.nostrdev.com:29418/mleku/next.orly.dev.git` - **gitea**: `ssh://mleku@git.mleku.dev:2222/mleku/next.orly.dev.git` (primary, mleku's own host)
There is no `gitea` or `git.mleku.dev` remote configured for this repo. Do not attempt to push to `gitea`. Push to both remotes. Use `GIT_SSH_COMMAND="ssh -i ~/.ssh/id_ed25519"` for gitea.
## Dependencies ## Dependencies

28
pkg/blossom/handlers.go

@ -223,11 +223,16 @@ func (s *Server) handleUpload(w http.ResponseWriter, r *http.Request) {
// Note: pubkey may be nil for anonymous uploads if ACL allows it // Note: pubkey may be nil for anonymous uploads if ACL allows it
// The storage layer will handle anonymous uploads appropriately // The storage layer will handle anonymous uploads appropriately
// Detect MIME type // Detect MIME type from header, extension, or content sniffing
mimeType := DetectMimeType( mimeType := DetectMimeType(
r.Header.Get("Content-Type"), r.Header.Get("Content-Type"),
GetFileExtensionFromPath(r.URL.Path), GetFileExtensionFromPath(r.URL.Path),
) )
if mimeType == "application/octet-stream" && len(body) > 0 {
if sniffed := http.DetectContentType(body); sniffed != "application/octet-stream" {
mimeType = sniffed
}
}
// Extract extension from path or infer from MIME type // Extract extension from path or infer from MIME type
ext := GetFileExtensionFromPath(r.URL.Path) ext := GetFileExtensionFromPath(r.URL.Path)
@ -469,9 +474,10 @@ func (s *Server) handleListBlobs(w http.ResponseWriter, r *http.Request) {
return return
} }
// Set URLs for descriptors // Set URLs for descriptors (include file extension for proper MIME handling)
for _, desc := range descriptors { for _, desc := range descriptors {
desc.URL = BuildBlobURL(s.getBaseURL(r), desc.SHA256, "") ext := GetExtensionFromMimeType(desc.Type)
desc.URL = BuildBlobURL(s.getBaseURL(r), desc.SHA256, ext)
} }
// Return JSON array // Return JSON array
@ -663,11 +669,16 @@ func (s *Server) handleMirror(w http.ResponseWriter, r *http.Request) {
// Note: pubkey may be nil for anonymous uploads if ACL allows it // Note: pubkey may be nil for anonymous uploads if ACL allows it
// Detect MIME type from remote response // Detect MIME type from remote response, extension, or content sniffing
mimeType := DetectMimeType( mimeType := DetectMimeType(
resp.Header.Get("Content-Type"), resp.Header.Get("Content-Type"),
GetFileExtensionFromPath(mirrorURL.Path), GetFileExtensionFromPath(mirrorURL.Path),
) )
if mimeType == "application/octet-stream" && len(body) > 0 {
if sniffed := http.DetectContentType(body); sniffed != "application/octet-stream" {
mimeType = sniffed
}
}
// Extract extension from path or infer from MIME type // Extract extension from path or infer from MIME type
ext := GetFileExtensionFromPath(mirrorURL.Path) ext := GetFileExtensionFromPath(mirrorURL.Path)
@ -748,11 +759,18 @@ func (s *Server) handleMediaUpload(w http.ResponseWriter, r *http.Request) {
// Note: pubkey may be nil for anonymous uploads if ACL allows it // Note: pubkey may be nil for anonymous uploads if ACL allows it
// Optimize media (placeholder - actual optimization would be implemented here) // Detect MIME type from header, extension, or content sniffing
originalMimeType := DetectMimeType( originalMimeType := DetectMimeType(
r.Header.Get("Content-Type"), r.Header.Get("Content-Type"),
GetFileExtensionFromPath(r.URL.Path), GetFileExtensionFromPath(r.URL.Path),
) )
if originalMimeType == "application/octet-stream" && len(body) > 0 {
if sniffed := http.DetectContentType(body); sniffed != "application/octet-stream" {
originalMimeType = sniffed
}
}
// Optimize media (placeholder - actual optimization would be implemented here)
optimizedData, mimeType := OptimizeMedia(body, originalMimeType) optimizedData, mimeType := OptimizeMedia(body, originalMimeType)
// Extract extension from path or infer from MIME type // Extract extension from path or infer from MIME type

2
pkg/version/version

@ -1 +1 @@
v0.58.7 v0.58.8

Loading…
Cancel
Save