clone

a self-hosted multitenant nostr relay with sites, file storage, git hosting, and inbox and outbox delivery

feat/standalone-relay
tinyrelay / cmd / tinyclient / main.go
main.go 2.0K
1// Command tinyclient runs the standalone, server-rendered relay website.2package main34import (5 "context"6 "errors"7 "flag"8 "fmt"9 "io"10 "net"11 "net/http"12 "os"13 "os/signal"14 "syscall"15 "time"1617 "github.com/FelineStateMachine/tinyrelay/tinyclient"18)1920func configure(args []string, output io.Writer) (*http.Server, error) {21 flags := flag.NewFlagSet("tinyclient", flag.ContinueOnError)22 flags.SetOutput(output)23 listen := flags.String("listen", "127.0.0.1:8081", "HTTP listen address")24 backend := flags.String("backend", "", "Upstream tinyrelay backend HTTP URL, including /r/<tenant> when used")25 public := flags.String("public-url", "", "Browser-facing HTTP(S) URL; preserve the relay's public origin and tenant path")26 if err := flags.Parse(args); err != nil {27 return nil, err28 }29 if flags.NArg() != 0 {30 return nil, errors.New("tinyclient accepts flags only")31 }32 handler, err := tinyclient.NewRemote(tinyclient.RemoteOptions{BackendURL: *backend, PublicURL: *public})33 if err != nil {34 return nil, err35 }36 return &http.Server{Addr: *listen, Handler: handler, ReadHeaderTimeout: 10 * time.Second, IdleTimeout: 90 * time.Second}, nil37}3839func run(ctx context.Context, args []string, output io.Writer) error {40 server, err := configure(args, output)41 if err != nil {42 return err43 }44 listener, err := net.Listen("tcp", server.Addr)45 if err != nil {46 return err47 }48 defer listener.Close()49 fmt.Fprintf(output, "tinyclient listening on %s\n", listener.Addr())50 done := make(chan struct{})51 defer close(done)52 go func() {53 select {54 case <-ctx.Done():55 shutdown, cancel := context.WithTimeout(context.Background(), 10*time.Second)56 defer cancel()57 _ = server.Shutdown(shutdown)58 case <-done:59 }60 }()61 err = server.Serve(listener)62 if errors.Is(err, http.ErrServerClosed) {63 return nil64 }65 return err66}6768func main() {69 ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)70 defer cancel()71 if err := run(ctx, os.Args[1:], os.Stderr); err != nil && !errors.Is(err, flag.ErrHelp) {72 fmt.Fprintln(os.Stderr, "tinyclient:", err)73 os.Exit(1)74 }75}