Grok 20.3.2
AZFetcher.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 AZFetcher : public CurlFetcher
32{
33protected:
34 void parse(const std::string& path) override
35 {
36 ParsedFetchPath parsed;
37 // Create a non-const copy of path for FetchPathParser
38 std::string mutable_path = path;
39 if(path.starts_with("/vsiaz/"))
40 {
41 // Parse /vsiaz/ path using FetchPathParser
42 std::string account;
43 if(!auth_.username_.empty())
44 {
45 account = auth_.username_;
46 grklog.debug("Using auth-provided account for vsiaz: %s", account.c_str());
47 }
48 else
49 {
50 grklog.error("No Azure account provided for /vsiaz/ path");
51 throw std::runtime_error("No Azure account provided for /vsiaz/ path");
52 }
53 FetchPathParser::parseVsiPath(mutable_path, parsed, "vsiaz");
54 parsed.host = account + ".blob.core.windows.net";
55 parsed.port = 443;
56 }
57 else if(path.starts_with("https://"))
58 {
59 // Parse HTTPS path using FetchPathParser
60 FetchPathParser::parseHttpsPath(mutable_path, parsed);
61 }
62 else
63 {
64 grklog.error("Unsupported URL format for Azure Blob: %s", path.c_str());
65 throw std::runtime_error("Unsupported URL format for Azure Blob");
66 }
67
68 grklog.debug("Parsed AZ URL - Host: %s, Port: %d, Container: %s, Blob: %s", parsed.host.c_str(),
69 parsed.port, parsed.bucket.c_str(), parsed.key.c_str());
70
71 // Construct the base URL without SAS token
72 url_ = "https://" + parsed.host + "/" + parsed.bucket + "/" + parsed.key;
73 grklog.debug("Parsed AZFetcher URL: %s", url_.c_str());
74 }
75
76 void auth(CURL* curl) override
77 {
78 // Apply parent auth settings (e.g., SSL verification)
79 CurlFetcher::auth(curl);
80
81 // Azure-specific authentication logic
82 std::string final_url = url_;
83
84 // Check environment variables for account and key/SAS token
85 std::string account = auth_.username_;
86 std::string secret = auth_.password_;
87
88 if(account.empty())
89 {
90 if(const char* key = std::getenv("AZURE_STORAGE_ACCOUNT"))
91 {
92 account = key;
93 grklog.debug("Set Azure account = %s", account.c_str());
94 }
95 }
96 if(secret.empty())
97 {
98 if(const char* key = std::getenv("AZURE_STORAGE_KEY"))
99 {
100 secret = key;
101 grklog.debug("Set Azure key = %s", secret.c_str());
102 }
103 else if(const char* sas = std::getenv("AZURE_STORAGE_SAS_TOKEN"))
104 {
105 secret = sas;
106 grklog.debug("Set Azure SAS token = %s", secret.c_str());
107 }
108 }
109
110 // Apply authentication
111 if(!account.empty() && !secret.empty() && secret.find("?") != 0)
112 {
113 // Use account key authentication
114 curl_easy_setopt(curl, CURLOPT_USERNAME, account.c_str());
115 curl_easy_setopt(curl, CURLOPT_PASSWORD, secret.c_str());
116 grklog.debug("Applied account key authentication for account: %s", account.c_str());
117 }
118 else if(!secret.empty() && secret.find("?") == 0)
119 {
120 // Append SAS token to URL
121 final_url += secret;
122 curl_easy_setopt(curl, CURLOPT_URL, final_url.c_str());
123 grklog.debug("Applied SAS token authentication, final URL: %s", final_url.c_str());
124 }
125 else
126 {
127 grklog.debug("No additional Azure authentication applied (public access or other auth)");
128 }
129 }
130
131 curl_slist* prepareAuthHeaders(curl_slist* headers) override
132 {
133 time_t now;
134 time(&now);
135 char date_buf[64];
136 strftime(date_buf, sizeof(date_buf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
137 std::string date_header = "x-ms-date: " + std::string(date_buf);
138 headers = curl_slist_append(headers, date_header.c_str());
139
140 return curl_slist_append(headers, "x-ms-version: 2020-04-08");
141 }
142};
143
144} // namespace grk
145
146#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