mirror of
https://github.com/nezhahq/nezha.git
synced 2025-01-22 12:48:14 -05:00
fix windows ci (#934)
* fix windows ci * perm * use custom writer * remove patches * fuck codeql
This commit is contained in:
parent
7662471c2f
commit
3c72d6ce64
5
.github/workflows/release.yml
vendored
5
.github/workflows/release.yml
vendored
@ -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
|
||||||
|
15
.github/workflows/test.yml
vendored
15
.github/workflows/test.yml
vendored
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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.
|
|
@ -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.
|
|
Loading…
Reference in New Issue
Block a user