187 lines
4.1 KiB
Go
187 lines
4.1 KiB
Go
package api
|
|
|
|
import (
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/gorilla/mux"
|
|
)
|
|
|
|
// KVInfoResponse is the response for GET /api/kv/info
|
|
type KVInfoResponse struct {
|
|
Prefix string `json:"prefix"`
|
|
FileCount int `json:"fileCount"`
|
|
KeyCount int `json:"keyCount"`
|
|
TotalSize int64 `json:"totalSize"`
|
|
MemoryUsage string `json:"memoryUsage"`
|
|
}
|
|
|
|
// KVKeysResponse is the response for GET /api/kv/keys
|
|
type KVKeysResponse struct {
|
|
Keys []string `json:"keys"`
|
|
Cursor string `json:"cursor"`
|
|
HasMore bool `json:"hasMore"`
|
|
}
|
|
|
|
// KVKeyValueResponse is the response for GET /api/kv/key/{key}
|
|
type KVKeyValueResponse struct {
|
|
Key string `json:"key"`
|
|
Type string `json:"type"`
|
|
Value map[string]string `json:"value"`
|
|
}
|
|
|
|
// handleKVInfo handles GET /api/kv/info
|
|
func (s *Server) handleKVInfo(w http.ResponseWriter, r *http.Request) {
|
|
if !s.storage.IsConnected() {
|
|
writeError(w, http.StatusServiceUnavailable, "storage not connected")
|
|
return
|
|
}
|
|
|
|
// Get all hash IDs to count files
|
|
hashIDs, err := s.storage.GetAllHashIDs()
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
// Get memory usage
|
|
memoryUsage, err := s.storage.GetMemoryInfo()
|
|
if err != nil {
|
|
memoryUsage = "N/A"
|
|
}
|
|
|
|
// Calculate total size from sizeByte metadata (if available)
|
|
var totalSize int64
|
|
for _, hashID := range hashIDs {
|
|
sizeStr, err := s.storage.GetProperty(hashID, "sizeByte")
|
|
if err == nil && sizeStr != "" {
|
|
if size, err := strconv.ParseInt(sizeStr, 10, 64); err == nil {
|
|
totalSize += size
|
|
}
|
|
}
|
|
}
|
|
|
|
response := KVInfoResponse{
|
|
Prefix: "file:",
|
|
FileCount: len(hashIDs),
|
|
KeyCount: len(hashIDs),
|
|
TotalSize: totalSize,
|
|
MemoryUsage: memoryUsage,
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, response)
|
|
}
|
|
|
|
// handleKVKeys handles GET /api/kv/keys
|
|
func (s *Server) handleKVKeys(w http.ResponseWriter, r *http.Request) {
|
|
if !s.storage.IsConnected() {
|
|
writeError(w, http.StatusServiceUnavailable, "storage not connected")
|
|
return
|
|
}
|
|
|
|
// Parse query parameters
|
|
cursorStr := r.URL.Query().Get("cursor")
|
|
countStr := r.URL.Query().Get("count")
|
|
|
|
cursor := 0
|
|
if cursorStr != "" {
|
|
if c, err := strconv.Atoi(cursorStr); err == nil {
|
|
cursor = c
|
|
}
|
|
}
|
|
|
|
count := 50
|
|
if countStr != "" {
|
|
if c, err := strconv.Atoi(countStr); err == nil && c > 0 {
|
|
count = c
|
|
}
|
|
}
|
|
|
|
// Get all hash IDs
|
|
allHashIDs, err := s.storage.GetAllHashIDs()
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
// Simple offset-based pagination
|
|
var keys []string
|
|
end := cursor + count
|
|
if end > len(allHashIDs) {
|
|
end = len(allHashIDs)
|
|
}
|
|
|
|
if cursor < len(allHashIDs) {
|
|
for _, id := range allHashIDs[cursor:end] {
|
|
keys = append(keys, "file:"+id)
|
|
}
|
|
}
|
|
|
|
nextCursor := cursor + len(keys)
|
|
hasMore := nextCursor < len(allHashIDs)
|
|
|
|
response := KVKeysResponse{
|
|
Keys: keys,
|
|
Cursor: strconv.Itoa(nextCursor),
|
|
HasMore: hasMore,
|
|
}
|
|
|
|
if !hasMore {
|
|
response.Cursor = "0"
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, response)
|
|
}
|
|
|
|
// handleKVGetKey handles GET /api/kv/key/{key}
|
|
func (s *Server) handleKVGetKey(w http.ResponseWriter, r *http.Request) {
|
|
vars := mux.Vars(r)
|
|
key := vars["key"]
|
|
|
|
if key == "" {
|
|
writeError(w, http.StatusBadRequest, "key is required")
|
|
return
|
|
}
|
|
|
|
// URL decode the key (in case it contains encoded characters)
|
|
decodedKey, err := url.PathUnescape(key)
|
|
if err != nil {
|
|
decodedKey = key
|
|
}
|
|
|
|
if !s.storage.IsConnected() {
|
|
writeError(w, http.StatusServiceUnavailable, "storage not connected")
|
|
return
|
|
}
|
|
|
|
// Extract hash ID from key (format: file:{hashId})
|
|
if !strings.HasPrefix(decodedKey, "file:") {
|
|
writeError(w, http.StatusBadRequest, "invalid key format, expected: file:{hashId}")
|
|
return
|
|
}
|
|
|
|
hashID := strings.TrimPrefix(decodedKey, "file:")
|
|
|
|
// Get metadata for this hash ID
|
|
metadata, err := s.storage.GetMetadataFlat(hashID)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
if metadata == nil {
|
|
writeError(w, http.StatusNotFound, "key not found")
|
|
return
|
|
}
|
|
|
|
response := KVKeyValueResponse{
|
|
Key: decodedKey,
|
|
Type: "hash",
|
|
Value: metadata,
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, response)
|
|
}
|