RemoteExists will check if a file at the given URL Exists. If it does, it will return its URL. If it does not, it will search the search for any files at the given URL with any of the default Taskfile files names. If any of these match a file, the first matching path will be returned. If no files ar
(ctx context.Context, u url.URL, client *http.Client)
| 39 | // these match a file, the first matching path will be returned. If no files are |
| 40 | // found, an error will be returned. |
| 41 | func RemoteExists(ctx context.Context, u url.URL, client *http.Client) (*url.URL, error) { |
| 42 | // Create a new HEAD request for the given URL to check if the resource exists |
| 43 | req, err := http.NewRequestWithContext(ctx, "HEAD", u.String(), nil) |
| 44 | if err != nil { |
| 45 | return nil, errors.TaskfileFetchFailedError{URI: u.Redacted()} |
| 46 | } |
| 47 | |
| 48 | // Request the given URL |
| 49 | resp, err := client.Do(req) |
| 50 | if err != nil { |
| 51 | if ctx.Err() != nil { |
| 52 | return nil, fmt.Errorf("checking remote file: %w", ctx.Err()) |
| 53 | } |
| 54 | return nil, errors.TaskfileFetchFailedError{URI: u.Redacted()} |
| 55 | } |
| 56 | defer resp.Body.Close() |
| 57 | |
| 58 | // If the request was successful and the content type is allowed, return the |
| 59 | // URL The content type check is to avoid downloading files that are not |
| 60 | // Taskfiles It means we can try other files instead of downloading |
| 61 | // something that is definitely not a Taskfile |
| 62 | contentType := resp.Header.Get("Content-Type") |
| 63 | if resp.StatusCode == http.StatusOK && slices.ContainsFunc(allowedContentTypes, func(s string) bool { |
| 64 | return strings.Contains(contentType, s) |
| 65 | }) { |
| 66 | return &u, nil |
| 67 | } |
| 68 | |
| 69 | // If the request was not successful, append the default Taskfile names to |
| 70 | // the URL and return the URL of the first successful request |
| 71 | for _, taskfile := range DefaultTaskfiles { |
| 72 | // Fixes a bug with JoinPath where a leading slash is not added to the |
| 73 | // path if it is empty |
| 74 | if u.Path == "" { |
| 75 | u.Path = "/" |
| 76 | } |
| 77 | alt := u.JoinPath(taskfile) |
| 78 | req.URL = alt |
| 79 | |
| 80 | // Try the alternative URL |
| 81 | resp, err = client.Do(req) |
| 82 | if err != nil { |
| 83 | return nil, errors.TaskfileFetchFailedError{URI: u.Redacted()} |
| 84 | } |
| 85 | defer resp.Body.Close() |
| 86 | |
| 87 | // If the request was successful, return the URL |
| 88 | if resp.StatusCode == http.StatusOK { |
| 89 | return alt, nil |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | return nil, errors.TaskfileNotFoundError{URI: u.Redacted(), Walk: false} |
| 94 | } |
no test coverage detected
searching dependent graphs…