feat: scaffold independent workbench service

This commit is contained in:
richjohnrambo
2026-09-13 22:17:01 +08:00
parent 482f9b80d9
commit 982e71f093
21 changed files with 3649 additions and 2 deletions
+86
View File
@@ -0,0 +1,86 @@
package httpapi
import (
"encoding/json"
"errors"
"net/http"
"time"
"git.118im.com/im_team/im_workbench/internal/auth"
"git.118im.com/im_team/im_workbench/internal/store"
)
const (
reasonMalformedRequest = "MALFORMED_REQUEST"
reasonMethodNotAllowed = "METHOD_NOT_ALLOWED"
reasonAuthRequired = "AUTH_REQUIRED"
reasonForbidden = "FORBIDDEN"
reasonNotFound = "RESOURCE_NOT_FOUND"
reasonConflict = "CONFLICT"
reasonInternal = "INTERNAL"
)
type apiError struct {
Code int `json:"code"`
Reason string `json:"reason"`
Message string `json:"message"`
Details map[string]any `json:"details,omitempty"`
RequestID string `json:"request_id,omitempty"`
ServerTime string `json:"server_time"`
}
func writeSuccess(w http.ResponseWriter, r *http.Request, data any) {
writeJSON(w, r, http.StatusOK, map[string]any{
"code": 0,
"data": data,
"request_id": requestID(r),
"server_time": time.Now().UTC().Format(time.RFC3339Nano),
})
}
func writeError(w http.ResponseWriter, r *http.Request, status, code int, reason, message string, details map[string]any) {
writeJSON(w, r, status, apiError{
Code: code,
Reason: reason,
Message: message,
Details: details,
RequestID: requestID(r),
ServerTime: time.Now().UTC().Format(time.RFC3339Nano),
})
}
func writeStoreError(w http.ResponseWriter, r *http.Request, err error) {
switch {
case errors.Is(err, ErrNotFound), errors.Is(err, store.ErrNotFound):
writeError(w, r, http.StatusNotFound, 30004, reasonNotFound, "resource not found", nil)
case errors.Is(err, ErrForbidden), errors.Is(err, store.ErrForbidden), errors.Is(err, auth.ErrForbidden):
writeError(w, r, http.StatusForbidden, 30041, reasonForbidden, "forbidden", nil)
case errors.Is(err, ErrConflict), errors.Is(err, store.ErrConflict):
writeError(w, r, http.StatusConflict, 30040, reasonConflict, "conflict", nil)
default:
writeError(w, r, http.StatusInternalServerError, 90000, reasonInternal, "internal error", nil)
}
}
func writeJSON(w http.ResponseWriter, r *http.Request, status int, value any) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.Header().Set("X-IM-Schema", firstNonEmpty(r.Header.Get("X-IM-Schema"), "1"))
if rid := requestID(r); rid != "" {
w.Header().Set("X-Request-ID", rid)
}
w.WriteHeader(status)
_ = json.NewEncoder(w).Encode(value)
}
func requestID(r *http.Request) string {
return r.Header.Get("X-Request-ID")
}
func firstNonEmpty(values ...string) string {
for _, value := range values {
if value != "" {
return value
}
}
return ""
}