restructure project

This commit is contained in:
Samuel Lorch 2023-03-26 18:50:18 +02:00
parent dd2db438f3
commit 2ca35d4461
46 changed files with 158 additions and 84 deletions

36
internal/server/api.go Normal file
View file

@ -0,0 +1,36 @@
package server
import (
"context"
"fmt"
"net/http"
"runtime/debug"
"time"
"golang.org/x/exp/slog"
"nfsense.net/nfsense/internal/session"
)
func HandleAPI(w http.ResponseWriter, r *http.Request) {
slog.Info("Api Handler hit")
_, s := session.GetSession(r)
if s == nil {
// Fallthrough after so that jsonrpc can still deliver a valid jsonrpc error
w.WriteHeader(http.StatusUnauthorized)
}
defer func() {
if r := recover(); r != nil {
slog.Error("Recovered Panic Handling HTTP API Request", fmt.Errorf("%v", r), "stack", debug.Stack())
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
}()
ctx, cancel := context.WithTimeout(context.WithValue(r.Context(), session.SessionKey, s), time.Second*10)
defer cancel()
err := apiHandler.HandleRequest(ctx, s, r.Body, w)
if err != nil {
slog.Error("Handling HTTP API Request", err)
}
}

53
internal/server/server.go Normal file
View file

@ -0,0 +1,53 @@
package server
import (
"context"
"errors"
"fmt"
"net/http"
"golang.org/x/exp/slog"
"nfsense.net/nfsense/internal/definitions"
"nfsense.net/nfsense/internal/jsonrpc"
"nfsense.net/nfsense/internal/session"
)
var server http.Server
var mux = http.NewServeMux()
var apiHandler *jsonrpc.Handler
var stopCleanup chan struct{}
func StartWebserver(conf *definitions.Config, _apiHandler *jsonrpc.Handler) {
server.Addr = ":8080"
server.Handler = mux
apiHandler = _apiHandler
// Routing
mux.HandleFunc("/login", HandleLogin)
mux.HandleFunc("/logout", HandleLogout)
mux.HandleFunc("/session", HandleSession)
mux.HandleFunc("/api", HandleAPI)
mux.HandleFunc("/ws/api", HandleWebsocketAPI)
mux.HandleFunc("/", HandleWebinterface)
stopCleanup = make(chan struct{})
go session.CleanupSessions(stopCleanup)
go func() {
if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
slog.Error("Webserver error", err)
}
slog.Info("Webserver Stopped")
}()
}
func ShutdownWebserver(ctx context.Context) error {
stopCleanup <- struct{}{}
err := server.Shutdown(ctx)
if err != nil {
return fmt.Errorf("Shutting down: %w", err)
}
return nil
}

View file

@ -0,0 +1,63 @@
package server
import (
"encoding/json"
"io"
"net/http"
"time"
"golang.org/x/exp/slog"
"nfsense.net/nfsense/internal/session"
)
type LoginRequest struct {
Username string `json:"username"`
Password string `json:"password"`
}
func HandleLogin(w http.ResponseWriter, r *http.Request) {
buf, err := io.ReadAll(r.Body)
if err != nil {
slog.Error("Reading Body", err)
return
}
var req LoginRequest
err = json.Unmarshal(buf, &req)
if err != nil {
slog.Error("Unmarshal", err)
return
}
if req.Username == "admin" && req.Password == "12345" {
slog.Info("User Login Successfull")
session.GenerateSession(w, req.Username)
w.WriteHeader(http.StatusOK)
return
}
w.WriteHeader(http.StatusUnauthorized)
}
func HandleLogout(w http.ResponseWriter, r *http.Request) {
http.SetCookie(w, session.GetCookie("", time.Now()))
w.WriteHeader(http.StatusOK)
}
func HandleSession(w http.ResponseWriter, r *http.Request) {
id, s := session.GetSession(r)
if s == nil {
w.WriteHeader(http.StatusUnauthorized)
return
}
session.ExtendSession(s)
http.SetCookie(w, session.GetCookie(id, s.Expires))
w.WriteHeader(http.StatusOK)
resp := session.SessionResponse{
CommitHash: session.CommitHash,
}
res, err := json.Marshal(resp)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Write(res)
}

View file

@ -0,0 +1,9 @@
package server
import (
"net/http"
)
func HandleWebinterface(w http.ResponseWriter, r *http.Request) {
}

View file

@ -0,0 +1,61 @@
package server
import (
"bytes"
"context"
"fmt"
"net/http"
"runtime/debug"
"time"
"golang.org/x/exp/slog"
"nfsense.net/nfsense/internal/session"
"nhooyr.io/websocket"
)
func HandleWebsocketAPI(w http.ResponseWriter, r *http.Request) {
_, s := session.GetSession(r)
if s == nil {
w.WriteHeader(http.StatusUnauthorized)
return
}
ctx, cancel := context.WithCancel(context.WithValue(r.Context(), session.SessionKey, s))
defer cancel()
c, err := websocket.Accept(w, r, nil)
if err != nil {
slog.Error("Accepting Websocket Connection", err)
return
}
defer c.Close(websocket.StatusInternalError, "Unexpected Closing")
slog.Info("Accepted API Websocket Connection")
for {
_, m, err := c.Read(ctx)
if websocket.CloseStatus(err) == websocket.StatusNormalClosure {
slog.Info("API Websocket Closed Normally")
cancel()
return
} else if err != nil {
slog.Error("API Websocket Closed Unexpectedly", err)
cancel()
}
go func() {
defer func() {
if r := recover(); r != nil {
slog.Error("Recovered Panic Handling Websocket API Request", fmt.Errorf("%v", r), "stack", debug.Stack())
return
}
}()
ctx, cancel := context.WithTimeout(ctx, time.Second*10)
defer cancel()
err := apiHandler.HandleRequest(ctx, s, bytes.NewReader(m), w)
if err != nil {
slog.Error("Handling Websocket API Request", err)
}
}()
}
}