@@ -10,6 +10,7 @@ import (
10
10
"net/url"
11
11
"os"
12
12
"path/filepath"
13
+ "regexp"
13
14
"strings"
14
15
"time"
15
16
@@ -293,50 +294,66 @@ func (g *HttpGetter) Get(dst string, u *url.URL) error {
293
294
// If there is a subdir component, then we download the root separately
294
295
// into a temporary directory, then copy over the proper subdir.
295
296
source , subDir := SourceDirSubdir (source )
296
- if subDir == "" {
297
- var opts []ClientOption
297
+ if subDir != "" {
298
+ // We have a subdir, time to jump some hoops
299
+ return g .getSubdir (ctx , dst , source , subDir )
300
+ }
301
+
302
+ var opts []ClientOption
303
+
304
+ // Check if the protocol was switched to one which was not configured.
305
+ if g .client != nil && g .client .Getters != nil {
306
+ // We must first use the Detectors provided, because `X-Terraform-Get does
307
+ // not necessarily return a valid URL. We can replace the source string
308
+ // here, since the detectors would have been called immediately during the
309
+ // next Get anyway.
310
+ source , err = Detect (source , g .client .Pwd , g .client .Detectors )
311
+ if err != nil {
312
+ return err
313
+ }
314
+
315
+ protocol := ""
316
+ // X-Terraform-Get allows paths relative to the previous request too,
317
+ // which won't have a protocol.
318
+ if ! relativeGet (source ) {
319
+ protocol = strings .Split (source , ":" )[0 ]
320
+ }
298
321
299
- // Check if the protocol was switched to one which was not configured.
300
- //
301
322
// Otherwise, all default getters are allowed.
302
- if g .client != nil && g .client .Getters != nil {
303
- protocol := strings .Split (source , ":" )[0 ]
323
+ if protocol != "" {
304
324
_ , allowed := g .client .Getters [protocol ]
305
325
if ! allowed {
306
326
return fmt .Errorf ("no getter available for X-Terraform-Get source protocol: %q" , protocol )
307
327
}
308
328
}
329
+ }
309
330
310
- // Add any getter client options.
311
- if g .client != nil {
312
- opts = g .client .Options
313
- }
314
-
315
- // If the client is nil, we know we're using the HttpGetter directly. In this case,
316
- // we don't know exactly which protocols are configued, but we can make a good guess.
317
- //
318
- // This prevents all default getters from being allowed when only using the
319
- // HttpGetter directly. To enable protocol switching, a client "wrapper" must
320
- // be used.
321
- if g .client == nil {
322
- opts = append (opts , WithGetters (map [string ]Getter {
323
- "http" : g ,
324
- "https" : g ,
325
- }))
326
- }
327
-
328
- // Ensure we pass along the context we constructed in this function.
329
- //
330
- // This is especially important to enforce a limit on X-Terraform-Get redirects
331
- // which could be setup, if configured, at the top of this function.
332
- opts = append (opts , WithContext (ctx ))
331
+ // Add any getter client options.
332
+ if g .client != nil {
333
+ opts = g .client .Options
334
+ }
333
335
334
- // Note: this allows the protocol to be switched to another configured getters.
335
- return Get (dst , source , opts ... )
336
+ // If the client is nil, we know we're using the HttpGetter directly. In this case,
337
+ // we don't know exactly which protocols are configued, but we can make a good guess.
338
+ //
339
+ // This prevents all default getters from being allowed when only using the
340
+ // HttpGetter directly. To enable protocol switching, a client "wrapper" must
341
+ // be used.
342
+ if g .client == nil {
343
+ opts = append (opts , WithGetters (map [string ]Getter {
344
+ "http" : g ,
345
+ "https" : g ,
346
+ }))
336
347
}
337
348
338
- // We have a subdir, time to jump some hoops
339
- return g .getSubdir (ctx , dst , source , subDir )
349
+ // Ensure we pass along the context we constructed in this function.
350
+ //
351
+ // This is especially important to enforce a limit on X-Terraform-Get redirects
352
+ // which could be setup, if configured, at the top of this function.
353
+ opts = append (opts , WithContext (ctx ))
354
+
355
+ // Note: this allows the protocol to be switched to another configured getters.
356
+ return Get (dst , source , opts ... )
340
357
}
341
358
342
359
// GetFile fetches the file from src and stores it at dst.
@@ -566,6 +583,9 @@ func (g *HttpGetter) parseMeta(ctx context.Context, r io.Reader) (string, error)
566
583
}
567
584
}
568
585
586
+ // X-Terraform-Get allows paths relative to the previous request
587
+ var relativeGet = regexp .MustCompile (`^\.{0,2}/` ).MatchString
588
+
569
589
// attrValue returns the attribute value for the case-insensitive key
570
590
// `name', or the empty string if nothing is found.
571
591
func attrValue (attrs []xml.Attr , name string ) string {
0 commit comments