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