diff --git a/bskyweb/cmd/bskyweb/main.go b/bskyweb/cmd/bskyweb/main.go index 5185ff573a..49629e3f2b 100644 --- a/bskyweb/cmd/bskyweb/main.go +++ b/bskyweb/cmd/bskyweb/main.go @@ -35,7 +35,7 @@ func run(args []string) { Flags: []cli.Flag{ &cli.StringFlag{ Name: "appview-host", - Usage: "method, hostname, and port of PDS instance", + Usage: "scheme, hostname, and port of PDS instance", Value: "http://localhost:2584", // retain old PDS env var for easy transition EnvVars: []string{"ATP_APPVIEW_HOST", "ATP_PDS_HOST"}, @@ -47,6 +47,13 @@ func run(args []string) { Value: ":8100", EnvVars: []string{"HTTP_ADDRESS"}, }, + &cli.StringFlag{ + Name: "link-host", + Usage: "scheme, hostname, and port of link service", + Required: false, + Value: "", + EnvVars: []string{"LINK_HOST"}, + }, &cli.BoolFlag{ Name: "debug", Usage: "Enable debug mode", diff --git a/bskyweb/cmd/bskyweb/server.go b/bskyweb/cmd/bskyweb/server.go index bb81e780f5..6d32e0e212 100644 --- a/bskyweb/cmd/bskyweb/server.go +++ b/bskyweb/cmd/bskyweb/server.go @@ -6,6 +6,7 @@ import ( "fmt" "io/fs" "net/http" + "net/url" "os" "os/signal" "strings" @@ -36,6 +37,7 @@ func serve(cctx *cli.Context) error { debug := cctx.Bool("debug") httpAddress := cctx.String("http-address") appviewHost := cctx.String("appview-host") + linkHost := cctx.String("link-host") // Echo e := echo.New() @@ -221,6 +223,14 @@ func serve(cctx *cli.Context) error { e.GET("/profile/:handleOrDID/post/:rkey/liked-by", server.WebGeneric) e.GET("/profile/:handleOrDID/post/:rkey/reposted-by", server.WebGeneric) + if linkHost != "" { + linkUrl, err := url.Parse(linkHost) + if err != nil { + return err + } + e.Group("/:linkId", server.LinkProxyMiddleware(linkUrl)) + } + // Start the server. log.Infof("starting server address=%s", httpAddress) go func() { @@ -292,6 +302,30 @@ func (srv *Server) Download(c echo.Context) error { return c.Redirect(http.StatusFound, "/") } +// Handler for proxying top-level paths to link service, which ends up serving a redirect +func (srv *Server) LinkProxyMiddleware(url *url.URL) echo.MiddlewareFunc { + return middleware.ProxyWithConfig( + middleware.ProxyConfig{ + Balancer: middleware.NewRoundRobinBalancer( + []*middleware.ProxyTarget{{URL: url}}, + ), + Skipper: func(c echo.Context) bool { + req := c.Request() + if req.Method == "GET" && + strings.LastIndex(strings.TrimRight(req.URL.Path, "/"), "/") == 0 && // top-level path + !strings.HasPrefix(req.URL.Path, "/_") { // e.g. /_health endpoint + return false + } + return true + }, + RetryCount: 2, + ErrorHandler: func(c echo.Context, err error) error { + return c.Redirect(302, "/") + }, + }, + ) +} + // handler for endpoint that have no specific server-side handling func (srv *Server) WebGeneric(c echo.Context) error { data := pongo2.Context{}