142 TS3WebFile::TS3WebFile(
const char* path, Option_t* options)
143 : TWebFile(path,
"IO")
147 Bool_t doMakeZombie = kFALSE;
152 TPMERegexp rex(
"^([a]?s3|s3http[s]?|gs|gshttp[s]?){1}://([^/]+)/([^/]+)/([^/].*)",
"i");
153 if (rex.Match(TString(path)) != 5) {
154 errorMsg = TString::Format(
"invalid S3 path '%s'", path);
155 doMakeZombie = kTRUE;
157 else if (!ParseOptions(options, accessKey, secretKey, token)) {
158 errorMsg = TString::Format(
"could not parse options '%s'", options);
159 doMakeZombie = kTRUE;
164 Error(
"TS3WebFile",
"%s", (
const char*)errorMsg);
172 fS3Request.SetBucket(rex[3]);
173 fS3Request.SetObjectKey(TString::Format(
"/%s", (
const char*)rex[4]));
177 TString protocol =
"https";
178 if (rex[1].EndsWith(
"http", TString::kIgnoreCase) ||
179 rex[1].EqualTo(
"as3", TString::kIgnoreCase))
181 fUrl.SetUrl(TString::Format(
"%s://%s/%s/%s", (
const char*)protocol,
182 (
const char*)rex[2], (
const char*)rex[3], (
const char*)rex[4]));
187 const char* kAccessKeyEnv =
"S3_ACCESS_KEY";
188 const char* kSecretKeyEnv =
"S3_SECRET_KEY";
189 const char* kSessionToken =
"S3_SESSION_TOKEN";
190 if (accessKey.IsNull())
191 GetCredentialsFromEnv(kAccessKeyEnv, kSecretKeyEnv, kSessionToken,
192 accessKey, secretKey, token);
195 fS3Request.SetHost(fUrl.GetHost());
196 if (accessKey.IsNull() || secretKey.IsNull()) {
201 fS3Request.SetAuthType(TS3HTTPRequest::kNoAuth);
205 fS3Request.SetAuthKeys(accessKey, secretKey);
207 fS3Request.SetSessionToken(token);
208 if (rex[1].BeginsWith(
"gs"))
209 fS3Request.SetAuthType(TS3HTTPRequest::kGoogle);
211 fS3Request.SetAuthType(TS3HTTPRequest::kAmazon);
217 fUseMultiRange = kFALSE;
220 TWebFile::Init(kFALSE);
223 if (IsZombie() && (accessKey.IsNull() || secretKey.IsNull())) {
226 Error(
"TS3WebFile",
"could not find authentication info in "\
227 "'options' argument and at least one of the environment variables '%s' or '%s' is not set",
228 kAccessKeyEnv, kSecretKeyEnv);
245 Bool_t TS3WebFile::ParseOptions(Option_t* options, TString& accessKey, TString& secretKey, TString& token)
247 TString optStr = (
const char*)options;
252 if (optStr.Contains(
"NOPROXY", TString::kIgnoreCase))
257 TPMERegexp rex_token(
"(^TOKEN=|^.* TOKEN=)([\\S]+)[\\s]*.*$",
"i");
258 if (rex_token.Match(optStr) == 3) {
259 token = rex_token[2];
261 TPMERegexp rex(
"(^AUTH=|^.* AUTH=)([a-z0-9]+):([a-z0-9+/]+)[\\s]*.*$",
"i");
262 if (rex.Match(optStr) == 4) {
267 Info(
"ParseOptions",
"using authentication information from 'options' argument");
277 Int_t TS3WebFile::GetHead()
279 fMsgGetHead = fS3Request.GetRequest(TS3HTTPRequest::kHEAD);
280 return TWebFile::GetHead();
291 void TS3WebFile::SetMsgReadBuffer10(
const char* redirectLocation, Bool_t tempRedirect)
293 TWebFile::SetMsgReadBuffer10(redirectLocation, tempRedirect);
294 fMsgReadBuffer10 = fS3Request.GetRequest(TS3HTTPRequest::kGET, kFALSE) +
"Range: bytes=";
301 Bool_t TS3WebFile::ReadBuffers(
char* buf, Long64_t* pos, Int_t* len, Int_t nbuf)
310 return TWebFile::ReadBuffers(buf, pos, len, nbuf);
314 for (Int_t i=0, offset=0; i < nbuf; i++) {
315 TString rangeHeader = TString::Format(
"Range: bytes=%lld-%lld\r\n\r\n",
316 pos[i], pos[i] + len[i] - 1);
317 TString s3Request = fS3Request.GetRequest(TS3HTTPRequest::kGET, kFALSE) + rangeHeader;
318 if (GetFromWeb10(&buf[offset], len[i], s3Request) == -1)
336 void TS3WebFile::ProcessHttpHeader(
const TString& headerLine)
338 TPMERegexp rex(
"^Server: (.+)",
"i");
339 if (rex.Match(headerLine) != 2)
346 TString serverId = rex[1].ReplaceAll(
"\r",
"").ReplaceAll(
"\n",
"");
347 TString multirangeServers(gEnv->GetValue(
"TS3WebFile.Root.MultiRangeServer",
""));
348 fUseMultiRange = multirangeServers.Contains(serverId, TString::kIgnoreCase) ? kTRUE : kFALSE;
356 Bool_t TS3WebFile::GetCredentialsFromEnv(
const char* accessKeyEnv,
const char* secretKeyEnv,
357 const char* tokenEnv, TString& outAccessKey,
358 TString& outSecretKey, TString& outToken)
362 TString accKey = gSystem->Getenv(accessKeyEnv);
363 TString secKey = gSystem->Getenv(secretKeyEnv);
364 TString token = gSystem->Getenv(tokenEnv);
365 if (!token.IsNull()) {
368 if (!accKey.IsNull() && !secKey.IsNull()) {
369 outAccessKey = accKey;
370 outSecretKey = secKey;
372 Info(
"GetCredentialsFromEnv",
"using authentication information from environmental variables '%s' and '%s'",
373 accessKeyEnv, secretKeyEnv);
379 accKey = gSystem->Getenv(
"S3_ACCESS_ID");
380 secKey = gSystem->Getenv(
"S3_ACCESS_KEY");
381 if (!accKey.IsNull() && !secKey.IsNull()) {
382 Warning(
"SetAuthKeys",
"usage of S3_ACCESS_ID and S3_ACCESS_KEY environmental variables is deprecated.");
383 Warning(
"SetAuthKeys",
"please use S3_ACCESS_KEY and S3_SECRET_KEY environmental variables.");
384 outAccessKey = accKey;
385 outSecretKey = secKey;