http and common
Build and Publish / BuildAndDeployAmd64 (push) Failing after 5s
Build and Publish / BuildAndDeployArm64 (push) Failing after 14s

This commit is contained in:
2026-07-18 23:23:27 +02:00
parent c150ac635c
commit 81569b051a
9 changed files with 207 additions and 328 deletions
+14 -17
View File
@@ -2,7 +2,6 @@ package main
import (
"context"
"errors"
"log"
"net/http"
"os"
@@ -10,6 +9,8 @@ import (
"git.k6n.net/mats/go-cart-actor/pkg/backofficeadmin"
"git.k6n.net/mats/platform/config"
"git.k6n.net/mats/platform/httpclient"
"git.k6n.net/mats/platform/httpserver"
"git.k6n.net/mats/platform/rabbit"
)
@@ -41,21 +42,14 @@ func main() {
})
// Global CORS middleware allowing all origins and handling preflight.
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With")
w.Header().Set("Access-Control-Expose-Headers", "*")
if r.Method == http.MethodOptions {
w.WriteHeader(http.StatusNoContent)
return
}
mux.ServeHTTP(w, r)
})
srv := &http.Server{
Addr: addr,
Handler: handler,
Addr: addr,
Handler: httpclient.CORS(
httpclient.WithOrigin("*"),
httpclient.WithMethods("GET, POST, PUT, PATCH, DELETE, OPTIONS"),
httpclient.WithHeaders("Content-Type, Authorization, X-Requested-With"),
httpclient.WithExposeHeaders("*"),
)(mux),
ReadTimeout: 15 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 60 * time.Second,
@@ -70,6 +64,7 @@ func main() {
if err != nil {
log.Fatalf("failed to connect to RabbitMQ: %v", err)
}
defer conn.Close()
}
if err := app.Start(ctx, conn); err != nil {
log.Printf("AMQP listener disabled: %v", err)
@@ -78,7 +73,9 @@ func main() {
}
log.Printf("backoffice HTTP listening on %s", addr)
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatalf("http server error: %v", err)
if err := httpserver.RunServerWithShutdown(srv, "cart-backoffice", 10*time.Second, 5*time.Second,
func(context.Context) error { cancel(); return nil },
); err != nil {
log.Fatalf("server: %v", err)
}
}
+11 -32
View File
@@ -5,7 +5,6 @@ import (
"encoding/json"
"fmt"
"log"
"net"
"net/http"
"net/http/pprof"
"os"
@@ -26,6 +25,7 @@ import (
"git.k6n.net/mats/platform/catalog"
"git.k6n.net/mats/platform/config"
"git.k6n.net/mats/platform/event"
"git.k6n.net/mats/platform/httpserver"
"git.k6n.net/mats/platform/rabbit"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/redis/go-redis/v9"
@@ -524,9 +524,11 @@ func main() {
httpAddr := normalizeListenAddr(cartPort)
debugAddr := normalizeListenAddr(config.EnvString("CART_DEBUG_PORT", "8081"))
// Debug mux on separate port (metrics + pprof).
go http.ListenAndServe(debugAddr, debugMux)
srv := &http.Server{
Addr: httpAddr,
BaseContext: func(net.Listener) context.Context { return ctx },
ReadTimeout: 10 * time.Second,
// Close idle keep-alive connections so a load test with many short-lived
// clients doesn't pin file handles open indefinitely.
@@ -535,38 +537,15 @@ func main() {
Handler: otelhttp.NewHandler(mux, "/"),
}
defer func() {
fmt.Println("Shutting down due to signal")
otelShutdown(context.Background())
diskStorage.Close()
pool.Close()
}()
srvErr := make(chan error, 1)
go func() {
srvErr <- srv.ListenAndServe()
}()
// Inventory change consumption used to live here over the bare Redis
// `inventory_changed` channel; it is now owned by the cart-inventory
// service, which translates quantity changes into inventory.level_changed
// bus crossings. The cart reads exact stock synchronously when it needs it.
// See docs/inventory-shape.md.
log.Printf("Server started at %s (debug %s)", httpAddr, debugAddr)
go http.ListenAndServe(debugAddr, debugMux)
select {
case err = <-srvErr:
// Error when starting HTTP server.
log.Fatalf("Unable to start server: %v", err)
case <-ctx.Done():
// Wait for first CTRL+C.
// Stop receiving signal notifications as soon as possible.
stop()
if err := httpserver.RunServerWithShutdown(srv, "cart", 15*time.Second, 5*time.Second,
func(context.Context) error { stop(); return nil },
func(context.Context) error { otelShutdown(context.Background()); return nil },
func(context.Context) error { diskStorage.Close(); return nil },
func(context.Context) error { pool.Close(); return nil },
); err != nil {
log.Fatalf("server: %v", err)
}
}
-8
View File
@@ -55,14 +55,6 @@ func getOriginalHost(r *http.Request) string {
return r.Host
}
func getClientIp(r *http.Request) string {
ip := r.Header.Get("X-Forwarded-For")
if ip == "" {
ip = r.RemoteAddr
}
return ip
}
func CookieCartIdHandler(fn func(cartId cart.CartId, w http.ResponseWriter, r *http.Request) error) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
+2 -1
View File
@@ -9,6 +9,7 @@ import (
"git.k6n.net/mats/go-cart-actor/pkg/cart"
"git.k6n.net/mats/go-cart-actor/pkg/checkout"
"git.k6n.net/mats/platform/httpclient"
"git.k6n.net/mats/platform/tax"
adyenCheckout "github.com/adyen/adyen-go-api-library/v21/src/checkout"
"github.com/adyen/adyen-go-api-library/v21/src/common"
@@ -233,7 +234,7 @@ func GetCheckoutMetaFromRequest(r *http.Request) *CheckoutMeta {
siteUrl = checkoutPublicURL
}
return &CheckoutMeta{
ClientIp: getClientIp(r),
ClientIp: httpclient.ClientIP(r),
SiteUrl: siteUrl,
CallbackBaseUrl: checkoutCallbackBaseURL,
Country: country,
+11 -21
View File
@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"log"
"net"
"net/http"
"os"
"os/signal"
@@ -17,6 +16,7 @@ import (
"git.k6n.net/mats/go-cart-actor/pkg/telemetry"
redisinv "git.k6n.net/mats/go-redis-inventory/pkg/inventory"
"git.k6n.net/mats/platform/config"
"git.k6n.net/mats/platform/httpserver"
"git.k6n.net/mats/platform/rabbit"
"git.k6n.net/mats/platform/tax"
"github.com/adyen/adyen-go-api-library/v21/src/adyen"
@@ -293,35 +293,25 @@ func main() {
w.Write([]byte("1.0.0"))
})
// Debug mux on separate port (metrics + pprof).
go http.ListenAndServe(":8081", debugMux)
srv := &http.Server{
Addr: ":8080",
BaseContext: func(net.Listener) context.Context { return ctx },
ReadTimeout: 10 * time.Second,
WriteTimeout: 20 * time.Second,
Handler: otelhttp.NewHandler(mux, "/"),
}
defer func() {
fmt.Println("Shutting down due to signal")
otelShutdown(context.Background())
diskStorage.Close()
pool.Close()
}()
srvErr := make(chan error, 1)
go func() {
srvErr <- srv.ListenAndServe()
}()
log.Print("Checkout server started at port 8080")
go http.ListenAndServe(":8081", debugMux)
select {
case err = <-srvErr:
log.Fatalf("Unable to start server: %v", err)
case <-ctx.Done():
stop()
if err := httpserver.RunServerWithShutdown(srv, "checkout", 15*time.Second, 5*time.Second,
func(context.Context) error { stop(); return nil },
func(context.Context) error { otelShutdown(context.Background()); return nil },
func(context.Context) error { diskStorage.Close(); return nil },
func(context.Context) error { pool.Close(); return nil },
); err != nil {
log.Fatalf("server: %v", err)
}
}
-8
View File
@@ -36,14 +36,6 @@ func getScheme(r *http.Request) string {
return "https"
}
func getClientIp(r *http.Request) string {
ip := r.Header.Get("X-Forwarded-For")
if ip == "" {
ip = r.RemoteAddr
}
return ip
}
func getCurrency(country string) string {
if country == "no" {
return "NOK"
+11 -22
View File
@@ -4,9 +4,7 @@ import (
"context"
"crypto/rand"
"encoding/hex"
"fmt"
"log"
"net"
"net/http"
"net/mail"
"os"
@@ -22,6 +20,7 @@ import (
"git.k6n.net/mats/go-cart-actor/pkg/proxy"
"git.k6n.net/mats/go-cart-actor/pkg/telemetry"
"git.k6n.net/mats/platform/config"
"git.k6n.net/mats/platform/httpserver"
"git.k6n.net/mats/platform/rabbit"
"github.com/redis/go-redis/v9"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
@@ -311,35 +310,25 @@ func main() {
w.Write([]byte("1.0.0"))
})
// Debug mux on separate port (metrics + pprof).
go http.ListenAndServe(":8081", debugMux)
srv := &http.Server{
Addr: config.EnvString("PROFILE_ADDR", ":8080"),
BaseContext: func(net.Listener) context.Context { return ctx },
ReadTimeout: 10 * time.Second,
WriteTimeout: 20 * time.Second,
Handler: otelhttp.NewHandler(mux, "/"),
}
defer func() {
fmt.Println("Shutting down profile service")
otelShutdown(context.Background())
diskStorage.Close()
pool.Close()
}()
srvErr := make(chan error, 1)
go func() {
srvErr <- srv.ListenAndServe()
}()
log.Print("Profile server started at port 8080")
go http.ListenAndServe(":8081", debugMux)
select {
case err = <-srvErr:
log.Fatalf("Unable to start server: %v", err)
case <-ctx.Done():
stop()
if err := httpserver.RunServerWithShutdown(srv, "profile", 15*time.Second, 5*time.Second,
func(context.Context) error { stop(); return nil },
func(context.Context) error { otelShutdown(context.Background()); return nil },
func(context.Context) error { diskStorage.Close(); return nil },
func(context.Context) error { pool.Close(); return nil },
); err != nil {
log.Fatalf("server: %v", err)
}
}