pkg/gateway/proxy/testdata/sse_server.go
Source
- Package:
testdata - File:
pkg/gateway/proxy/testdata/sse_server.go - GitHub: https://github.com/theroutercompany/api_router/blob/main/pkg/gateway/proxy/testdata/sse_server.go
Overview
What: Test-only upstream handler that emits Server-Sent Events (SSE).
Why:
SSE is a long-lived streaming protocol that depends on:
- correct
text/event-streamcontent type - periodic flushes
- request cancellation propagation
This handler exists so proxy tests can validate that the gateway forwards SSE streams correctly without buffering and without requiring an external upstream.
How:
NewSSEServer() returns an http.Handler that:
- validates flush support
- sets standard SSE response headers
- emits a small JSON payload every tick using the SSE wire format
- flushes each event
- stops after a small number of messages (or when the client cancels)
Notes:
The handler uses math/rand to vary a small hint field. The randomness is not used for assertions;
it simply ensures the payload is not constant and exercises JSON encoding.
Contents
Imports
import block 1
import (
"encoding/json"
"fmt"
"math/rand"
"net/http"
"time"
)
Functions and Methods
NewSSEServer
What: Constructs an SSE handler suitable for proxy streaming tests.
Why: Provides a deterministic, local SSE upstream to exercise the gateway's proxying of event streams.
How: Returns an http.HandlerFunc that writes SSE frames (id, event, data) on a timer, flushing after each frame and stopping after a small number of events.
Notes: SSE requires http.Flusher; the handler returns 500 if flushing is unsupported.
func NewSSEServer() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
flusher, ok := w.(http.Flusher)
if !ok {
http.Error(w, "streaming unsupported", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
ticker := time.NewTicker(50 * time.Millisecond)
defer ticker.Stop()
type payload struct {
ID int `json:"id"`
Hint string `json:"hint"`
}
sent := 0
for {
select {
case <-r.Context().Done():
return
case <-ticker.C:
sent++
message := payload{ID: sent, Hint: fmt.Sprintf("seed-%d", rand.Intn(100))}
data, _ := json.Marshal(message)
fmt.Fprintf(w, "id: %d\nevent: tick\ndata: %s\n\n", sent, data)
flusher.Flush()
if sent >= 5 {
return
}
}
}
})
}
Walkthrough
The list below documents the statements inside the function body, including nested blocks and inline closures.
- L13:
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { flusher, ok := w.(http.Flusher) if !ok { http.Error(w, "streaming un…- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values). - Nested steps:
- L13:
func(w http.ResponseWriter, r *http.Request) { flusher, ok := w.(http.Flusher) if !ok { http.Error(w, "streaming unsupported", http.StatusI…- What: Defines an inline function (closure).
- Why: Encapsulates callback logic and may capture variables from the surrounding scope.
- How: Declares a
funcliteral and uses it as a value (for example, as an HTTP handler or callback). - Nested steps:
- L14:
flusher, ok := w.(http.Flusher)- What: Defines flusher, ok.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L15:
if !ok { http.Error(w, "streaming unsupported", http.StatusInternalServerError) return }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L16:
http.Error(w, "streaming unsupported", http.StatusInternalServerError)- What: Calls http.Error.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L17:
return- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L16:
- L20:
w.Header().Set("Content-Type", "text/event-stream")- What: Calls w.Header().Set.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L21:
w.Header().Set("Cache-Control", "no-cache")- What: Calls w.Header().Set.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L22:
w.Header().Set("Connection", "keep-alive")- What: Calls w.Header().Set.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L24:
ticker := time.NewTicker(50 * time.Millisecond)- What: Defines ticker.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L25:
defer ticker.Stop()- What: Defers a call for cleanup.
- Why: Ensures the deferred action runs even on early returns.
- How: Schedules the call to run when the surrounding function returns.
- L27:
type payload struct { ID int `json:"id"` Hint string `json:"hint"` }- What: Declares local names.
- Why: Introduces variables or types used later in the function.
- How: Executes a Go declaration statement inside the function body.
- L32:
sent := 0- What: Defines sent.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L33:
for { select { case <-r.Context().Done(): return case <-ticker.C: sent++ message := payload{ID: sent, Hint: fmt.Sprintf("seed-%d", rand.Int…- What: Runs a loop.
- Why: Repeats logic until a condition is met or the loop terminates.
- How: Executes a
forloop statement. - Nested steps:
- L34:
select { case <-r.Context().Done(): return case <-ticker.C: sent++ message := payload{ID: sent, Hint: fmt.Sprintf("seed-%d", rand.Intn(100)…- What: Selects among concurrent operations.
- Why: Coordinates channel operations without blocking incorrectly.
- How: Executes a
selectstatement and runs one ready case. - Nested steps:
- L35:
case <-r.Context().Done():- What: Selects a select-case branch.
- Why: Coordinates concurrent operations without blocking incorrectly.
- How: Runs this case body when its channel operation is ready (or runs default immediately).
- Nested steps:
- L36:
return- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L36:
- L37:
case <-ticker.C:- What: Selects a select-case branch.
- Why: Coordinates concurrent operations without blocking incorrectly.
- How: Runs this case body when its channel operation is ready (or runs default immediately).
- Nested steps:
- L38:
sent++- What: Updates a counter.
- Why: Maintains an index or tally used by subsequent logic.
- How: Executes an increment/decrement statement.
- L39:
message := payload{ID: sent, Hint: fmt.Sprintf("seed-%d", rand.Intn(100))}- What: Defines message.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L40:
data, _ := json.Marshal(message)- What: Defines data, _.
- Why: Keeps intermediate state available for later steps in the function.
- How: Evaluates the right-hand side expressions and stores results in the left-hand variables.
- L41:
fmt.Fprintf(w, "id: %d\nevent: tick\ndata: %s\n\n", sent, data)- What: Calls fmt.Fprintf.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L42:
flusher.Flush()- What: Calls flusher.Flush.
- Why: Performs side effects or delegates work to a helper.
- How: Executes the expression statement.
- L43:
if sent >= 5 { return }- What: Branches conditionally.
- Why: Short-circuits early when a precondition is not met or an error/edge case is detected.
- How: Evaluates the condition and executes the matching branch.
- Nested steps:
- L44:
return- What: Returns from the current function.
- Why: Ends the current execution path and hands control back to the caller.
- How: Executes a
returnstatement (possibly returning values).
- L44:
- L38:
- L35:
- L34:
- L14:
- L13: