poc of serve domain args
This commit is contained in:
parent
02495554cf
commit
c89c68a4dc
|
@ -1,5 +1,7 @@
|
||||||
## v0.18.0 - WIP
|
## v0.18.0 - WIP
|
||||||
|
|
||||||
|
- (@todo docs) Simplified the `serve` command when used with a domain name.
|
||||||
|
|
||||||
- Added new `SmtpConfig.LocalName` option to specify a custom domain name (or IP address) for the initial EHLO/HELO exchange ([#3097](https://github.com/pocketbase/pocketbase/discussions/3097)).
|
- Added new `SmtpConfig.LocalName` option to specify a custom domain name (or IP address) for the initial EHLO/HELO exchange ([#3097](https://github.com/pocketbase/pocketbase/discussions/3097)).
|
||||||
_This is usually required for verification purposes only by some SMTP providers, such as on-premise [Gmail SMTP-relay](https://support.google.com/a/answer/2956491)._
|
_This is usually required for verification purposes only by some SMTP providers, such as on-premise [Gmail SMTP-relay](https://support.google.com/a/answer/2956491)._
|
||||||
|
|
||||||
|
|
|
@ -11,11 +11,13 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
|
"github.com/labstack/echo/v5"
|
||||||
"github.com/labstack/echo/v5/middleware"
|
"github.com/labstack/echo/v5/middleware"
|
||||||
"github.com/pocketbase/dbx"
|
"github.com/pocketbase/dbx"
|
||||||
"github.com/pocketbase/pocketbase/core"
|
"github.com/pocketbase/pocketbase/core"
|
||||||
"github.com/pocketbase/pocketbase/migrations"
|
"github.com/pocketbase/pocketbase/migrations"
|
||||||
"github.com/pocketbase/pocketbase/migrations/logs"
|
"github.com/pocketbase/pocketbase/migrations/logs"
|
||||||
|
"github.com/pocketbase/pocketbase/tools/list"
|
||||||
"github.com/pocketbase/pocketbase/tools/migrate"
|
"github.com/pocketbase/pocketbase/tools/migrate"
|
||||||
"golang.org/x/crypto/acme"
|
"golang.org/x/crypto/acme"
|
||||||
"golang.org/x/crypto/acme/autocert"
|
"golang.org/x/crypto/acme/autocert"
|
||||||
|
@ -26,12 +28,20 @@ type ServeConfig struct {
|
||||||
// ShowStartBanner indicates whether to show or hide the server start console message.
|
// ShowStartBanner indicates whether to show or hide the server start console message.
|
||||||
ShowStartBanner bool
|
ShowStartBanner bool
|
||||||
|
|
||||||
// HttpAddr is the HTTP server address to bind (eg. `127.0.0.1:80`).
|
// HttpAddr is the TCP address to listen for the HTTP server (eg. `127.0.0.1:80`).
|
||||||
HttpAddr string
|
HttpAddr string
|
||||||
|
|
||||||
// HttpsAddr is the HTTPS server address to bind (eg. `127.0.0.1:443`).
|
// HttpsAddr is the TCP address to listen for the HTTPS server (eg. `127.0.0.1:443`).
|
||||||
HttpsAddr string
|
HttpsAddr string
|
||||||
|
|
||||||
|
// Optional domains list to use when issuing the TLS certificate.
|
||||||
|
//
|
||||||
|
// If not set, the host from the bound server address will be used.
|
||||||
|
//
|
||||||
|
// For convenience, for each "non-www" domain a "www" entry and
|
||||||
|
// redirect will be automatically added.
|
||||||
|
CertificateDomains []string
|
||||||
|
|
||||||
// AllowedOrigins is an optional list of CORS origins (default to "*").
|
// AllowedOrigins is an optional list of CORS origins (default to "*").
|
||||||
AllowedOrigins []string
|
AllowedOrigins []string
|
||||||
}
|
}
|
||||||
|
@ -85,16 +95,53 @@ func Serve(app core.App, config ServeConfig) (*http.Server, error) {
|
||||||
mainAddr = config.HttpsAddr
|
mainAddr = config.HttpsAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
mainHost, _, _ := net.SplitHostPort(mainAddr)
|
var wwwRedirects []string
|
||||||
|
|
||||||
|
// extract the host names for the certificate host policy
|
||||||
|
hostNames := config.CertificateDomains
|
||||||
|
if len(hostNames) == 0 {
|
||||||
|
host, _, _ := net.SplitHostPort(mainAddr)
|
||||||
|
hostNames = append(hostNames, host)
|
||||||
|
}
|
||||||
|
for _, host := range hostNames {
|
||||||
|
if strings.HasPrefix(host, "www.") {
|
||||||
|
continue // explicitly set www host
|
||||||
|
}
|
||||||
|
|
||||||
|
wwwHost := "www." + host
|
||||||
|
if !list.ExistInSlice(wwwHost, hostNames) {
|
||||||
|
hostNames = append(hostNames, wwwHost)
|
||||||
|
wwwRedirects = append(wwwRedirects, wwwHost)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// implicit www->non-www redirect(s)
|
||||||
|
if len(wwwRedirects) > 0 {
|
||||||
|
router.Pre(func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
|
return func(c echo.Context) error {
|
||||||
|
host := c.Request().Host
|
||||||
|
|
||||||
|
if strings.HasPrefix(host, "www.") && list.ExistInSlice(host, wwwRedirects) {
|
||||||
|
return c.Redirect(
|
||||||
|
http.StatusTemporaryRedirect,
|
||||||
|
(c.Scheme() + "://" + host[4:] + c.Request().RequestURI),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return next(c)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
certManager := &autocert.Manager{
|
certManager := &autocert.Manager{
|
||||||
Prompt: autocert.AcceptTOS,
|
Prompt: autocert.AcceptTOS,
|
||||||
Cache: autocert.DirCache(filepath.Join(app.DataDir(), ".autocert_cache")),
|
Cache: autocert.DirCache(filepath.Join(app.DataDir(), ".autocert_cache")),
|
||||||
HostPolicy: autocert.HostWhitelist(mainHost, "www."+mainHost),
|
HostPolicy: autocert.HostWhitelist(hostNames...),
|
||||||
}
|
}
|
||||||
|
|
||||||
server := &http.Server{
|
server := &http.Server{
|
||||||
TLSConfig: &tls.Config{
|
TLSConfig: &tls.Config{
|
||||||
|
MinVersion: tls.VersionTLS12,
|
||||||
GetCertificate: certManager.GetCertificate,
|
GetCertificate: certManager.GetCertificate,
|
||||||
NextProtos: []string{acme.ALPNProto},
|
NextProtos: []string{acme.ALPNProto},
|
||||||
},
|
},
|
||||||
|
@ -117,8 +164,14 @@ func Serve(app core.App, config ServeConfig) (*http.Server, error) {
|
||||||
|
|
||||||
if config.ShowStartBanner {
|
if config.ShowStartBanner {
|
||||||
schema := "http"
|
schema := "http"
|
||||||
|
addr := server.Addr
|
||||||
|
|
||||||
if config.HttpsAddr != "" {
|
if config.HttpsAddr != "" {
|
||||||
schema = "https"
|
schema = "https"
|
||||||
|
|
||||||
|
if len(config.CertificateDomains) > 0 {
|
||||||
|
addr = config.CertificateDomains[0]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
date := new(strings.Builder)
|
date := new(strings.Builder)
|
||||||
|
@ -128,12 +181,12 @@ func Serve(app core.App, config ServeConfig) (*http.Server, error) {
|
||||||
bold.Printf(
|
bold.Printf(
|
||||||
"%s Server started at %s\n",
|
"%s Server started at %s\n",
|
||||||
strings.TrimSpace(date.String()),
|
strings.TrimSpace(date.String()),
|
||||||
color.CyanString("%s://%s", schema, server.Addr),
|
color.CyanString("%s://%s", schema, addr),
|
||||||
)
|
)
|
||||||
|
|
||||||
regular := color.New()
|
regular := color.New()
|
||||||
regular.Printf("├─ REST API: %s\n", color.CyanString("%s://%s/api/", schema, server.Addr))
|
regular.Printf("├─ REST API: %s\n", color.CyanString("%s://%s/api/", schema, addr))
|
||||||
regular.Printf("└─ Admin UI: %s\n", color.CyanString("%s://%s/_/", schema, server.Addr))
|
regular.Printf("└─ Admin UI: %s\n", color.CyanString("%s://%s/_/", schema, addr))
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to gracefully shutdown the server on app termination
|
// try to gracefully shutdown the server on app termination
|
||||||
|
|
22
cmd/serve.go
22
cmd/serve.go
|
@ -17,14 +17,26 @@ func NewServeCommand(app core.App, showStartBanner bool) *cobra.Command {
|
||||||
var httpsAddr string
|
var httpsAddr string
|
||||||
|
|
||||||
command := &cobra.Command{
|
command := &cobra.Command{
|
||||||
Use: "serve",
|
Use: "serve [domain(s)]",
|
||||||
Short: "Starts the web server (default to 127.0.0.1:8090)",
|
Args: cobra.ArbitraryArgs,
|
||||||
|
Short: "Starts the web server (default to 127.0.0.1:8090 if no domain is specified)",
|
||||||
Run: func(command *cobra.Command, args []string) {
|
Run: func(command *cobra.Command, args []string) {
|
||||||
|
// set default listener addresses if at least one domain is specified
|
||||||
|
if len(args) > 0 {
|
||||||
|
if httpAddr == "" {
|
||||||
|
httpAddr = "0.0.0.0:80"
|
||||||
|
}
|
||||||
|
if httpsAddr == "" {
|
||||||
|
httpsAddr = "0.0.0.0:443"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_, err := apis.Serve(app, apis.ServeConfig{
|
_, err := apis.Serve(app, apis.ServeConfig{
|
||||||
HttpAddr: httpAddr,
|
HttpAddr: httpAddr,
|
||||||
HttpsAddr: httpsAddr,
|
HttpsAddr: httpsAddr,
|
||||||
ShowStartBanner: showStartBanner,
|
ShowStartBanner: showStartBanner,
|
||||||
AllowedOrigins: allowedOrigins,
|
AllowedOrigins: allowedOrigins,
|
||||||
|
CertificateDomains: args,
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != http.ErrServerClosed {
|
if err != http.ErrServerClosed {
|
||||||
|
@ -43,15 +55,15 @@ func NewServeCommand(app core.App, showStartBanner bool) *cobra.Command {
|
||||||
command.PersistentFlags().StringVar(
|
command.PersistentFlags().StringVar(
|
||||||
&httpAddr,
|
&httpAddr,
|
||||||
"http",
|
"http",
|
||||||
"127.0.0.1:8090",
|
"",
|
||||||
"api HTTP server address",
|
"TCP address to listen for the HTTP server\n(if domain args are specified - default to 0.0.0.0:80, otherwise - default to 127.0.0.1:8090)",
|
||||||
)
|
)
|
||||||
|
|
||||||
command.PersistentFlags().StringVar(
|
command.PersistentFlags().StringVar(
|
||||||
&httpsAddr,
|
&httpsAddr,
|
||||||
"https",
|
"https",
|
||||||
"",
|
"",
|
||||||
"api HTTPS server address (auto TLS via Let's Encrypt)\nthe incoming --http address traffic also will be redirected to this address",
|
"TCP address to listen for the HTTPS server\n(if domain args are specified - default to 0.0.0.0:443, otherwise - default to empty string, aka. no TLS)\nThe incoming HTTP traffic also will be auto redirected to the HTTPS version",
|
||||||
)
|
)
|
||||||
|
|
||||||
return command
|
return command
|
||||||
|
|
Loading…
Reference in New Issue