|
4 | 4 | "bytes" |
5 | 5 | "context" |
6 | 6 | "errors" |
| 7 | + "fmt" |
7 | 8 | "io" |
8 | 9 | "net/http" |
9 | 10 | "strings" |
@@ -50,110 +51,93 @@ func NewDirectConfidentialHTTPAction(lggr logger.Logger) *DirectConfidentialHTTP |
50 | 51 | return fc |
51 | 52 | } |
52 | 53 |
|
53 | | -func (fh *DirectConfidentialHTTPAction) SendRequests(ctx context.Context, metadata commonCap.RequestMetadata, input *confidentialhttp.EnclaveActionInput) (*commonCap.ResponseAndMetadata[*confidentialhttp.HTTPEnclaveResponseData], caperrors.Error) { |
54 | | - fh.eng.Infow("Confidential HTTP Action SendRequests Started", "input", input, "secretsCount", len(input.GetVaultDonSecrets())) |
| 54 | +func (fh *DirectConfidentialHTTPAction) SendRequest(ctx context.Context, metadata commonCap.RequestMetadata, input *confidentialhttp.ConfidentialHTTPRequest) (*commonCap.ResponseAndMetadata[*confidentialhttp.HTTPResponse], caperrors.Error) { |
| 55 | + fh.eng.Infow("Confidential HTTP Action SendRequest Started", "input", input, "secretsCount", len(input.GetVaultDonSecrets())) |
55 | 56 |
|
56 | 57 | // Warn if secrets are provided - this fake does not handle secret resolution |
57 | 58 | if len(input.GetVaultDonSecrets()) > 0 { |
58 | 59 | fh.eng.Warnw("This fake does not handle secrets - VaultDonSecrets will be ignored. Template variables like {{.secretName}} will not be resolved.", "secretsCount", len(input.GetVaultDonSecrets())) |
59 | 60 | } |
60 | 61 |
|
61 | | - if input.GetInput() == nil { |
62 | | - return nil, caperrors.NewPublicUserError(errors.New("input cannot be nil"), caperrors.InvalidArgument) |
| 62 | + req := input.GetRequest() |
| 63 | + if req == nil { |
| 64 | + return nil, caperrors.NewPublicUserError(errors.New("request cannot be nil"), caperrors.InvalidArgument) |
63 | 65 | } |
64 | 66 |
|
65 | | - requests := input.GetInput().GetRequests() |
66 | | - if len(requests) == 0 { |
67 | | - return nil, caperrors.NewPublicUserError(errors.New("no requests provided"), caperrors.InvalidArgument) |
68 | | - } |
69 | | - |
70 | | - // Process each request |
71 | | - responses := make([]*confidentialhttp.ResponseTemplate, 0, len(requests)) |
72 | | - |
73 | | - for i, req := range requests { |
74 | | - fh.eng.Infow("Processing confidential HTTP request", "index", i, "url", req.GetUrl(), "method", req.GetMethod()) |
| 67 | + fh.eng.Infow("Processing confidential HTTP request", "url", req.GetUrl(), "method", req.GetMethod()) |
75 | 68 |
|
76 | | - // Create HTTP client with timeout (default 30 seconds) |
77 | | - timeout := time.Duration(30) * time.Second |
78 | | - client := &http.Client{ |
79 | | - Timeout: timeout, |
80 | | - } |
| 69 | + // Create HTTP client with timeout (default 30 seconds) |
| 70 | + timeout := time.Duration(30) * time.Second |
| 71 | + client := &http.Client{ |
| 72 | + Timeout: timeout, |
| 73 | + } |
81 | 74 |
|
82 | | - // Validate HTTP method |
83 | | - method := strings.TrimSpace(req.GetMethod()) |
84 | | - if method == "" { |
85 | | - return nil, caperrors.NewPublicUserError(errors.New("http method cannot be empty"), caperrors.InvalidArgument) |
86 | | - } |
87 | | - method = strings.ToUpper(method) |
| 75 | + // Validate HTTP method |
| 76 | + method := strings.TrimSpace(req.GetMethod()) |
| 77 | + if method == "" { |
| 78 | + return nil, caperrors.NewPublicUserError(errors.New("http method cannot be empty"), caperrors.InvalidArgument) |
| 79 | + } |
| 80 | + method = strings.ToUpper(method) |
| 81 | + |
| 82 | + // Create request body |
| 83 | + var body io.Reader |
| 84 | + if bodyStr := req.GetBodyString(); bodyStr != "" { |
| 85 | + body = bytes.NewReader([]byte(bodyStr)) |
| 86 | + } else if bodyBytes := req.GetBodyBytes(); len(bodyBytes) > 0 { |
| 87 | + body = bytes.NewReader(bodyBytes) |
| 88 | + } |
88 | 89 |
|
89 | | - // Create request body |
90 | | - var body io.Reader |
91 | | - if len(req.GetBody()) > 0 { |
92 | | - body = bytes.NewReader([]byte(req.GetBody())) |
93 | | - } |
| 90 | + // Create the HTTP request |
| 91 | + httpReq, err := http.NewRequestWithContext(ctx, method, req.GetUrl(), body) |
| 92 | + if err != nil { |
| 93 | + fh.eng.Errorw("Failed to create HTTP request", "error", err) |
| 94 | + return nil, caperrors.NewPublicUserError(fmt.Errorf("failed to create HTTP request: %w", err), caperrors.InvalidArgument) |
| 95 | + } |
94 | 96 |
|
95 | | - // Create the HTTP request |
96 | | - httpReq, err := http.NewRequestWithContext(ctx, method, req.GetUrl(), body) |
97 | | - if err != nil { |
98 | | - fh.eng.Errorw("Failed to create HTTP request", "error", err, "index", i) |
99 | | - responses = append(responses, &confidentialhttp.ResponseTemplate{ |
100 | | - StatusCode: 0, |
101 | | - Body: []byte(err.Error()), |
102 | | - }) |
103 | | - continue |
104 | | - } |
| 97 | + // Add headers |
| 98 | + for name, value := range req.GetHeaders() { |
| 99 | + httpReq.Header.Set(name, value) |
| 100 | + } |
105 | 101 |
|
106 | | - // Add headers |
107 | | - for _, header := range req.GetHeaders() { |
108 | | - parts := strings.SplitN(header, ":", 2) |
109 | | - if len(parts) == 2 { |
110 | | - httpReq.Header.Set(strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])) |
111 | | - } |
112 | | - } |
| 102 | + // Make the HTTP request |
| 103 | + resp, err := client.Do(httpReq) |
| 104 | + if err != nil { |
| 105 | + fh.eng.Errorw("Failed to execute confidential HTTP request", "error", err) |
| 106 | + return nil, caperrors.NewPublicUserError(fmt.Errorf("failed to execute HTTP request: %w", err), caperrors.InvalidArgument) |
| 107 | + } |
| 108 | + defer resp.Body.Close() |
113 | 109 |
|
114 | | - // Make the HTTP request |
115 | | - resp, err := client.Do(httpReq) |
116 | | - if err != nil { |
117 | | - fh.eng.Errorw("Failed to execute confidential HTTP request", "error", err, "index", i) |
118 | | - responses = append(responses, &confidentialhttp.ResponseTemplate{ |
119 | | - StatusCode: 0, |
120 | | - Body: []byte(err.Error()), |
121 | | - }) |
122 | | - continue |
123 | | - } |
| 110 | + // Read response body |
| 111 | + respBody, err := io.ReadAll(resp.Body) |
| 112 | + if err != nil { |
| 113 | + fh.eng.Errorw("Failed to read response body", "error", err) |
| 114 | + return nil, caperrors.NewPublicUserError(fmt.Errorf("failed to read response body: %w", err), caperrors.InvalidArgument) |
| 115 | + } |
124 | 116 |
|
125 | | - // Read response body |
126 | | - respBody, err := io.ReadAll(resp.Body) |
127 | | - resp.Body.Close() |
128 | | - if err != nil { |
129 | | - fh.eng.Errorw("Failed to read response body", "error", err, "index", i) |
130 | | - responses = append(responses, &confidentialhttp.ResponseTemplate{ |
131 | | - StatusCode: int64(resp.StatusCode), |
132 | | - Body: []byte(err.Error()), |
| 117 | + // Convert response headers to []*Header |
| 118 | + var responseHeaders []*confidentialhttp.Header |
| 119 | + for name, values := range resp.Header { |
| 120 | + for _, value := range values { |
| 121 | + responseHeaders = append(responseHeaders, &confidentialhttp.Header{ |
| 122 | + Name: name, |
| 123 | + Value: value, |
133 | 124 | }) |
134 | | - continue |
135 | | - } |
136 | | - |
137 | | - // Create response template |
138 | | - response := &confidentialhttp.ResponseTemplate{ |
139 | | - StatusCode: int64(resp.StatusCode), |
140 | | - Body: respBody, |
141 | 125 | } |
142 | | - responses = append(responses, response) |
143 | | - fh.eng.Infow("Confidential HTTP request finished", "index", i, "status", resp.StatusCode, "url", req.GetUrl()) |
144 | 126 | } |
145 | 127 |
|
146 | | - // Create response data |
147 | | - responseData := &confidentialhttp.HTTPEnclaveResponseData{ |
148 | | - Responses: responses, |
| 128 | + // Create response |
| 129 | + response := &confidentialhttp.HTTPResponse{ |
| 130 | + StatusCode: uint32(resp.StatusCode), //nolint:gosec // HTTP status codes are always positive (100-599) |
| 131 | + Body: respBody, |
| 132 | + Headers: responseHeaders, |
149 | 133 | } |
150 | 134 |
|
151 | | - responseAndMetadata := commonCap.ResponseAndMetadata[*confidentialhttp.HTTPEnclaveResponseData]{ |
152 | | - Response: responseData, |
| 135 | + responseAndMetadata := commonCap.ResponseAndMetadata[*confidentialhttp.HTTPResponse]{ |
| 136 | + Response: response, |
153 | 137 | ResponseMetadata: commonCap.ResponseMetadata{}, |
154 | 138 | } |
155 | 139 |
|
156 | | - fh.eng.Infow("Confidential HTTP Action Finished", "requestCount", len(requests), "responseCount", len(responses)) |
| 140 | + fh.eng.Infow("Confidential HTTP Action Finished", "status", resp.StatusCode, "url", req.GetUrl()) |
157 | 141 | return &responseAndMetadata, nil |
158 | 142 | } |
159 | 143 |
|
|
0 commit comments