Repository navigation
Expand file tree
/
Copy pathresponse_builder.go
More file actions
136 lines (118 loc) · 3.67 KB
/
Copy pathresponse_builder.go
File metadata and controls
136 lines (118 loc) · 3.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package httpsuite
import "net/http"
// ReplyBuilder configures metadata and headers before writing a response.
type ReplyBuilder struct {
meta any
headers http.Header
}
// ResponseBuilder builds and writes HTTP responses declaratively.
type ResponseBuilder[T any] struct {
code int
data T
meta any
problem *ProblemDetails
headers http.Header
}
// Respond starts a success response builder.
func Respond[T any](data T) *ResponseBuilder[T] {
return &ResponseBuilder[T]{
code: http.StatusOK,
data: data,
}
}
// RespondProblem starts a problem response builder.
func RespondProblem(problem *ProblemDetails) *ResponseBuilder[any] {
code := http.StatusInternalServerError
if problem != nil && problem.Status >= 400 && problem.Status <= 599 {
code = problem.Status
}
return &ResponseBuilder[any]{
code: code,
problem: problem,
}
}
// Meta sets response metadata for a fluent helper chain.
func (b *ReplyBuilder) Meta(meta any) *ReplyBuilder {
b.meta = meta
return b
}
// Header sets a single response header for a fluent helper chain.
func (b *ReplyBuilder) Header(key, value string) *ReplyBuilder {
if b.headers == nil {
b.headers = make(http.Header)
}
b.headers.Set(key, value)
return b
}
// Headers merges multiple response headers for a fluent helper chain.
func (b *ReplyBuilder) Headers(headers http.Header) *ReplyBuilder {
if b.headers == nil {
b.headers = make(http.Header)
}
for key, values := range headers {
for _, value := range values {
b.headers.Add(key, value)
}
}
return b
}
// OK writes a 200 JSON response using the fluent helper configuration.
func (b *ReplyBuilder) OK(w http.ResponseWriter, data any) {
Respond(data).Meta(b.meta).Headers(b.headers).Write(w)
}
// Created writes a 201 JSON response using the fluent helper configuration.
func (b *ReplyBuilder) Created(w http.ResponseWriter, data any, location string) {
builder := Respond(data).Status(http.StatusCreated).Meta(b.meta).Headers(b.headers)
if location != "" {
builder.Header("Location", location)
}
builder.Write(w)
}
// Accepted writes a 202 JSON response using the fluent helper configuration.
func (b *ReplyBuilder) Accepted(w http.ResponseWriter, data any) {
Respond(data).Status(http.StatusAccepted).Meta(b.meta).Headers(b.headers).Write(w)
}
// NoContent writes a 204 response with no body using the fluent helper configuration.
// Metadata is ignored because a 204 response must not carry a body.
func (b *ReplyBuilder) NoContent(w http.ResponseWriter) {
applyHeaders(w, b.headers)
w.WriteHeader(http.StatusNoContent)
}
// Problem writes a problem response using the fluent helper configuration.
func (b *ReplyBuilder) Problem(w http.ResponseWriter, problem *ProblemDetails) {
RespondProblem(problem).Headers(b.headers).Write(w)
}
// Status overrides the response status code.
func (b *ResponseBuilder[T]) Status(code int) *ResponseBuilder[T] {
b.code = code
return b
}
// Meta sets response metadata.
func (b *ResponseBuilder[T]) Meta(meta any) *ResponseBuilder[T] {
b.meta = meta
return b
}
// Header sets a single response header.
func (b *ResponseBuilder[T]) Header(key, value string) *ResponseBuilder[T] {
if b.headers == nil {
b.headers = make(http.Header)
}
b.headers.Set(key, value)
return b
}
// Headers merges multiple response headers.
func (b *ResponseBuilder[T]) Headers(headers http.Header) *ResponseBuilder[T] {
if b.headers == nil {
b.headers = make(http.Header)
}
for key, values := range headers {
for _, value := range values {
b.headers.Add(key, value)
}
}
return b
}
// Write writes the configured response.
func (b *ResponseBuilder[T]) Write(w http.ResponseWriter) {
writeResponse(w, b.code, b.data, b.problem, b.meta, b.headers)
}