| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- package main
- import (
- "bufio"
- "fmt"
- "io"
- "log"
- "net/http"
- "os"
- "path"
- "strings"
- "time"
- )
- func loadDotEnvIfExists(filename string) bool {
- f, err := os.Open(filename)
- if err != nil {
- return false
- }
- defer f.Close()
- scanner := bufio.NewScanner(f)
- for scanner.Scan() {
- line := strings.TrimSpace(scanner.Text())
- if line == "" || strings.HasPrefix(line, "#") {
- continue
- }
- k, v, ok := strings.Cut(line, "=")
- if !ok {
- continue
- }
- k = strings.TrimSpace(k)
- v = strings.TrimSpace(v)
- v = strings.Trim(v, "\"'")
- if k == "" {
- continue
- }
- if _, exists := os.LookupEnv(k); exists {
- continue
- }
- _ = os.Setenv(k, v)
- }
- return true
- }
- func envOr(key, def string) string {
- if v, ok := os.LookupEnv(key); ok {
- v = strings.TrimSpace(v)
- if v != "" {
- return v
- }
- }
- return def
- }
- func normalizeHookPath(p string) string {
- p = strings.TrimSpace(p)
- if p == "" {
- return "/hook"
- }
- p = "/" + strings.TrimLeft(p, "/")
- p = path.Clean(p)
- if p == "." {
- return "/hook"
- }
- return p
- }
- func main() {
- _ = loadDotEnvIfExists(".env") || loadDotEnvIfExists("../.env")
- port := envOr("PORT", "8080")
- hookPath := normalizeHookPath(envOr("HOOK_PATH", "/hook"))
- mux := http.NewServeMux()
- mux.HandleFunc(hookPath, func(w http.ResponseWriter, r *http.Request) {
- if r.Method != http.MethodPost {
- w.Header().Set("Allow", http.MethodPost)
- http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
- return
- }
- body, err := io.ReadAll(r.Body)
- if err != nil {
- http.Error(w, "failed to read body", http.StatusBadRequest)
- return
- }
- ts := time.Now().Format(time.RFC3339Nano)
- log.Printf("hook received ts=%s bytes=%d payload=%s", ts, len(body), string(body))
- w.Header().Set("Content-Type", "application/json")
- _, _ = w.Write([]byte("{\"ok\":true}"))
- })
- mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- _, _ = w.Write([]byte("{\"status\":\"up\"}"))
- })
- addr := ":" + port
- fmt.Printf("Listening on http://localhost%s\n", addr)
- fmt.Printf("Hook URL: http://localhost%s%s\n", addr, hookPath)
- srv := &http.Server{
- Addr: addr,
- Handler: mux,
- ReadHeaderTimeout: 5 * time.Second,
- }
- log.Fatal(srv.ListenAndServe())
- }
|