| // Copyright 2023 The LUCI Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package config |
| |
| import ( |
| "context" |
| "fmt" |
| "io" |
| "net/http" |
| |
| "github.com/klauspost/compress/gzip" |
| ) |
| |
| // DownloadConfigFromSignedURL downloads the config file content from the |
| // provided GCS signed url. The signed url is generated by Config Service V2. |
| func DownloadConfigFromSignedURL(ctx context.Context, client *http.Client, signedURL string) ([]byte, error) { |
| if client == nil { |
| return nil, fmt.Errorf("http client is nil") |
| } |
| if signedURL == "" { |
| return nil, fmt.Errorf("empty signedURL") |
| } |
| |
| req, err := http.NewRequestWithContext(ctx, http.MethodGet, signedURL, http.NoBody) |
| if err != nil { |
| return nil, fmt.Errorf("failed to create http request to download file: %w", err) |
| } |
| req.Header.Add("Accept-Encoding", "gzip") |
| res, err := client.Do(req) |
| if err != nil { |
| return nil, fmt.Errorf("failed to execute http request to download file: %w", err) |
| } |
| |
| defer func() { _ = res.Body.Close() }() |
| |
| switch { |
| case res.StatusCode != http.StatusOK: |
| body, err := io.ReadAll(res.Body) |
| if err != nil { |
| return nil, fmt.Errorf("failed to read response body: %w", err) |
| } |
| return nil, fmt.Errorf("failed to download file, got http response code: %d, body: %q", res.StatusCode, string(body)) |
| |
| case res.Header.Get("Content-Encoding") == "gzip": |
| reader, err := gzip.NewReader(res.Body) |
| if err != nil { |
| return nil, fmt.Errorf("failed to create gzip reader: %w", err) |
| } |
| ret, err := io.ReadAll(reader) |
| if err != nil { |
| _ = reader.Close() |
| return nil, fmt.Errorf("failed to read or decompress response body: %w", err) |
| } |
| if err := reader.Close(); err != nil { |
| return nil, fmt.Errorf("failed to close gzip reader: %w", err) |
| } |
| return ret, nil |
| |
| default: |
| ret, err := io.ReadAll(res.Body) |
| if err != nil { |
| return nil, fmt.Errorf("failed to read response body: %w", err) |
| } |
| return ret, nil |
| } |
| } |