如何通过GraphQL API获取并下载GitHub发布资产?
解决GitHub私有仓库发布资产下载的问题
1. GraphQL ID转REST整数ID的方案
GraphQL返回的id是GitHub的全局节点ID(base64编码字符串),无法直接转换为REST API要求的整数asset_id。解决方法是在GraphQL查询中额外请求databaseId字段,这个字段的值就是REST API需要的整数ID。
修改你的GraphQL查询,添加databaseId:
query GetReleaseAssets($owner: String!, $repo: String!, $tag: String!) { repository(owner: $owner, name: $repo) { release(tagName: $tag) { releaseAssets(first: 10) { nodes { id # GraphQL全局ID databaseId # 对应REST的整数asset_id name assetDownloadUrl } } } } }
查询结果中会直接返回整数类型的databaseId,可直接传给go-github的REST API方法使用。
2. 解决assetDownloadUrl返回404的问题
出现404的核心原因是私有资产的下载请求未携带有效认证信息,即使使用已认证的GitHub客户端,下载assetDownloadUrl时需要单独处理认证:
方案一:复用GraphQL客户端的认证信息发起下载
githubv4的客户端默认携带认证token,直接用它发起GET请求即可:
import ( "io" "os" "context" "github.com/shurcooL/githubv4" ) // 假设已初始化带认证的githubv4.Client client := githubv4.NewClient(yourAuthenticatedHTTPClient) // 从GraphQL查询获取下载链接 downloadUrl := "https://github.com/xxx/xxx/releases/download/v1.0.0/asset.zip" resp, err := client.Get(context.Background(), downloadUrl) if err != nil { // 处理错误 } defer resp.Body.Close() // 写入本地文件 out, err := os.Create("asset.zip") if err != nil { // 处理错误 } defer out.Close() _, err = io.Copy(out, resp.Body) if err != nil { // 处理错误 }
方案二:用go-github的REST API直接下载
如果已经拿到databaseId,可以调用go-github的内置方法,它会自动处理认证和下载逻辑:
import ( "context" "io" "os" "github.com/google/go-github/v56/github" ) // 假设已初始化带认证的github.Client restClient := github.NewClient(yourAuthenticatedHTTPClient) assetID := int64(12345678) // 从GraphQL的databaseId获取 owner := "your-owner" repo := "your-repo" resp, _, err := restClient.Repositories.DownloadReleaseAsset(context.Background(), owner, repo, assetID, http.DefaultClient) if err != nil { // 处理错误 } defer resp.Body.Close() // 写入本地文件逻辑同上
3. 推荐的GraphQL优先方案
既然你倾向于用GraphQL减少请求次数,推荐在一次查询中同时获取databaseId和assetDownloadUrl:
- 若想直接用URL下载,复用GraphQL客户端的http.Client发起请求即可
- 若追求稳定性,用
databaseId调用REST API下载
内容的提问来源于stack exchange,提问作者Moritz Schmitz v. Hülst
相关产品推荐
相关产品推荐

