From f80ca90e9406dbeb38670827b7ec5ba588043f5f Mon Sep 17 00:00:00 2001 From: Bruce Date: Wed, 11 May 2022 11:44:19 +0800 Subject: [PATCH] feat: middleware --- .../handler/gateway/disonnecthandler.go | 33 ++++ .../api/studio/internal/handler/routes.go | 5 + .../internal/logic/gateway/disonnectlogic.go | 29 ++++ .../api/studio/internal/service/gateway.go | 49 +----- server-v2/api/studio/internal/types/types.go | 5 + server-v2/api/studio/pkg/auth/authorize.go | 118 ++++++++----- server-v2/api/studio/pkg/middleware/assets.go | 100 +++++++++++ server-v2/api/studio/pkg/utils/http.go | 157 +++++------------- server-v2/api/studio/pkg/utils/route.go | 58 ------- server-v2/api/studio/restapi/gateway.api | 8 + server-v2/api/studio/studio.go | 13 +- 11 files changed, 314 insertions(+), 261 deletions(-) create mode 100644 server-v2/api/studio/internal/handler/gateway/disonnecthandler.go create mode 100644 server-v2/api/studio/internal/logic/gateway/disonnectlogic.go create mode 100644 server-v2/api/studio/pkg/middleware/assets.go delete mode 100644 server-v2/api/studio/pkg/utils/route.go diff --git a/server-v2/api/studio/internal/handler/gateway/disonnecthandler.go b/server-v2/api/studio/internal/handler/gateway/disonnecthandler.go new file mode 100644 index 00000000..ef7418dd --- /dev/null +++ b/server-v2/api/studio/internal/handler/gateway/disonnecthandler.go @@ -0,0 +1,33 @@ +// Code generated by goctl. DO NOT EDIT. +package gateway + +import ( + "net/http" + + "github.com/vesoft-inc/go-pkg/validator" + "github.com/vesoft-inc/nebula-studio/server/api/studio/pkg/ecode" + + "github.com/vesoft-inc/nebula-studio/server/api/studio/internal/logic/gateway" + "github.com/vesoft-inc/nebula-studio/server/api/studio/internal/svc" + "github.com/vesoft-inc/nebula-studio/server/api/studio/internal/types" + "github.com/zeromicro/go-zero/rest/httpx" +) + +func DisonnectHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.DisconnectDBParams + if err := httpx.Parse(r, &req); err != nil { + err = ecode.WithCode(ecode.ErrParam, err) + svcCtx.ResponseHandler.Handle(w, r, nil, err) + return + } + if err := validator.Struct(req); err != nil { + svcCtx.ResponseHandler.Handle(w, r, nil, err) + return + } + + l := gateway.NewDisonnectLogic(r.Context(), svcCtx) + data, err := l.Disonnect(req) + svcCtx.ResponseHandler.Handle(w, r, data, err) + } +} diff --git a/server-v2/api/studio/internal/handler/routes.go b/server-v2/api/studio/internal/handler/routes.go index f47653c5..3ac7849a 100644 --- a/server-v2/api/studio/internal/handler/routes.go +++ b/server-v2/api/studio/internal/handler/routes.go @@ -41,6 +41,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { Path: "/connect", Handler: gateway.ConnectHandler(serverCtx), }, + { + Method: http.MethodPost, + Path: "/disconnect", + Handler: gateway.DisonnectHandler(serverCtx), + }, }, rest.WithPrefix("/api-nebula/db"), ) diff --git a/server-v2/api/studio/internal/logic/gateway/disonnectlogic.go b/server-v2/api/studio/internal/logic/gateway/disonnectlogic.go new file mode 100644 index 00000000..a49cd1aa --- /dev/null +++ b/server-v2/api/studio/internal/logic/gateway/disonnectlogic.go @@ -0,0 +1,29 @@ +package gateway + +import ( + "context" + + "github.com/vesoft-inc/nebula-studio/server/api/studio/internal/service" + "github.com/vesoft-inc/nebula-studio/server/api/studio/internal/svc" + "github.com/vesoft-inc/nebula-studio/server/api/studio/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type DisonnectLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewDisonnectLogic(ctx context.Context, svcCtx *svc.ServiceContext) DisonnectLogic { + return DisonnectLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *DisonnectLogic) Disonnect(req types.DisconnectDBParams) (*types.AnyResponse, error) { + return service.NewGatewayService(l.ctx, l.svcCtx).DisconnectDB(&req) +} diff --git a/server-v2/api/studio/internal/service/gateway.go b/server-v2/api/studio/internal/service/gateway.go index 87ee65cb..ca7be670 100644 --- a/server-v2/api/studio/internal/service/gateway.go +++ b/server-v2/api/studio/internal/service/gateway.go @@ -2,15 +2,10 @@ package service import ( "context" - "encoding/base64" - "fmt" - "strings" "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/gateway/dao" "github.com/vesoft-inc/nebula-studio/server/api/studio/internal/svc" "github.com/vesoft-inc/nebula-studio/server/api/studio/internal/types" - "github.com/vesoft-inc/nebula-studio/server/api/studio/pkg/auth" - "github.com/vesoft-inc/nebula-studio/server/api/studio/pkg/ecode" "github.com/zeromicro/go-zero/core/logx" ) @@ -21,6 +16,7 @@ type ( GatewayService interface { GetExec(request *types.ExecNGQLParams) (*types.AnyResponse, error) ConnectDB(request *types.ConnectDBParams) (*types.ConnectDBResult, error) + DisconnectDB(request *types.DisconnectDBParams) (*types.AnyResponse, error) } gatewayService struct { @@ -47,41 +43,14 @@ func (s *gatewayService) GetExec(request *types.ExecNGQLParams) (*types.AnyRespo } func (s *gatewayService) ConnectDB(request *types.ConnectDBParams) (*types.ConnectDBResult, error) { - fmt.Println("======request999", request) - tokenSplit := strings.Split(request.Authorization, " ") - if len(tokenSplit) != 2 { - return nil, ecode.WithCode(ecode.ErrParam, nil, "invalid authorization") - } - - decode, err := base64.StdEncoding.DecodeString(tokenSplit[1]) - if err != nil { - return nil, ecode.WithCode(ecode.ErrParam, err) - } - - loginInfo := strings.Split(string(decode), ":") - if len(loginInfo) < 2 { - return nil, ecode.WithCode(ecode.ErrParam, nil, "len of account is less than two") - } - - username, password := loginInfo[0], loginInfo[1] - clientInfo, err := dao.Connect(request.Address, request.Port, username, password) - - tokenString, err := auth.CreateToken( - &auth.AuthData{ - NebulaAddress: request.Address, - Username: username, - ClientID: clientInfo.ClientID, - }, - &s.svcCtx.Config, - ) - - fmt.Println("=====tokenString", tokenString) - - if err != nil { - return nil, ecode.WithInternalServer(err, "connect db failed") - } - return &types.ConnectDBResult{ - Version: string(clientInfo.NebulaVersion), + Version: string(request.NebulaVersion), }, nil } + +func (s *gatewayService) DisconnectDB(request *types.DisconnectDBParams) (*types.AnyResponse, error) { + if request.Nsid != "" { + dao.Disconnect(request.Nsid) + } + return nil, nil +} diff --git a/server-v2/api/studio/internal/types/types.go b/server-v2/api/studio/internal/types/types.go index 373f0ca5..e5d2d7fb 100644 --- a/server-v2/api/studio/internal/types/types.go +++ b/server-v2/api/studio/internal/types/types.go @@ -13,6 +13,7 @@ type ExecNGQLParams struct { type ConnectDBParams struct { Address string `json:"address"` Port int `json:"port"` + NebulaVersion string `form:"nebulaVersion,optional"` Authorization string `header:"Authorization"` } @@ -20,6 +21,10 @@ type ConnectDBResult struct { Version string `json:"version"` } +type DisconnectDBParams struct { + Nsid string `form:"nsid,optional"` +} + type AnyResponse struct { Data interface{} `json:"data"` } diff --git a/server-v2/api/studio/pkg/auth/authorize.go b/server-v2/api/studio/pkg/auth/authorize.go index b75c27f9..6513a4df 100644 --- a/server-v2/api/studio/pkg/auth/authorize.go +++ b/server-v2/api/studio/pkg/auth/authorize.go @@ -9,8 +9,11 @@ import ( "github.com/golang-jwt/jwt/v4" "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/gateway/dao" + "github.com/vesoft-inc/nebula-http-gateway/ccore/nebula/gateway/pool" "github.com/vesoft-inc/nebula-studio/server/api/studio/internal/config" "github.com/vesoft-inc/nebula-studio/server/api/studio/internal/types" + "github.com/vesoft-inc/nebula-studio/server/api/studio/pkg/ecode" + "github.com/vesoft-inc/nebula-studio/server/api/studio/pkg/utils" "github.com/zeromicro/go-zero/rest" "github.com/zeromicro/go-zero/rest/httpx" ) @@ -32,6 +35,38 @@ type ( var globalConfig = new(config.Config) +func parseConnectDBParams(params *types.ConnectDBParams, config *config.Config) (string, *pool.ClientInfo, error) { + tokenSplit := strings.Split(params.Authorization, " ") + if len(tokenSplit) != 2 { + return "", nil, ecode.WithCode(ecode.ErrParam, nil, "invalid authorization") + } + + decode, err := base64.StdEncoding.DecodeString(tokenSplit[1]) + if err != nil { + return "", nil, ecode.WithCode(ecode.ErrParam, err) + } + + loginInfo := strings.Split(string(decode), ":") + if len(loginInfo) < 2 { + return "", nil, ecode.WithCode(ecode.ErrParam, nil, "len of account is less than two") + } + + username, password := loginInfo[0], loginInfo[1] + clientInfo, err := dao.Connect(params.Address, params.Port, username, password) + if err != nil { + return "", nil, ecode.WithCode(ecode.ErrInternalServer, err) + } + + tokenString, err := CreateToken( + &AuthData{ + NebulaAddress: params.Address, + Username: username, + }, + config, + ) + return tokenString, clientInfo, err +} + func CreateToken(authData *AuthData, config *config.Config) (string, error) { now := time.Now() expiresAt := now.Add(time.Duration(config.Auth.AccessExpire) * time.Second).Unix() @@ -52,52 +87,57 @@ func AuthMiddlewareWithConfig(config *config.Config) rest.Middleware { return func(w http.ResponseWriter, r *http.Request) { // login handler if strings.HasSuffix(r.URL.Path, "/connect") { - fmt.Println("=====global middleware", r.URL.Path) var req types.ConnectDBParams - err := httpx.Parse(r, &req) + rClone := utils.CopyHttpRequest(r) + err := httpx.Parse(rClone, &req) if err != nil { - fmt.Println("=====req3333", req) + http.Error(w, err.Error(), http.StatusBadRequest) + return } - fmt.Println("=====err", err) - fmt.Println("=====req.Address", req.Address) - fmt.Println("=====req.Port", req.Port) - fmt.Println("=====req.Authorization", req.Authorization) - } - c1 := http.Cookie{ - Name: "access_token", - Value: "12333", - Path: "/", - HttpOnly: true, - MaxAge: 3600, - } - var req1 types.ConnectDBParams - err1 := httpx.Parse(r, &req1) - fmt.Println("=====err1=====", err1) + tokenString, clientInfo, err := parseConnectDBParams(&req, config) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } - w.Header().Set("Access-Control-Allow-Origin", "*") - w.Header().Set("Set-Cookie", c1.String()) - next(w, r) - } - } -} + token := http.Cookie{ + Name: "token", + Value: tokenString, + Path: "/", + HttpOnly: true, + MaxAge: 1800, + } + nsid := http.Cookie{ + Name: "nsid", + Value: clientInfo.ClientID, + Path: "/", + HttpOnly: true, + MaxAge: 1800, + } -func AuthMiddleware(next http.HandlerFunc) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - // login handler - if strings.HasSuffix(r.URL.Path, "/connect") { - fmt.Println("=====global middleware", r.URL.Path) - } - c1 := http.Cookie{ - Name: "access_token", - Value: "12333", - Path: "/", - HttpOnly: true, - MaxAge: 3600, + query := r.URL.Query() + query.Set("nebulaVersion", string(clientInfo.NebulaVersion)) + r.URL, _ = r.URL.Parse(r.URL.Path + "?" + query.Encode()) + + // w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Set-Cookie", token.String()) + w.Header().Add("Set-Cookie", nsid.String()) + } else if strings.HasSuffix(r.URL.Path, "/disconnect") { + nsidCookie, err := r.Cookie("nsid") + + if err == nil { + query := r.URL.Query() + query.Set("nsid", nsidCookie.Value) + r.URL, _ = r.URL.Parse(r.URL.Path + "?" + query.Encode()) + } + + w.Header().Set("Set-Cookie", utils.DisabledCookie("token").String()) + w.Header().Add("Set-Cookie", utils.DisabledCookie("nsid").String()) + } else { + } + next(w, r) } - w.Header().Set("Access-Control-Allow-Origin", "*") - w.Header().Set("Set-Cookie", c1.String()) - next(w, r) } } diff --git a/server-v2/api/studio/pkg/middleware/assets.go b/server-v2/api/studio/pkg/middleware/assets.go new file mode 100644 index 00000000..a58a2abb --- /dev/null +++ b/server-v2/api/studio/pkg/middleware/assets.go @@ -0,0 +1,100 @@ +package middleware + +import ( + "net/http" + "net/url" + "path/filepath" + "strings" +) + +type ( + AssertsConfig struct { + Prefix string + Root string + Index string + SPA bool + Filesystem http.FileSystem + } + + assertsHandler struct { + config AssertsConfig + } +) + +func NewAssertsHandler(config AssertsConfig) http.Handler { + if config.Root == "" { + config.Root = "." + } + if config.Index == "" { + config.Index = "/index.html" + } else { + config.Index = filepath.Clean("/" + config.Index) + } + if config.Filesystem == nil { + config.Filesystem = http.Dir(config.Root) + config.Root = "." + } + + return &assertsHandler{ + config: config, + } +} + +func (h *assertsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + urlPath, err := url.PathUnescape(r.URL.Path) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + pathInFs := filepath.Clean("/" + urlPath) + if h.config.Prefix != "" { + if strings.HasPrefix(urlPath, h.config.Prefix) { + pathInFs = filepath.Clean("/" + urlPath[len(h.config.Prefix):]) + } else { + if !h.config.SPA { + http.NotFound(w, r) + return + } + pathInFs = h.config.Index + } + } + + file, err := h.config.Filesystem.Open(filepath.Join(h.config.Root, pathInFs)) + if err != nil { + if !h.config.SPA || urlPath == h.config.Index { + http.NotFound(w, r) + return + } + pathInFs = h.config.Index + file, err = h.config.Filesystem.Open(filepath.Join(h.config.Root, pathInFs)) + if err != nil { + http.NotFound(w, r) + return + } + } + defer file.Close() + + stat, err := file.Stat() + if err != nil { + http.NotFound(w, r) + return + } + + if stat.IsDir() { + pathInFs = filepath.Join(pathInFs, h.config.Index) + file, err = h.config.Filesystem.Open(filepath.Join(h.config.Root, pathInFs)) + if err != nil { + http.NotFound(w, r) + return + } + defer file.Close() + stat, err = file.Stat() + if err != nil || stat.IsDir() { + http.NotFound(w, r) + return + } + } + + http.ServeContent(w, r, stat.Name(), stat.ModTime(), file) +} diff --git a/server-v2/api/studio/pkg/utils/http.go b/server-v2/api/studio/pkg/utils/http.go index f81d283f..a3ae820d 100644 --- a/server-v2/api/studio/pkg/utils/http.go +++ b/server-v2/api/studio/pkg/utils/http.go @@ -1,128 +1,47 @@ package utils +import ( + "bytes" + "io" + "io/ioutil" + "net/http" +) + const MIMEOctetStream = "application/octet-stream" -// GetMIME returns the content-type of a file extension -func GetMIME(extension string) (mime string) { - if len(extension) == 0 { - return mime - } - if extension[0] == '.' { - mime = mimeExtensions[extension[1:]] - } else { - mime = mimeExtensions[extension] +func CopyHttpRequest(r *http.Request) *http.Request { + reqCopy := new(http.Request) + + if r == nil { + return reqCopy } - if len(mime) == 0 { - return MIMEOctetStream + + *reqCopy = *r + + if r.Body != nil { + defer r.Body.Close() + + // Buffer body data + var bodyBuffer bytes.Buffer + newBodyBuffer := new(bytes.Buffer) + + io.Copy(&bodyBuffer, r.Body) + *newBodyBuffer = bodyBuffer + + // Create new ReadClosers so we can split output + r.Body = ioutil.NopCloser(&bodyBuffer) + reqCopy.Body = ioutil.NopCloser(newBodyBuffer) } - return mime + + return reqCopy } -// MIME types were copied from https://github.com/nginx/nginx/blob/master/conf/mime.types -var mimeExtensions = map[string]string{ - "html": "text/html", - "htm": "text/html", - "shtml": "text/html", - "css": "text/css", - "gif": "image/gif", - "jpeg": "image/jpeg", - "jpg": "image/jpeg", - "xml": "application/xml", - "js": "application/javascript", - "atom": "application/atom+xml", - "rss": "application/rss+xml", - "mml": "text/mathml", - "txt": "text/plain", - "jad": "text/vnd.sun.j2me.app-descriptor", - "wml": "text/vnd.wap.wml", - "htc": "text/x-component", - "png": "image/png", - "svg": "image/svg+xml", - "svgz": "image/svg+xml", - "tif": "image/tiff", - "tiff": "image/tiff", - "wbmp": "image/vnd.wap.wbmp", - "webp": "image/webp", - "ico": "image/x-icon", - "jng": "image/x-jng", - "bmp": "image/x-ms-bmp", - "woff": "font/woff", - "woff2": "font/woff2", - "jar": "application/java-archive", - "war": "application/java-archive", - "ear": "application/java-archive", - "json": "application/json", - "hqx": "application/mac-binhex40", - "doc": "application/msword", - "pdf": "application/pdf", - "ps": "application/postscript", - "eps": "application/postscript", - "ai": "application/postscript", - "rtf": "application/rtf", - "m3u8": "application/vnd.apple.mpegurl", - "kml": "application/vnd.google-earth.kml+xml", - "kmz": "application/vnd.google-earth.kmz", - "xls": "application/vnd.ms-excel", - "eot": "application/vnd.ms-fontobject", - "ppt": "application/vnd.ms-powerpoint", - "odg": "application/vnd.oasis.opendocument.graphics", - "odp": "application/vnd.oasis.opendocument.presentation", - "ods": "application/vnd.oasis.opendocument.spreadsheet", - "odt": "application/vnd.oasis.opendocument.text", - "wmlc": "application/vnd.wap.wmlc", - "7z": "application/x-7z-compressed", - "cco": "application/x-cocoa", - "jardiff": "application/x-java-archive-diff", - "jnlp": "application/x-java-jnlp-file", - "run": "application/x-makeself", - "pl": "application/x-perl", - "pm": "application/x-perl", - "prc": "application/x-pilot", - "pdb": "application/x-pilot", - "rar": "application/x-rar-compressed", - "rpm": "application/x-redhat-package-manager", - "sea": "application/x-sea", - "swf": "application/x-shockwave-flash", - "sit": "application/x-stuffit", - "tcl": "application/x-tcl", - "tk": "application/x-tcl", - "der": "application/x-x509-ca-cert", - "pem": "application/x-x509-ca-cert", - "crt": "application/x-x509-ca-cert", - "xpi": "application/x-xpinstall", - "xhtml": "application/xhtml+xml", - "xspf": "application/xspf+xml", - "zip": "application/zip", - "bin": "application/octet-stream", - "exe": "application/octet-stream", - "dll": "application/octet-stream", - "deb": "application/octet-stream", - "dmg": "application/octet-stream", - "iso": "application/octet-stream", - "img": "application/octet-stream", - "msi": "application/octet-stream", - "msp": "application/octet-stream", - "msm": "application/octet-stream", - "mid": "audio/midi", - "midi": "audio/midi", - "kar": "audio/midi", - "mp3": "audio/mpeg", - "ogg": "audio/ogg", - "m4a": "audio/x-m4a", - "ra": "audio/x-realaudio", - "3gpp": "video/3gpp", - "3gp": "video/3gpp", - "ts": "video/mp2t", - "mp4": "video/mp4", - "mpeg": "video/mpeg", - "mpg": "video/mpeg", - "mov": "video/quicktime", - "webm": "video/webm", - "flv": "video/x-flv", - "m4v": "video/x-m4v", - "mng": "video/x-mng", - "asx": "video/x-ms-asf", - "asf": "video/x-ms-asf", - "wmv": "video/x-ms-wmv", - "avi": "video/x-msvideo", +func DisabledCookie(name string) *http.Cookie { + return &http.Cookie{ + Name: name, + Value: "", + Path: "/", + HttpOnly: true, + MaxAge: -1, + } } diff --git a/server-v2/api/studio/pkg/utils/route.go b/server-v2/api/studio/pkg/utils/route.go deleted file mode 100644 index 13ad7ef6..00000000 --- a/server-v2/api/studio/pkg/utils/route.go +++ /dev/null @@ -1,58 +0,0 @@ -package utils - -import ( - "embed" - "net/http" - "path" - "path/filepath" - "strconv" - "strings" - - "github.com/vesoft-inc/nebula-studio/server/api/studio/internal/svc" - "github.com/zeromicro/go-zero/core/logx" - "github.com/zeromicro/go-zero/rest" -) - -var embedAssetsFolder = "assets" - -func RegisterHandlers(engine *rest.Server, serverCtx *svc.ServiceContext, fs embed.FS) { - dirlevel := []string{"/:1", ":2", ":3", ":4", ":5", ":6", ":7", ":8"} - for i := 1; i < len(dirlevel); i++ { - pathname := strings.Join(dirlevel[:i], "/") - //最后生成 /asset - engine.AddRoute( - rest.Route{ - Method: http.MethodGet, - Path: pathname, - Handler: filehandler(fs), - }) - logx.Infof("register route %s", pathname) - } -} - -func filehandler(fs embed.FS) http.HandlerFunc { - return func(w http.ResponseWriter, req *http.Request) { - fileType := filepath.Ext(req.URL.Path) - // subpath default: index.html - if len(fileType) == 0 { - htmlFileData, _ := fs.ReadFile(path.Join(embedAssetsFolder, "index.html")) - w.Write(htmlFileData) - return - } - - // assets file: a/b/c.(js|css|png) - data, err := fs.ReadFile(path.Join(embedAssetsFolder, req.URL.Path)) - if err != nil { - logx.Errorf("open resource error %s", err.Error()) - http.NotFound(w, req) - return - } - - // set assets response header - w.Header().Set("Content-Type", GetMIME(fileType)+"; charset=utf-8") - w.Header().Set("Content-Length", strconv.Itoa(len(data))) - w.Header().Set("Cache-Control", "public, max-age=7200") - - w.Write(data) - } -} diff --git a/server-v2/api/studio/restapi/gateway.api b/server-v2/api/studio/restapi/gateway.api index 006dab1d..733c0836 100644 --- a/server-v2/api/studio/restapi/gateway.api +++ b/server-v2/api/studio/restapi/gateway.api @@ -8,11 +8,15 @@ type ( ConnectDBParams { Address string `json:"address"` Port int `json:"port"` + NebulaVersion string `form:"nebulaVersion,optional"` Authorization string `header:"Authorization"` } ConnectDBResult { Version string `json:"version"` } + DisconnectDBParams { + Nsid string `form:"nsid,optional"` + } AnyResponse { Data interface{} `json:"data"` @@ -39,4 +43,8 @@ service studio-api { @doc "Connect DB" @handler Connect post /connect(ConnectDBParams) returns (ConnectDBResult) + + @doc "Disonnect DB" + @handler Disonnect + post /disconnect(DisconnectDBParams) returns (AnyResponse) } \ No newline at end of file diff --git a/server-v2/api/studio/studio.go b/server-v2/api/studio/studio.go index 101e5787..c455e1d9 100644 --- a/server-v2/api/studio/studio.go +++ b/server-v2/api/studio/studio.go @@ -4,12 +4,13 @@ import ( "embed" "flag" "fmt" + "net/http" "github.com/vesoft-inc/nebula-studio/server/api/studio/internal/config" "github.com/vesoft-inc/nebula-studio/server/api/studio/internal/handler" "github.com/vesoft-inc/nebula-studio/server/api/studio/internal/svc" "github.com/vesoft-inc/nebula-studio/server/api/studio/pkg/auth" - "github.com/vesoft-inc/nebula-studio/server/api/studio/pkg/utils" + "github.com/vesoft-inc/nebula-studio/server/api/studio/pkg/middleware" "github.com/zeromicro/go-zero/core/conf" "github.com/zeromicro/go-zero/rest" @@ -27,16 +28,18 @@ func main() { conf.MustLoad(*configFile, &c, conf.UseEnv()) svcCtx := svc.NewServiceContext(c) - server := rest.MustNewServer(c.RestConf) + server := rest.MustNewServer(c.RestConf, rest.WithNotFoundHandler(middleware.NewAssertsHandler(middleware.AssertsConfig{ + Root: "assets", + Filesystem: http.FS(embedAssets), + SPA: true, + }))) + defer server.Stop() // global middleware // server.Use(auth.AuthMiddleware) server.Use(auth.AuthMiddlewareWithConfig(&c)) - // static assets handlers - utils.RegisterHandlers(server, svcCtx, embedAssets) - // api handlers handler.RegisterHandlers(server, svcCtx)