mirror of
https://github.com/1f349/gomvn.git
synced 2024-12-21 15:34:05 +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 (
|
||||
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/julienschmidt/httprouter v1.3.0
|
||||
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/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/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/go.mod h1:+Cp2mtLP4/aXDTKb9wmXYitdrNx2HGs45rbWAo6OsKM=
|
||||
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/julienschmidt/httprouter"
|
||||
"github.com/thanhpk/randstr"
|
||||
"html/template"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type routeCtx struct {
|
||||
@ -63,9 +58,9 @@ func Router(db *database.Queries, name, basePath string, repository []string) ht
|
||||
|
||||
rWeb := httprouter.New()
|
||||
rWeb.PUT("/*filepath", base.repoAuth(base.handlePut))
|
||||
rWeb.GET("/", base.handleIndex)
|
||||
rWeb.GET("/", base.handleFiles)
|
||||
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()
|
||||
@ -85,47 +80,3 @@ func Router(db *database.Queries, name, basePath string, repository []string) ht
|
||||
|
||||
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