Skip to content
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
4 changes: 3 additions & 1 deletion cmd/cli/cmd/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"os"
"strings"

"github.com/nullify-platform/cli/internal/auth"
"github.com/nullify-platform/cli/internal/client"
Expand Down Expand Up @@ -42,7 +43,8 @@ var securityStatusCmd = &cobra.Command{

// Fetch metrics overview
qs := lib.BuildQueryString(queryParams)
overviewBody, err := lib.DoGet(ctx, nullifyClient.HttpClient, nullifyClient.BaseURL, "/admin/metrics/overview"+qs)
overviewBody, err := lib.DoPostJSON(ctx, nullifyClient.HttpClient, nullifyClient.BaseURL, "/admin/metrics/overview"+qs, strings.NewReader(`{"query":{}}`))

if err != nil {
fmt.Fprintf(os.Stderr, "Error fetching metrics: %v\n", err)
os.Exit(ExitNetworkError)
Expand Down
7 changes: 6 additions & 1 deletion internal/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ type NullifyClient struct {

// NewNullifyClient creates a client for the given host with bearer token auth.
func NewNullifyClient(nullifyHost string, token string) *NullifyClient {
apiHost := nullifyHost
if !strings.HasPrefix(nullifyHost, "api.") {
apiHost = "api." + nullifyHost
}

httpClient := &http.Client{
Timeout: 30 * time.Second,
Transport: NewRetryTransport(&authTransport{
Expand All @@ -37,7 +42,7 @@ func NewNullifyClient(nullifyHost string, token string) *NullifyClient {

return &NullifyClient{
Host: nullifyHost,
BaseURL: "https://" + nullifyHost,
BaseURL: "https://" + apiHost,
Token: token,
HttpClient: httpClient,
}
Expand Down
11 changes: 7 additions & 4 deletions internal/client/refreshing_transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package client
import (
"context"
"net/http"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -47,9 +48,14 @@ func NewRefreshingNullifyClient(nullifyHost string, tokenProvider TokenProvider)
Transport: NewRetryTransport(t),
}

apiHost := nullifyHost
if !strings.HasPrefix(nullifyHost, "api.") {
apiHost = "api." + nullifyHost
}

return &NullifyClient{
Host: nullifyHost,
BaseURL: "https://" + nullifyHost,
BaseURL: "https://" + apiHost,
Token: "", // Token is managed by the refreshing transport; do not use this field directly.
HttpClient: httpClient,
}, nil
Expand Down Expand Up @@ -87,9 +93,6 @@ func (t *refreshingAuthTransport) RoundTrip(req *http.Request) (*http.Response,
token := t.getToken(req.Context())

r := req.Clone(req.Context())
r.URL.Scheme = "https"
r.URL.Host = t.nullifyHost
r.Host = t.nullifyHost
r.Header.Set("Authorization", "Bearer "+token)
r.Header.Set("User-Agent", "Nullify-CLI/mcp")
return t.transport.RoundTrip(r)
Expand Down
3 changes: 0 additions & 3 deletions internal/client/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ type authTransport struct {

func (t *authTransport) RoundTrip(req *http.Request) (*http.Response, error) {
r := req.Clone(req.Context())
r.URL.Scheme = "https"
r.URL.Host = t.nullifyHost
r.Host = t.nullifyHost
r.Header.Set("Authorization", "Bearer "+t.token)
r.Header.Set("User-Agent", "Nullify-CLI/"+logger.Version)
return t.transport.RoundTrip(r)
Expand Down
26 changes: 26 additions & 0 deletions internal/lib/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,32 @@ func DoPost(ctx context.Context, httpClient Doer, baseURL, path string) (string,
return string(body), nil
}

// DoPostJSON performs a POST request with a JSON body and returns the response body as a string.
func DoPostJSON(ctx context.Context, httpClient Doer, baseURL, path string, body io.Reader) (string, error) {
req, err := http.NewRequestWithContext(ctx, "POST", baseURL+path, body)
if err != nil {
return "", err
}
req.Header.Set("Content-Type", "application/json")

resp, err := httpClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()

respBody, err := io.ReadAll(io.LimitReader(resp.Body, 10<<20))
if err != nil {
return "", err
}

if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return "", fmt.Errorf("API returned %d: %s", resp.StatusCode, string(respBody))
}

return string(respBody), nil
}

// DoGet performs a GET request and returns the response body as a string.
// Returns an error if the request fails or the status code is not 2xx.
func DoGet(ctx context.Context, httpClient Doer, baseURL, path string) (string, error) {
Expand Down
Loading