this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(server) init cli to start http server

eagleusb 15fb8d85 8293104e

+113
+3
go.mod
··· 1 + module github.com/eagleusb/proxycon 2 + 3 + go 1.26
+50
internal/handlers/server.go
··· 1 + package handlers 2 + 3 + import ( 4 + "log/slog" 5 + "net/http" 6 + 7 + "github.com/eagleusb/proxycon/internal/data" 8 + ) 9 + 10 + // HttpServer holds dependencies for HTTP handlers. 11 + type HttpServer struct { 12 + datasource *data.BitcoinPrices 13 + pageSize int 14 + serveMux *http.ServeMux 15 + } 16 + 17 + // NewHttpServer returns the http api 18 + func NewHttpServer(p *data.BitcoinPrices, pageSize int) *HttpServer { 19 + return &HttpServer{ 20 + datasource: p, 21 + pageSize: pageSize, 22 + serveMux: http.NewServeMux(), 23 + } 24 + } 25 + 26 + func (h *HttpServer) Listen(addr string) error { 27 + h.registerHandler() 28 + 29 + s := &http.Server{ 30 + Addr: addr, 31 + Handler: h.serveMux, 32 + Protocols: &http.Protocols{}, 33 + } 34 + 35 + s.Protocols.SetHTTP2(true) 36 + s.Protocols.SetUnencryptedHTTP2(true) 37 + 38 + slog.Debug("http server protocol", "http2", s.Protocols.HTTP2(), "unencrypted", s.Protocols.UnencryptedHTTP2()) 39 + 40 + if err := s.ListenAndServe(); err != nil { 41 + return err 42 + } 43 + 44 + return nil 45 + } 46 + 47 + func (h *HttpServer) registerHandler() { 48 + h.serveMux.HandleFunc("GET /list", h.listEndpoint) 49 + h.serveMux.HandleFunc("GET /price", h.priceEndpoint) 50 + }
+60
main.go
··· 1 + package main 2 + 3 + import ( 4 + "context" 5 + "flag" 6 + "log/slog" 7 + "os" 8 + "strconv" 9 + "time" 10 + 11 + . "github.com/eagleusb/proxycon/internal/data" 12 + . "github.com/eagleusb/proxycon/internal/handlers" 13 + ) 14 + 15 + var ( 16 + version = "dev" 17 + buildTime = "unknown" 18 + ) 19 + 20 + func main() { 21 + port := flag.Int("port", 8080, "HTTP listening port") 22 + verbose := flag.Bool("verbose", false, "enable DEBUG log level") 23 + page := flag.Int("page", 10, "page size for /list endpoint") 24 + versionFlag := flag.Bool("version", false, "print version and exit") 25 + 26 + flag.Parse() 27 + 28 + if *versionFlag { 29 + slog.Info("proxycon version", "vers", version, "built", buildTime) 30 + os.Exit(0) 31 + } 32 + 33 + if *port <= 1024 || *port > 65535 { 34 + slog.Error("invalid port number", "port", *port) 35 + os.Exit(1) 36 + } 37 + 38 + opts := &slog.HandlerOptions{Level: slog.LevelInfo} 39 + if *verbose { 40 + opts.Level = slog.LevelDebug 41 + } 42 + logger := slog.New(slog.NewTextHandler(os.Stdout, opts)) 43 + slog.SetDefault(logger) 44 + 45 + datasource := NewBitcoinPrices() 46 + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) 47 + defer cancel() 48 + 49 + if err := datasource.SetPrices(ctx); err != nil { 50 + slog.Error("failed to fetch prices from datasource", "error", err) 51 + os.Exit(1) 52 + } 53 + 54 + addr := ":" + strconv.Itoa(*port) 55 + slog.Info("starting proxycon", "addr", addr, "page_size", *page, "version", version) 56 + if err := NewHttpServer(datasource, *page).Listen(addr); err != nil { 57 + slog.Error("proxycon init failed", "error", err) 58 + os.Exit(1) 59 + } 60 + }