Skip to content

Commit 015babf

Browse files
authored
feat(server/did): serve did:web docs (#57)
* serve did:web * fix settings.yaml reload * better error
1 parent 76593ad commit 015babf

File tree

5 files changed

+94
-20
lines changed

5 files changed

+94
-20
lines changed

internal/server/datasite/datasite.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,11 @@ func (d *DatasiteService) ReloadVanityDomains(email string) error {
184184
// handleBlobChange handles blob change notifications and reloads settings if needed
185185
func (d *DatasiteService) handleBlobChange(key string, eventType blob.BlobEventType) {
186186
// ignore events other than put and delete or non-acl files
187-
if eventType&(blob.BlobEventPut|blob.BlobEventDelete) == 0 || !strings.Contains(key, aclspec.ACLFileName) {
187+
if eventType&(blob.BlobEventPut|blob.BlobEventDelete) == 0 {
188+
return
189+
}
190+
191+
if !strings.Contains(key, aclspec.ACLFileName) && !strings.Contains(key, SettingsFileName) {
188192
return
189193
}
190194

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package did
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"net/http"
7+
8+
"github.com/gin-gonic/gin"
9+
"github.com/openmined/syftbox/internal/server/blob"
10+
"github.com/openmined/syftbox/internal/server/handlers/api"
11+
"github.com/openmined/syftbox/internal/utils"
12+
)
13+
14+
type DIDHandler struct {
15+
blobService *blob.BlobService
16+
}
17+
18+
func NewDIDHandler(blobService *blob.BlobService) *DIDHandler {
19+
return &DIDHandler{blobService: blobService}
20+
}
21+
22+
func (h *DIDHandler) GetDID(c *gin.Context) {
23+
user := c.Param("user")
24+
25+
// check if user is a valid email
26+
if !utils.IsValidEmail(user) {
27+
api.ServeErrorHTML(c, http.StatusBadRequest, "Invalid Request", "<b><code>"+user+"</code></b> is not a valid user.")
28+
return
29+
}
30+
31+
didKey := fmt.Sprintf("%s/public/did.json", user)
32+
33+
// check if it exists in blob index
34+
_, exists := h.blobService.Index().Get(didKey)
35+
if !exists {
36+
api.Serve404HTML(c)
37+
return
38+
}
39+
40+
resp, err := h.blobService.Backend().GetObject(c.Request.Context(), didKey)
41+
if err != nil {
42+
c.Error(err)
43+
api.Serve500HTML(c, err)
44+
return
45+
}
46+
defer resp.Body.Close()
47+
48+
// resp.ContentType may not have the correct MIME type
49+
contentType := utils.DetectContentType(didKey)
50+
c.Header("Content-Type", contentType)
51+
c.Status(http.StatusOK)
52+
53+
// Stream response body directly
54+
_, err = io.Copy(c.Writer, resp.Body)
55+
if err != nil {
56+
c.Error(err)
57+
api.Serve500HTML(c, fmt.Errorf("failed to read file: %w", err))
58+
return
59+
}
60+
}

internal/server/handlers/explorer/explorer_handler.go

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"io"
66
"log/slog"
77
"maps"
8-
"mime"
98
"net/http"
109
"path/filepath"
1110
"slices"
@@ -23,6 +22,7 @@ import (
2322
"github.com/openmined/syftbox/internal/server/datasite"
2423
"github.com/openmined/syftbox/internal/server/handlers/api"
2524
"github.com/openmined/syftbox/internal/server/middlewares"
25+
"github.com/openmined/syftbox/internal/utils"
2626
)
2727

2828
//go:embed index.html.tmpl
@@ -235,38 +235,22 @@ func (e *ExplorerHandler) serveFile(c *gin.Context, key string) {
235235
defer resp.Body.Close()
236236

237237
// resp.ContentType may not have the correct MIME type
238-
contentType := e.detectContentType(key)
238+
contentType := utils.DetectContentType(key)
239239
c.Header("Content-Type", contentType)
240240
c.Status(http.StatusOK)
241241

242242
// Stream response body directly
243243
_, err = io.Copy(c.Writer, resp.Body)
244244
if err != nil {
245-
api.Serve500HTML(c, fmt.Errorf("failed to stream file: %w", err))
245+
api.Serve500HTML(c, fmt.Errorf("failed to read file: %w", err))
246246
return
247247
}
248248
}
249249

250-
func (e *ExplorerHandler) detectContentType(key string) string {
251-
if isTextLike(key) {
252-
return "text/plain; charset=utf-8"
253-
} else if mimeType := mime.TypeByExtension(filepath.Ext(key)); mimeType != "" {
254-
return mimeType
255-
}
256-
return "application/octet-stream"
257-
}
258-
259250
func datasiteFromPath(path string) string {
260251
parts := strings.Split(path, "/")
261252
if len(parts) > 1 {
262253
return parts[0]
263254
}
264255
return ""
265256
}
266-
267-
func isTextLike(key string) bool {
268-
return strings.HasSuffix(key, ".yaml") ||
269-
strings.HasSuffix(key, ".yml") ||
270-
strings.HasSuffix(key, ".toml") ||
271-
strings.HasSuffix(key, ".md")
272-
}

internal/server/routes.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/openmined/syftbox/internal/server/handlers/auth"
1515
"github.com/openmined/syftbox/internal/server/handlers/blob"
1616
"github.com/openmined/syftbox/internal/server/handlers/datasite"
17+
"github.com/openmined/syftbox/internal/server/handlers/did"
1718
"github.com/openmined/syftbox/internal/server/handlers/explorer"
1819
"github.com/openmined/syftbox/internal/server/handlers/install"
1920
"github.com/openmined/syftbox/internal/server/handlers/send"
@@ -58,6 +59,7 @@ func SetupRoutes(cfg *Config, svc *Services, hub *ws.WebsocketHub) http.Handler
5859
authH := auth.New(svc.Auth)
5960
aclH := acl.NewACLHandler(svc.ACL)
6061
sendH := send.New(send.NewWSMsgDispatcher(hub), send.NewBlobMsgStore(svc.Blob))
62+
didH := did.NewDIDHandler(svc.Blob)
6163

6264
// --------------------------- routes ---------------------------
6365

@@ -71,6 +73,7 @@ func SetupRoutes(cfg *Config, svc *Services, hub *ws.WebsocketHub) http.Handler
7173
r.GET("/install.ps1", install.ServePS1)
7274
r.GET("/datasites/*filepath", explorerH.Handler)
7375
r.StaticFS("/releases", http.Dir("./releases"))
76+
r.GET("/users/:user/did.json", didH.GetDID)
7477

7578
auth := r.Group("/auth")
7679
auth.Use(middlewares.RateLimiter("10-M")) // 10 req/min

internal/utils/content_type.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package utils
2+
3+
import (
4+
"mime"
5+
"path/filepath"
6+
"strings"
7+
)
8+
9+
func DetectContentType(key string) string {
10+
if isTextLike(key) {
11+
return "text/plain; charset=utf-8"
12+
} else if mimeType := mime.TypeByExtension(filepath.Ext(key)); mimeType != "" {
13+
return mimeType
14+
}
15+
return "application/octet-stream"
16+
}
17+
18+
func isTextLike(key string) bool {
19+
return strings.HasSuffix(key, ".yaml") ||
20+
strings.HasSuffix(key, ".yml") ||
21+
strings.HasSuffix(key, ".toml") ||
22+
strings.HasSuffix(key, ".md")
23+
}

0 commit comments

Comments
 (0)