Skip to content

Commit 7204646

Browse files
committed
fix: do not encode version prefix in host
1 parent 61c2d74 commit 7204646

File tree

3 files changed

+126
-59
lines changed

3 files changed

+126
-59
lines changed

api/internal/handler/datalogger_proxy.go

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func (h *TelemetryHandler) RegisterDataloggerProxy(api huma.API) {
3030
RawBody []byte
3131
}) (*ResponseWithStatus[any], error) {
3232
ctx := context.Background() // continue request in case of proxy server shutdown or slow cutover
33-
body, err := json.Marshal(DataloggerTelemetryDTO{
33+
payloadBytes, err := json.Marshal(DataloggerTelemetryDTO{
3434
DataloggerApiKey: input.XApiKey,
3535
Payload: input.RawBody,
3636
DataloggerInfo: DataloggerInfo{
@@ -41,57 +41,77 @@ func (h *TelemetryHandler) RegisterDataloggerProxy(api huma.API) {
4141
if err != nil {
4242
return nil, httperr.BadRequest(err)
4343
}
44-
req, err := http.NewRequestWithContext(
45-
ctx,
46-
http.MethodPost,
47-
fmt.Sprintf("%s/telemetry/dataloggers?key=%s", h.Config.ApiHost, h.Config.ApplicationKey),
48-
bytes.NewReader(body),
49-
)
44+
45+
base, err := url.Parse(h.Config.ApiHost)
5046
if err != nil {
51-
return nil, httperr.BadRequest(errors.New("could not construct request with given parameters"))
47+
return nil, httperr.InternalServerError(fmt.Errorf("invalid api host: %w", err))
5248
}
53-
defer func() {
54-
if err := req.Body.Close(); err != nil {
55-
h.Logger.Error(ctx, "error closing request body", "error", err)
56-
}
57-
}()
49+
50+
base.Path = API_VERSION_PREFIX + "/telemetry/dataloggers"
51+
q := base.Query()
52+
q.Set("key", h.Config.ApplicationKey)
53+
base.RawQuery = q.Encode()
54+
55+
req, err := http.NewRequestWithContext(ctx, http.MethodPost, base.String(), bytes.NewReader(payloadBytes))
56+
if err != nil {
57+
return nil, httperr.BadRequest(fmt.Errorf("could not construct request: %w", err))
58+
}
59+
req.Header.Set("Content-Type", "application/json")
60+
61+
h.Logger.Debug(ctx, "sending request",
62+
"type", "datalogger",
63+
"request_uri", func() string {
64+
u := *base
65+
util.RedactQueryParams(&u, "key")
66+
return u.String()
67+
}(),
68+
)
5869

5970
res, err := h.Client.Do(req)
6071
if err != nil {
6172
var urlErr *url.Error
6273
if errors.As(err, &urlErr) {
63-
u, err := url.Parse(urlErr.URL)
64-
if err != nil {
65-
return nil, httperr.InternalServerError(errors.New("error occured while attempting to parse the url of another error"))
74+
if u, parseErr := url.Parse(urlErr.URL); parseErr == nil {
75+
util.RedactQueryParams(u, "key")
76+
urlErr.URL = u.String()
6677
}
67-
util.RedactQueryParams(u, "key")
68-
urlErr.URL = u.String()
69-
return nil, httperr.InternalServerError(fmt.Errorf("urlErr %w", urlErr))
78+
return nil, httperr.InternalServerError(fmt.Errorf("upstream request failed: %w", urlErr))
7079
}
71-
return nil, httperr.InternalServerError(fmt.Errorf("expected error to be *url.Error type, got %T", err))
80+
return nil, httperr.InternalServerError(fmt.Errorf("upstream request failed: %w", err))
7281
}
7382
defer func() {
7483
if err := res.Body.Close(); err != nil {
7584
h.Logger.Error(ctx, "error closing response body", "error", err)
7685
}
7786
}()
78-
resBody, err := io.ReadAll(res.Body)
79-
if err != nil {
80-
return nil, httperr.InternalServerError(fmt.Errorf("failed to read response body %w", err))
87+
88+
resBody, readErr := io.ReadAll(res.Body)
89+
if readErr != nil {
90+
return nil, httperr.InternalServerError(fmt.Errorf("failed to read upstream response body: %w", readErr))
8191
}
8292

83-
h.Logger.Debug(ctx, "received response from api server", "code", res.StatusCode, "response_body", json.RawMessage(resBody))
93+
h.Logger.Debug(ctx, "received response from api server",
94+
"type", "datalogger",
95+
"code", res.StatusCode,
96+
"response_body", json.RawMessage(resBody),
97+
)
8498

8599
switch res.StatusCode {
86-
case http.StatusCreated:
87-
return NewResponseWithStatus(http.StatusCreated, any(resBody)), nil
100+
case http.StatusNoContent:
101+
return nil, nil
102+
103+
case http.StatusUnauthorized, http.StatusForbidden:
104+
return nil, httperr.Message(http.StatusBadGateway, "upstream rejected credentials")
105+
88106
case http.StatusNotFound:
89-
// Issue with upstream server
90-
return nil, httperr.Message(http.StatusBadGateway, "invalid response from upstream proxy")
107+
return nil, httperr.Message(http.StatusBadGateway, "upstream route not found")
108+
91109
default:
92-
return NewResponseWithStatus(http.StatusInternalServerError, any(json.RawMessage(resBody))), nil
110+
if len(resBody) == 0 {
111+
return nil, nil
112+
}
113+
return NewResponseWithStatus(res.StatusCode, any(json.RawMessage(resBody))), nil
93114
}
94-
95115
})
96116

97117
huma.Register(api, huma.Operation{
@@ -103,7 +123,7 @@ func (h *TelemetryHandler) RegisterDataloggerProxy(api huma.API) {
103123
Description: "checks the health of the datalogger proxy server",
104124
Tags: healthcheckTags,
105125
}, func(ctx context.Context, input *struct{}) (*ResponseWithContentType[any], error) {
106-
res, err := h.Client.Get(h.Config.ApiHost + "/telemetry/health")
126+
res, err := h.Client.Get(h.Config.ApiHost + API_VERSION_PREFIX + "/telemetry/health")
107127
if err != nil {
108128
return nil, httperr.InternalServerError(fmt.Errorf("request error %w", err))
109129
}

api/internal/handler/survey123_proxy.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,17 @@ func (h *TelemetryHandler) RegisterSurvey123Proxy(api huma.API) {
2727
}, func(_ context.Context, input *struct {
2828
Key string `query:"key"`
2929
Survey123IDParam
30-
RawBody map[string]json.RawMessage
30+
RawBody []byte
3131
}) (*ResponseWithStatus[any], error) {
3232
ctx := context.Background()
33+
var m map[string]json.RawMessage
34+
if err := json.Unmarshal(input.RawBody, &m); err != nil {
35+
return nil, httperr.BadRequest(fmt.Errorf("invalid json body: %w", err))
36+
}
37+
3338
payloadBytes, err := json.Marshal(dto.Survey123TelemetryDTO{
3439
Key: input.Key,
35-
Payload: input.RawBody,
40+
Payload: m,
3641
})
3742
if err != nil {
3843
return nil, httperr.BadRequest(err)
@@ -44,7 +49,7 @@ func (h *TelemetryHandler) RegisterSurvey123Proxy(api huma.API) {
4449
}
4550

4651
surveyID := input.Survey123IDParam.Survey123ID.UUID.String()
47-
base.Path = fmt.Sprintf("/webhooks/survey123/%s/measurements", surveyID)
52+
base.Path = fmt.Sprintf(API_VERSION_PREFIX+"/webhooks/survey123/%s/measurements", surveyID)
4853
q := base.Query()
4954
q.Set("key", h.Config.ApplicationKey)
5055
base.RawQuery = q.Encode()
@@ -55,6 +60,8 @@ func (h *TelemetryHandler) RegisterSurvey123Proxy(api huma.API) {
5560
}
5661
req.Header.Set("Content-Type", "application/json")
5762

63+
h.Logger.Debug(ctx, "sending request", "host", base.Host, "path", base.Path)
64+
5865
res, err := h.Client.Do(req)
5966
if err != nil {
6067
var urlErr *url.Error
@@ -75,6 +82,8 @@ func (h *TelemetryHandler) RegisterSurvey123Proxy(api huma.API) {
7582
}
7683

7784
h.Logger.Debug(ctx, "received response from api server",
85+
"request_host", base.Host,
86+
"request_path", base.Path,
7887
"code", res.StatusCode,
7988
"response_body", json.RawMessage(resBody),
8089
)

api/internal/service/dcsloader.go

Lines changed: 63 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ type DcsLoaderService struct {
3030
logger *logger.Logger
3131
}
3232

33+
const (
34+
API_VERSION_PREFIX = "/v4"
35+
)
36+
3337
func NewDcsLoaderService(apiClient *http.Client, cfg *config.DcsLoaderConfig, logger *logger.Logger) *DcsLoaderService {
3438
return &DcsLoaderService{apiClient, cfg, logger}
3539
}
@@ -40,7 +44,16 @@ func (s *DcsLoaderService) PostMeasurementCollectionToApi(ctx context.Context, m
4044
return err
4145
}
4246

43-
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fmt.Sprintf("%s/timeseries_measurements?key=%s", s.cfg.ApiHost, s.cfg.APIKey), bytes.NewReader(requestBodyBytes))
47+
base, err := url.Parse(s.cfg.ApiHost)
48+
if err != nil {
49+
return fmt.Errorf("invalid api host: %w", err)
50+
}
51+
base.Path = API_VERSION_PREFIX + "/timeseries_measurements"
52+
q := base.Query()
53+
q.Set("key", s.cfg.APIKey)
54+
base.RawQuery = q.Encode()
55+
56+
req, err := http.NewRequestWithContext(ctx, http.MethodPost, base.String(), bytes.NewReader(requestBodyBytes))
4457
if err != nil {
4558
return err
4659
}
@@ -50,35 +63,39 @@ func (s *DcsLoaderService) PostMeasurementCollectionToApi(ctx context.Context, m
5063
}
5164
}()
5265

53-
req.Header.Add("Content-Type", "application/json")
66+
req.Header.Set("Content-Type", "application/json")
5467

5568
resp, err := s.apiClient.Do(req)
5669
if err != nil {
57-
urlErr := err.(*url.Error)
58-
u, pErr := url.Parse(urlErr.URL)
59-
if pErr != nil || u == nil {
60-
return errors.New("unable to parse url string")
70+
var urlErr *url.Error
71+
if errors.As(err, &urlErr) {
72+
if u, pErr := url.Parse(urlErr.URL); pErr == nil && u != nil {
73+
util.RedactQueryParams(u, "key")
74+
urlErr.URL = u.String()
75+
}
76+
s.logger.Error(ctx, "unable to make request", "error", urlErr)
77+
return urlErr
6178
}
62-
util.RedactQueryParams(u, "key")
63-
urlErr.URL = u.String()
64-
s.logger.Error(ctx, "unable to make request", "error", urlErr)
65-
return urlErr
79+
s.logger.Error(ctx, "unable to make request", "error", err)
80+
return err
6681
}
6782
defer func() {
6883
if err := resp.Body.Close(); err != nil {
6984
s.logger.Error(ctx, "error closing response body", "error", err)
7085
}
7186
}()
7287

73-
if resp.StatusCode != 201 {
88+
if resp.StatusCode != http.StatusCreated {
7489
if resp.StatusCode == http.StatusBadRequest {
7590
s.logger.Info(ctx, "timeseries_id foreign key does not exist for upload",
7691
"id", resp.Header.Get("X-Request-Id"),
7792
"status", http.StatusNotFound,
7893
)
7994
return nil
8095
}
96+
return fmt.Errorf("expected http %d, got %d", http.StatusCreated, resp.StatusCode)
8197
}
98+
8299
return nil
83100
}
84101

@@ -87,11 +104,22 @@ func (s *DcsLoaderService) PostSeisMeasurementCollectionToApi(ctx context.Contex
87104
log.Print("no measurements to post")
88105
return nil
89106
}
107+
90108
requestBodyBytes, err := json.Marshal(mcs)
91109
if err != nil {
92110
return err
93111
}
94-
req, err := http.NewRequestWithContext(ctx, http.MethodPost, fmt.Sprintf("%s/timeseries_measurements_seis?key=%s", s.cfg.ApiHost, s.cfg.APIKey), bytes.NewReader(requestBodyBytes))
112+
113+
base, err := url.Parse(s.cfg.ApiHost)
114+
if err != nil {
115+
return fmt.Errorf("invalid api host: %w", err)
116+
}
117+
base.Path = API_VERSION_PREFIX + "/timeseries_measurements_seis"
118+
q := base.Query()
119+
q.Set("key", s.cfg.APIKey)
120+
base.RawQuery = q.Encode()
121+
122+
req, err := http.NewRequestWithContext(ctx, http.MethodPost, base.String(), bytes.NewReader(requestBodyBytes))
95123
if err != nil {
96124
return err
97125
}
@@ -101,35 +129,45 @@ func (s *DcsLoaderService) PostSeisMeasurementCollectionToApi(ctx context.Contex
101129
}
102130
}()
103131

104-
req.Header.Add("Content-Type", "application/json")
132+
req.Header.Set("Content-Type", "application/json")
105133

106134
resp, err := s.apiClient.Do(req)
107135
if err != nil {
108-
urlErr := err.(*url.Error)
109-
u, pErr := url.Parse(urlErr.URL)
110-
if pErr != nil || u == nil {
111-
return errors.New("unable to parse url string")
136+
var urlErr *url.Error
137+
if errors.As(err, &urlErr) {
138+
if u, pErr := url.Parse(urlErr.URL); pErr == nil && u != nil {
139+
util.RedactQueryParams(u, "key")
140+
urlErr.URL = u.String()
141+
}
142+
s.logger.Error(ctx, "unable to make request", "error", urlErr)
143+
return urlErr
112144
}
113-
util.RedactQueryParams(u, "key")
114-
urlErr.URL = u.String()
115-
s.logger.Error(ctx, "unable to make request", "error", urlErr)
116-
return urlErr
145+
s.logger.Error(ctx, "unable to make request", "error", err)
146+
return err
117147
}
118148
defer func() {
119149
if err := resp.Body.Close(); err != nil {
120150
s.logger.Error(ctx, "error closing response body", "error", err)
121151
}
122152
}()
123153

124-
if resp.StatusCode != 201 {
125-
s.logger.Error(ctx, "request was unsuccessful", "error", fmt.Errorf("expected HTTP response code 201, got %d", resp.StatusCode))
154+
if resp.StatusCode != http.StatusCreated {
155+
s.logger.Error(ctx, "request was unsuccessful",
156+
"error", fmt.Errorf("expected http %d, got %d", http.StatusCreated, resp.StatusCode),
157+
)
158+
126159
body, err := io.ReadAll(resp.Body)
127160
if err != nil {
128-
s.logger.Error(ctx, "Error reading response body", "error", err)
161+
s.logger.Error(ctx, "error reading response body", "error", err)
129162
return err
130163
}
131-
s.logger.Debug(ctx, "http response", "body", fmt.Sprintf("%s", body))
164+
if len(body) > 0 {
165+
s.logger.Debug(ctx, "http response", "body", string(body))
166+
}
167+
168+
return fmt.Errorf("expected http %d, got %d", http.StatusCreated, resp.StatusCode)
132169
}
170+
133171
return nil
134172
}
135173

0 commit comments

Comments
 (0)