精简后的项目:仅保留 api/ui 源码、文档、构建依赖

This commit is contained in:
gallery
2026-09-11 16:11:09 +08:00
commit 490e85634e
457 changed files with 86862 additions and 0 deletions
+55
View File
@@ -0,0 +1,55 @@
package server
import (
"net/http"
"net/url"
"strings"
"github.com/gorilla/mux"
"github.com/photoview/photoview/api/utils"
)
func CORSMiddleware(devMode bool) mux.MiddlewareFunc {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
var uiEndpoint *url.URL = nil
if devMode {
// Development environment
w.Header().Set("Access-Control-Allow-Origin", req.Header.Get("origin"))
w.Header().Set("Vary", "Origin")
} else {
// Production environment
uiEndpoint = utils.UiEndpointUrl()
if uiEndpoint != nil {
// Only allow CORS if UI endpoint is defined
w.Header().Set("Access-Control-Allow-Origin", uiEndpoint.Scheme+"://"+uiEndpoint.Host)
}
}
w = handleCORS(devMode, uiEndpoint, w)
if req.Method != http.MethodOptions {
next.ServeHTTP(w, req)
} else {
w.WriteHeader(200)
}
})
}
}
func handleCORS(devMode bool, uiEndpoint *url.URL, w http.ResponseWriter) http.ResponseWriter {
corsEnabled := devMode || uiEndpoint != nil
if corsEnabled {
methods := []string{http.MethodGet, http.MethodPost, http.MethodOptions}
requestHeaders := []string{"authorization", "content-type", "content-length", "TokenPassword"}
responseHeaders := []string{"content-length"}
w.Header().Set("Access-Control-Allow-Methods", strings.Join(methods, ", "))
w.Header().Set("Access-Control-Allow-Headers", strings.Join(requestHeaders, ", "))
w.Header().Set("Access-Control-Allow-Credentials", "true")
w.Header().Set("Access-Control-Expose-Headers", strings.Join(responseHeaders, ", "))
}
return w
}
+98
View File
@@ -0,0 +1,98 @@
package server
import (
"bufio"
"errors"
"fmt"
"net"
"net/http"
"time"
"github.com/photoview/photoview/api/graphql/auth"
"github.com/wsxiaoys/terminal/color"
)
func LoggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
statusWriter := newStatusResponseWriter(&w)
next.ServeHTTP(statusWriter, r)
elapsed := time.Since(start)
date := time.Now().Format("2006/01/02 15:04:05")
status := statusWriter.status
var statusColor string
switch {
case status < 200:
statusColor = color.Colorize("b")
case status < 300:
statusColor = color.Colorize("g")
case status < 400:
statusColor = color.Colorize("c")
case status < 500:
statusColor = color.Colorize("y")
default:
statusColor = color.Colorize("r")
}
method := r.Method
var methodColor string
switch {
case method == http.MethodGet:
methodColor = color.Colorize("b")
case method == http.MethodPost:
methodColor = color.Colorize("g")
case method == http.MethodOptions:
methodColor = color.Colorize("y")
default:
methodColor = color.Colorize("r")
}
user := auth.UserFromContext(r.Context())
userText := "unauthenticated"
if user != nil {
userText = color.Sprintf("@ruser: %s", user.Username)
}
statusText := color.Sprintf("%s%s %s%d", methodColor, r.Method, statusColor, status)
requestText := fmt.Sprintf("%s%s", r.Host, r.URL.Path)
durationText := color.Sprintf("@c%s", elapsed)
fmt.Printf("%s %s %s %s %s\n", date, statusText, requestText, durationText, userText)
})
}
type statusResponseWriter struct {
http.ResponseWriter
status int
hijacker http.Hijacker
}
func newStatusResponseWriter(w *http.ResponseWriter) *statusResponseWriter {
return &statusResponseWriter{
ResponseWriter: *w,
hijacker: (*w).(http.Hijacker),
}
}
func (w *statusResponseWriter) WriteHeader(status int) {
w.status = status
w.ResponseWriter.WriteHeader(status)
}
func (w *statusResponseWriter) Write(b []byte) (int, error) {
if w.status == 0 {
w.status = 200
}
return w.ResponseWriter.Write(b)
}
func (w *statusResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
if w.hijacker == nil {
return nil, nil, errors.New("http.Hijacker not implemented by underlying http.ResponseWriter")
}
return w.hijacker.Hijack()
}
+47
View File
@@ -0,0 +1,47 @@
package server
import (
"log"
"net/http"
"net/url"
"github.com/gorilla/websocket"
"github.com/photoview/photoview/api/utils"
)
func WebsocketUpgrader(devMode bool) websocket.Upgrader {
return websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
if devMode {
return true
} else {
uiEndpoint := utils.UiEndpointUrl()
if uiEndpoint == nil {
return true
}
if r.Header.Get("origin") == "" {
return true
}
originURL, err := url.Parse(r.Header.Get("origin"))
if err != nil {
log.Printf("Could not parse origin header of websocket request: %s", err)
return false
}
return isUIOnSameHost(uiEndpoint, originURL)
}
},
}
}
func isUIOnSameHost(uiEndpoint *url.URL, originURL *url.URL) bool {
if uiEndpoint.Host == originURL.Host {
return true
} else {
log.Printf("Not allowing websocket request from %s because it doesn't match PHOTOVIEW_UI_ENDPOINT %s",
originURL.Host, uiEndpoint.Host)
return false
}
}