executeRequest performs a single HTTP request.
(ctx context.Context, method, path string, data interface{}, result *map[string]interface{})
| 108 | |
| 109 | // executeRequest performs a single HTTP request. |
| 110 | func (hc *HTTPClient) executeRequest(ctx context.Context, method, path string, data interface{}, result *map[string]interface{}) error { |
| 111 | // Construct full URL |
| 112 | fullURL := hc.baseURL + path |
| 113 | if !strings.HasPrefix(path, "/") { |
| 114 | fullURL = hc.baseURL + "/" + path |
| 115 | } |
| 116 | |
| 117 | // Prepare request body |
| 118 | var body io.Reader |
| 119 | |
| 120 | if data != nil { |
| 121 | jsonData, err := json.Marshal(data) |
| 122 | if err != nil { |
| 123 | return fmt.Errorf("failed to marshal request data: %w", err) |
| 124 | } |
| 125 | |
| 126 | body = bytes.NewReader(jsonData) |
| 127 | } |
| 128 | |
| 129 | // Create HTTP request |
| 130 | req, err := http.NewRequestWithContext(ctx, method, fullURL, body) |
| 131 | if err != nil { |
| 132 | return fmt.Errorf("failed to create request: %w", err) |
| 133 | } |
| 134 | |
| 135 | hc.logger.Debug("API Request: %s %s", method, fullURL) |
| 136 | |
| 137 | // Set headers |
| 138 | req.Header.Set("User-Agent", "pvetui") |
| 139 | req.Header.Set("Accept", "application/json") |
| 140 | |
| 141 | // Handle authentication |
| 142 | if hc.apiToken != "" { |
| 143 | // Use API token authentication |
| 144 | req.Header.Set("Authorization", hc.apiToken) |
| 145 | hc.logger.Debug("Using API token authentication") |
| 146 | } else if hc.authManager != nil { |
| 147 | // Use ticket-based authentication |
| 148 | token, authErr := hc.authManager.GetValidToken(ctx) |
| 149 | if authErr != nil { |
| 150 | return fmt.Errorf("authentication failed: %w", authErr) |
| 151 | } |
| 152 | |
| 153 | // Set authentication cookie |
| 154 | req.Header.Set("Cookie", fmt.Sprintf("PVEAuthCookie=%s", token.Ticket)) |
| 155 | |
| 156 | // Set CSRF token for write operations |
| 157 | if method == HTTPMethodPOST || method == HTTPMethodPUT || method == HTTPMethodDELETE { |
| 158 | if token.CSRFToken != "" { |
| 159 | req.Header.Set("CSRFPreventionToken", token.CSRFToken) |
| 160 | } |
| 161 | } |
| 162 | |
| 163 | hc.logger.Debug("Using ticket-based authentication") |
| 164 | } |
| 165 | |
| 166 | // Set content type for write operations |
| 167 | if (method == HTTPMethodPOST || method == HTTPMethodPUT || method == HTTPMethodDELETE) && data != nil { |
no test coverage detected