mirror of https://gitee.com/godoos/godoos.git
9 changed files with 245 additions and 5 deletions
@ -0,0 +1,3 @@ |
|||||
|
tmp |
||||
|
deps/dist |
||||
|
deps/*.zip |
@ -0,0 +1,69 @@ |
|||||
|
/* |
||||
|
* GodoOS - A lightweight cloud desktop |
||||
|
* Copyright (C) 2024 https://godoos.com
|
||||
|
* |
||||
|
* This program is free software: you can redistribute it and/or modify |
||||
|
* it under the terms of the GNU Lesser General Public License as published by |
||||
|
* the Free Software Foundation, either version 2.1 of the License, or |
||||
|
* (at your option) any later version. |
||||
|
* |
||||
|
* This program is distributed in the hope that it will be useful, |
||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
* GNU Lesser General Public License for more details. |
||||
|
* |
||||
|
* You should have received a copy of the GNU Lesser General Public License |
||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
|
||||
|
package cmd |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"godocloud/deps" |
||||
|
"io/fs" |
||||
|
"log" |
||||
|
"net/http" |
||||
|
"time" |
||||
|
|
||||
|
"github.com/gorilla/mux" |
||||
|
) |
||||
|
|
||||
|
const serverAddress = ":56781" |
||||
|
|
||||
|
var srv *http.Server |
||||
|
|
||||
|
func OsStart() { |
||||
|
//InitServer()
|
||||
|
router := mux.NewRouter() |
||||
|
router.Use(recoverMiddleware) |
||||
|
router.Use(corsMiddleware()) |
||||
|
// 使用带有日志装饰的处理器注册路由
|
||||
|
router.Use(loggingMiddleware{}.Middleware) |
||||
|
|
||||
|
// 注册根路径的处理函数
|
||||
|
distFS, _ := fs.Sub(deps.Frontendassets, "dist") |
||||
|
fileServer := http.FileServer(http.FS(distFS)) |
||||
|
|
||||
|
// 注册根路径的处理函数
|
||||
|
router.PathPrefix("/").Handler(fileServer) |
||||
|
|
||||
|
//serverAddress := ":56781"
|
||||
|
log.Printf("Listening on port: %v", serverAddress) |
||||
|
srv = &http.Server{Addr: serverAddress, Handler: router} |
||||
|
Serve(srv) |
||||
|
} |
||||
|
func OsStop() { |
||||
|
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) |
||||
|
defer cancel() |
||||
|
if err := srv.Shutdown(ctx); err != nil { |
||||
|
log.Fatalf("Server forced to shutdown: %v", err) |
||||
|
} |
||||
|
log.Println("Server stopped.") |
||||
|
} |
||||
|
func OsRestart() { |
||||
|
// 停止当前服务
|
||||
|
OsStop() |
||||
|
// 重新启动服务
|
||||
|
OsStart() |
||||
|
} |
@ -0,0 +1,54 @@ |
|||||
|
/* |
||||
|
* GodoOS - A lightweight cloud desktop |
||||
|
* Copyright (C) 2024 https://godoos.com
|
||||
|
* |
||||
|
* This program is free software: you can redistribute it and/or modify |
||||
|
* it under the terms of the GNU Lesser General Public License as published by |
||||
|
* the Free Software Foundation, either version 2.1 of the License, or |
||||
|
* (at your option) any later version. |
||||
|
* |
||||
|
* This program is distributed in the hope that it will be useful, |
||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
* GNU Lesser General Public License for more details. |
||||
|
* |
||||
|
* You should have received a copy of the GNU Lesser General Public License |
||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
|
||||
|
package cmd |
||||
|
|
||||
|
import ( |
||||
|
"encoding/json" |
||||
|
"net/http" |
||||
|
) |
||||
|
|
||||
|
type APIResponse struct { |
||||
|
Message string `json:"message"` |
||||
|
Code int `json:"code"` |
||||
|
Data any `json:"data,omitempty"` |
||||
|
Error string `json:"error,omitempty"` |
||||
|
} |
||||
|
|
||||
|
func WriteJSONResponse(w http.ResponseWriter, res APIResponse, status int) { |
||||
|
w.Header().Set("Content-Type", "application/json") |
||||
|
w.WriteHeader(status) |
||||
|
json.NewEncoder(w).Encode(res) |
||||
|
} |
||||
|
|
||||
|
// HTTPError 返回带有JSON错误消息的HTTP错误
|
||||
|
func HTTPError(w http.ResponseWriter, status int, message string) { |
||||
|
WriteJSONResponse(w, APIResponse{Message: message, Code: -1}, status) |
||||
|
} |
||||
|
func ErrorMsg(w http.ResponseWriter, message string) { |
||||
|
WriteJSONResponse(w, APIResponse{Message: message, Code: -1}, 200) |
||||
|
} |
||||
|
func ErrorData(w http.ResponseWriter, data any, message string) { |
||||
|
WriteJSONResponse(w, APIResponse{Message: message, Data: data, Code: -1}, 200) |
||||
|
} |
||||
|
func Error(w http.ResponseWriter, message string, err string) { |
||||
|
WriteJSONResponse(w, APIResponse{Message: message, Error: err, Code: -1}, 200) |
||||
|
} |
||||
|
func SuccessMsg(w http.ResponseWriter, data any, message string) { |
||||
|
WriteJSONResponse(w, APIResponse{Message: message, Data: data, Code: 0}, 200) |
||||
|
} |
@ -0,0 +1,97 @@ |
|||||
|
package cmd |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"fmt" |
||||
|
"log" |
||||
|
"net/http" |
||||
|
"os" |
||||
|
"os/signal" |
||||
|
"sync" |
||||
|
"syscall" |
||||
|
"time" |
||||
|
|
||||
|
"github.com/gorilla/mux" |
||||
|
) |
||||
|
|
||||
|
func Serve(srv *http.Server) { |
||||
|
var wg sync.WaitGroup |
||||
|
wg.Add(1) |
||||
|
|
||||
|
go func() { |
||||
|
defer wg.Done() |
||||
|
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { |
||||
|
log.Fatalf("Error starting server: %v\n", err) |
||||
|
} |
||||
|
}() |
||||
|
// 监听退出信号
|
||||
|
ctx, cancel := context.WithCancel(context.Background()) |
||||
|
go func() { |
||||
|
c := make(chan os.Signal, 1) |
||||
|
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) |
||||
|
<-c |
||||
|
log.Println("Received signal, gracefully shutting down...") |
||||
|
cancel() |
||||
|
}() |
||||
|
|
||||
|
<-ctx.Done() |
||||
|
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 5*time.Second) |
||||
|
defer shutdownCancel() |
||||
|
if err := srv.Shutdown(shutdownCtx); err != nil { |
||||
|
log.Printf("Error during server shutdown: %v\n", err) |
||||
|
} |
||||
|
wg.Wait() |
||||
|
} |
||||
|
|
||||
|
type loggingMiddleware struct { |
||||
|
} |
||||
|
|
||||
|
func (l loggingMiddleware) Middleware(next http.Handler) http.Handler { |
||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
||||
|
startTime := time.Now() |
||||
|
defer func() { |
||||
|
log.Printf( |
||||
|
"%s %s %s %v", |
||||
|
r.Method, |
||||
|
r.URL.Path, |
||||
|
r.Proto, |
||||
|
time.Since(startTime), |
||||
|
) |
||||
|
}() |
||||
|
next.ServeHTTP(w, r) |
||||
|
}) |
||||
|
} |
||||
|
func recoverMiddleware(next http.Handler) http.Handler { |
||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
||||
|
defer func() { |
||||
|
if err := recover(); err != nil { |
||||
|
// log.Printf("Recovered from panic: %v", err)
|
||||
|
// http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
|
ErrorMsg(w, "Internal Server Error:"+fmt.Sprintf("%v", err)) |
||||
|
} |
||||
|
}() |
||||
|
next.ServeHTTP(w, r) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// CORS 中间件
|
||||
|
func corsMiddleware() mux.MiddlewareFunc { |
||||
|
allowHeaders := "Content-Type, Accept, Authorization, Origin,Pwd" |
||||
|
allowMethods := "GET, POST, PUT, DELETE, OPTIONS" |
||||
|
|
||||
|
return func(next http.Handler) http.Handler { |
||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
||||
|
w.Header().Set("Access-Control-Allow-Origin", "*") |
||||
|
w.Header().Set("Access-Control-Allow-Methods", allowMethods) |
||||
|
w.Header().Set("Access-Control-Allow-Headers", allowHeaders) |
||||
|
|
||||
|
// 如果是预检请求(OPTIONS),直接返回 200 OK
|
||||
|
if r.Method == http.MethodOptions { |
||||
|
w.WriteHeader(http.StatusOK) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
next.ServeHTTP(w, r) |
||||
|
}) |
||||
|
} |
||||
|
} |
@ -0,0 +1,6 @@ |
|||||
|
package deps |
||||
|
|
||||
|
import "embed" |
||||
|
|
||||
|
//go:embed dist
|
||||
|
var Frontendassets embed.FS |
@ -0,0 +1,5 @@ |
|||||
|
module godocloud |
||||
|
|
||||
|
go 1.23.2 |
||||
|
|
||||
|
require github.com/gorilla/mux v1.8.1 |
@ -0,0 +1,2 @@ |
|||||
|
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= |
||||
|
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= |
@ -0,0 +1,7 @@ |
|||||
|
package main |
||||
|
|
||||
|
import "godocloud/cmd" |
||||
|
|
||||
|
func main() { |
||||
|
cmd.OsStart() |
||||
|
} |
Loading…
Reference in new issue