🔌 客户端 ComposerClient
pkg/client.ComposerClient 是 Packagist API SDK 的高级门面。它把 Packagist 的公开 HTTP/JSON 端点封装成 20 个类型安全的 Go 方法,返回值直接是 pkg/domain 下的强类型结构,调用方无需自行处理 HTTP 请求、状态码判断与 JSON 反序列化。
纯 Go,无需 PHP
ComposerClient 只依赖 Go 标准库 net/http,不调用本地 composer 二进制,也不需要 PHP 运行时。可独立于 Composer CLI SDK 单独使用。
何时使用
- 🌐 你的服务在 Go 中需要查询 Packagist 上的包元数据、下载统计或安全公告。
- 🛠️ CI/CD 流水线里用 Go 脚本检查依赖的漏洞或下载量,不想为了一个 HTTP 调用再装 PHP。
- 📊 需要把 Packagist 数据落库做长期趋势分析,
ComposerClient给你强类型结构直接入库。 - 🔌 需要指向自建镜像 / Satis 实例:用
WithBaseURL/WithRepoURL覆盖默认地址。
创建客户端
NewComposerClient
func NewComposerClient(timeout time.Duration, options ...ComposerClientOption) *ComposerClient| 参数 | 类型 | 说明 |
|---|---|---|
timeout | time.Duration | HTTP 客户端整体超时,传给 http.Client.Timeout |
options | ...ComposerClientOption | 可选配置函数,按需覆盖默认 base URL、repo URL、API 凭证 |
默认值:
| 字段 | 默认值 | 含义 |
|---|---|---|
baseURL | https://packagist.org | 业务 API 端点(包信息、搜索、统计、列表、管理) |
repoURL | https://repo.packagist.org | 仓库元数据端点(V2 元数据 p2/...、dev 版本) |
username / apiToken | 空 | 仅写操作需要,见 WithAPICredentials |
示例
package main
import (
"fmt"
"log"
"time"
"github.com/scagogogo/composer-skills/pkg/client"
)
func main() {
// 最简:30 秒超时,匿名访问官方 Packagist
c := client.NewComposerClient(30 * time.Second)
stats, err := c.GetStatistics()
if err != nil {
log.Fatalf("获取统计失败: %v", err)
}
fmt.Printf("Packagist 共有 %d 个包\n", stats.Totals.Packages)
}配置选项
所有选项都是 ComposerClientOption 函数,按需传入 NewComposerClient。
WithBaseURL
func WithBaseURL(baseURL string) ComposerClientOption| 参数 | 类型 | 说明 |
|---|---|---|
baseURL | string | 业务 API 基础 URL,覆盖默认 https://packagist.org |
覆盖后,GetPackage、GetStatistics、SearchPackages、ListPackages*、GetSecurityAdvisories*、CreatePackage 等方法都会拼接这个前缀。指向自建 Packagist 镜像或私有 Packagist 实例时使用。
c := client.NewComposerClient(
30*time.Second,
client.WithBaseURL("https://packagist.mycompany.com"),
)WithRepoURL
func WithRepoURL(repoURL string) ComposerClientOption| 参数 | 类型 | 说明 |
|---|---|---|
repoURL | string | 仓库元数据基础 URL,覆盖默认 https://repo.packagist.org |
仅影响 GetPackageWithV2Metadata 与 GetPackageDevVersions 两个方法(它们走 p2/... 端点)。
c := client.NewComposerClient(
30*time.Second,
client.WithRepoURL("https://repo.packagist.mycompany.com"),
)WithAPICredentials
func WithAPICredentials(username, apiToken string) ComposerClientOption| 参数 | 类型 | 说明 |
|---|---|---|
username | string | Packagist 账号用户名 |
apiToken | string | Packagist 个人 API token(在 packagist.org 个人页生成) |
凭证安全
username 与 apiToken 会作为 URL 查询参数拼接到请求 URL 中(Packagist API 的设计)。请勿在不安全的日志中打印完整请求 URL。建议从环境变量或密钥管理服务读取,不要硬编码进源码。
只有三个写操作需要凭证,未配置时调用会直接返回错误:
c := client.NewComposerClient(
30*time.Second,
client.WithAPICredentials(
os.Getenv("PACKAGIST_USERNAME"),
os.Getenv("PACKAGIST_API_TOKEN"),
),
)完整方法清单
下表列出 ComposerClient 的全部 20 个方法。详细签名、参数与示例见对应子文档。
| 方法 | 签名概要 | 返回类型 | 子文档 |
|---|---|---|---|
📦 GetPackage | (packageName string) | (*domain.ComposerPackageInfo, error) | package-info |
📦 GetPackageWithV2Metadata | (packageName string) | ([]byte, error) | package-info |
📦 GetPackageDevVersions | (packageName string) | ([]byte, error) | package-info |
📦 GetPackageStats | (packageName string) | (*domain.PackageStatsResponse, error) | package-info |
📦 GetPackageChanges | (ctx context.Context, since int64) | (*domain.ChangeTrackingResponse, error) | package-info |
🔍 SearchPackages | (query string, perPage, page int) | (*domain.SearchResponse, error) | search |
🔍 SearchPackagesByTags | (tags []string, perPage, page int) | (*domain.SearchResponse, error) | search |
🔍 SearchPackagesByType | (query, packageType string, perPage, page int) | (*domain.SearchResponse, error) | search |
📊 GetStatistics | () | (*domain.StatisticsResponse, error) | statistics |
🔒 GetSecurityAdvisories | () | (*domain.AdvisoriesResponse, error) | advisories |
🔒 GetSecurityAdvisoriesForPackages | (packageNames []string) | (*domain.AdvisoriesResponse, error) | advisories |
🔒 GetSecurityAdvisoriesSince | (updatedSince time.Time) | (*domain.AdvisoriesResponse, error) | advisories |
📋 ListPackages | () | (*domain.PackageListResponse, error) | listing |
📋 ListPackagesByVendor | (vendor string) | (*domain.PackageListResponse, error) | listing |
📋 ListPackagesByType | (packageType string) | (*domain.PackageListResponse, error) | listing |
📋 ListPackagesWithData | (fields []string) | (*domain.PackageListWithDataResponse, error) | listing |
📋 ListPopularPackages | (perPage int) | (*domain.PopularPackagesResponse, error) | listing |
🛠️ CreatePackage | (ctx, *domain.PackageCreateRequest) | (*domain.PackageCreateResponse, error) | management |
🛠️ EditPackage | (ctx, packageName, *domain.PackageEditRequest) | (*domain.PackageEditResponse, error) | management |
🛠️ UpdatePackage | (ctx, *domain.PackageUpdateRequest) | (*domain.PackageUpdateResponse, error) | management |
进阶
超时设置
NewComposerClient 的第一个参数 timeout 直接赋给 http.Client.Timeout,覆盖所有阶段(连接、TLS 握手、读 body)。生产环境建议设 30s–60s;下载大型索引(ListPackagesWithData 返回量大)时可适当调大,或改用底层 Repository 层 的 DownloadIndexToFile 落盘后流式处理。
c := client.NewComposerClient(60 * time.Second)注意
ComposerClient 不支持自定义 http.Transport(如需自定义重试、连接池、TLS 配置,请改用底层 repository.Repository,它通过 go-requests 支持 Proxy 等设置项)。
组合多个选项
c := client.NewComposerClient(
45*time.Second,
client.WithBaseURL("https://packagist.mycompany.com"),
client.WithRepoURL("https://repo.packagist.mycompany.com"),
client.WithAPICredentials(user, token),
)🔗 相关
- 📦 方法细节:包信息
- 🏗️ 底层 HTTP 层:Repository
- ⚙️ 代理配置:Options