gitea-pages/main.go
2024-10-30 22:20:03 +03:00

208 lines
5.0 KiB
Go

package main
import (
"embed"
"encoding/json"
"fmt"
"html/template"
"io"
"mime"
"net/http"
"os"
"path/filepath"
"strings"
"github.com/gin-gonic/gin"
"github.com/joho/godotenv"
)
//go:embed pages
var embeddedFiles embed.FS
type transport struct {
apiKey string
underlyingTransport http.RoundTripper
}
func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
if t.apiKey != "" {
req.Header.Add("Authorization", "token "+t.apiKey)
}
return t.underlyingTransport.RoundTrip(req)
}
func main() {
godotenv.Load()
// if os.Args[len(os.Args)-1] == "gencrt" {
// GenCerts()
// os.Exit(0)
// }
// if _, err := os.Stat("./certs/cert.crt"); err != nil {
// fmt.Println("Not found cert file")
// GenCerts()
// }
// if _, err := os.Stat("./certs/priv.key"); err != nil {
// fmt.Println("Not fount cert key file")
// GenCerts()
// }
//certFile, _ := os.ReadFile("./certs/cert.crt")
//block, _ := pem.Decode(certFile)
//if block == nil {
// fmt.Println("invalid certificate")
// GenCerts()
// }
// cert, _ := x509.ParseCertificate(block.Bytes)
// certExpired := time.Now().After(cert.NotAfter)
// if certExpired {
// GenCerts()
// }
rootDomain, exists := os.LookupEnv("ROOT_DOMAIN")
if !exists {
rootDomain = "localhost"
}
giteaUrl, exists := os.LookupEnv("GITEA_URL")
if !exists {
giteaUrl = "https://codeberg.org"
}
defaultRef, exists := os.LookupEnv("DEFAULT_REF")
if !exists {
defaultRef = "pages"
}
indexFile, exists := os.LookupEnv("INDEX_FILE")
if !exists {
indexFile = "index.html"
}
directoryIndexStr := os.Getenv("DIRECTORY_INDEX")
fmt.Println(rootDomain, giteaUrl)
directoryIndex := false
if directoryIndexStr == "true" {
directoryIndex = true
}
defaultUser := os.Getenv("DEFAULT_USER")
servePort, exists := os.LookupEnv("SERVE_PORT")
if !exists {
servePort = "8080"
}
giteaToken := os.Getenv("GITEA_TOKEN")
gitea := http.Client{Transport: &transport{underlyingTransport: http.DefaultTransport, apiKey: giteaToken}}
r := gin.Default()
templ := template.Must(template.New("").ParseFS(embeddedFiles, "pages/*"))
r.SetHTMLTemplate(templ)
r.GET("/*path", func(ctx *gin.Context) {
path := ctx.Params.ByName("path")
rawHost := ctx.Request.Host
if !strings.HasSuffix(rawHost, rootDomain) {
ctx.HTML(404, "error.html", gin.H{
"error_code": "400",
"error_message": "invalid root domain",
})
return
}
hostPrefix := strings.TrimSuffix(rawHost, rootDomain)
host := strings.Split(hostPrefix, ".")
var owner string
switch len(host) - 1 {
case 0:
ctx.HTML(200, "index.html", gin.H{
"root_domain": rootDomain,
})
return
case 2:
owner = host[1]
case 1:
if defaultUser == "" {
goto godefault
}
owner = defaultUser
break
godefault:
fallthrough
default:
ctx.HTML(400, "index.html", gin.H{
"root_domain": rootDomain,
})
return
}
repo := host[0]
contentPath := giteaUrl + "/api/v1/repos/" + owner + "/" + repo + "/contents/" + path + "?ref=" + defaultRef
apiPath := giteaUrl + "/api/v1/repos/" + owner + "/" + repo + "/raw" + path
resp, err := gitea.Get(apiPath + "?ref=" + defaultRef)
if err != nil {
ctx.AbortWithError(500, err)
}
body, _ := io.ReadAll(resp.Body)
var message struct {
Message string
}
if resp.StatusCode == 200 {
// if file found
ct := mime.TypeByExtension(filepath.Ext(path))
ctx.Data(200, ct, body)
} else {
// if file not found, and get err message
json.Unmarshal(body, &message)
if message.Message != "getBlobForEntry" && path != "/" {
ctx.HTML(404, "error.html", gin.H{
"error_code": "404",
"error_message": "file not found",
})
return
}
// check is index file (from env) exists
indexPath := apiPath + "/" + indexFile + "?ref=" + defaultRef
resp, _ := gitea.Get(indexPath)
if resp.StatusCode == 200 {
// index file exist
body, _ := io.ReadAll(resp.Body)
ctx.Data(200, "text/html", body)
return
} else {
// else this is directory
resp, _ := gitea.Get(contentPath)
body, _ := io.ReadAll(resp.Body)
var dir []struct {
Name string
Path string
}
json.Unmarshal(body, &dir)
if len(dir) == 0 {
// zero files, empty or non-existent repo
ctx.HTML(404, "error.html", gin.H{
"error_code": "404",
"error_message": "pages for repository not found",
})
return
}
if !directoryIndex {
// if directory index disabled
ctx.HTML(401, "error.html", gin.H{
"error_code": "401",
"error_message": "directory index disabled",
})
return
}
var html string
html += "<h1>Index of " + path + "</h1>"
html += "<a href=\"" + filepath.Dir(path) + "\">Parrent directory</a><br/>"
for _, file := range dir {
html += "<a href=\"/" + file.Path + "\">" + file.Name + "</a><br/>"
}
ctx.Data(200, "text/html", []byte(html))
return
}
}
//ctx.JSON(200, gin.H{"host": host, "path": path})
})
r.Run(":" + servePort)
}