@@ -4,21 +4,20 @@ import (
44 "context"
55 "encoding/json"
66 "fmt"
7+ "io"
78 "net/http"
89 "net/url"
910 "strconv"
1011
1112 "github.com/cloudflare/cloudflared/logger"
1213)
1314
14- const configurationEndpoint = "diag/configuration"
15-
1615type httpClient struct {
1716 http.Client
18- baseURL url.URL
17+ baseURL * url.URL
1918}
2019
21- func NewHTTPClient (baseURL url. URL ) * httpClient {
20+ func NewHTTPClient () * httpClient {
2221 httpTransport := http.Transport {
2322 TLSHandshakeTimeout : defaultTimeout ,
2423 ResponseHeaderTimeout : defaultTimeout ,
@@ -29,12 +28,21 @@ func NewHTTPClient(baseURL url.URL) *httpClient {
2928 Transport : & httpTransport ,
3029 Timeout : defaultTimeout ,
3130 },
32- baseURL ,
31+ nil ,
3332 }
3433}
3534
36- func (client * httpClient ) GET (ctx context.Context , url string ) (* http.Response , error ) {
37- req , err := http .NewRequestWithContext (ctx , http .MethodGet , url , nil )
35+ func (client * httpClient ) SetBaseURL (baseURL * url.URL ) {
36+ client .baseURL = baseURL
37+ }
38+
39+ func (client * httpClient ) GET (ctx context.Context , endpoint string ) (* http.Response , error ) {
40+ if client .baseURL == nil {
41+ return nil , ErrNoBaseUrl
42+ }
43+ url := client .baseURL .JoinPath (endpoint )
44+
45+ req , err := http .NewRequestWithContext (ctx , http .MethodGet , url .String (), nil )
3846 if err != nil {
3947 return nil , fmt .Errorf ("error creating GET request: %w" , err )
4048 }
@@ -56,12 +64,7 @@ type LogConfiguration struct {
5664}
5765
5866func (client * httpClient ) GetLogConfiguration (ctx context.Context ) (* LogConfiguration , error ) {
59- endpoint , err := url .JoinPath (client .baseURL .String (), configurationEndpoint )
60- if err != nil {
61- return nil , fmt .Errorf ("error parsing URL: %w" , err )
62- }
63-
64- response , err := client .GET (ctx , endpoint )
67+ response , err := client .GET (ctx , configurationEndpoint )
6568 if err != nil {
6669 return nil , err
6770 }
@@ -93,9 +96,79 @@ func (client *httpClient) GetLogConfiguration(ctx context.Context) (*LogConfigur
9396 return & LogConfiguration {"" , logDirectory , uid }, nil
9497 }
9598
96- return nil , ErrKeyNotFound
99+ // No log configured may happen when cloudflared is executed as a managed service or
100+ // when containerized
101+ return & LogConfiguration {"" , "" , uid }, nil
102+ }
103+
104+ func (client * httpClient ) GetMemoryDump (ctx context.Context , writer io.Writer ) error {
105+ response , err := client .GET (ctx , memoryDumpEndpoint )
106+ if err != nil {
107+ return err
108+ }
109+
110+ return copyToWriter (response , writer )
111+ }
112+
113+ func (client * httpClient ) GetGoroutineDump (ctx context.Context , writer io.Writer ) error {
114+ response , err := client .GET (ctx , goroutineDumpEndpoint )
115+ if err != nil {
116+ return err
117+ }
118+
119+ return copyToWriter (response , writer )
120+ }
121+
122+ func (client * httpClient ) GetTunnelState (ctx context.Context ) (* TunnelState , error ) {
123+ response , err := client .GET (ctx , tunnelStateEndpoint )
124+ if err != nil {
125+ return nil , err
126+ }
127+
128+ defer response .Body .Close ()
129+
130+ var state TunnelState
131+ if err := json .NewDecoder (response .Body ).Decode (& state ); err != nil {
132+ return nil , fmt .Errorf ("failed to decode body: %w" , err )
133+ }
134+
135+ return & state , nil
136+ }
137+
138+ func (client * httpClient ) GetSystemInformation (ctx context.Context , writer io.Writer ) error {
139+ response , err := client .GET (ctx , systemInformationEndpoint )
140+ if err != nil {
141+ return err
142+ }
143+
144+ return copyToWriter (response , writer )
145+ }
146+
147+ func (client * httpClient ) GetMetrics (ctx context.Context , writer io.Writer ) error {
148+ response , err := client .GET (ctx , metricsEndpoint )
149+ if err != nil {
150+ return err
151+ }
152+
153+ return copyToWriter (response , writer )
154+ }
155+
156+ func copyToWriter (response * http.Response , writer io.Writer ) error {
157+ defer response .Body .Close ()
158+
159+ _ , err := io .Copy (writer , response .Body )
160+ if err != nil {
161+ return fmt .Errorf ("error writing metrics: %w" , err )
162+ }
163+
164+ return nil
97165}
98166
99167type HTTPClient interface {
100- GetLogConfiguration (ctx context.Context ) (LogConfiguration , error )
168+ GetLogConfiguration (ctx context.Context ) (* LogConfiguration , error )
169+ GetMemoryDump (ctx context.Context , writer io.Writer ) error
170+ GetGoroutineDump (ctx context.Context , writer io.Writer ) error
171+ GetTunnelState (ctx context.Context ) (* TunnelState , error )
172+ GetSystemInformation (ctx context.Context , writer io.Writer ) error
173+ GetMetrics (ctx context.Context , writer io.Writer ) error
101174}
0 commit comments