Browse Source

add cloud server

master
godo 6 months ago
parent
commit
b8d263bf86
  1. 3
      cloud/.gitignore
  2. 69
      cloud/cmd/main.go
  3. 54
      cloud/cmd/msg.go
  4. 97
      cloud/cmd/serve.go
  5. 6
      cloud/deps/frontend.go
  6. 5
      cloud/go.mod
  7. 2
      cloud/go.sum
  8. 7
      cloud/main.go
  9. 7
      frontend/src/system/config.ts

3
cloud/.gitignore

@ -0,0 +1,3 @@
tmp
deps/dist
deps/*.zip

69
cloud/cmd/main.go

@ -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()
}

54
cloud/cmd/msg.go

@ -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)
}

97
cloud/cmd/serve.go

@ -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)
})
}
}

6
cloud/deps/frontend.go

@ -0,0 +1,6 @@
package deps
import "embed"
//go:embed dist
var Frontendassets embed.FS

5
cloud/go.mod

@ -0,0 +1,5 @@
module godocloud
go 1.23.2
require github.com/gorilla/mux v1.8.1

2
cloud/go.sum

@ -0,0 +1,2 @@
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=

7
cloud/main.go

@ -0,0 +1,7 @@
package main
import "godocloud/cmd"
func main() {
cmd.OsStart()
}

7
frontend/src/system/config.ts

@ -28,7 +28,7 @@ export const getSystemConfig = (ifset = false) => {
config.apiUrl = `${window.location.protocol}//${window.location.hostname}:56780`;
}
if (!config.userType) {
config.userType = 'person'
config.userType = 'person'//如果是企业版请改为member
}
if (!config.file) {
config.file = {
@ -43,7 +43,7 @@ export const getSystemConfig = (ifset = false) => {
// 初始化用户信息,若本地存储中已存在则不进行覆盖
if (!config.userInfo) {
config.userInfo = {
url: '',
url: '',//如果是企业版请改为服务器地址,不要加斜线
username: '',
password: '',
id: 0,
@ -88,9 +88,6 @@ export const getSystemConfig = (ifset = false) => {
if(!config.netPort) {
config.netPort = "56780";
}
if (!config.userType) {
config.userType = 'person';
}
// 初始化背景设置,若本地存储中已存在则不进行覆盖
if (!config.background) {
config.background = {

Loading…
Cancel
Save