Skip to content

Commit 4ba7380

Browse files
committed
More server scaffolding
Implements JSON unmarshalling/marshalling of request/response bodies.
1 parent 3190a84 commit 4ba7380

File tree

2 files changed

+122
-3
lines changed

2 files changed

+122
-3
lines changed

handler.go

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/caddyserver/caddy/v2/caddyconfig"
99
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
1010
"github.com/caddyserver/caddy/v2/modules/caddyhttp/caddyauth"
11+
"github.com/liujed/caddy-dns01proxy/jsonutil"
1112
"github.com/liujed/goutil/optionals"
1213
)
1314

@@ -108,8 +109,50 @@ func (h *Handler) Provision(ctx caddy.Context) error {
108109
func (h *Handler) ServeHTTP(
109110
w http.ResponseWriter,
110111
req *http.Request,
111-
_ caddyhttp.Handler,
112+
nextHandler caddyhttp.Handler,
112113
) error {
113-
w.WriteHeader(http.StatusNotFound)
114-
return nil
114+
var mode handlerMode
115+
switch req.URL.Path {
116+
case "/present":
117+
if req.Method != http.MethodPost {
118+
w.WriteHeader(http.StatusMethodNotAllowed)
119+
return nil
120+
}
121+
mode = hmPresent
122+
123+
case "/cleanup":
124+
if req.Method != http.MethodPost {
125+
w.WriteHeader(http.StatusMethodNotAllowed)
126+
return nil
127+
}
128+
mode = hmCleanup
129+
130+
default:
131+
return nextHandler.ServeHTTP(w, req)
132+
}
133+
134+
handlerImpl := jsonutil.WrapHandler(h.handleDNSRequest(mode))
135+
if auth, exists := h.Authentication.Get(); exists {
136+
return auth.ServeHTTP(w, req, handlerImpl)
137+
}
138+
return handlerImpl.ServeHTTP(w, req)
139+
}
140+
141+
type handlerMode string
142+
143+
const (
144+
hmPresent handlerMode = "present"
145+
hmCleanup handlerMode = "cleanup"
146+
)
147+
148+
func (h *Handler) handleDNSRequest(
149+
mode handlerMode,
150+
) func(*http.Request, any) (int, optionals.Optional[any], error) {
151+
return func(
152+
req *http.Request,
153+
reqBody any,
154+
) (httpStatus int, respBody optionals.Optional[any], err error) {
155+
// TODO
156+
return http.StatusInternalServerError, optionals.None[any](), nil
157+
}
115158
}

jsonutil/handler.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package jsonutil
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"net/http"
7+
8+
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
9+
"github.com/liujed/goutil/optionals"
10+
)
11+
12+
// Wraps the given handler function with a layer that handles the marshalling
13+
// and unmarshalling of request/response modies.
14+
func WrapHandler[RequestT any, ResponseT any](
15+
handler func(
16+
req *http.Request,
17+
requestBody RequestT,
18+
) (
19+
httpStatus int,
20+
responseBody optionals.Optional[ResponseT],
21+
err error,
22+
),
23+
) caddyhttp.Handler {
24+
return wrappedHandler[RequestT, ResponseT]{handler: handler}
25+
}
26+
27+
type wrappedHandler[RequestT any, ResponseT any] struct {
28+
handler func(
29+
req *http.Request,
30+
requestBody RequestT,
31+
) (
32+
httpStatus int,
33+
responseBody optionals.Optional[ResponseT],
34+
err error,
35+
)
36+
}
37+
38+
var _ caddyhttp.Handler = (*wrappedHandler[any, any])(nil)
39+
40+
func (h wrappedHandler[RequestT, ResponseT]) ServeHTTP(
41+
w http.ResponseWriter,
42+
req *http.Request,
43+
) error {
44+
// Unmarshal the request body.
45+
var reqBody RequestT
46+
err := json.NewDecoder(req.Body).Decode(&reqBody)
47+
if err != nil {
48+
http.Error(
49+
w,
50+
"Unable to read request body as JSON",
51+
http.StatusBadRequest,
52+
)
53+
return nil
54+
}
55+
56+
// Call the wrapped handler.
57+
httpStatus, responseBodyOpt, err := h.handler(req, reqBody)
58+
if err != nil {
59+
return err
60+
}
61+
62+
// Write out the response.
63+
if respBody, exists := responseBodyOpt.Get(); exists {
64+
w.Header().Set("Content-Type", "application/json")
65+
w.WriteHeader(httpStatus)
66+
err = json.NewEncoder(w).Encode(respBody)
67+
if err != nil {
68+
return fmt.Errorf("unable to write response body: %w", err)
69+
}
70+
return nil
71+
}
72+
73+
// No response body. Just write the HTTP status.
74+
w.WriteHeader(httpStatus)
75+
return nil
76+
}

0 commit comments

Comments
 (0)