Grok 20.3.2
GSFetcher.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2016-2026 Grok Image Compression Inc.
3 *
4 * This source code is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License, version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This source code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Affero General Public License for more details.
12 *
13 * You should have received a copy of the GNU Affero General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18#pragma once
19
20#include <ctime>
21
22#include "grk_config_private.h"
23#include "CurlFetcher.h"
24#include "FetchPathParser.h"
25
26#ifdef GRK_ENABLE_LIBCURL
27
28namespace grk
29{
30
31class GSFetcher : public CurlFetcher
32{
33protected:
34 void parse(const std::string& path) override
35 {
36 // Create a non-const copy of path for FetchPathParser
37 std::string mutable_path = path;
38 ParsedFetchPath parsed;
39 if(mutable_path.starts_with("/vsigs/"))
40 {
41 // Parse /vsigs/ path using FetchPathParser
42 FetchPathParser::parseVsiPath(mutable_path, parsed, "vsigs");
43 parsed.host = "storage.googleapis.com";
44 parsed.port = 443;
45 }
46 else if(mutable_path.starts_with("https://"))
47 {
48 // Parse HTTPS path using FetchPathParser
49 FetchPathParser::parseHttpsPath(mutable_path, parsed);
50 }
51 else
52 {
53 grklog.error("Unsupported URL format for GS: %s", path.c_str());
54 throw std::runtime_error("Unsupported URL format for GS");
55 }
56
57 grklog.debug("Parsed GS URL - Host: %s, Port: %d, Bucket: %s, Key: %s", parsed.host.c_str(),
58 parsed.port, parsed.bucket.c_str(), parsed.key.c_str());
59
60 // Construct the final URL
61 url_ = "https://" + parsed.host + "/" + parsed.bucket + "/" + parsed.key;
62 grklog.debug("Parsed GSFetcher URL: %s", url_.c_str());
63 }
64
65 void auth(CURL* curl) override
66 {
67 // Apply parent auth settings (e.g., SSL verification, proxy, cookies)
68 CurlFetcher::auth(curl);
69
70 // Check environment variables for access key and secret
71 std::string access_key = auth_.username_;
72 std::string secret_key = auth_.password_;
73
74 if(access_key.empty())
75 {
76 if(const char* key = std::getenv("GS_ACCESS_KEY_ID"))
77 {
78 access_key = key;
79 grklog.debug("Set GS access key = %s", access_key.c_str());
80 }
81 }
82 if(secret_key.empty())
83 {
84 if(const char* secret = std::getenv("GS_SECRET_ACCESS_KEY"))
85 {
86 secret_key = secret;
87 grklog.debug("Set GS secret key = %s", secret_key.c_str());
88 }
89 }
90
91 // GCS HMAC interop mode uses AWS SigV4-compatible signing
92 if(!access_key.empty() && !secret_key.empty())
93 {
94 curl_easy_setopt(curl, CURLOPT_USERNAME, access_key.c_str());
95 curl_easy_setopt(curl, CURLOPT_PASSWORD, secret_key.c_str());
96 std::string sigv4 = "aws:amz:auto:s3";
97 curl_easy_setopt(curl, CURLOPT_AWS_SIGV4, sigv4.c_str());
98 grklog.debug("Applied GCS HMAC interop authentication (SigV4) for access key: %s",
99 access_key.c_str());
100 }
101 else
102 {
103 grklog.debug("No GS authentication applied (public access or other auth)");
104 }
105 }
106
107 curl_slist* prepareAuthHeaders(curl_slist* headers) override
108 {
109 time_t now;
110 time(&now);
111 char date_buf[64];
112 strftime(date_buf, sizeof(date_buf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
113 std::string date_header = "Date: " + std::string(date_buf);
114 headers = curl_slist_append(headers, date_header.c_str());
115
116 return headers;
117 }
118};
119
120} // namespace grk
121
122#endif
ResWindow.
Definition CompressedChunkCache.h:36
ILogger & grklog
Definition Logger.cpp:24
virtual void error(const char *fmt,...)=0
virtual void debug(const char *fmt,...)=0