mirror of
https://codeberg.org/Codeberg/pages-server
synced 2024-09-19 23:28:30 +01:00
Compare commits
17 Commits
e82f48b636
...
53efc01268
Author | SHA1 | Date | |
---|---|---|---|
|
53efc01268 | ||
|
b2d40c5154 | ||
|
2410137438 | ||
|
557a295732 | ||
|
c76daaca4d | ||
|
6cff8d2ee9 | ||
|
9524b1eb12 | ||
|
c9be1ce75d | ||
|
5265b3884b | ||
|
68825a1727 | ||
|
abbebbbcee | ||
|
6ce17461e6 | ||
|
efd1adae0f | ||
|
bc9111a05f | ||
|
17530a065b | ||
|
d583587773 | ||
|
4e44ea1d58 |
@ -1,71 +1,59 @@
|
||||
when:
|
||||
- event: [pull_request, tag, cron]
|
||||
- event: push
|
||||
branch:
|
||||
- ${CI_REPO_DEFAULT_BRANCH}
|
||||
- renovate/*
|
||||
|
||||
depends_on:
|
||||
- lint
|
||||
- event: [push, pull_request, tag, cron]
|
||||
branch: ${CI_REPO_DEFAULT_BRANCH}
|
||||
|
||||
steps:
|
||||
# use vendor to cache dependencies
|
||||
vendor:
|
||||
image: golang:1.22
|
||||
image: golang:1.23
|
||||
commands:
|
||||
- go mod vendor
|
||||
|
||||
build:
|
||||
depends_on: vendor
|
||||
image: codeberg.org/6543/docker-images/golang_just
|
||||
pull: true
|
||||
commands:
|
||||
- go version
|
||||
- just build
|
||||
when:
|
||||
- event: [push, pull_request]
|
||||
branch:
|
||||
- ${CI_REPO_DEFAULT_BRANCH}
|
||||
- renovate/*
|
||||
|
||||
docker-dryrun:
|
||||
depends_on: vendor
|
||||
image: woodpeckerci/plugin-docker-buildx:4.0.0
|
||||
image: woodpeckerci/plugin-docker-buildx:4.2.0
|
||||
settings:
|
||||
dockerfile: Dockerfile
|
||||
platforms: linux/amd64
|
||||
dry-run: true
|
||||
tags: latest
|
||||
when:
|
||||
- event: [push, pull_request]
|
||||
branch:
|
||||
- ${CI_REPO_DEFAULT_BRANCH}
|
||||
- renovate/*
|
||||
- event: [pull_request]
|
||||
path: Dockerfile
|
||||
|
||||
build-tag:
|
||||
depends_on: vendor
|
||||
image: codeberg.org/6543/docker-images/golang_just
|
||||
pull: true
|
||||
commands:
|
||||
- go version
|
||||
- just build-tag ${CI_COMMIT_TAG##v}
|
||||
when:
|
||||
- event: ['tag']
|
||||
branch:
|
||||
- ${CI_REPO_DEFAULT_BRANCH}
|
||||
- event: [tag]
|
||||
|
||||
test:
|
||||
depends_on: build
|
||||
image: codeberg.org/6543/docker-images/golang_just
|
||||
pull: true
|
||||
commands:
|
||||
- just test
|
||||
when:
|
||||
- event: pull_request
|
||||
- event: push
|
||||
branch: renovate/*
|
||||
- event: [pull_request]
|
||||
|
||||
integration-tests:
|
||||
depends_on: build
|
||||
image: codeberg.org/6543/docker-images/golang_just
|
||||
pull: true
|
||||
commands:
|
||||
- just integration
|
||||
environment:
|
||||
@ -74,32 +62,23 @@ steps:
|
||||
- RAW_DOMAIN=raw.localhost.mock.directory
|
||||
- PORT=4430
|
||||
when:
|
||||
- event: pull_request
|
||||
- event: push
|
||||
branch: renovate/*
|
||||
- event: [pull_request]
|
||||
|
||||
release:
|
||||
depends_on: build
|
||||
image: plugins/gitea-release:1.1.0
|
||||
image: woodpeckerci/plugin-release:0.2.1
|
||||
settings:
|
||||
base_url: https://codeberg.org
|
||||
file_exists: overwrite
|
||||
files: build/codeberg-pages-server
|
||||
api_key:
|
||||
from_secret: bot_token
|
||||
environment:
|
||||
- CI_REPO_OWNER=${CI_REPO_OWNER}
|
||||
- CI_REPO_NAME=${CI_REPO_NAME}
|
||||
- CI_BUILD_EVENT=${CI_BUILD_EVENT}
|
||||
- CI_COMMIT_REF=${CI_COMMIT_REF}
|
||||
when:
|
||||
- event: ['tag']
|
||||
branch:
|
||||
- ${CI_REPO_DEFAULT_BRANCH}
|
||||
- event: [tag]
|
||||
|
||||
docker-next:
|
||||
depends_on: vendor
|
||||
image: woodpeckerci/plugin-docker-buildx:4.0.0
|
||||
image: woodpeckerci/plugin-docker-buildx:4.2.0
|
||||
settings:
|
||||
registry: codeberg.org
|
||||
dockerfile: Dockerfile
|
||||
@ -111,11 +90,10 @@ steps:
|
||||
password:
|
||||
from_secret: bot_token
|
||||
when:
|
||||
- event: ['push']
|
||||
branch: ${CI_REPO_DEFAULT_BRANCH}
|
||||
- event: [push]
|
||||
|
||||
'Publish PR image':
|
||||
image: woodpeckerci/plugin-docker-buildx:3.2.1
|
||||
image: woodpeckerci/plugin-docker-buildx:4.2.0
|
||||
depends_on: test
|
||||
settings:
|
||||
registry: codeberg.org
|
||||
@ -131,9 +109,9 @@ steps:
|
||||
evaluate: 'CI_COMMIT_PULL_REQUEST_LABELS contains "build_pr_image"'
|
||||
event: pull_request
|
||||
|
||||
docker-tag:
|
||||
docker-release:
|
||||
depends_on: vendor
|
||||
image: woodpeckerci/plugin-docker-buildx:4.0.0
|
||||
image: woodpeckerci/plugin-docker-buildx:4.2.0
|
||||
settings:
|
||||
registry: codeberg.org
|
||||
dockerfile: Dockerfile
|
||||
@ -145,5 +123,4 @@ steps:
|
||||
password:
|
||||
from_secret: bot_token
|
||||
when:
|
||||
- event: ['push']
|
||||
branch: ${CI_REPO_DEFAULT_BRANCH}
|
||||
- event: [tag]
|
||||
|
@ -1,41 +1,27 @@
|
||||
when:
|
||||
- event: pull_request
|
||||
- event: push
|
||||
branch:
|
||||
- ${CI_REPO_DEFAULT_BRANCH}
|
||||
- renovate/**
|
||||
|
||||
steps:
|
||||
lint:
|
||||
depends_on: []
|
||||
image: golangci/golangci-lint:v1.59.1
|
||||
image: golangci/golangci-lint:v1.60.1
|
||||
commands:
|
||||
- go version
|
||||
- go install mvdan.cc/gofumpt@latest
|
||||
- "[ $(gofumpt -extra -l . | wc -l) != 0 ] && { echo 'code not formated'; exit 1; }"
|
||||
- golangci-lint run --timeout 5m --build-tags integration
|
||||
when:
|
||||
- event: pull_request
|
||||
- event: push
|
||||
branch: renovate/*
|
||||
|
||||
editor-config:
|
||||
depends_on: []
|
||||
image: mstruebing/editorconfig-checker:v3.0.1
|
||||
when:
|
||||
- event: pull_request
|
||||
- event: push
|
||||
branch: renovate/*
|
||||
image: mstruebing/editorconfig-checker:v3.0.3
|
||||
|
||||
yamllint:
|
||||
image: pipelinecomponents/yamllint:0.31.2
|
||||
image: pipelinecomponents/yamllint:0.31.3
|
||||
depends_on: []
|
||||
commands:
|
||||
- yamllint .
|
||||
when:
|
||||
- event: pull_request
|
||||
- event: push
|
||||
branch: renovate/*
|
||||
|
||||
prettier:
|
||||
image: docker.io/woodpeckerci/plugin-prettier:0.1.0
|
||||
|
@ -70,7 +70,7 @@ This will trigger a build of the PR which will build a docker image to be used f
|
||||
### Environment Variables
|
||||
|
||||
- `ACME_ACCEPT_TERMS` (default: use self-signed certificate): Set this to "true" to accept the Terms of Service of your ACME provider.
|
||||
- `ACME_API` (default: <https://acme-v02.api.letsencrypt.org/directory>): set this to <https://acme.mock.director> to use invalid certificates without any verification (great for debugging). ZeroSSL might be better in the future as it doesn't have rate limits and doesn't clash with the official Codeberg certificates (which are using Let's Encrypt), but I couldn't get it to work yet.
|
||||
- `ACME_API` (default: <https://acme-v02.api.letsencrypt.org/directory>): set this to <https://acme.mock.directory> to use invalid certificates without any verification (great for debugging). ZeroSSL might be better in the future as it doesn't have rate limits and doesn't clash with the official Codeberg certificates (which are using Let's Encrypt), but I couldn't get it to work yet.
|
||||
- `ACME_EAB_KID` & `ACME_EAB_HMAC` (default: don't use EAB): EAB credentials, for example for ZeroSSL.
|
||||
- `ACME_EMAIL` (default: `noreply@example.email`): Set the email sent to the ACME API server to receive, for example, renewal reminders.
|
||||
- `ACME_USE_RATE_LIMITS` (default: true): Set this to false to disable rate limits, e.g. with ZeroSSL.
|
||||
|
@ -81,6 +81,12 @@ var (
|
||||
Usage: "specifies the domain from which raw repository content shall be served, not set disable raw content hosting",
|
||||
EnvVars: []string{"RAW_DOMAIN"},
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "canonical-domain-file",
|
||||
Usage: "specifies the file from which the canonical domain may be specified in. Use this flag multiple times to support multiple different file names, if multiple files exist in a single repository they will be merged.",
|
||||
EnvVars: []string{"CANONICAL_DOMAIN_FILES"},
|
||||
Value: cli.NewStringSlice(".domains"),
|
||||
},
|
||||
|
||||
// #########################
|
||||
// ### Page Server Setup ###
|
||||
|
@ -9,15 +9,16 @@ type Config struct {
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
Host string `default:"[::]"`
|
||||
Port uint16 `default:"443"`
|
||||
HttpPort uint16 `default:"80"`
|
||||
HttpServerEnabled bool `default:"true"`
|
||||
MainDomain string
|
||||
RawDomain string
|
||||
PagesBranches []string
|
||||
AllowedCorsDomains []string
|
||||
BlacklistedPaths []string
|
||||
Host string `default:"[::]"`
|
||||
Port uint16 `default:"443"`
|
||||
HttpPort uint16 `default:"80"`
|
||||
HttpServerEnabled bool `default:"true"`
|
||||
MainDomain string
|
||||
RawDomain string
|
||||
CanonicalDomainFiles []string `default:"[\".domains\"]"`
|
||||
PagesBranches []string `default:"[\"main\", \"master\", \"pages\"]"`
|
||||
AllowedCorsDomains []string
|
||||
BlacklistedPaths []string
|
||||
}
|
||||
|
||||
type ForgeConfig struct {
|
||||
|
@ -20,9 +20,6 @@ func NewDefaultConfig() Config {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// defaults does not support setting arrays from strings
|
||||
config.Server.PagesBranches = []string{"main", "master", "pages"}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
@ -75,6 +72,9 @@ func mergeServerConfig(ctx *cli.Context, config *ServerConfig) {
|
||||
if ctx.IsSet("raw-domain") {
|
||||
config.RawDomain = ctx.String("raw-domain")
|
||||
}
|
||||
if ctx.IsSet("canonical-domain-file") {
|
||||
config.CanonicalDomainFiles = ctx.StringSlice("canonical-domain-file")
|
||||
}
|
||||
if ctx.IsSet("pages-branch") {
|
||||
config.PagesBranches = ctx.StringSlice("pages-branch")
|
||||
}
|
||||
|
@ -136,15 +136,16 @@ func TestMergeConfigShouldReplaceAllExistingValuesGivenAllArgsExist(t *testing.T
|
||||
cfg := &Config{
|
||||
LogLevel: "original",
|
||||
Server: ServerConfig{
|
||||
Host: "original",
|
||||
Port: 8080,
|
||||
HttpPort: 80,
|
||||
HttpServerEnabled: false,
|
||||
MainDomain: "original",
|
||||
RawDomain: "original",
|
||||
PagesBranches: []string{"original"},
|
||||
AllowedCorsDomains: []string{"original"},
|
||||
BlacklistedPaths: []string{"original"},
|
||||
Host: "original",
|
||||
Port: 8080,
|
||||
HttpPort: 80,
|
||||
HttpServerEnabled: false,
|
||||
MainDomain: "original",
|
||||
RawDomain: "original",
|
||||
CanonicalDomainFiles: []string{"original"},
|
||||
PagesBranches: []string{"original"},
|
||||
AllowedCorsDomains: []string{"original"},
|
||||
BlacklistedPaths: []string{"original"},
|
||||
},
|
||||
Forge: ForgeConfig{
|
||||
Root: "original",
|
||||
@ -176,15 +177,16 @@ func TestMergeConfigShouldReplaceAllExistingValuesGivenAllArgsExist(t *testing.T
|
||||
expectedConfig := &Config{
|
||||
LogLevel: "changed",
|
||||
Server: ServerConfig{
|
||||
Host: "changed",
|
||||
Port: 8443,
|
||||
HttpPort: 443,
|
||||
HttpServerEnabled: true,
|
||||
MainDomain: "changed",
|
||||
RawDomain: "changed",
|
||||
PagesBranches: []string{"changed"},
|
||||
AllowedCorsDomains: []string{"changed"},
|
||||
BlacklistedPaths: append([]string{"changed"}, ALWAYS_BLACKLISTED_PATHS...),
|
||||
Host: "changed",
|
||||
Port: 8443,
|
||||
HttpPort: 443,
|
||||
HttpServerEnabled: true,
|
||||
MainDomain: "changed",
|
||||
RawDomain: "changed",
|
||||
CanonicalDomainFiles: []string{"changed"},
|
||||
PagesBranches: []string{"changed"},
|
||||
AllowedCorsDomains: []string{"changed"},
|
||||
BlacklistedPaths: append([]string{"changed"}, ALWAYS_BLACKLISTED_PATHS...),
|
||||
},
|
||||
Forge: ForgeConfig{
|
||||
Root: "changed",
|
||||
@ -220,6 +222,7 @@ func TestMergeConfigShouldReplaceAllExistingValuesGivenAllArgsExist(t *testing.T
|
||||
// Server
|
||||
"--pages-domain", "changed",
|
||||
"--raw-domain", "changed",
|
||||
"--canonical-domain-file", "changed",
|
||||
"--allowed-cors-domains", "changed",
|
||||
"--blacklisted-paths", "changed",
|
||||
"--pages-branch", "changed",
|
||||
@ -273,27 +276,29 @@ func TestMergeServerConfigShouldReplaceAllExistingValuesGivenAllArgsExist(t *tes
|
||||
t,
|
||||
func(ctx *cli.Context) error {
|
||||
cfg := &ServerConfig{
|
||||
Host: "original",
|
||||
Port: 8080,
|
||||
HttpPort: 80,
|
||||
HttpServerEnabled: false,
|
||||
MainDomain: "original",
|
||||
RawDomain: "original",
|
||||
AllowedCorsDomains: []string{"original"},
|
||||
BlacklistedPaths: []string{"original"},
|
||||
Host: "original",
|
||||
Port: 8080,
|
||||
HttpPort: 80,
|
||||
HttpServerEnabled: false,
|
||||
MainDomain: "original",
|
||||
RawDomain: "original",
|
||||
CanonicalDomainFiles: []string{"original"},
|
||||
AllowedCorsDomains: []string{"original"},
|
||||
BlacklistedPaths: []string{"original"},
|
||||
}
|
||||
|
||||
mergeServerConfig(ctx, cfg)
|
||||
|
||||
expectedConfig := &ServerConfig{
|
||||
Host: "changed",
|
||||
Port: 8443,
|
||||
HttpPort: 443,
|
||||
HttpServerEnabled: true,
|
||||
MainDomain: "changed",
|
||||
RawDomain: "changed",
|
||||
AllowedCorsDomains: fixArrayFromCtx(ctx, "allowed-cors-domains", []string{"changed"}),
|
||||
BlacklistedPaths: fixArrayFromCtx(ctx, "blacklisted-paths", append([]string{"changed"}, ALWAYS_BLACKLISTED_PATHS...)),
|
||||
Host: "changed",
|
||||
Port: 8443,
|
||||
HttpPort: 443,
|
||||
HttpServerEnabled: true,
|
||||
MainDomain: "changed",
|
||||
RawDomain: "changed",
|
||||
CanonicalDomainFiles: fixArrayFromCtx(ctx, "canonical-domain-file", []string{"changed"}),
|
||||
AllowedCorsDomains: fixArrayFromCtx(ctx, "allowed-cors-domains", []string{"changed"}),
|
||||
BlacklistedPaths: fixArrayFromCtx(ctx, "blacklisted-paths", append([]string{"changed"}, ALWAYS_BLACKLISTED_PATHS...)),
|
||||
}
|
||||
|
||||
assert.Equal(t, expectedConfig, cfg)
|
||||
@ -303,6 +308,7 @@ func TestMergeServerConfigShouldReplaceAllExistingValuesGivenAllArgsExist(t *tes
|
||||
[]string{
|
||||
"--pages-domain", "changed",
|
||||
"--raw-domain", "changed",
|
||||
"--canonical-domain-file", "changed",
|
||||
"--allowed-cors-domains", "changed",
|
||||
"--blacklisted-paths", "changed",
|
||||
"--host", "changed",
|
||||
@ -326,6 +332,7 @@ func TestMergeServerConfigShouldReplaceOnlyOneValueExistingValueGivenOnlyOneArgE
|
||||
{args: []string{"--enable-http-server"}, callback: func(sc *ServerConfig) { sc.HttpServerEnabled = true }},
|
||||
{args: []string{"--pages-domain", "changed"}, callback: func(sc *ServerConfig) { sc.MainDomain = "changed" }},
|
||||
{args: []string{"--raw-domain", "changed"}, callback: func(sc *ServerConfig) { sc.RawDomain = "changed" }},
|
||||
{args: []string{"--canonical-domain-file", "changed"}, callback: func(sc *ServerConfig) { sc.CanonicalDomainFiles = []string{"changed"} }},
|
||||
{args: []string{"--pages-branch", "changed"}, callback: func(sc *ServerConfig) { sc.PagesBranches = []string{"changed"} }},
|
||||
{args: []string{"--allowed-cors-domains", "changed"}, callback: func(sc *ServerConfig) { sc.AllowedCorsDomains = []string{"changed"} }},
|
||||
{args: []string{"--blacklisted-paths", "changed"}, callback: func(sc *ServerConfig) { sc.BlacklistedPaths = []string{"changed"} }},
|
||||
@ -336,21 +343,23 @@ func TestMergeServerConfigShouldReplaceOnlyOneValueExistingValueGivenOnlyOneArgE
|
||||
t,
|
||||
func(ctx *cli.Context) error {
|
||||
cfg := ServerConfig{
|
||||
Host: "original",
|
||||
Port: 8080,
|
||||
HttpPort: 80,
|
||||
HttpServerEnabled: false,
|
||||
MainDomain: "original",
|
||||
RawDomain: "original",
|
||||
PagesBranches: []string{"original"},
|
||||
AllowedCorsDomains: []string{"original"},
|
||||
BlacklistedPaths: []string{"original"},
|
||||
Host: "original",
|
||||
Port: 8080,
|
||||
HttpPort: 80,
|
||||
HttpServerEnabled: false,
|
||||
MainDomain: "original",
|
||||
RawDomain: "original",
|
||||
CanonicalDomainFiles: []string{"original"},
|
||||
PagesBranches: []string{"original"},
|
||||
AllowedCorsDomains: []string{"original"},
|
||||
BlacklistedPaths: []string{"original"},
|
||||
}
|
||||
|
||||
expectedConfig := cfg
|
||||
pair.callback(&expectedConfig)
|
||||
expectedConfig.BlacklistedPaths = append(expectedConfig.BlacklistedPaths, ALWAYS_BLACKLISTED_PATHS...)
|
||||
|
||||
expectedConfig.CanonicalDomainFiles = fixArrayFromCtx(ctx, "canonical-domain-file", expectedConfig.CanonicalDomainFiles)
|
||||
expectedConfig.PagesBranches = fixArrayFromCtx(ctx, "pages-branch", expectedConfig.PagesBranches)
|
||||
expectedConfig.AllowedCorsDomains = fixArrayFromCtx(ctx, "allowed-cors-domains", expectedConfig.AllowedCorsDomains)
|
||||
expectedConfig.BlacklistedPaths = fixArrayFromCtx(ctx, "blacklisted-paths", expectedConfig.BlacklistedPaths)
|
||||
|
2
go.mod
2
go.mod
@ -20,7 +20,7 @@ require (
|
||||
github.com/rs/zerolog v1.27.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
|
||||
xorm.io/xorm v1.3.2
|
||||
)
|
||||
|
||||
|
12
go.sum
12
go.sum
@ -786,8 +786,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@ -810,8 +810,8 @@ 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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
|
||||
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
|
||||
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
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=
|
||||
@ -1004,8 +1004,8 @@ golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4f
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
|
||||
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
|
||||
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
|
||||
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -32,6 +32,7 @@ func TLSConfig(mainDomainSuffix string,
|
||||
giteaClient *gitea.Client,
|
||||
acmeClient *AcmeClient,
|
||||
firstDefaultBranch string,
|
||||
canonicalDomainConfigs []string,
|
||||
challengeCache, canonicalDomainCache cache.ICache,
|
||||
certDB database.CertDB,
|
||||
noDNS01 bool,
|
||||
@ -100,10 +101,10 @@ func TLSConfig(mainDomainSuffix string,
|
||||
TargetRepo: targetRepo,
|
||||
TargetBranch: targetBranch,
|
||||
}
|
||||
_, valid := targetOpt.CheckCanonicalDomain(giteaClient, domain, mainDomainSuffix, canonicalDomainCache)
|
||||
_, valid := targetOpt.CheckCanonicalDomain(giteaClient, domain, mainDomainSuffix, canonicalDomainConfigs, canonicalDomainCache)
|
||||
if !valid {
|
||||
// We shouldn't obtain a certificate when we cannot check if the
|
||||
// repository has specified this domain in the `.domains` file.
|
||||
// repository has specified this domain in the specified canonical domain file such as the `.domains` file.
|
||||
mayObtainCert = false
|
||||
}
|
||||
}
|
||||
@ -196,7 +197,7 @@ func (c *AcmeClient) retrieveCertFromDB(sni, mainDomainSuffix string, useDnsProv
|
||||
// renew certificates 7 days before they expire
|
||||
if tlsCertificate.Leaf.NotAfter.Before(time.Now().Add(7 * 24 * time.Hour)) {
|
||||
// TODO: use ValidTill of custom cert struct
|
||||
if res.CSR != nil && len(res.CSR) > 0 {
|
||||
if len(res.CSR) > 0 {
|
||||
// CSR stores the time when the renewal shall be tried again
|
||||
nextTryUnix, err := strconv.ParseInt(string(res.CSR), 10, 64)
|
||||
if err == nil && time.Now().Before(time.Unix(nextTryUnix, 0)) {
|
||||
|
@ -92,6 +92,7 @@ func Handler(
|
||||
cfg.MainDomain,
|
||||
trimmedHost,
|
||||
pathElements,
|
||||
cfg.CanonicalDomainFiles,
|
||||
canonicalDomainCache, redirectsCache)
|
||||
} else if strings.HasSuffix(trimmedHost, cfg.MainDomain) {
|
||||
log.Debug().Msg("subdomain request detected")
|
||||
@ -100,6 +101,7 @@ func Handler(
|
||||
cfg.PagesBranches,
|
||||
trimmedHost,
|
||||
pathElements,
|
||||
cfg.CanonicalDomainFiles,
|
||||
canonicalDomainCache, redirectsCache)
|
||||
} else {
|
||||
log.Debug().Msg("custom domain request detected")
|
||||
@ -108,6 +110,7 @@ func Handler(
|
||||
trimmedHost,
|
||||
pathElements,
|
||||
cfg.PagesBranches[0],
|
||||
cfg.CanonicalDomainFiles,
|
||||
canonicalDomainCache, redirectsCache)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
@ -19,6 +20,7 @@ func handleCustomDomain(log zerolog.Logger, ctx *context.Context, giteaClient *g
|
||||
trimmedHost string,
|
||||
pathElements []string,
|
||||
firstDefaultBranch string,
|
||||
canonicalDomainConfigs []string,
|
||||
canonicalDomainCache, redirectsCache cache.ICache,
|
||||
) {
|
||||
// Serve pages from custom domains
|
||||
@ -47,9 +49,10 @@ func handleCustomDomain(log zerolog.Logger, ctx *context.Context, giteaClient *g
|
||||
TargetBranch: targetBranch,
|
||||
TargetPath: path.Join(pathParts...),
|
||||
}, canonicalLink); works {
|
||||
canonicalDomain, valid := targetOpt.CheckCanonicalDomain(giteaClient, trimmedHost, mainDomainSuffix, canonicalDomainCache)
|
||||
canonicalDomain, valid := targetOpt.CheckCanonicalDomain(giteaClient, trimmedHost, mainDomainSuffix, canonicalDomainConfigs, canonicalDomainCache)
|
||||
if !valid {
|
||||
html.ReturnErrorPage(ctx, "domain not specified in <code>.domains</code> file", http.StatusMisdirectedRequest)
|
||||
msg := fmt.Sprintf("canonical domain not specified, files checked: <code>%s</code>", strings.Join(canonicalDomainConfigs, "</code>, <code>"))
|
||||
html.ReturnErrorPage(ctx, msg, http.StatusMisdirectedRequest)
|
||||
return
|
||||
} else if canonicalDomain != trimmedHost {
|
||||
// only redirect if the target is also a codeberg page!
|
||||
@ -64,7 +67,7 @@ func handleCustomDomain(log zerolog.Logger, ctx *context.Context, giteaClient *g
|
||||
}
|
||||
|
||||
log.Debug().Msg("tryBranch, now trying upstream 7")
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainCache, redirectsCache)
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfigs, canonicalDomainCache, redirectsCache)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ func handleRaw(log zerolog.Logger, ctx *context.Context, giteaClient *gitea.Clie
|
||||
mainDomainSuffix string,
|
||||
trimmedHost string,
|
||||
pathElements []string,
|
||||
canonicalDomainConfigs []string,
|
||||
canonicalDomainCache, redirectsCache cache.ICache,
|
||||
) {
|
||||
// Serve raw content from RawDomain
|
||||
@ -45,7 +46,7 @@ func handleRaw(log zerolog.Logger, ctx *context.Context, giteaClient *gitea.Clie
|
||||
TargetPath: path.Join(pathElements[3:]...),
|
||||
}, true); works {
|
||||
log.Trace().Msg("tryUpstream: serve raw domain with specified branch")
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainCache, redirectsCache)
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfigs, canonicalDomainCache, redirectsCache)
|
||||
return
|
||||
}
|
||||
log.Debug().Msg("missing branch info")
|
||||
@ -62,7 +63,7 @@ func handleRaw(log zerolog.Logger, ctx *context.Context, giteaClient *gitea.Clie
|
||||
TargetPath: path.Join(pathElements[2:]...),
|
||||
}, true); works {
|
||||
log.Trace().Msg("tryUpstream: serve raw domain with default branch")
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainCache, redirectsCache)
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfigs, canonicalDomainCache, redirectsCache)
|
||||
} else {
|
||||
html.ReturnErrorPage(ctx,
|
||||
fmt.Sprintf("raw domain could not find repo <code>%s/%s</code> or repo is empty", targetOpt.TargetOwner, targetOpt.TargetRepo),
|
||||
|
@ -21,6 +21,7 @@ func handleSubDomain(log zerolog.Logger, ctx *context.Context, giteaClient *gite
|
||||
defaultPagesBranches []string,
|
||||
trimmedHost string,
|
||||
pathElements []string,
|
||||
canonicalDomainConfigs []string,
|
||||
canonicalDomainCache, redirectsCache cache.ICache,
|
||||
) {
|
||||
// Serve pages from subdomains of MainDomainSuffix
|
||||
@ -53,7 +54,7 @@ func handleSubDomain(log zerolog.Logger, ctx *context.Context, giteaClient *gite
|
||||
TargetPath: path.Join(pathElements[2:]...),
|
||||
}, true); works {
|
||||
log.Trace().Msg("tryUpstream: serve with specified repo and branch")
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainCache, redirectsCache)
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfigs, canonicalDomainCache, redirectsCache)
|
||||
} else {
|
||||
html.ReturnErrorPage(
|
||||
ctx,
|
||||
@ -85,7 +86,7 @@ func handleSubDomain(log zerolog.Logger, ctx *context.Context, giteaClient *gite
|
||||
TargetPath: path.Join(pathElements[1:]...),
|
||||
}, true); works {
|
||||
log.Trace().Msg("tryUpstream: serve default pages repo with specified branch")
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainCache, redirectsCache)
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfigs, canonicalDomainCache, redirectsCache)
|
||||
} else {
|
||||
html.ReturnErrorPage(
|
||||
ctx,
|
||||
@ -110,7 +111,7 @@ func handleSubDomain(log zerolog.Logger, ctx *context.Context, giteaClient *gite
|
||||
TargetPath: path.Join(pathElements[1:]...),
|
||||
}, false); works {
|
||||
log.Debug().Msg("tryBranch, now trying upstream 5")
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainCache, redirectsCache)
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfigs, canonicalDomainCache, redirectsCache)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -126,7 +127,7 @@ func handleSubDomain(log zerolog.Logger, ctx *context.Context, giteaClient *gite
|
||||
TargetPath: path.Join(pathElements...),
|
||||
}, false); works {
|
||||
log.Debug().Msg("tryBranch, now trying upstream 6")
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainCache, redirectsCache)
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfigs, canonicalDomainCache, redirectsCache)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -141,7 +142,7 @@ func handleSubDomain(log zerolog.Logger, ctx *context.Context, giteaClient *gite
|
||||
TargetPath: path.Join(pathElements...),
|
||||
}, false); works {
|
||||
log.Debug().Msg("tryBranch, now trying upstream 6")
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainCache, redirectsCache)
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfigs, canonicalDomainCache, redirectsCache)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -18,12 +18,13 @@ import (
|
||||
func tryUpstream(ctx *context.Context, giteaClient *gitea.Client,
|
||||
mainDomainSuffix, trimmedHost string,
|
||||
options *upstream.Options,
|
||||
canonicalDomainConfigs []string,
|
||||
canonicalDomainCache cache.ICache,
|
||||
redirectsCache cache.ICache,
|
||||
) {
|
||||
// check if a canonical domain exists on a request on MainDomain
|
||||
if strings.HasSuffix(trimmedHost, mainDomainSuffix) && !options.ServeRaw {
|
||||
canonicalDomain, _ := options.CheckCanonicalDomain(giteaClient, "", mainDomainSuffix, canonicalDomainCache)
|
||||
canonicalDomain, _ := options.CheckCanonicalDomain(giteaClient, "", mainDomainSuffix, canonicalDomainConfigs, canonicalDomainCache)
|
||||
if !strings.HasSuffix(strings.SplitN(canonicalDomain, "/", 2)[0], mainDomainSuffix) {
|
||||
canonicalPath := ctx.Req.RequestURI
|
||||
if options.TargetRepo != defaultPagesRepo {
|
||||
|
@ -101,6 +101,7 @@ func Serve(ctx *cli.Context) error {
|
||||
giteaClient,
|
||||
acmeClient,
|
||||
cfg.Server.PagesBranches[0],
|
||||
cfg.Server.CanonicalDomainFiles,
|
||||
challengeCache, canonicalDomainCache,
|
||||
certDB,
|
||||
cfg.ACME.NoDNS01,
|
||||
|
@ -14,57 +14,92 @@ import (
|
||||
// canonicalDomainCacheTimeout specifies the timeout for the canonical domain cache.
|
||||
var canonicalDomainCacheTimeout = 15 * time.Minute
|
||||
|
||||
const canonicalDomainConfig = ".domains"
|
||||
|
||||
// CheckCanonicalDomain returns the canonical domain specified in the repo (using the `.domains` file).
|
||||
func (o *Options) CheckCanonicalDomain(giteaClient *gitea.Client, actualDomain, mainDomainSuffix string, canonicalDomainCache cache.ICache) (domain string, valid bool) {
|
||||
// Check if this request is cached.
|
||||
if cachedValue, ok := canonicalDomainCache.Get(o.TargetOwner + "/" + o.TargetRepo + "/" + o.TargetBranch); ok {
|
||||
domains := cachedValue.([]string)
|
||||
for _, domain := range domains {
|
||||
if domain == actualDomain {
|
||||
valid = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return domains[0], valid
|
||||
}
|
||||
|
||||
body, err := giteaClient.GiteaRawContent(o.TargetOwner, o.TargetRepo, o.TargetBranch, canonicalDomainConfig)
|
||||
if err != nil && !errors.Is(err, gitea.ErrorNotFound) {
|
||||
log.Error().Err(err).Msgf("could not read %s of %s/%s", canonicalDomainConfig, o.TargetOwner, o.TargetRepo)
|
||||
}
|
||||
func (o *Options) CheckCanonicalDomain(giteaClient *gitea.Client, actualDomain, mainDomainSuffix string, canonicalDomainConfigs []string, canonicalDomainCache cache.ICache) (domain string, valid bool) {
|
||||
canonicalDomainCacheKey := o.TargetOwner + "/" + o.TargetRepo + "/" + o.TargetBranch + "/(" + strings.Join(canonicalDomainConfigs, "|") + ")"
|
||||
|
||||
var domains []string
|
||||
for _, domain := range strings.Split(string(body), "\n") {
|
||||
domain = strings.ToLower(domain)
|
||||
domain = strings.TrimSpace(domain)
|
||||
domain = strings.TrimPrefix(domain, "http://")
|
||||
domain = strings.TrimPrefix(domain, "https://")
|
||||
if domain != "" && !strings.HasPrefix(domain, "#") && !strings.ContainsAny(domain, "\t /") && strings.ContainsRune(domain, '.') {
|
||||
domains = append(domains, domain)
|
||||
}
|
||||
|
||||
// Check if this request is cached.
|
||||
if cachedValue, ok := canonicalDomainCache.Get(canonicalDomainCacheKey); ok {
|
||||
domains = cachedValue.([]string)
|
||||
} else {
|
||||
// Create cache entry for future invocations.
|
||||
domains = o.canonicalDomainList(giteaClient, mainDomainSuffix, canonicalDomainConfigs)
|
||||
|
||||
// Add result to cache.
|
||||
_ = canonicalDomainCache.Set(canonicalDomainCacheKey, domains, canonicalDomainCacheTimeout)
|
||||
}
|
||||
|
||||
for _, domain := range domains {
|
||||
if domain == actualDomain {
|
||||
valid = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Add [owner].[pages-domain] as valid domain.
|
||||
domains = append(domains, o.TargetOwner+mainDomainSuffix)
|
||||
if domains[len(domains)-1] == actualDomain {
|
||||
valid = true
|
||||
}
|
||||
|
||||
// If the target repository isn't called pages, add `/[repository]` to the
|
||||
// previous valid domain.
|
||||
if o.TargetRepo != "" && o.TargetRepo != "pages" {
|
||||
domains[len(domains)-1] += "/" + o.TargetRepo
|
||||
}
|
||||
|
||||
// Add result to cache.
|
||||
_ = canonicalDomainCache.Set(o.TargetOwner+"/"+o.TargetRepo+"/"+o.TargetBranch, domains, canonicalDomainCacheTimeout)
|
||||
|
||||
// Return the first domain from the list and return if any of the domains
|
||||
// matched the requested domain.
|
||||
return domains[0], valid
|
||||
}
|
||||
|
||||
// canonicalDomainList returns a list of normalized canonical domains as reported by the repository being served.
|
||||
func (o *Options) canonicalDomainList(giteaClient *gitea.Client, mainDomainSuffix string, canonicalDomainConfigs []string) []string {
|
||||
domainConfigMerge := ""
|
||||
|
||||
for _, canonicalDomainConfig := range canonicalDomainConfigs {
|
||||
body, err := giteaClient.GiteaRawContent(o.TargetOwner, o.TargetRepo, o.TargetBranch, canonicalDomainConfig)
|
||||
if err != nil && !errors.Is(err, gitea.ErrorNotFound) {
|
||||
log.Error().Err(err).Msgf("could not read %s of %s/%s", canonicalDomainConfig, o.TargetOwner, o.TargetRepo)
|
||||
continue
|
||||
}
|
||||
|
||||
// Ensures files that don't end with a `\n` don't cause domains to be concatenated when combining files.
|
||||
domainConfigMerge = domainConfigMerge + "\n" + string(body)
|
||||
}
|
||||
|
||||
domains := normalizeDomainEntries(domainConfigMerge)
|
||||
|
||||
// Add [owner].[pages-domain] as valid domain.
|
||||
domains = append(domains, o.pageMainDomain(mainDomainSuffix))
|
||||
|
||||
return domains
|
||||
}
|
||||
|
||||
// pageMainDomain returns the [owner].[pages-domain] domain.
|
||||
func (o *Options) pageMainDomain(mainDomainSuffix string) string {
|
||||
pageMainDomain := o.TargetOwner + mainDomainSuffix
|
||||
|
||||
// If the target repository isn't called pages, add `/[repository]` to the
|
||||
// previous valid domain.
|
||||
if o.TargetRepo != "" && o.TargetRepo != "pages" {
|
||||
pageMainDomain += "/" + o.TargetRepo
|
||||
}
|
||||
|
||||
return pageMainDomain
|
||||
}
|
||||
|
||||
// normalizeDomainEntries returns a list of domains, ill formatted domains are skipped.
|
||||
// domainEntries is a new-line separated list of domains.
|
||||
func normalizeDomainEntries(domainEntries string) []string {
|
||||
domains := []string{}
|
||||
|
||||
for _, domain := range strings.Split(domainEntries, "\n") {
|
||||
domain = strings.ToLower(domain)
|
||||
domain = strings.TrimSpace(domain)
|
||||
domain = strings.TrimPrefix(domain, "http://")
|
||||
domain = strings.TrimPrefix(domain, "https://")
|
||||
|
||||
// Skip blank lines.
|
||||
// Skip commented lines.
|
||||
// Skip poorly formatted lines.
|
||||
// Skip domains without '.'.
|
||||
if domain == "" || strings.HasPrefix(domain, "#") || strings.ContainsAny(domain, "\t /") || !strings.ContainsRune(domain, '.') {
|
||||
continue
|
||||
}
|
||||
|
||||
domains = append(domains, domain)
|
||||
}
|
||||
|
||||
return domains
|
||||
}
|
||||
|
75
server/upstream/domains_test.go
Normal file
75
server/upstream/domains_test.go
Normal file
@ -0,0 +1,75 @@
|
||||
package upstream
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPageMainDomainGeneratesTheExpectedDomain(t *testing.T) {
|
||||
defaultOptions := Options{
|
||||
TargetOwner: "",
|
||||
TargetRepo: "",
|
||||
TargetBranch: "",
|
||||
TargetPath: "",
|
||||
Host: "",
|
||||
TryIndexPages: false,
|
||||
BranchTimestamp: time.Time{},
|
||||
appendTrailingSlash: false,
|
||||
redirectIfExists: "",
|
||||
ServeRaw: false,
|
||||
}
|
||||
|
||||
for _, tc := range []struct {
|
||||
targetOwner string
|
||||
targetRepo string
|
||||
domainSuffix string
|
||||
expectedDomain string
|
||||
}{
|
||||
{"foo", "", ".localhost.mock.directory", "foo.localhost.mock.directory"},
|
||||
{"foo", "pages", ".localhost.mock.directory", "foo.localhost.mock.directory"},
|
||||
{"foo", "bar", ".localhost.mock.directory", "foo.localhost.mock.directory/bar"},
|
||||
} {
|
||||
options := defaultOptions
|
||||
options.TargetOwner = tc.targetOwner
|
||||
options.TargetRepo = tc.targetRepo
|
||||
|
||||
actualDomain := options.pageMainDomain(tc.domainSuffix)
|
||||
|
||||
assert.Equal(t, tc.expectedDomain, actualDomain)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeDomainEntries(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
domain string
|
||||
}{
|
||||
{"abc.com"},
|
||||
{"ABC.com"},
|
||||
{" ABC.com"},
|
||||
{"ABC.com "},
|
||||
{" ABC.com "},
|
||||
{"http://ABC.com"},
|
||||
{"https://ABC.com"},
|
||||
} {
|
||||
actualDomains := normalizeDomainEntries(tc.domain)
|
||||
expectedDomains := []string{"abc.com"}
|
||||
|
||||
assert.Equal(t, expectedDomains, actualDomains)
|
||||
}
|
||||
|
||||
for _, tc := range []struct {
|
||||
domains string
|
||||
expectedDomains []string
|
||||
}{
|
||||
{"", []string{}},
|
||||
{"ABC.com", []string{"abc.com"}},
|
||||
{"ABC.com\nhttps://example.com", []string{"abc.com", "example.com"}},
|
||||
{"\n\nABC.com\n\nhttps://example.com\n", []string{"abc.com", "example.com"}},
|
||||
} {
|
||||
actualDomains := normalizeDomainEntries(tc.domains)
|
||||
|
||||
assert.Equal(t, tc.expectedDomains, actualDomains)
|
||||
}
|
||||
}
|
@ -24,5 +24,5 @@ func (o *Options) setHeader(ctx *context.Context, header http.Header) {
|
||||
} else {
|
||||
ctx.RespWriter.Header().Set(gitea.ContentTypeHeader, mime)
|
||||
}
|
||||
ctx.RespWriter.Header().Set(headerLastModified, o.BranchTimestamp.In(time.UTC).Format(time.RFC1123))
|
||||
ctx.RespWriter.Header().Set(headerLastModified, o.BranchTimestamp.In(time.UTC).Format(http.TimeFormat))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user