github.com/safing/portbase@v0.19.5/updater/get.go (about) 1 package updater 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "net/http" 8 9 "github.com/safing/portbase/log" 10 ) 11 12 // Errors returned by the updater package. 13 var ( 14 ErrNotFound = errors.New("the requested file could not be found") 15 ErrNotAvailableLocally = errors.New("the requested file is not available locally") 16 ErrVerificationNotConfigured = errors.New("verification not configured for this resource") 17 ) 18 19 // GetFile returns the selected (mostly newest) file with the given 20 // identifier or an error, if it fails. 21 func (reg *ResourceRegistry) GetFile(identifier string) (*File, error) { 22 reg.RLock() 23 res, ok := reg.resources[identifier] 24 reg.RUnlock() 25 if !ok { 26 return nil, ErrNotFound 27 } 28 29 file := res.GetFile() 30 // check if file is available locally 31 if file.version.Available { 32 file.markActiveWithLocking() 33 34 // Verify file, if configured. 35 _, err := file.Verify() 36 if err != nil && !errors.Is(err, ErrVerificationNotConfigured) { 37 // TODO: If verification is required, try deleting the resource and downloading it again. 38 return nil, fmt.Errorf("failed to verify file: %w", err) 39 } 40 41 return file, nil 42 } 43 44 // check if online 45 if !reg.Online { 46 return nil, ErrNotAvailableLocally 47 } 48 49 // check download dir 50 err := reg.tmpDir.Ensure() 51 if err != nil { 52 return nil, fmt.Errorf("could not prepare tmp directory for download: %w", err) 53 } 54 55 // Start registry operation. 56 reg.state.StartOperation(StateFetching) 57 defer reg.state.EndOperation() 58 59 // download file 60 log.Tracef("%s: starting download of %s", reg.Name, file.versionedPath) 61 client := &http.Client{} 62 for tries := 0; tries < 5; tries++ { 63 err = reg.fetchFile(context.TODO(), client, file.version, tries) 64 if err != nil { 65 log.Tracef("%s: failed to download %s: %s, retrying (%d)", reg.Name, file.versionedPath, err, tries+1) 66 } else { 67 file.markActiveWithLocking() 68 69 // TODO: We just download the file - should we verify it again? 70 return file, nil 71 } 72 } 73 log.Warningf("%s: failed to download %s: %s", reg.Name, file.versionedPath, err) 74 return nil, err 75 } 76 77 // GetVersion returns the selected version of the given identifier. 78 // The returned resource version may not be modified. 79 func (reg *ResourceRegistry) GetVersion(identifier string) (*ResourceVersion, error) { 80 reg.RLock() 81 res, ok := reg.resources[identifier] 82 reg.RUnlock() 83 if !ok { 84 return nil, ErrNotFound 85 } 86 87 res.Lock() 88 defer res.Unlock() 89 90 return res.SelectedVersion, nil 91 }