mirror of
https://codeberg.org/Codeberg/pages-server.git
synced 2024-11-05 14:07:01 +00:00
Merge branch 'main' into std-http
This commit is contained in:
commit
e1c78d6069
17 changed files with 138 additions and 79 deletions
|
@ -26,12 +26,12 @@ pipeline:
|
|||
when:
|
||||
event: [ "pull_request", "push" ]
|
||||
|
||||
build-docker:
|
||||
docker-dryrun:
|
||||
group: compliant
|
||||
image: plugins/kaniko
|
||||
settings:
|
||||
dockerfile: Dockerfile
|
||||
no_push: true
|
||||
repo: Codeberg/pages-server
|
||||
tags: latest
|
||||
when:
|
||||
event: [ "pull_request", "push" ]
|
||||
|
@ -47,14 +47,14 @@ pipeline:
|
|||
event: [ "tag" ]
|
||||
|
||||
test:
|
||||
image: a6543/golang_just
|
||||
group: test
|
||||
image: a6543/golang_just
|
||||
commands:
|
||||
- just test
|
||||
|
||||
integration-tests:
|
||||
image: a6543/golang_just
|
||||
group: test
|
||||
image: a6543/golang_just
|
||||
commands:
|
||||
- just integration
|
||||
environment:
|
||||
|
@ -78,3 +78,31 @@ pipeline:
|
|||
- DRONE_COMMIT_REF=${CI_COMMIT_REF}
|
||||
when:
|
||||
event: [ "tag" ]
|
||||
|
||||
docker-next:
|
||||
image: plugins/kaniko
|
||||
settings:
|
||||
registry: codeberg.org
|
||||
dockerfile: Dockerfile
|
||||
repo: codeberg.org/codeberg/pages-server
|
||||
tags: next
|
||||
username:
|
||||
from_secret: bot_user
|
||||
password:
|
||||
from_secret: bot_token
|
||||
when:
|
||||
event: [ "push" ]
|
||||
|
||||
docker-tag:
|
||||
image: plugins/kaniko
|
||||
settings:
|
||||
registry: codeberg.org
|
||||
dockerfile: Dockerfile
|
||||
repo: codeberg.org/codeberg/pages-server
|
||||
tag: [ latest, "${CI_COMMIT_TAG}" ]
|
||||
username:
|
||||
from_secret: bot_user
|
||||
password:
|
||||
from_secret: bot_token
|
||||
when:
|
||||
event: [ "tag" ]
|
||||
|
|
5
Justfile
5
Justfile
|
@ -6,7 +6,8 @@ dev:
|
|||
export PAGES_DOMAIN=localhost.mock.directory
|
||||
export RAW_DOMAIN=raw.localhost.mock.directory
|
||||
export PORT=4430
|
||||
go run . --verbose
|
||||
export LOG_LEVEL=trace
|
||||
go run .
|
||||
|
||||
build:
|
||||
CGO_ENABLED=0 go build -ldflags '-s -w' -v -o build/codeberg-pages-server ./
|
||||
|
@ -45,4 +46,4 @@ integration:
|
|||
go test -race -tags integration codeberg.org/codeberg/pages/integration/...
|
||||
|
||||
integration-run TEST:
|
||||
go test -race -tags integration -run "^{{TEST}}$" codeberg.org/codeberg/pages/integration/...
|
||||
go test -race -tags integration -run "^{{TEST}}$" codeberg.org/codeberg/pages/integration/...
|
||||
|
|
14
cmd/flags.go
14
cmd/flags.go
|
@ -5,12 +5,6 @@ import (
|
|||
)
|
||||
|
||||
var ServeFlags = []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "verbose",
|
||||
// TODO: Usage
|
||||
EnvVars: []string{"DEBUG"},
|
||||
},
|
||||
|
||||
// MainDomainSuffix specifies the main domain (starting with a dot) for which subdomains shall be served as static
|
||||
// pages, or used for comparison in CNAME lookups. Static pages can be accessed through
|
||||
// https://{owner}.{MainDomain}[/{repo}], with repo defaulting to "pages".
|
||||
|
@ -74,11 +68,19 @@ var ServeFlags = []cli.Flag{
|
|||
Name: "enable-lfs-support",
|
||||
Usage: "enable lfs support, require gitea v1.17.0 as backend",
|
||||
EnvVars: []string{"ENABLE_LFS_SUPPORT"},
|
||||
Value: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "enable-symlink-support",
|
||||
Usage: "follow symlinks if enabled, require gitea v1.18.0 as backend",
|
||||
EnvVars: []string{"ENABLE_SYMLINK_SUPPORT"},
|
||||
Value: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "log-level",
|
||||
Value: "warn",
|
||||
Usage: "specify at which log level should be logged. Possible options: info, warn, error, fatal",
|
||||
EnvVars: []string{"LOG_LEVEL"},
|
||||
},
|
||||
|
||||
// ACME
|
||||
|
|
15
cmd/main.go
15
cmd/main.go
|
@ -7,6 +7,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -36,10 +37,12 @@ var BlacklistedPaths = [][]byte{
|
|||
|
||||
// Serve sets up and starts the web server.
|
||||
func Serve(ctx *cli.Context) error {
|
||||
verbose := ctx.Bool("verbose")
|
||||
if !verbose {
|
||||
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
||||
// Initalize the logger.
|
||||
logLevel, err := zerolog.ParseLevel(ctx.String("log-level"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Logger = zerolog.New(zerolog.ConsoleWriter{Out: os.Stderr}).With().Timestamp().Logger().Level(logLevel)
|
||||
|
||||
giteaRoot := strings.TrimSuffix(ctx.String("gitea-root"), "/")
|
||||
giteaAPIToken := ctx.String("gitea-api-token")
|
||||
|
@ -98,7 +101,7 @@ func Serve(ctx *cli.Context) error {
|
|||
log.Info().Msgf("Listening on https://%s", listeningAddress)
|
||||
listener, err := net.Listen("tcp", listeningAddress)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't create listener: %s", err)
|
||||
return fmt.Errorf("couldn't create listener: %v", err)
|
||||
}
|
||||
|
||||
// TODO: make "key-database.pogreb" set via flag
|
||||
|
@ -131,7 +134,7 @@ func Serve(ctx *cli.Context) error {
|
|||
|
||||
if enableHTTPServer {
|
||||
go func() {
|
||||
log.Info().Timestamp().Msg("Start listening on :80")
|
||||
log.Info().Msg("Start HTTP server listening on :80")
|
||||
err := httpServer.ListenAndServe("[::]:80")
|
||||
if err != nil {
|
||||
log.Panic().Err(err).Msg("Couldn't start HTTP fastServer")
|
||||
|
@ -140,7 +143,7 @@ func Serve(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
// Start the web fastServer
|
||||
log.Info().Timestamp().Msgf("Start listening on %s", listener.Addr())
|
||||
log.Info().Msgf("Start listening on %s", listener.Addr())
|
||||
err = fastServer.Serve(listener)
|
||||
if err != nil {
|
||||
log.Panic().Err(err).Msg("Couldn't start fastServer")
|
||||
|
|
5
go.mod
5
go.mod
|
@ -9,7 +9,7 @@ require (
|
|||
github.com/go-acme/lego/v4 v4.5.3
|
||||
github.com/joho/godotenv v1.4.0
|
||||
github.com/reugn/equalizer v0.0.0-20210216135016-a959c509d7ad
|
||||
github.com/rs/zerolog v1.26.0
|
||||
github.com/rs/zerolog v1.27.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
github.com/valyala/fasthttp v1.31.0
|
||||
|
@ -76,7 +76,8 @@ require (
|
|||
github.com/liquidweb/go-lwApi v0.0.5 // indirect
|
||||
github.com/liquidweb/liquidweb-cli v0.6.9 // indirect
|
||||
github.com/liquidweb/liquidweb-go v1.6.3 // indirect
|
||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/miekg/dns v1.1.43 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
||||
|
|
18
go.sum
18
go.sum
|
@ -97,7 +97,7 @@ github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkE
|
|||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpu/goacmedns v0.1.1 h1:DM3H2NiN2oam7QljgGY5ygy4yDXhK5Z4JUnqaugs2C4=
|
||||
github.com/cpu/goacmedns v0.1.1/go.mod h1:MuaouqEhPAHxsbqjgnck5zeghuwBP1dLnPoobeGqugQ=
|
||||
|
@ -330,12 +330,15 @@ github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc
|
|||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
|
@ -437,8 +440,8 @@ github.com/reugn/equalizer v0.0.0-20210216135016-a959c509d7ad/go.mod h1:h0+DiDRe
|
|||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.26.0 h1:ORM4ibhEZeTeQlCojCK2kPz1ogAY4bGs4tD+SaAdGaE=
|
||||
github.com/rs/zerolog v1.26.0/go.mod h1:yBiM87lvSqX8h0Ww4sdzNSkVYZ8dL2xjZJG1lAuGZEo=
|
||||
github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs=
|
||||
github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
|
@ -519,7 +522,6 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
|
|||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
|
@ -580,7 +582,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
|||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -614,7 +615,6 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
|
@ -680,7 +680,8 @@ golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
|
@ -737,7 +738,6 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK
|
|||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
|
@ -7,17 +7,17 @@ import (
|
|||
"bytes"
|
||||
"crypto/tls"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetRedirect(t *testing.T) {
|
||||
log.Printf("=== TestGetRedirect ===\n")
|
||||
log.Println("=== TestGetRedirect ===")
|
||||
// test custom domain redirect
|
||||
resp, err := getTestHTTPSClient().Get("https://calciumdibromid.localhost.mock.directory:4430")
|
||||
assert.NoError(t, err)
|
||||
|
@ -29,7 +29,7 @@ func TestGetRedirect(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetContent(t *testing.T) {
|
||||
log.Printf("=== TestGetContent ===\n")
|
||||
log.Println("=== TestGetContent ===")
|
||||
// test get image
|
||||
resp, err := getTestHTTPSClient().Get("https://magiclike.localhost.mock.directory:4430/images/827679288a.jpg")
|
||||
assert.NoError(t, err)
|
||||
|
@ -65,7 +65,7 @@ func TestGetContent(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCustomDomain(t *testing.T) {
|
||||
log.Printf("=== TestCustomDomain ===\n")
|
||||
log.Println("=== TestCustomDomain ===")
|
||||
resp, err := getTestHTTPSClient().Get("https://mock-pages.codeberg-test.org:4430/README.md")
|
||||
assert.NoError(t, err)
|
||||
if !assert.EqualValues(t, http.StatusOK, resp.StatusCode) {
|
||||
|
@ -77,7 +77,7 @@ func TestCustomDomain(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetNotFound(t *testing.T) {
|
||||
log.Printf("=== TestGetNotFound ===\n")
|
||||
log.Println("=== TestGetNotFound ===")
|
||||
// test custom not found pages
|
||||
resp, err := getTestHTTPSClient().Get("https://crystal.localhost.mock.directory:4430/pages-404-demo/blah")
|
||||
assert.NoError(t, err)
|
||||
|
|
|
@ -5,25 +5,25 @@ package integration
|
|||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"codeberg.org/codeberg/pages/cmd"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
log.Printf("=== TestMain: START Server ===\n")
|
||||
log.Println("=== TestMain: START Server ===")
|
||||
serverCtx, serverCancel := context.WithCancel(context.Background())
|
||||
if err := startServer(serverCtx); err != nil {
|
||||
log.Fatal().Msgf("could not start server: %v", err)
|
||||
log.Fatalf("could not start server: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
serverCancel()
|
||||
log.Printf("=== TestMain: Server STOPED ===\n")
|
||||
log.Println("=== TestMain: Server STOPED ===")
|
||||
}()
|
||||
|
||||
time.Sleep(10 * time.Second)
|
||||
|
@ -48,7 +48,7 @@ func startServer(ctx context.Context) error {
|
|||
|
||||
go func() {
|
||||
if err := app.RunContext(ctx, args); err != nil {
|
||||
log.Fatal().Msgf("run server error: %v", err)
|
||||
log.Fatalf("run server error: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -229,7 +228,7 @@ func retrieveCertFromDB(sni, mainDomainSuffix []byte, dnsProvider string, acmeUs
|
|||
res.CSR = nil // acme client doesn't like CSR to be set
|
||||
tlsCertificate, err = obtainCert(acmeClient, []string{string(sni)}, res, "", dnsProvider, mainDomainSuffix, acmeUseRateLimits, certDB)
|
||||
if err != nil {
|
||||
log.Printf("Couldn't renew certificate for %s: %s", sni, err)
|
||||
log.Error().Msgf("Couldn't renew certificate for %s: %v", string(sni), err)
|
||||
}
|
||||
})()
|
||||
}
|
||||
|
@ -272,10 +271,10 @@ func obtainCert(acmeClient *lego.Client, domains []string, renew *certificate.Re
|
|||
if acmeUseRateLimits {
|
||||
acmeClientRequestLimit.Take()
|
||||
}
|
||||
log.Printf("Renewing certificate for %v", domains)
|
||||
log.Debug().Msgf("Renewing certificate for: %v", domains)
|
||||
res, err = acmeClient.Certificate.Renew(*renew, true, false, "")
|
||||
if err != nil {
|
||||
log.Printf("Couldn't renew certificate for %v, trying to request a new one: %s", domains, err)
|
||||
log.Error().Err(err).Msgf("Couldn't renew certificate for %v, trying to request a new one", domains)
|
||||
res = nil
|
||||
}
|
||||
}
|
||||
|
@ -290,7 +289,7 @@ func obtainCert(acmeClient *lego.Client, domains []string, renew *certificate.Re
|
|||
acmeClientOrderLimit.Take()
|
||||
acmeClientRequestLimit.Take()
|
||||
}
|
||||
log.Printf("Requesting new certificate for %v", domains)
|
||||
log.Debug().Msgf("Re-requesting new certificate for %v", domains)
|
||||
res, err = acmeClient.Certificate.Obtain(certificate.ObtainRequest{
|
||||
Domains: domains,
|
||||
Bundle: true,
|
||||
|
@ -298,7 +297,7 @@ func obtainCert(acmeClient *lego.Client, domains []string, renew *certificate.Re
|
|||
})
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("Couldn't obtain certificate for %v: %s", domains, err)
|
||||
log.Error().Err(err).Msgf("Couldn't obtain again a certificate or %v", domains)
|
||||
if renew != nil && renew.CertURL != "" {
|
||||
tlsCertificate, err := tls.X509KeyPair(renew.Certificate, renew.PrivateKey)
|
||||
if err == nil && tlsCertificate.Leaf.NotAfter.After(time.Now()) {
|
||||
|
@ -312,7 +311,7 @@ func obtainCert(acmeClient *lego.Client, domains []string, renew *certificate.Re
|
|||
}
|
||||
return mockCert(domains[0], err.Error(), string(mainDomainSuffix), keyDatabase), err
|
||||
}
|
||||
log.Printf("Obtained certificate for %v", domains)
|
||||
log.Debug().Msgf("Obtained certificate for %v", domains)
|
||||
|
||||
if err := keyDatabase.Put(name, res); err != nil {
|
||||
return tls.Certificate{}, err
|
||||
|
@ -329,7 +328,7 @@ func SetupAcmeConfig(acmeAPI, acmeMail, acmeEabHmac, acmeEabKID string, acmeAcce
|
|||
var myAcmeAccount AcmeAccount
|
||||
var myAcmeConfig *lego.Config
|
||||
|
||||
if account, err := ioutil.ReadFile(configFile); err == nil {
|
||||
if account, err := os.ReadFile(configFile); err == nil {
|
||||
if err := json.Unmarshal(account, &myAcmeAccount); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -345,7 +344,7 @@ func SetupAcmeConfig(acmeAPI, acmeMail, acmeEabHmac, acmeEabKID string, acmeAcce
|
|||
_, err := lego.NewClient(myAcmeConfig)
|
||||
if err != nil {
|
||||
// TODO: should we fail hard instead?
|
||||
log.Printf("[ERROR] Can't create ACME client, continuing with mock certs only: %s", err)
|
||||
log.Error().Err(err).Msg("Can't create ACME client, continuing with mock certs only")
|
||||
}
|
||||
return myAcmeConfig, nil
|
||||
} else if !os.IsNotExist(err) {
|
||||
|
@ -366,13 +365,13 @@ func SetupAcmeConfig(acmeAPI, acmeMail, acmeEabHmac, acmeEabKID string, acmeAcce
|
|||
myAcmeConfig.Certificate.KeyType = certcrypto.RSA2048
|
||||
tempClient, err := lego.NewClient(myAcmeConfig)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Can't create ACME client, continuing with mock certs only: %s", err)
|
||||
log.Error().Err(err).Msg("Can't create ACME client, continuing with mock certs only")
|
||||
} else {
|
||||
// accept terms & log in to EAB
|
||||
if acmeEabKID == "" || acmeEabHmac == "" {
|
||||
reg, err := tempClient.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: acmeAcceptTerms})
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Can't register ACME account, continuing with mock certs only: %s", err)
|
||||
log.Error().Err(err).Msg("Can't register ACME account, continuing with mock certs only")
|
||||
} else {
|
||||
myAcmeAccount.Registration = reg
|
||||
}
|
||||
|
@ -383,7 +382,7 @@ func SetupAcmeConfig(acmeAPI, acmeMail, acmeEabHmac, acmeEabKID string, acmeAcce
|
|||
HmacEncoded: acmeEabHmac,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Can't register ACME account, continuing with mock certs only: %s", err)
|
||||
log.Error().Err(err).Msg("Can't register ACME account, continuing with mock certs only")
|
||||
} else {
|
||||
myAcmeAccount.Registration = reg
|
||||
}
|
||||
|
@ -392,12 +391,12 @@ func SetupAcmeConfig(acmeAPI, acmeMail, acmeEabHmac, acmeEabKID string, acmeAcce
|
|||
if myAcmeAccount.Registration != nil {
|
||||
acmeAccountJSON, err := json.Marshal(myAcmeAccount)
|
||||
if err != nil {
|
||||
log.Printf("[FAIL] Error during json.Marshal(myAcmeAccount), waiting for manual restart to avoid rate limits: %s", err)
|
||||
log.Error().Err(err).Msg("json.Marshalfailed, waiting for manual restart to avoid rate limits")
|
||||
select {}
|
||||
}
|
||||
err = ioutil.WriteFile(configFile, acmeAccountJSON, 0o600)
|
||||
err = os.WriteFile(configFile, acmeAccountJSON, 0o600)
|
||||
if err != nil {
|
||||
log.Printf("[FAIL] Error during ioutil.WriteFile(\"acme-account.json\"), waiting for manual restart to avoid rate limits: %s", err)
|
||||
log.Error().Err(err).Msg("os.WriteFile failed, waiting for manual restart to avoid rate limits")
|
||||
select {}
|
||||
}
|
||||
}
|
||||
|
@ -415,38 +414,38 @@ func SetupCertificates(mainDomainSuffix []byte, dnsProvider string, acmeConfig *
|
|||
|
||||
acmeClient, err = lego.NewClient(acmeConfig)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Can't create ACME client, continuing with mock certs only: %s", err)
|
||||
log.Error().Err(err).Msg("Can't create ACME client, continuing with mock certs only")
|
||||
} else {
|
||||
err = acmeClient.Challenge.SetTLSALPN01Provider(AcmeTLSChallengeProvider{challengeCache})
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Can't create TLS-ALPN-01 provider: %s", err)
|
||||
log.Error().Err(err).Msg("Can't create TLS-ALPN-01 provider")
|
||||
}
|
||||
if enableHTTPServer {
|
||||
err = acmeClient.Challenge.SetHTTP01Provider(AcmeHTTPChallengeProvider{challengeCache})
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Can't create HTTP-01 provider: %s", err)
|
||||
log.Error().Err(err).Msg("Can't create HTTP-01 provider")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mainDomainAcmeClient, err = lego.NewClient(acmeConfig)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Can't create ACME client, continuing with mock certs only: %s", err)
|
||||
log.Error().Err(err).Msg("Can't create ACME client, continuing with mock certs only")
|
||||
} else {
|
||||
if dnsProvider == "" {
|
||||
// using mock server, don't use wildcard certs
|
||||
err := mainDomainAcmeClient.Challenge.SetTLSALPN01Provider(AcmeTLSChallengeProvider{challengeCache})
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Can't create TLS-ALPN-01 provider: %s", err)
|
||||
log.Error().Err(err).Msg("Can't create TLS-ALPN-01 provider")
|
||||
}
|
||||
} else {
|
||||
provider, err := dns.NewDNSChallengeProviderByName(dnsProvider)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Can't create DNS Challenge provider: %s", err)
|
||||
log.Error().Err(err).Msg("Can't create DNS Challenge provider")
|
||||
}
|
||||
err = mainDomainAcmeClient.Challenge.SetDNS01Provider(provider)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Can't create DNS-01 provider: %s", err)
|
||||
log.Error().Err(err).Msg("Can't create DNS-01 provider")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -454,7 +453,7 @@ func SetupCertificates(mainDomainSuffix []byte, dnsProvider string, acmeConfig *
|
|||
if mainCertBytes == nil {
|
||||
_, err = obtainCert(mainDomainAcmeClient, []string{"*" + string(mainDomainSuffix), string(mainDomainSuffix[1:])}, nil, "", dnsProvider, mainDomainSuffix, acmeUseRateLimits, certDB)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Couldn't renew main domain certificate, continuing with mock certs only: %s", err)
|
||||
log.Error().Err(err).Msg("Couldn't renew main domain certificate, continuing with mock certs only")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -482,7 +481,7 @@ func MaintainCertDB(ctx context.Context, interval time.Duration, mainDomainSuffi
|
|||
if err != nil || !tlsCertificates[0].NotAfter.After(now) {
|
||||
err := certDB.Delete(string(key))
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Deleting expired certificate for %s failed: %s", string(key), err)
|
||||
log.Error().Err(err).Msgf("Deleting expired certificate for %q failed", string(key))
|
||||
} else {
|
||||
expiredCertCount++
|
||||
}
|
||||
|
@ -490,22 +489,22 @@ func MaintainCertDB(ctx context.Context, interval time.Duration, mainDomainSuffi
|
|||
}
|
||||
key, resBytes, err = keyDatabaseIterator.Next()
|
||||
}
|
||||
log.Printf("[INFO] Removed %d expired certificates from the database", expiredCertCount)
|
||||
log.Debug().Msgf("Removed %d expired certificates from the database", expiredCertCount)
|
||||
|
||||
// compact the database
|
||||
msg, err := certDB.Compact()
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Compacting key database failed: %s", err)
|
||||
log.Error().Err(err).Msg("Compacting key database failed")
|
||||
} else {
|
||||
log.Printf("[INFO] Compacted key database (%s)", msg)
|
||||
log.Debug().Msgf("Compacted key database: %s", msg)
|
||||
}
|
||||
|
||||
// update main cert
|
||||
res, err := certDB.Get(string(mainDomainSuffix))
|
||||
if err != nil {
|
||||
log.Err(err).Msgf("could not get cert for domain '%s'", mainDomainSuffix)
|
||||
log.Error().Msgf("Couldn't get cert for domain %q", mainDomainSuffix)
|
||||
} else if res == nil {
|
||||
log.Error().Msgf("Couldn't renew certificate for main domain: %s", "expected main domain cert to exist, but it's missing - seems like the database is corrupted")
|
||||
log.Error().Msgf("Couldn't renew certificate for main domain %q expected main domain cert to exist, but it's missing - seems like the database is corrupted", string(mainDomainSuffix))
|
||||
} else {
|
||||
tlsCertificates, err := certcrypto.ParsePEMBundle(res.Certificate)
|
||||
|
||||
|
@ -514,7 +513,7 @@ func MaintainCertDB(ctx context.Context, interval time.Duration, mainDomainSuffi
|
|||
go (func() {
|
||||
_, err = obtainCert(mainDomainAcmeClient, []string{"*" + string(mainDomainSuffix), string(mainDomainSuffix[1:])}, res, "", dnsProvider, mainDomainSuffix, acmeUseRateLimits, certDB)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Couldn't renew certificate for main domain: %s", err)
|
||||
log.Error().Err(err).Msg("Couldn't renew certificate for main domain")
|
||||
}
|
||||
})()
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ func (p aDB) sync() {
|
|||
for {
|
||||
err := p.intern.Sync()
|
||||
if err != nil {
|
||||
log.Err(err).Msg("Syncing cert database failed")
|
||||
log.Error().Err(err).Msg("Syncing cert database failed")
|
||||
}
|
||||
select {
|
||||
case <-p.ctx.Done():
|
||||
|
|
|
@ -9,4 +9,5 @@ var ErrorNotFound = errors.New("not found")
|
|||
const (
|
||||
branchTimestampCacheKeyPrefix = "branchTime"
|
||||
defaultBranchCacheKeyPrefix = "defaultBranch"
|
||||
giteaObjectTypeHeader = "X-Gitea-Object-Type"
|
||||
)
|
||||
|
|
|
@ -16,8 +16,7 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
giteaAPIRepos = "/api/v1/repos/"
|
||||
giteaObjectTypeHeader = "X-Gitea-Object-Type"
|
||||
giteaAPIRepos = "/api/v1/repos/"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
|
@ -71,7 +70,10 @@ func (client *Client) ServeRawContent(targetOwner, targetRepo, ref, resource str
|
|||
|
||||
switch resp.StatusCode() {
|
||||
case fasthttp.StatusOK:
|
||||
if client.followSymlinks && string(resp.Header.Peek(giteaObjectTypeHeader)) == "symlink" {
|
||||
objType := string(resp.Header.Peek(giteaObjectTypeHeader))
|
||||
log.Trace().Msgf("server raw content object: %s", objType)
|
||||
if client.followSymlinks && objType == "symlink" {
|
||||
// TODO: limit to 1000 chars if we switched to std
|
||||
linkDest := strings.TrimSpace(string(resp.Body()))
|
||||
log.Debug().Msgf("follow symlink from '%s' to '%s'", resource, linkDest)
|
||||
return client.ServeRawContent(targetOwner, targetRepo, ref, linkDest)
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"time"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"codeberg.org/codeberg/pages/server/cache"
|
||||
)
|
||||
|
@ -25,14 +26,19 @@ type Client struct {
|
|||
|
||||
func NewClient(giteaRoot, giteaAPIToken string, respCache cache.SetGetKey, followSymlinks, supportLFS bool) (*Client, error) {
|
||||
rootURL, err := url.Parse(giteaRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
giteaRoot = strings.Trim(rootURL.String(), "/")
|
||||
|
||||
stdClient := http.Client{Timeout: 10 * time.Second}
|
||||
|
||||
sdk, err := gitea.NewClient(giteaRoot, gitea.SetHTTPClient(&stdClient), gitea.SetToken(giteaAPIToken))
|
||||
return &Client{
|
||||
sdkClient: sdk,
|
||||
responseCache: respCache,
|
||||
sdkClient: sdk,
|
||||
responseCache: respCache,
|
||||
followSymlinks: followSymlinks,
|
||||
supportLFS: supportLFS,
|
||||
}, err
|
||||
}
|
||||
|
||||
|
@ -78,6 +84,21 @@ func (client *Client) ServeRawContent(targetOwner, targetRepo, ref, resource str
|
|||
// _ = fileResponseCache.Set(uri+"?timestamp="+o.timestamp(), cachedResponse, fileCacheTimeout)
|
||||
// }
|
||||
|
||||
objType := resp.Header.Get(giteaObjectTypeHeader)
|
||||
log.Trace().Msgf("server raw content object: %s", objType)
|
||||
if client.followSymlinks && objType == "symlink" {
|
||||
// limit to 1000 chars
|
||||
defer reader.Close()
|
||||
linkDestBytes, err := io.ReadAll(io.LimitReader(reader, 10000))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
linkDest := strings.TrimSpace(string(linkDestBytes))
|
||||
|
||||
log.Debug().Msgf("follow symlink from '%s' to '%s'", resource, linkDest)
|
||||
return client.ServeRawContent(targetOwner, targetRepo, ref, linkDest)
|
||||
}
|
||||
|
||||
return reader, resp.Response, err
|
||||
case http.StatusNotFound:
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ func Handler(mainDomainSuffix, rawDomain []byte,
|
|||
dnsLookupCache, canonicalDomainCache cache.SetGetKey,
|
||||
) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, req *http.Request) {
|
||||
log := log.With().Str("Handler", req.RequestURI).Logger()
|
||||
log := log.With().Strs("Handler", []string{string(req.Host), req.RequestURI}).Logger()
|
||||
|
||||
w.Header().Set("Server", "CodebergPages/"+version.Version)
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ func Handler(mainDomainSuffix, rawDomain []byte,
|
|||
dnsLookupCache, canonicalDomainCache cache.SetGetKey,
|
||||
) func(ctx *fasthttp.RequestCtx) {
|
||||
return func(ctx *fasthttp.RequestCtx) {
|
||||
log := log.With().Str("Handler", string(ctx.Request.Header.RequestURI())).Logger()
|
||||
log := log.With().Strs("Handler", []string{string(ctx.Request.Host()), string(ctx.Request.Header.RequestURI())}).Logger()
|
||||
|
||||
ctx.Response.Header.Set("Server", "CodebergPages/"+version.Version)
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@ package server
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"github.com/valyala/fasthttp"
|
||||
|
||||
"codeberg.org/codeberg/pages/server/cache"
|
||||
|
@ -18,7 +18,7 @@ import (
|
|||
type fasthttpLogger struct{}
|
||||
|
||||
func (fasthttpLogger) Printf(format string, args ...interface{}) {
|
||||
log.Printf("[FASTHTTP] "+format, args...)
|
||||
log.Printf("FastHTTP: %s", fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func SetupServer(handler fasthttp.RequestHandler) *fasthttp.Server {
|
||||
|
|
|
@ -43,6 +43,7 @@ func tryUpstream(ctx *context.Context, giteaClient *gitea.Client,
|
|||
targetOptions.TargetRepo = targetRepo
|
||||
targetOptions.TargetBranch = targetBranch
|
||||
targetOptions.TargetPath = targetPath
|
||||
targetOptions.Host = string(trimmedHost)
|
||||
|
||||
// Try to request the file from the Gitea API
|
||||
if !targetOptions.Upstream(ctx, giteaClient) {
|
||||
|
|
Loading…
Reference in a new issue