github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/pkg/covermerger/provider_web.go (about) 1 // Copyright 2024 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package covermerger 5 6 import ( 7 "encoding/base64" 8 "errors" 9 "fmt" 10 "io" 11 "net/http" 12 "net/url" 13 "strings" 14 ) 15 16 type FuncProxyURI func(filePath, commit string) string 17 18 type webGit struct { 19 funcProxy FuncProxyURI 20 } 21 22 func (mr *webGit) GetFileVersions(targetFilePath string, repoCommits ...RepoCommit, 23 ) (FileVersions, error) { 24 res := make(FileVersions) 25 for _, repoCommit := range repoCommits { 26 fileBytes, err := mr.loadFile(targetFilePath, repoCommit.Repo, repoCommit.Commit) 27 // It is ok if some file doesn't exist. It means we have repo FS diff. 28 if err == errFileNotFound { 29 continue 30 } 31 if err != nil { 32 return nil, fmt.Errorf("failed to loadFile: %w", err) 33 } 34 res[repoCommit] = string(fileBytes) 35 } 36 return res, nil 37 } 38 39 var errFileNotFound = errors.New("file not found") 40 41 func (mr *webGit) loadFile(filePath, repo, commit string) ([]byte, error) { 42 var uri string 43 if mr.funcProxy != nil { 44 uri = mr.funcProxy(filePath, commit) 45 } else { 46 uri = fmt.Sprintf("%s/plain/%s", repo, filePath) 47 if commit != "latest" { 48 uri += "?id=" + commit 49 } 50 } 51 u, err := url.Parse(uri) 52 if err != nil { 53 return nil, fmt.Errorf("failed to parse %v: %w", uri, err) 54 } 55 u.Scheme = "https" 56 uri = u.String() 57 resp, err := http.Get(uri) 58 if err != nil { 59 return nil, fmt.Errorf("failed to http.Get: %w", err) 60 } 61 defer resp.Body.Close() 62 63 if resp.StatusCode == 404 { 64 return nil, errFileNotFound 65 } 66 if resp.StatusCode != 200 { 67 return nil, fmt.Errorf("error: status %d getting '%s'", resp.StatusCode, uri) 68 } 69 body, err := io.ReadAll(resp.Body) 70 if err != nil { 71 return nil, fmt.Errorf("failed to io.ReadAll from body: %w", err) 72 } 73 if isGerritServer(resp) { 74 if body, err = base64.StdEncoding.DecodeString(string(body)); err != nil { 75 return nil, fmt.Errorf("base64.StdEncoding.DecodeString: %w", err) 76 } 77 } 78 return body, nil 79 } 80 81 func isGerritServer(resp *http.Response) bool { 82 for _, headerVals := range resp.Header { 83 for _, header := range headerVals { 84 if strings.Contains(header, "gerrit") { 85 return true 86 } 87 } 88 } 89 return false 90 } 91 92 func MakeWebGit(funcProxy FuncProxyURI) FileVersProvider { 93 return &webGit{ 94 funcProxy: funcProxy, 95 } 96 }