diff --git a/xapi/endpoint.go b/xapi/endpoint.go index 82ebba1..29b7891 100644 --- a/xapi/endpoint.go +++ b/xapi/endpoint.go @@ -3,6 +3,7 @@ package xapi import ( "context" "encoding/json" + "io" "net/http" ) @@ -69,13 +70,18 @@ func (e *Endpoint[TReq, TRes]) Handler() http.Handler { h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var req TReq - if r.Body != nil { - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + data, err := io.ReadAll(r.Body) + if err != nil { + e.opts.errorHandler.HandleError(w, err) + return + } + defer r.Body.Close() + + if len(data) > 0 { + if err := json.Unmarshal(data, &req); err != nil { e.opts.errorHandler.HandleError(w, err) return } - - defer r.Body.Close() } if extracter, ok := any(&req).(Extracter); ok { diff --git a/xapi/endpoint_test.go b/xapi/endpoint_test.go index c44a7f4..643f80d 100644 --- a/xapi/endpoint_test.go +++ b/xapi/endpoint_test.go @@ -48,6 +48,34 @@ func TestEndpoint_Handler(t *testing.T) { }`, rec.Body.String()) }) + t.Run("GetEndpoint", func(t *testing.T) { + t.Parallel() + + rec := httptest.NewRecorder() + + handler := EndpointFunc[EmptyRequest, BasicResponse]( + func(ctx context.Context, req *EmptyRequest) (*BasicResponse, error) { + return &BasicResponse{ + Message: "Hello Tester", + ID: 321, + }, nil + }, + ) + + endpoint := NewEndpoint(handler) + req := httptest.NewRequest(http.MethodGet, "/test?name=Tester", nil) + req.Header.Set("Content-Type", "application/json") + + endpoint.Handler().ServeHTTP(rec, req) + + assert.Equal(t, http.StatusOK, rec.Result().StatusCode) + assert.Equal(t, "application/json; charset=utf-8", rec.Header().Get("Content-Type")) + assert.JSONEq(t, `{ + "message": "Hello Tester", + "id": 321 + }`, rec.Body.String()) + }) + t.Run("WithValidation", func(t *testing.T) { t.Parallel() @@ -443,6 +471,8 @@ func TestEndpoint_ContextCancellation(t *testing.T) { // Test types and implementations +type EmptyRequest struct{} + type BasicRequest struct { Name string `json:"name"` }