fix windows ci (#934)

* fix windows ci

* perm

* use custom writer

* remove patches

* fuck codeql
This commit is contained in:
UUBulb 2025-01-01 00:58:57 +08:00 committed by GitHub
parent 7662471c2f
commit 3c72d6ce64
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 29 additions and 131 deletions

View File

@ -50,11 +50,6 @@ jobs:
with: with:
go-version: "1.23.1" go-version: "1.23.1"
- name: patch net/http/fs.go
run: |
patch -p0 --forward `go env GOROOT`/src/net/http/fs.go < ./script/patch/fs.patch || true
patch -p0 --forward `go env GOMODCACHE`/github.com/gin-gonic/gin@v1.10.0/context.go < ./script/patch/gin-context.patch || true
- name: generate swagger docs - name: generate swagger docs
run: | run: |
go install github.com/swaggo/swag/cmd/swag@latest go install github.com/swaggo/swag/cmd/swag@latest

View File

@ -18,36 +18,31 @@ jobs:
fail-fast: true fail-fast: true
matrix: matrix:
os: [ubuntu, windows, macos] os: [ubuntu, windows, macos]
runs-on: ${{ matrix.os }}-latest runs-on: ${{ matrix.os }}-latest
env: env:
GO111MODULE: on GO111MODULE: on
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-go@v5 - uses: actions/setup-go@v5
with: with:
go-version: "1.23.1" go-version: "1.23.1"
- name: patch net/http/fs.go
run: |
patch -p0 --forward `go env GOROOT`/src/net/http/fs.go < ./script/patch/fs.patch || true
patch -p0 --forward `go env GOMODCACHE`/github.com/gin-gonic/gin@v1.10.0/context.go < ./script/patch/gin-context.patch || true
- name: generate swagger docs - name: generate swagger docs
run: | run: |
go install github.com/swaggo/swag/cmd/swag@latest go install github.com/swaggo/swag/cmd/swag@latest
touch ./cmd/dashboard/user-dist/a touch ./cmd/dashboard/user-dist/a
touch ./cmd/dashboard/admin-dist/a touch ./cmd/dashboard/admin-dist/a
swag init --pd -d . -g ./cmd/dashboard/main.go -o ./cmd/dashboard/docs --parseGoList=false swag init --pd -d . -g ./cmd/dashboard/main.go -o ./cmd/dashboard/docs --parseGoList=false
- name: Unit test - name: Unit test
run: | run: |
go test -v ./... go test -v ./...
- name: Build test - name: Build test
run: go build -v ./cmd/dashboard run: go build -v ./cmd/dashboard
- name: Run Gosec Security Scanner - name: Run Gosec Security Scanner
if: runner.os == 'Linux' if: runner.os == 'Linux'
uses: securego/gosec@master uses: securego/gosec@master

View File

@ -285,10 +285,31 @@ func getUid(c *gin.Context) uint64 {
return user.ID return user.ID
} }
type ginCustomWriter struct {
gin.ResponseWriter
customCode int
}
func newCustomWriter(c *gin.Context, code int) *ginCustomWriter {
return &ginCustomWriter{
ResponseWriter: c.Writer,
customCode: code,
}
}
func (w *ginCustomWriter) WriteHeader(code int) {
w.ResponseWriter.WriteHeader(w.customCode)
}
func fileWithCustomStatusCode(c *gin.Context, filepath string, customCode int) {
http.ServeFile(newCustomWriter(c, customCode), c.Request, path.Clean(filepath))
}
func fallbackToFrontend(frontendDist fs.FS) func(*gin.Context) { func fallbackToFrontend(frontendDist fs.FS) func(*gin.Context) {
checkLocalFileOrFs := func(c *gin.Context, fs fs.FS, path string, customStatusCode int) bool { checkLocalFileOrFs := func(c *gin.Context, fs fs.FS, path string, customStatusCode int) bool {
if _, err := os.Stat(path); err == nil { if _, err := os.Stat(path); err == nil {
c.FileWithCustomStatusCode(path, customStatusCode) fileWithCustomStatusCode(c, path, customStatusCode)
return true return true
} }
f, err := fs.Open(path) f, err := fs.Open(path)
@ -303,7 +324,7 @@ func fallbackToFrontend(frontendDist fs.FS) func(*gin.Context) {
if fileStat.IsDir() { if fileStat.IsDir() {
return false return false
} }
http.ServeContentCustomStatusCode(c.Writer, c.Request, path, fileStat.ModTime(), f.(io.ReadSeeker), customStatusCode) http.ServeContent(newCustomWriter(c, customStatusCode), c.Request, path, fileStat.ModTime(), f.(io.ReadSeeker))
return true return true
} }
return func(c *gin.Context) { return func(c *gin.Context) {
@ -323,7 +344,7 @@ func fallbackToFrontend(frontendDist fs.FS) func(*gin.Context) {
} }
return return
} }
localFilePath := path.Join(singleton.Conf.UserTemplate, c.Request.URL.Path) localFilePath := path.Join(singleton.Conf.UserTemplate, path.Clean(c.Request.URL.Path))
if checkLocalFileOrFs(c, frontendDist, localFilePath, http.StatusOK) { if checkLocalFileOrFs(c, frontendDist, localFilePath, http.StatusOK) {
return return
} }

View File

@ -1,102 +0,0 @@
@@ -249,9 +249,24 @@
}
return size, nil
}
- serveContent(w, req, name, modtime, sizeFunc, content)
+ serveContent(w, req, name, modtime, sizeFunc, content, StatusOK)
}
+func ServeContentCustomStatusCode(w ResponseWriter, req *Request, name string, modtime time.Time, content io.ReadSeeker, code int) {
+ sizeFunc := func() (int64, error) {
+ size, err := content.Seek(0, io.SeekEnd)
+ if err != nil {
+ return 0, errSeeker
+ }
+ _, err = content.Seek(0, io.SeekStart)
+ if err != nil {
+ return 0, errSeeker
+ }
+ return size, nil
+ }
+ serveContent(w, req, name, modtime, sizeFunc, content, code)
+}
+
// errSeeker is returned by ServeContent's sizeFunc when the content
// doesn't seek properly. The underlying Seeker's error text isn't
// included in the sizeFunc reply so it's not sent over HTTP to end
@@ -266,15 +281,13 @@
// if modtime.IsZero(), modtime is unknown.
// content must be seeked to the beginning of the file.
// The sizeFunc is called at most once. Its error, if any, is sent in the HTTP response.
-func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time, sizeFunc func() (int64, error), content io.ReadSeeker) {
+func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time, sizeFunc func() (int64, error), content io.ReadSeeker, code int) {
setLastModified(w, modtime)
done, rangeReq := checkPreconditions(w, r, modtime)
if done {
return
}
- code := StatusOK
-
// If Content-Type isn't set, use the file's extension to find it, but
// if the Content-Type is unset explicitly, do not sniff the type.
ctypes, haveType := w.Header()["Content-Type"]
@@ -671,7 +684,7 @@
}
// name is '/'-separated, not filepath.Separator.
-func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirect bool) {
+func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirect bool, statusCode int) {
const indexPage = "/index.html"
// redirect .../index.html to .../
@@ -753,7 +766,7 @@
// serveContent will check modification time
sizeFunc := func() (int64, error) { return d.Size(), nil }
- serveContent(w, r, d.Name(), d.ModTime(), sizeFunc, f)
+ serveContent(w, r, d.Name(), d.ModTime(), sizeFunc, f, statusCode)
}
// toHTTPError returns a non-specific HTTP error message and status code
@@ -814,7 +827,21 @@
return
}
dir, file := filepath.Split(name)
- serveFile(w, r, Dir(dir), file, false)
+ serveFile(w, r, Dir(dir), file, false, StatusOK)
+}
+
+func ServeFileWithCustomStatusCode(w ResponseWriter, r *Request, name string, statusCode int) {
+ if containsDotDot(r.URL.Path) {
+ // Too many programs use r.URL.Path to construct the argument to
+ // serveFile. Reject the request under the assumption that happened
+ // here and ".." may not be wanted.
+ // Note that name might not contain "..", for example if code (still
+ // incorrectly) used filepath.Join(myDir, r.URL.Path).
+ serveError(w, "invalid URL path", StatusBadRequest)
+ return
+ }
+ dir, file := filepath.Split(name)
+ serveFile(w, r, Dir(dir), file, false, statusCode)
}
// ServeFileFS replies to the request with the contents
@@ -847,7 +874,7 @@
serveError(w, "invalid URL path", StatusBadRequest)
return
}
- serveFile(w, r, FS(fsys), name, false)
+ serveFile(w, r, FS(fsys), name, false, StatusOK)
}
func containsDotDot(v string) bool {
@@ -983,7 +1010,7 @@
upath = "/" + upath
r.URL.Path = upath
}
- serveFile(w, r, f.root, path.Clean(upath), true)
+ serveFile(w, r, f.root, path.Clean(upath), true, StatusOK)
}
// httpRange specifies the byte range to be sent to the client.

View File

@ -1,11 +0,0 @@
@@ -1073,6 +1073,10 @@
// File writes the specified file into the body stream in an efficient way.
func (c *Context) File(filepath string) {
http.ServeFile(c.Writer, c.Request, filepath)
+}
+
+func (c *Context) FileWithCustomStatusCode(filepath string, statusCode int) {
+ http.ServeFileWithCustomStatusCode(c.Writer, c.Request, filepath, statusCode)
}
// FileFromFS writes the specified file from http.FileSystem into the body stream in an efficient way.