Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import (
"context"
"encoding/json"
"fmt"
"net/http"
"os"
"os/signal"
"strings"
Expand Down Expand Up @@ -61,6 +63,7 @@

// Service configuration
GRPCPort int `help:"gRPC service port" default:"8080" env:"GRPC_PORT"`
HTTPPort int `help:"HTTP API port for health checks and scan triggers" default:"8081" env:"HTTP_PORT"`

// Tag configuration (comma-separated lists for AWS resource tags)
TagAppKeys string `help:"Comma-separated tag keys for application/service name" default:"app,application,service" env:"TAG_APP_KEYS"`
Expand Down Expand Up @@ -342,12 +345,52 @@
return fmt.Errorf("failed to start worker: %w", err)
}

// Start HTTP API server for health checks and scan triggers
mux := http.NewServeMux()
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprintln(w, "ok")
})
mux.HandleFunc("/scan", func(hw http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(hw, "method not allowed", http.StatusMethodNotAllowed)
return
}
workflowID := fmt.Sprintf("version-guard-scan-%d", time.Now().Unix())
run, err := temporalClient.ExecuteWorkflow(
context.Background(),
client.StartWorkflowOptions{
ID: workflowID,
TaskQueue: s.TemporalTaskQueue,
},
orchestrator.OrchestratorWorkflowType,
)
if err != nil {
http.Error(hw, fmt.Sprintf("failed to start workflow: %v", err), http.StatusInternalServerError)
return
}
hw.Header().Set("Content-Type", "application/json")
json.NewEncoder(hw).Encode(map[string]string{

Check failure on line 373 in cmd/server/main.go

View workflow job for this annotation

GitHub Actions / Test

Error return value of `(*encoding/json.Encoder).Encode` is not checked (errcheck)
"workflow_id": workflowID,
"run_id": run.GetRunID(),
"status": "started",
})
})
httpServer := &http.Server{Addr: fmt.Sprintf(":%d", s.HTTPPort), Handler: mux}

Check failure on line 379 in cmd/server/main.go

View workflow job for this annotation

GitHub Actions / Test

G112: Potential Slowloris Attack because ReadHeaderTimeout is not configured in the http.Server (gosec)
go func() {
fmt.Printf("✓ HTTP API listening on :%d (GET /healthz, POST /scan)\n", s.HTTPPort)
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
fmt.Fprintf(os.Stderr, "HTTP server error: %v\n", err)
}
}()

// Wait for interrupt signal
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
<-sigChan

fmt.Println("\n\nShutting down gracefully...")
httpServer.Shutdown(context.Background())

Check failure on line 393 in cmd/server/main.go

View workflow job for this annotation

GitHub Actions / Test

Error return value of `httpServer.Shutdown` is not checked (errcheck)
w.Stop()
//nolint:gocritic // Intentionally commented - template for future gRPC implementation
// grpcServer.GracefulStop() // Uncomment when gRPC server is enabled
Expand Down
Loading