Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow requests with adhoc RequestEditor #69

Merged
merged 1 commit into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 72 additions & 16 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,17 @@

// Get will get a resource by ID
func (c *Client[T]) Get(ctx context.Context, id string, parentIDs ...string) (*Response[T], error) {
return c.GetWithEditor(ctx, id, c.requestEditor, parentIDs...)
}

// GetWithEditor will get a resource by ID after modifying the request with requestEditor
func (c *Client[T]) GetWithEditor(ctx context.Context, id string, requestEditor RequestEditor, parentIDs ...string) (*Response[T], error) {
req, err := c.GetRequest(ctx, id, parentIDs...)
if err != nil {
return nil, fmt.Errorf("error creating request: %w", err)
}

result, err := c.MakeRequest(req, c.customResponseCodes[http.MethodGet])
result, err := c.MakeRequestWithEditor(req, c.customResponseCodes[http.MethodGet], requestEditor)
if err != nil {
return nil, fmt.Errorf("error getting resource: %w", err)
}
Expand All @@ -176,12 +181,17 @@

// GetAll gets all resources from the API
func (c *Client[T]) GetAll(ctx context.Context, rawQuery string, parentIDs ...string) (*Response[*ResourceList[T]], error) {
return c.GetAllWithEditor(ctx, rawQuery, c.requestEditor, parentIDs...)
}

// GetAllWithEditor gets all resources from the API after modifying the request with requestEditor
func (c *Client[T]) GetAllWithEditor(ctx context.Context, rawQuery string, requestEditor RequestEditor, parentIDs ...string) (*Response[*ResourceList[T]], error) {
req, err := c.GetAllRequest(ctx, rawQuery, parentIDs...)
if err != nil {
return nil, fmt.Errorf("error creating request: %w", err)
}

result, err := MakeRequest[*ResourceList[T]](req, c.client, c.customResponseCodes[MethodGetAll], c.requestEditor)
result, err := MakeRequest[*ResourceList[T]](req, c.client, c.customResponseCodes[MethodGetAll], requestEditor)
if err != nil {
return nil, fmt.Errorf("error getting all resources: %w", err)
}
Expand All @@ -203,12 +213,17 @@

// GetAllAny allows using GetAll when using a custom response wrapper
func (c *Client[T]) GetAllAny(ctx context.Context, rawQuery string, parentIDs ...string) (*Response[any], error) {
return c.GetAllAnyWithEditor(ctx, rawQuery, c.requestEditor, parentIDs...)
}

// GetAllAnyWithEditor allows using GetAll when using a custom response wrapper after modifying the request with requestEditor
func (c *Client[T]) GetAllAnyWithEditor(ctx context.Context, rawQuery string, requestEditor RequestEditor, parentIDs ...string) (*Response[any], error) {
req, err := c.GetAllRequest(ctx, rawQuery, parentIDs...)
if err != nil {
return nil, fmt.Errorf("error creating request: %w", err)
}

result, err := MakeRequest[any](req, c.client, c.customResponseCodes[MethodGetAll], c.requestEditor)
result, err := MakeRequest[any](req, c.client, c.customResponseCodes[MethodGetAll], requestEditor)
if err != nil {
return nil, fmt.Errorf("error getting all resources: %w", err)
}
Expand All @@ -218,13 +233,18 @@

// Put makes a PUT request to create/modify a resource by ID
func (c *Client[T]) Put(ctx context.Context, resource T, parentIDs ...string) (*Response[T], error) {
return c.PutWithEditor(ctx, resource, c.requestEditor, parentIDs...)
}

// PutWithEditor makes a PUT request to create/modify a resource by ID after modifying the request with requestEditor
func (c *Client[T]) PutWithEditor(ctx context.Context, resource T, requestEditor RequestEditor, parentIDs ...string) (*Response[T], error) {
var body bytes.Buffer
err := json.NewEncoder(&body).Encode(resource)
if err != nil {
return nil, fmt.Errorf("error encoding request body: %w", err)
}

return c.put(ctx, resource.GetID(), &body, parentIDs...)
return c.put(ctx, resource.GetID(), &body, requestEditor, parentIDs...)
}

// PutRequest creates a request that can be used to PUT a resource
Expand All @@ -241,16 +261,21 @@

// PutRaw makes a PUT request to create/modify a resource by ID. It uses the provided string as the request body
func (c *Client[T]) PutRaw(ctx context.Context, id, body string, parentIDs ...string) (*Response[T], error) {
return c.put(ctx, id, bytes.NewBufferString(body), parentIDs...)
return c.PutRawWithEditor(ctx, id, body, c.requestEditor, parentIDs...)

Check warning on line 264 in client.go

View check run for this annotation

Codecov / codecov/patch

client.go#L264

Added line #L264 was not covered by tests
}

// PutRaw makes a PUT request to create/modify a resource by ID. It uses the provided string as the request body
func (c *Client[T]) PutRawWithEditor(ctx context.Context, id, body string, requestEditor RequestEditor, parentIDs ...string) (*Response[T], error) {
return c.put(ctx, id, bytes.NewBufferString(body), requestEditor, parentIDs...)
}

func (c *Client[T]) put(ctx context.Context, id string, body io.Reader, parentIDs ...string) (*Response[T], error) {
func (c *Client[T]) put(ctx context.Context, id string, body io.Reader, requestEditor RequestEditor, parentIDs ...string) (*Response[T], error) {
req, err := c.PutRequest(ctx, body, id, parentIDs...)
if err != nil {
return nil, fmt.Errorf("error creating request: %w", err)
}

result, err := c.MakeRequest(req, c.customResponseCodes[http.MethodPut])
result, err := c.MakeRequestWithEditor(req, c.customResponseCodes[http.MethodPut], requestEditor)
if err != nil {
return nil, fmt.Errorf("error putting resource: %w", err)
}
Expand All @@ -260,13 +285,18 @@

// Post makes a POST request to create a new resource
func (c *Client[T]) Post(ctx context.Context, resource T, parentIDs ...string) (*Response[T], error) {
return c.PostWithEditor(ctx, resource, c.requestEditor, parentIDs...)
}

// PostWithEditor makes a POST request to create a new resource after modifying the request with requestEditor
func (c *Client[T]) PostWithEditor(ctx context.Context, resource T, requestEditor RequestEditor, parentIDs ...string) (*Response[T], error) {
var body bytes.Buffer
err := json.NewEncoder(&body).Encode(resource)
if err != nil {
return nil, fmt.Errorf("error encoding request body: %w", err)
}

return c.post(ctx, &body, parentIDs...)
return c.post(ctx, &body, requestEditor, parentIDs...)
}

// PostRequest creates a request that can be used to POST a resource
Expand All @@ -283,16 +313,21 @@

// PostRaw makes a POST request using the provided string as the body
func (c *Client[T]) PostRaw(ctx context.Context, body string, parentIDs ...string) (*Response[T], error) {
return c.post(ctx, bytes.NewBufferString(body), parentIDs...)
return c.PostRawWithEditor(ctx, body, c.requestEditor, parentIDs...)

Check warning on line 316 in client.go

View check run for this annotation

Codecov / codecov/patch

client.go#L316

Added line #L316 was not covered by tests
}

// PostRawWithEditor makes a POST request using the provided string as the body after modifying the request with requestEditor
func (c *Client[T]) PostRawWithEditor(ctx context.Context, body string, requestEditor RequestEditor, parentIDs ...string) (*Response[T], error) {
return c.post(ctx, bytes.NewBufferString(body), requestEditor, parentIDs...)
}

func (c *Client[T]) post(ctx context.Context, body io.Reader, parentIDs ...string) (*Response[T], error) {
func (c *Client[T]) post(ctx context.Context, body io.Reader, requestEditor RequestEditor, parentIDs ...string) (*Response[T], error) {
req, err := c.PostRequest(ctx, body, parentIDs...)
if err != nil {
return nil, fmt.Errorf("error creating request: %w", err)
}

result, err := c.MakeRequest(req, c.customResponseCodes[http.MethodPost])
result, err := c.MakeRequestWithEditor(req, c.customResponseCodes[http.MethodPost], requestEditor)
if err != nil {
return result, fmt.Errorf("error posting resource: %w", err)
}
Expand All @@ -302,13 +337,18 @@

// Patch makes a PATCH request to modify a resource by ID
func (c *Client[T]) Patch(ctx context.Context, id string, resource T, parentIDs ...string) (*Response[T], error) {
return c.PatchWithEditor(ctx, id, resource, c.requestEditor, parentIDs...)
}

// PatchWithEditor makes a PATCH request to modify a resource by ID after modifying the request with requestEditor
func (c *Client[T]) PatchWithEditor(ctx context.Context, id string, resource T, requestEditor RequestEditor, parentIDs ...string) (*Response[T], error) {
var body bytes.Buffer
err := json.NewEncoder(&body).Encode(resource)
if err != nil {
return nil, fmt.Errorf("error encoding request body: %w", err)
}

return c.patch(ctx, id, &body, parentIDs...)
return c.patch(ctx, id, &body, requestEditor, parentIDs...)
}

// PatchRequest creates a request that can be used to PATCH a resource
Expand All @@ -325,16 +365,21 @@

// PatchRaw makes a PATCH request to modify a resource by ID. It uses the provided string as the request body
func (c *Client[T]) PatchRaw(ctx context.Context, id, body string, parentIDs ...string) (*Response[T], error) {
return c.patch(ctx, id, bytes.NewBufferString(body), parentIDs...)
return c.PatchRawWithEditor(ctx, id, body, c.requestEditor, parentIDs...)

Check warning on line 368 in client.go

View check run for this annotation

Codecov / codecov/patch

client.go#L368

Added line #L368 was not covered by tests
}

func (c *Client[T]) patch(ctx context.Context, id string, body io.Reader, parentIDs ...string) (*Response[T], error) {
// PatchRawWithEditor makes a PATCH request to modify a resource by ID after modifying the request with requestEditor. It uses the provided string as the request body
func (c *Client[T]) PatchRawWithEditor(ctx context.Context, id, body string, requestEditor RequestEditor, parentIDs ...string) (*Response[T], error) {
return c.patch(ctx, id, bytes.NewBufferString(body), requestEditor, parentIDs...)
}

func (c *Client[T]) patch(ctx context.Context, id string, body io.Reader, requestEditor RequestEditor, parentIDs ...string) (*Response[T], error) {
req, err := c.PatchRequest(ctx, body, id, parentIDs...)
if err != nil {
return nil, fmt.Errorf("error creating request: %w", err)
}

resp, err := c.MakeRequest(req, c.customResponseCodes[http.MethodPatch])
resp, err := c.MakeRequestWithEditor(req, c.customResponseCodes[http.MethodPatch], requestEditor)
if err != nil {
return nil, fmt.Errorf("error patching resource: %w", err)
}
Expand All @@ -344,12 +389,17 @@

// Delete makes a DELETE request to delete a resource by ID
func (c *Client[T]) Delete(ctx context.Context, id string, parentIDs ...string) (*Response[T], error) {
return c.DeleteWithEditor(ctx, id, c.requestEditor, parentIDs...)
}

// DeleteWithEditor makes a DELETE request to delete a resource by ID after modifying the request with requestEditor
func (c *Client[T]) DeleteWithEditor(ctx context.Context, id string, requestEditor RequestEditor, parentIDs ...string) (*Response[T], error) {
req, err := c.DeleteRequest(ctx, id, parentIDs...)
if err != nil {
return nil, fmt.Errorf("error creating request: %w", err)
}

resp, err := c.MakeRequest(req, c.customResponseCodes[http.MethodDelete])
resp, err := c.MakeRequestWithEditor(req, c.customResponseCodes[http.MethodDelete], requestEditor)
if err != nil {
return nil, fmt.Errorf("error deleting resource: %w", err)
}
Expand Down Expand Up @@ -399,6 +449,12 @@
return MakeRequest[T](req, c.client, expectedStatusCode, c.requestEditor)
}

// MakeRequestWithEditor is like MakeRequest, but allows setting a RequestEditor instead of using the Client's
// configured editor
func (c *Client[T]) MakeRequestWithEditor(req *http.Request, expectedStatusCode int, requestEditor RequestEditor) (*Response[T], error) {
return MakeRequest[T](req, c.client, expectedStatusCode, requestEditor)
}

// MakeGenericRequest allows making a request without specifying the return type. It accepts a pointer receiver
// to pass to json.Unmarshal. This allows returning any type using the Client.
func (c *Client[T]) MakeGenericRequest(req *http.Request, target any) (*Response[any], error) {
Expand Down
19 changes: 10 additions & 9 deletions test/request_test_case.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,17 @@ func (tt RequestTest[T]) Run(t *testing.T, client *babyapi.Client[T], getRespons
body = tt.BodyFunc(getResponse)
}

requestEditor := babyapi.DefaultRequestEditor

rawQuery := tt.RawQuery
if tt.RawQueryFunc != nil {
rawQuery = tt.RawQueryFunc(getResponse)
}
if rawQuery != "" {
client.SetRequestEditor(func(r *http.Request) error {
requestEditor = func(r *http.Request) error {
r.URL.RawQuery = rawQuery
return nil
})
defer client.SetRequestEditor(babyapi.DefaultRequestEditor)
}
}

parentIDs := tt.ParentIDs
Expand All @@ -70,17 +71,17 @@ func (tt RequestTest[T]) Run(t *testing.T, client *babyapi.Client[T], getRespons
var err error
switch tt.Method {
case babyapi.MethodGetAll:
r, err = client.GetAll(context.Background(), rawQuery, parentIDs...)
r, err = client.GetAllWithEditor(context.Background(), rawQuery, requestEditor, parentIDs...)
case http.MethodPost:
r, err = client.PostRaw(context.Background(), body, parentIDs...)
r, err = client.PostRawWithEditor(context.Background(), body, requestEditor, parentIDs...)
case http.MethodGet:
r, err = client.Get(context.Background(), id, parentIDs...)
r, err = client.GetWithEditor(context.Background(), id, requestEditor, parentIDs...)
case http.MethodPut:
r, err = client.PutRaw(context.Background(), id, body, parentIDs...)
r, err = client.PutRawWithEditor(context.Background(), id, body, requestEditor, parentIDs...)
case http.MethodPatch:
r, err = client.PatchRaw(context.Background(), id, body, parentIDs...)
r, err = client.PatchRawWithEditor(context.Background(), id, body, requestEditor, parentIDs...)
case http.MethodDelete:
r, err = client.Delete(context.Background(), id, parentIDs...)
r, err = client.DeleteWithEditor(context.Background(), id, requestEditor, parentIDs...)
}

switch v := r.(type) {
Expand Down
Loading