feat: implement /s5/debug/storage_locations/:hash

This commit is contained in:
Derrick Hammer 2024-01-17 21:59:27 -05:00
parent 0c88e80a66
commit 510a57162c
Signed by: pcfreak30
GPG Key ID: C997C339BE476FF2
3 changed files with 115 additions and 1 deletions

View File

@ -49,7 +49,8 @@ func getRoutes(h *s5.HttpHandler, portal interfaces.Portal) map[string]jape.Hand
"DELETE /s5/delete/:cid": s5.AuthMiddleware(h.AccountPinDelete, portal),
// Debug API
"GET /s5/debug/download_urls/:cid": s5.AuthMiddleware(h.DebugDownloadUrls, portal),
"GET /s5/debug/download_urls/:cid": s5.AuthMiddleware(h.DebugDownloadUrls, portal),
"GET /s5/debug/storage_locations/:hash": s5.AuthMiddleware(h.DebugStorageLocations, portal),
//Registry API
"GET /s5/registry": s5.AuthMiddleware(h.RegistryQuery, portal),

View File

@ -28,6 +28,7 @@ import (
"mime/multipart"
"net/http"
"nhooyr.io/websocket"
"strconv"
"strings"
"time"
)
@ -1137,6 +1138,106 @@ func (h *HttpHandler) DownloadBlob(jc jape.Context) {
http.Redirect(jc.ResponseWriter, jc.Request, next.Location().BytesURL(), http.StatusFound)
}
func (h *HttpHandler) DebugStorageLocations(jc jape.Context) {
var hash string
if jc.DecodeParam("hash", &hash) != nil {
return
}
var kinds string
if jc.DecodeForm("kinds", &kinds) != nil {
return
}
decodedHash, err := encoding.MultihashFromBase64Url(hash)
if jc.Check("error decoding hash", err) != nil {
return
}
typeList := strings.Split(kinds, ",")
typeIntList := make([]types.StorageLocationType, 0)
for _, typeStr := range typeList {
typeInt, err := strconv.Atoi(typeStr)
if err != nil {
continue
}
typeIntList = append(typeIntList, types.StorageLocationType(typeInt))
}
if len(typeIntList) == 0 {
typeIntList = []types.StorageLocationType{
types.StorageLocationTypeFull,
types.StorageLocationTypeFile,
types.StorageLocationTypeBridge,
types.StorageLocationTypeArchive,
}
}
dlUriProvider := s5storage.NewStorageLocationProvider(h.getNode(), decodedHash, types.StorageLocationTypeFull, types.StorageLocationTypeFile, types.StorageLocationTypeBridge)
err = dlUriProvider.Start()
if jc.Check("error starting search", err) != nil {
return
}
_, err = dlUriProvider.Next()
if jc.Check("error fetching locations", err) != nil {
return
}
locations, err := h.getNode().GetCachedStorageLocations(decodedHash, typeIntList)
if jc.Check("error getting cached locations", err) != nil {
return
}
availableNodes := lo.Keys[string, s5interfaces.StorageLocation](locations)
availableNodesIds := make([]*encoding.NodeId, len(availableNodes))
for i, nodeIdStr := range availableNodes {
nodeId, err := encoding.DecodeNodeId(nodeIdStr)
if jc.Check("error decoding node id", err) != nil {
return
}
availableNodesIds[i] = nodeId
}
availableNodesIds, err = h.getNode().Services().P2P().SortNodesByScore(availableNodesIds)
if jc.Check("error sorting nodes", err) != nil {
return
}
debugLocations := make([]DebugStorageLocation, len(availableNodes))
for i, nodeId := range availableNodesIds {
nodeIdStr, err := nodeId.ToBase58()
if jc.Check("error encoding node id", err) != nil {
return
}
score, err := h.getNode().Services().P2P().GetNodeScore(nodeId)
if jc.Check("error getting node score", err) != nil {
return
}
debugLocations[i] = DebugStorageLocation{
Type: locations[nodeIdStr].Type(),
Parts: locations[nodeIdStr].Parts(),
Expiry: locations[nodeIdStr].Expiry(),
NodeId: nodeIdStr,
Score: score,
}
}
jc.Encode(&DebugStorageLocationsResponse{
Locations: debugLocations,
})
}
func setAuthCookie(jwt string, jc jape.Context) {
authCookie := http.Cookie{
Name: "s5-auth-token",

View File

@ -66,3 +66,15 @@ type RegistrySetRequest struct {
Data string `json:"data"`
Signature string `json:"signature"`
}
type DebugStorageLocation struct {
Type int `json:"type"`
Parts []string `json:"parts"`
Expiry int64 `json:"expiry"`
NodeId string `json:"nodeId"`
Score float64 `json:"score"`
}
type DebugStorageLocationsResponse struct {
Locations []DebugStorageLocation `json:"locations"`
}