mirror of
https://github.com/1f349/gomvn.git
synced 2024-12-21 23:44:07 +00:00
Use custom dirlist
This commit is contained in:
parent
aa32eec589
commit
d7b6f38f40
1
go.mod
1
go.mod
@ -4,6 +4,7 @@ go 1.22
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/MrMelon54/exit-reload v0.0.1
|
github.com/MrMelon54/exit-reload v0.0.1
|
||||||
|
github.com/dustin/go-humanize v1.0.1
|
||||||
github.com/golang-migrate/migrate/v4 v4.17.0
|
github.com/golang-migrate/migrate/v4 v4.17.0
|
||||||
github.com/julienschmidt/httprouter v1.3.0
|
github.com/julienschmidt/httprouter v1.3.0
|
||||||
github.com/thanhpk/randstr v1.0.6
|
github.com/thanhpk/randstr v1.0.6
|
||||||
|
2
go.sum
2
go.sum
@ -2,6 +2,8 @@ github.com/MrMelon54/exit-reload v0.0.1 h1:sxHa59tNEQMcikwuX2+93lw6Vi1+R7oCRF8a0
|
|||||||
github.com/MrMelon54/exit-reload v0.0.1/go.mod h1:PLiSfmUzwdpTTQP3BBfUPhkqPwaIZjx0DuXBnM76Bug=
|
github.com/MrMelon54/exit-reload v0.0.1/go.mod h1:PLiSfmUzwdpTTQP3BBfUPhkqPwaIZjx0DuXBnM76Bug=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/golang-migrate/migrate/v4 v4.17.0 h1:rd40H3QXU0AA4IoLllFcEAEo9dYKRHYND2gB4p7xcaU=
|
github.com/golang-migrate/migrate/v4 v4.17.0 h1:rd40H3QXU0AA4IoLllFcEAEo9dYKRHYND2gB4p7xcaU=
|
||||||
github.com/golang-migrate/migrate/v4 v4.17.0/go.mod h1:+Cp2mtLP4/aXDTKb9wmXYitdrNx2HGs45rbWAo6OsKM=
|
github.com/golang-migrate/migrate/v4 v4.17.0/go.mod h1:+Cp2mtLP4/aXDTKb9wmXYitdrNx2HGs45rbWAo6OsKM=
|
||||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
126
routes/dirlist.go
Normal file
126
routes/dirlist.go
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
package routes
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"github.com/dustin/go-humanize"
|
||||||
|
"github.com/julienschmidt/httprouter"
|
||||||
|
"html/template"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed dirlist.go.html
|
||||||
|
var dirListHtml string
|
||||||
|
|
||||||
|
var dirListTemplate = template.Must(template.New("dirlist").Parse(dirListHtml))
|
||||||
|
|
||||||
|
func (r *routeCtx) handleFiles(rw http.ResponseWriter, req *http.Request, _ httprouter.Params) {
|
||||||
|
if containsDotDot(req.URL.Path) {
|
||||||
|
http.Error(rw, "invalid URL path", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(req.URL.Path, "/") {
|
||||||
|
r.handleDirList(rw, req)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
open, err := os.Open(filepath.Join(r.basePath, req.URL.Path))
|
||||||
|
if err != nil {
|
||||||
|
http.Error(rw, "404 Not Found", http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
stat, err := open.Stat()
|
||||||
|
if err != nil {
|
||||||
|
http.Error(rw, "500 Internal Server Error: Failed to stat file", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
http.ServeContent(rw, req, open.Name(), stat.ModTime(), open)
|
||||||
|
}
|
||||||
|
|
||||||
|
type fileInfo struct {
|
||||||
|
Name string
|
||||||
|
URL string
|
||||||
|
Size string
|
||||||
|
ModTime string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *routeCtx) handleDirList(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
openDir, err := os.ReadDir(filepath.Join(r.basePath, req.URL.Path))
|
||||||
|
if err != nil {
|
||||||
|
http.Error(rw, "404 Not Found", http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fileInfos := make([]*fileInfo, len(openDir))
|
||||||
|
for i := range openDir {
|
||||||
|
info, err := openDir[i].Info()
|
||||||
|
if err != nil {
|
||||||
|
http.Error(rw, "500 Internal Server Error: Failed to stat file", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
url := path.Join(req.URL.Path, info.Name())
|
||||||
|
name := path.Base(url)
|
||||||
|
size := ""
|
||||||
|
if info.IsDir() {
|
||||||
|
url += "/"
|
||||||
|
name += "/"
|
||||||
|
} else {
|
||||||
|
size = humanize.IBytes(uint64(info.Size()))
|
||||||
|
}
|
||||||
|
fileInfos[i] = &fileInfo{
|
||||||
|
Name: name,
|
||||||
|
URL: url,
|
||||||
|
Size: size,
|
||||||
|
ModTime: info.ModTime().Format("2006-01-02 15:04:05 -0700"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = dirListTemplate.Execute(rw, map[string]any{
|
||||||
|
"Name": r.name,
|
||||||
|
"Path": req.URL.Path,
|
||||||
|
"Files": fileInfos,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Println("[GoMVN] Index template error: ", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *routeCtx) handlePut(rw http.ResponseWriter, req *http.Request, _ httprouter.Params) {
|
||||||
|
p, err := r.pathUtils.ParsePath(req)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(rw, "404 Not Found", http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p = filepath.Join(r.basePath, p)
|
||||||
|
err = os.MkdirAll(filepath.Dir(p), os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(rw, "500 Failed to create directory", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
create, err := os.Create(p)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(rw, "500 Failed to open file", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = io.Copy(create, req.Body)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(rw, "500 Failed to write file", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func containsDotDot(v string) bool {
|
||||||
|
if !strings.Contains(v, "..") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, ent := range strings.FieldsFunc(v, isSlashRune) {
|
||||||
|
if ent == ".." {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isSlashRune(r rune) bool { return r == '/' || r == '\\' }
|
41
routes/dirlist.go.html
Normal file
41
routes/dirlist.go.html
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>{{ .Name }} - {{ .Path }}</title>
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
font-size: 13px;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr.header {
|
||||||
|
border-bottom-color: #3a3e41;
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr td {
|
||||||
|
padding-inline: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>{{.Name}}</h1>
|
||||||
|
<table>
|
||||||
|
<tr class="header">
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Last Modified</th>
|
||||||
|
<th>Size</th>
|
||||||
|
</tr>
|
||||||
|
{{range .Files}}
|
||||||
|
<tr>
|
||||||
|
<td class="bold"><a href="{{ .URL }}">{{ .Name }}</a></td>
|
||||||
|
<td>{{ .ModTime }}</td>
|
||||||
|
<td>{{ .Size }}</td>
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,22 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>GoMVN - {{.Name}}</title>
|
|
||||||
<style>
|
|
||||||
.dir {
|
|
||||||
font-weight: bold;
|
|
||||||
font-family: monospace;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>{{.Name}}</h1>
|
|
||||||
{{range $k, $v := .Repositories}}
|
|
||||||
<ul>
|
|
||||||
{{range $v}}
|
|
||||||
<li><a href="{{ $k }}/{{ .GetPath }}" class="dir">{{ .MvnGroup }}:{{ .Artifact }}:{{ .Version }}</a>, last modified {{ .Modified }}</li>
|
|
||||||
{{end}}
|
|
||||||
</ul>
|
|
||||||
{{end}}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -7,13 +7,8 @@ import (
|
|||||||
"github.com/1f349/gomvn/paths"
|
"github.com/1f349/gomvn/paths"
|
||||||
"github.com/julienschmidt/httprouter"
|
"github.com/julienschmidt/httprouter"
|
||||||
"github.com/thanhpk/randstr"
|
"github.com/thanhpk/randstr"
|
||||||
"html/template"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type routeCtx struct {
|
type routeCtx struct {
|
||||||
@ -63,9 +58,9 @@ func Router(db *database.Queries, name, basePath string, repository []string) ht
|
|||||||
|
|
||||||
rWeb := httprouter.New()
|
rWeb := httprouter.New()
|
||||||
rWeb.PUT("/*filepath", base.repoAuth(base.handlePut))
|
rWeb.PUT("/*filepath", base.repoAuth(base.handlePut))
|
||||||
rWeb.GET("/", base.handleIndex)
|
rWeb.GET("/", base.handleFiles)
|
||||||
for _, repo := range repository {
|
for _, repo := range repository {
|
||||||
rWeb.ServeFiles(path.Join("/", repo, "*filepath"), http.FS(os.DirFS(filepath.Join(basePath, repo))))
|
rWeb.GET(path.Join("/", repo, "*filepath"), base.handleFiles)
|
||||||
}
|
}
|
||||||
|
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
@ -85,47 +80,3 @@ func Router(db *database.Queries, name, basePath string, repository []string) ht
|
|||||||
|
|
||||||
return mux
|
return mux
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:embed index.go.html
|
|
||||||
var indexHtml string
|
|
||||||
|
|
||||||
var indexTemplate = template.Must(template.New("index").Parse(indexHtml))
|
|
||||||
|
|
||||||
func (r *routeCtx) handleIndex(rw http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
|
|
||||||
repositories, err := paths.GetRepositories(r.basePath, r.repository)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(rw, "500 Internal Server Error", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = indexTemplate.Execute(rw, map[string]any{
|
|
||||||
"Name": r.name,
|
|
||||||
"Repositories": repositories,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Println("[GoMVN] Index template error: ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *routeCtx) handlePut(rw http.ResponseWriter, req *http.Request, params httprouter.Params) {
|
|
||||||
p, err := r.pathUtils.ParsePath(req)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(rw, "404 Not Found", http.StatusNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p = filepath.Join(r.basePath, p)
|
|
||||||
err = os.MkdirAll(filepath.Dir(p), os.ModePerm)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(rw, "500 Failed to create directory", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
create, err := os.Create(p)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(rw, "500 Failed to open file", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = io.Copy(create, req.Body)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(rw, "500 Failed to write file", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user