feat: complete 2.0.7.12 platform overhaul
This commit is contained in:
@@ -2,12 +2,31 @@ package web
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func withSecurity(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
defer func() {
|
||||
if recovered := recover(); recovered != nil {
|
||||
if recovered == http.ErrAbortHandler {
|
||||
panic(recovered)
|
||||
}
|
||||
log.Printf("recovered request panic method=%s path=%s error=%v\n%s", r.Method, r.URL.Path, recovered, debug.Stack())
|
||||
w.Header().Set("Cache-Control", "no-store")
|
||||
if strings.HasPrefix(cleanPath(r.URL.Path), "/api/") {
|
||||
writeError(w, http.StatusInternalServerError, "INTERNAL_SERVER_ERROR", fmt.Errorf("request failed unexpectedly"))
|
||||
return
|
||||
}
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
}
|
||||
}()
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.Header().Set("Referrer-Policy", "same-origin")
|
||||
next.ServeHTTP(w, r)
|
||||
@@ -77,6 +96,7 @@ func localizedErrorMessage(code, message string) string {
|
||||
return translated
|
||||
}
|
||||
byCode := map[string]string{
|
||||
"INTERNAL_SERVER_ERROR": "服务端处理请求时发生异常,请稍后重试并检查服务日志",
|
||||
"UNAUTHORIZED": "需要登录后继续操作",
|
||||
"LOGIN_FAILED": "登录失败,请检查密码和验证码",
|
||||
"LOGIN_LOCKED": "登录失败次数过多,请 5 分钟后重试",
|
||||
@@ -98,6 +118,9 @@ func localizedErrorMessage(code, message string) string {
|
||||
"PACKAGE_UPLOAD_FAILED": "发布包上传失败",
|
||||
"PACKAGE_EMPTY": "发布包不能为空",
|
||||
"PACKAGE_TOO_LARGE": "发布包超过服务端上传上限",
|
||||
"PACKAGE_INDEX_FAILED": "发布包已回滚,数据库索引更新失败",
|
||||
"PACKAGE_TYPE_UNSUPPORTED": "仅支持 EXE、MSIX、APPINSTALLER、MSI、ZIP 或 7Z 发布包",
|
||||
"PACKAGE_NAME_INVALID": "发布包文件名不合法",
|
||||
"UPLOAD_STORAGE_FAILED": "服务端无法保存上传文件",
|
||||
"MANIFEST_UPDATE_FAILED": "发布包已回滚,更新清单写入失败",
|
||||
"UPLOAD_INTERRUPTED": "上传连接已中断,请重新上传",
|
||||
@@ -163,20 +186,45 @@ func cleanPath(path string) string {
|
||||
}
|
||||
|
||||
func requestBaseURL(r *http.Request, fallback string) string {
|
||||
scheme := r.Header.Get("X-Forwarded-Proto")
|
||||
if scheme == "" {
|
||||
scheme := firstForwardedHeader(r.Header.Get("X-Forwarded-Proto"))
|
||||
if scheme != "http" && scheme != "https" {
|
||||
if r.TLS != nil {
|
||||
scheme = "https"
|
||||
} else {
|
||||
scheme = "http"
|
||||
}
|
||||
}
|
||||
if r.Host != "" {
|
||||
return scheme + "://" + r.Host
|
||||
host := firstForwardedHeader(r.Header.Get("X-Forwarded-Host"))
|
||||
if !validForwardedHost(host) {
|
||||
host = strings.TrimSpace(r.Host)
|
||||
}
|
||||
if validForwardedHost(host) {
|
||||
return scheme + "://" + host
|
||||
}
|
||||
return strings.TrimRight(fallback, "/")
|
||||
}
|
||||
|
||||
func firstForwardedHeader(value string) string {
|
||||
return strings.ToLower(strings.TrimSpace(strings.Split(value, ",")[0]))
|
||||
}
|
||||
|
||||
func validForwardedHost(value string) bool {
|
||||
if value == "" || strings.TrimSpace(value) != value || strings.ContainsAny(value, "\\\\\r\n\t ") {
|
||||
return false
|
||||
}
|
||||
parsed, err := url.Parse("http://" + value)
|
||||
if err != nil || parsed.Host != value || parsed.User != nil || parsed.Hostname() == "" || parsed.Path != "" || parsed.RawQuery != "" || parsed.Fragment != "" {
|
||||
return false
|
||||
}
|
||||
if port := parsed.Port(); port != "" {
|
||||
value, err := strconv.Atoi(port)
|
||||
if err != nil || value < 1 || value > 65535 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func firstNonEmpty(values ...string) string {
|
||||
for _, value := range values {
|
||||
if strings.TrimSpace(value) != "" {
|
||||
|
||||
Reference in New Issue
Block a user