diff --git a/auto/deps_pro-ha.yml b/auto/deps_pro-ha.yml index dbc645a..633d30d 100644 --- a/auto/deps_pro-ha.yml +++ b/auto/deps_pro-ha.yml @@ -23,8 +23,8 @@ services: container_name: openldap image: osixia/openldap:1.5.0 ports: - - '389:389' - - '636:636' + - "389:389" + - "636:636" environment: - LDAP_READONLY_USER=true - LDAP_READONLY_USER_USERNAME=read-only-admin @@ -50,8 +50,16 @@ services: profiles: ["all", "master-datacenter"] container_name: restcountries image: bigpapoo/restcountries:1.0 - + trevorblades: profiles: ["all", "master-datacenter"] container_name: trevorblades image: mangomm/trevorblades-countries + + webhook: + profiles: ["all", "master-datacenter"] + container_name: webhook-server + build: + context: ./webhook-server + ports: + - "9003:9003" diff --git a/auto/deps_pro.yml b/auto/deps_pro.yml index 82211fa..633d30d 100644 --- a/auto/deps_pro.yml +++ b/auto/deps_pro.yml @@ -1,6 +1,5 @@ version: "3.9" services: - bundle-server: profiles: ["all", "master-datacenter"] container_name: bundle-server @@ -24,8 +23,8 @@ services: container_name: openldap image: osixia/openldap:1.5.0 ports: - - '389:389' - - '636:636' + - "389:389" + - "636:636" environment: - LDAP_READONLY_USER=true - LDAP_READONLY_USER_USERNAME=read-only-admin @@ -51,8 +50,16 @@ services: profiles: ["all", "master-datacenter"] container_name: restcountries image: bigpapoo/restcountries:1.0 - + trevorblades: profiles: ["all", "master-datacenter"] container_name: trevorblades image: mangomm/trevorblades-countries + + webhook: + profiles: ["all", "master-datacenter"] + container_name: webhook-server + build: + context: ./webhook-server + ports: + - "9003:9003" diff --git a/auto/webhook-server/Dockerfile b/auto/webhook-server/Dockerfile new file mode 100644 index 0000000..3172019 --- /dev/null +++ b/auto/webhook-server/Dockerfile @@ -0,0 +1,17 @@ +# Use the official Golang image as the build stage +FROM golang:alpine as builder + +# Set the Current Working Directory inside the container +WORKDIR /app + +# Copy the source code into the container +COPY . . + +# Build the Go app +RUN go build -o webhook . + +# Expose port 9003 to the outside world +EXPOSE 9003 + +# Command to run the executable +CMD ["./webhook"] diff --git a/auto/webhook-server/README.md b/auto/webhook-server/README.md new file mode 100644 index 0000000..2eacfba --- /dev/null +++ b/auto/webhook-server/README.md @@ -0,0 +1,61 @@ +# Webhook Server + +A simple Go application to receive and store webhook events, and retrieve them based on an ID. + +## Features + +- Receives webhook events at `/webhook/{id}` +- Stores requests associated with each `{id}` +- Retrieves stored requests at `/requests/{id}` + + +## Usage + +### Start webhook server + +`go run main.go` runs the webhook server listening on port `8080`. + +### Sending a Webhook Event + +Send a POST request to `/webhook/{id}` with your webhook payload: + +``` +curl -X POST http://localhost:8080/webhook/1 \ + -H "Content-Type: application/json" \ + -d '{"event": "test"}' +``` + +### Retrieving Stored Requests +Send a GET request to `/requests/{id}` to retrieve the requests stored for a particular ID (ID is of string type) +``` +curl http://localhost:8080/requests/1 +``` + +This will return a JSON array of all received webhook requests for the given ID. + +### Example +1. Send a webhook event to ID `wh-1`: + +``` +curl -X POST http://localhost:8080/webhook/wh-1 \ + -H "Content-Type: application/json" \ + -d '{"event": "test event for ID wh-1"}' +``` + +2. Retrieve stored requests for ID `wh-1`: +``` +curl http://localhost:8080/requests/wh-1 +``` + +Response +``` +[ + { + "headers": { + "Content-Type": ["application/json"], + ... + }, + "body": {"event": "test event for ID wh-1"} + } +] +``` \ No newline at end of file diff --git a/auto/webhook-server/go.mod b/auto/webhook-server/go.mod new file mode 100644 index 0000000..5d2c5e7 --- /dev/null +++ b/auto/webhook-server/go.mod @@ -0,0 +1,3 @@ +module webhook + +go 1.22.0 diff --git a/auto/webhook-server/main.go b/auto/webhook-server/main.go new file mode 100644 index 0000000..bd90e2c --- /dev/null +++ b/auto/webhook-server/main.go @@ -0,0 +1,82 @@ +package main + +import ( + "encoding/json" + "fmt" + "io" + "log" + "net/http" + "regexp" + "sync" +) + +const root = "root" + +type WebhookRequest struct { + Headers map[string][]string `json:"headers"` + Body json.RawMessage `json:"body"` +} + +var ( + receivedRequests = make(map[string][]WebhookRequest) + mutex sync.Mutex + idPattern = regexp.MustCompile(`^/webhook/(\d+)$`) + requestPattern = regexp.MustCompile(`^/requests/(\d+)$`) +) + +func webhookHandler(w http.ResponseWriter, r *http.Request) { + body, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, "couldn't read body", http.StatusBadRequest) + return + } + + matches := idPattern.FindStringSubmatch(r.URL.Path) + id := root + if len(matches) >= 2 { + id = matches[1] + } + + request := WebhookRequest{ + Headers: r.Header, + Body: body, + } + + mutex.Lock() + receivedRequests[id] = append(receivedRequests[id], request) + mutex.Unlock() + + w.WriteHeader(http.StatusOK) +} + +func requestsHandler(w http.ResponseWriter, r *http.Request) { + matches := requestPattern.FindStringSubmatch(r.URL.Path) + id := root + if len(matches) >= 2 { + id = matches[1] + } + + log.Println("id =", id) + + mutex.Lock() + defer mutex.Unlock() + + requests, exists := receivedRequests[id] + if !exists { + http.Error(w, "No requests found for the given ID", http.StatusNotFound) + return + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(requests) +} + +func main() { + http.HandleFunc("/webhook/", webhookHandler) + http.HandleFunc("/requests/", requestsHandler) + + fmt.Println("Starting server on :9003") + if err := http.ListenAndServe(":9003", nil); err != nil { + log.Fatalf("Could not start server: %s\n", err) + } +}