package main import ( "fmt" "net" "os" "os/signal" "strconv" "syscall" "time" "github.com/gofiber/fiber/v2" "github.com/kanna5/qrtxt" ) func getLocalAddr() (string, error) { conn, err := net.Dial("udp", "1.0.0.1:53") if err != nil { return "", err } defer conn.Close() host, _, err := net.SplitHostPort(conn.LocalAddr().String()) return host, err } func serve(port int) (*fiber.App, <-chan error) { ch := make(chan error) app := fiber.New(fiber.Config{ AppName: "StaticFileServer", BodyLimit: 1, DisableStartupMessage: true, ReadTimeout: 5 * time.Second, RequestMethods: []string{"GET", "HEAD"}, ServerHeader: "StaticFileServer", }) app.Static("/", "./", fiber.Static{ Browse: true, ByteRange: true, }) go func() { defer close(ch) ch <- app.Listen(":" + strconv.Itoa(port)) }() return app, ch } func main() { listenPort := 8080 var err error if len(os.Args) >= 2 { portStr := os.Args[1] listenPort, err = strconv.Atoi(portStr) } if err != nil { panic(fmt.Errorf("Cannot parse port number: %w", err)) } if listenPort < 1 || listenPort > 65535 { panic(fmt.Errorf("Invalid port number: %d", listenPort)) } localAddr, err := getLocalAddr() if err != nil { panic(fmt.Errorf("Cannot get local address: %w", err)) } fullAddress := fmt.Sprintf("http://%s:%d/", localAddr, listenPort) app, errCh := serve(listenPort) // Early check to see if the server is started successfully. This might not be reliable select { case err := <-errCh: panic(fmt.Errorf("Cannot start server: %w", err)) case <-time.After(1 * time.Millisecond): } if qrText, err := qrtxt.Encode(fullAddress, qrtxt.Low); err == nil { fmt.Println(qrText) } fmt.Printf("\nListening on %s\n", fullAddress) sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM) go func() { <-sigCh _ = app.Shutdown() }() err, ok := <-errCh if !ok { panic("Server closed unexpectedly") } if err != nil { panic(fmt.Errorf("Failed to run server: %w", err)) } fmt.Println("Bye!") }