commit eae5f6165d9358f97386c987bde7450c210b97a1 Author: stackops Date: Thu Apr 9 16:53:42 2026 +0300 api-gateway with depends_on users-api diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c8f1b21 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM golang:1.25-alpine AS builder +WORKDIR /src +COPY go.mod ./ +RUN go mod download +COPY . . +RUN go build -o /api-gateway . + +FROM alpine:3.20 +RUN apk add --no-cache ca-certificates +COPY --from=builder /api-gateway /usr/local/bin/api-gateway +EXPOSE 8080 +ENTRYPOINT ["api-gateway"] diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..7003075 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module api-gateway + +go 1.25.6 diff --git a/main.go b/main.go new file mode 100644 index 0000000..f693b77 --- /dev/null +++ b/main.go @@ -0,0 +1,95 @@ +package main + +import ( + "fmt" + "io" + "log" + "net/http" + "os" + "time" +) + +func env(key, fallback string) string { + if v := os.Getenv(key); v != "" { + return v + } + return fallback +} + +type status struct { + Service string `json:"service"` + OK bool `json:"ok"` + Data string `json:"data"` +} + +func fetchUsers(usersURL string) status { + client := &http.Client{Timeout: 5 * time.Second} + resp, err := client.Get(usersURL + "/users") + if err != nil { + return status{"users-api", false, fmt.Sprintf("error: %v", err)} + } + defer resp.Body.Close() + body, _ := io.ReadAll(resp.Body) + if resp.StatusCode != 200 { + return status{"users-api", false, fmt.Sprintf("status %d: %s", resp.StatusCode, body)} + } + return status{"users-api", true, string(body)} +} + +func main() { + usersURL := env("USERS_API_URL", "http://users-api:8080") + + http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + }) + + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/healthz" { + w.WriteHeader(200) + return + } + + users := fetchUsers(usersURL) + + w.Header().Set("Content-Type", "text/html; charset=utf-8") + fmt.Fprintf(w, ` + + + API Gateway + + + +

API Gateway

+

Service-to-service communication test

+`) + cls := "ok" + if !users.OK { + cls = "fail" + } + fmt.Fprintf(w, `
+
%s
+
→ %s
+
%s
+
+`, cls, users.Service, usersURL, users.Data) + + fmt.Fprintf(w, `
Checked at %s
+`, time.Now().Format(time.RFC3339)) + }) + + port := env("PORT", "8080") + log.Printf("api-gateway listening on :%s", port) + log.Fatal(http.ListenAndServe(":"+port, nil)) +} diff --git a/stackfile.toml b/stackfile.toml new file mode 100644 index 0000000..1ceaabd --- /dev/null +++ b/stackfile.toml @@ -0,0 +1,17 @@ +[app] +name = "api-gateway" +image = "git.nodeup.ru/stackops/api-gateway:latest" +replicas = 1 +port = 8080 + +[depends_on.services] +users-api = 8080 + +[ingress] +host = "gateway.app.nodeup.ru" +path = "/" +tls = true + +[health] +liveness = "/healthz" +readiness = "/healthz"