From 55812b03940852f1f91cd0a46b5c093601c854a9 Mon Sep 17 00:00:00 2001 From: devin ivy Date: Fri, 21 Jun 2024 12:41:06 -0400 Subject: Bsky short link service (#4542) * bskylink: scaffold service w/ initial config and schema * bskylink: implement link creation and redirects * bskylink: tidy * bskylink: tests * bskylink: tidy, add error handler * bskylink: add dockerfile * bskylink: add build * bskylink: fix some express plumbing * bskyweb: proxy fallthrough routes to link service redirects * bskyweb: build w/ link proxy * Add AASA to bskylink (#4588) --------- Co-authored-by: Hailey --- bskyweb/cmd/bskyweb/main.go | 9 ++++++++- bskyweb/cmd/bskyweb/server.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) (limited to 'bskyweb') diff --git a/bskyweb/cmd/bskyweb/main.go b/bskyweb/cmd/bskyweb/main.go index 5185ff573..49629e3f2 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 bb81e780f..6d32e0e21 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{} -- cgit 1.4.1