fleet/server/platform/http/post_json.go
Victor Lyuboslavsky 92bc1c650e
Move PostJSONWithTimeout to platform/http package and activity cleanup (#40561)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #38536

- Moved PostJSONWithTimeout to platform/http
- Created platform/errors package with only types needed by ctxerr. This
way, ctxerr did not need to import fleethttp.
- Made activity bounded context use PostJSONWithTimeout directly
- Removed some activity types from legacy code that were no longer
needed

# Checklist for submitter

- [ ] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
- Changes file `38536-new-activity-bc` already present, and this is just
cleanup from that work.

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **Refactor**
* Reorganized error handling utilities for improved clarity and
decoupling.
* Consolidated HTTP utilities to centralize JSON posting functionality
with timeout support.
* Simplified activity service initialization by removing unused internal
parameters.
* Cleaned up test utilities and removed webhook-related test
scaffolding.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-02-26 17:39:10 -06:00

68 lines
1.7 KiB
Go

package http
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"log/slog"
"net/http"
"time"
"github.com/fleetdm/fleet/v4/pkg/fleethttp"
)
// errWithStatus is an error with a particular status code.
type errWithStatus struct {
err string
statusCode int
}
// Error implements the error interface.
func (e *errWithStatus) Error() string {
return e.err
}
// StatusCode implements the StatusCoder interface for returning custom status codes.
func (e *errWithStatus) StatusCode() int {
return e.statusCode
}
// PostJSONWithTimeout marshals v as JSON and POSTs it to the given URL with a 30-second timeout.
func PostJSONWithTimeout(ctx context.Context, url string, v any, logger *slog.Logger) error {
jsonBytes, err := json.Marshal(v)
if err != nil {
return err
}
client := fleethttp.NewClient(fleethttp.WithTimeout(30 * time.Second))
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewBuffer(jsonBytes))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("failed to POST to %s: %s, request-size=%d", MaskSecretURLParams(url), MaskURLError(err), len(jsonBytes))
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode > 299 {
body, _ := io.ReadAll(io.LimitReader(resp.Body, 513))
bodyStr := string(body)
if len(bodyStr) > 512 {
bodyStr = bodyStr[:512]
}
logger.DebugContext(ctx, "non-success response from POST",
"url", MaskSecretURLParams(url),
"status_code", resp.StatusCode,
"body", bodyStr,
)
return &errWithStatus{err: fmt.Sprintf("error posting to %s", MaskSecretURLParams(url)), statusCode: resp.StatusCode}
}
return nil
}