Web API

注册表可以在 config.json 中定义的位置托管 Web API,以支持以下列出的任何操作。

Cargo 在需要身份验证的请求中包含 Authorization 标头。标头值是 API 令牌。如果令牌无效,服务器应响应 403 响应代码。用户需要访问注册表的网站以获取令牌,Cargo 可以使用 cargo login 命令存储令牌,或者在命令行上传递令牌。

响应使用 2xx 响应代码表示成功。错误应使用适当的响应代码,例如 404。失败响应应具有以下结构的 JSON 对象

{
    // Array of errors to display to the user.
    "errors": [
        {
            // The error message as a string.
            "detail": "error message text"
        }
    ]
}

如果响应具有此结构,即使响应代码为 200,Cargo 也会向用户显示详细消息。如果响应代码指示错误并且内容不具有此结构,则 Cargo 将向用户显示旨在帮助调试服务器错误的消息。返回 errors 对象的服务器允许注册表提供更详细或以用户为中心的错误消息。

为了向后兼容,服务器应忽略任何意外的查询参数或 JSON 字段。如果缺少 JSON 字段,则应假定它为空。端点使用路径的 v1 组件进行版本控制,Cargo 负责处理将来可能需要的任何向后兼容回退。

Cargo 为所有请求设置以下标头

  • Content-Typeapplication/json(对于具有正文有效负载的请求)
  • Acceptapplication/json
  • User-Agent:Cargo 版本,例如 cargo/1.32.0 (8610973aa 2019-01-02)。用户可以在配置值中修改此项。在 1.29 中添加。

发布

  • 端点:/api/v1/crates/new
  • 方法:PUT
  • 授权:已包含

发布端点用于发布新版本的 crate。服务器应验证 crate,使其可供下载,并将其添加到索引中。

在发送成功响应之前,不需要更新索引。成功响应后,Cargo 将在短时间内轮询索引,以识别已添加新 crate。如果短时间后索引中未出现该 crate,则 Cargo 将显示警告,告知用户新 crate 尚不可用。

Cargo 发送的数据主体是

  • JSON 数据长度的 32 位无符号小端整数。
  • 包的元数据,以 JSON 对象表示。
  • .crate 文件长度的 32 位无符号小端整数。
  • .crate 文件。

以下是 JSON 对象的注释示例。有关 crates.io 强加的一些限制的说明仅用于说明对可能完成的验证类型的建议,不应被视为 crates.io 强加的限制的详尽列表。

{
    // The name of the package.
    "name": "foo",
    // The version of the package being published.
    "vers": "0.1.0",
    // Array of direct dependencies of the package.
    "deps": [
        {
            // Name of the dependency.
            // If the dependency is renamed from the original package name,
            // this is the original name. The new package name is stored in
            // the `explicit_name_in_toml` field.
            "name": "rand",
            // The semver requirement for this dependency.
            "version_req": "^0.6",
            // Array of features (as strings) enabled for this dependency.
            "features": ["i128_support"],
            // Boolean of whether or not this is an optional dependency.
            "optional": false,
            // Boolean of whether or not default features are enabled.
            "default_features": true,
            // The target platform for the dependency.
            // null if not a target dependency.
            // Otherwise, a string such as "cfg(windows)".
            "target": null,
            // The dependency kind.
            // "dev", "build", or "normal".
            "kind": "normal",
            // The URL of the index of the registry where this dependency is
            // from as a string. If not specified or null, it is assumed the
            // dependency is in the current registry.
            "registry": null,
            // If the dependency is renamed, this is a string of the new
            // package name. If not specified or null, this dependency is not
            // renamed.
            "explicit_name_in_toml": null,
        }
    ],
    // Set of features defined for the package.
    // Each feature maps to an array of features or dependencies it enables.
    // Cargo does not impose limitations on feature names, but crates.io
    // requires alphanumeric ASCII, `_` or `-` characters.
    "features": {
        "extras": ["rand/simd_support"]
    },
    // List of strings of the authors.
    // May be empty.
    "authors": ["Alice <[email protected]>"],
    // Description field from the manifest.
    // May be null. crates.io requires at least some content.
    "description": null,
    // String of the URL to the website for this package's documentation.
    // May be null.
    "documentation": null,
    // String of the URL to the website for this package's home page.
    // May be null.
    "homepage": null,
    // String of the content of the README file.
    // May be null.
    "readme": null,
    // String of a relative path to a README file in the crate.
    // May be null.
    "readme_file": null,
    // Array of strings of keywords for the package.
    "keywords": [],
    // Array of strings of categories for the package.
    "categories": [],
    // String of the license for the package.
    // May be null. crates.io requires either `license` or `license_file` to be set.
    "license": null,
    // String of a relative path to a license file in the crate.
    // May be null.
    "license_file": null,
    // String of the URL to the website for the source repository of this package.
    // May be null.
    "repository": null,
    // Optional object of "status" badges. Each value is an object of
    // arbitrary string to string mappings.
    // crates.io has special interpretation of the format of the badges.
    "badges": {
        "travis-ci": {
            "branch": "master",
            "repository": "rust-lang/cargo"
        }
    },
    // The `links` string value from the package's manifest, or null if not
    // specified. This field is optional and defaults to null.
    "links": null,
    // The minimal supported Rust version (optional)
    // This must be a valid version requirement without an operator (e.g. no `=`)
    "rust_version": null
}

成功响应包括 JSON 对象

{
    // Optional object of warnings to display to the user.
    "warnings": {
        // Array of strings of categories that are invalid and ignored.
        "invalid_categories": [],
        // Array of strings of badge names that are invalid and ignored.
        "invalid_badges": [],
        // Array of strings of arbitrary warnings to display to the user.
        "other": []
    }
}

撤销

  • 端点:/api/v1/crates/{crate_name}/{version}/yank
  • 方法:DELETE
  • 授权:已包含

撤销端点会将索引中给定版本的 crate 的 yank 字段设置为 true

成功响应包括 JSON 对象

{
    // Indicates the yank succeeded, always true.
    "ok": true,
}

取消撤销

  • 端点:/api/v1/crates/{crate_name}/{version}/unyank
  • 方法:PUT
  • 授权:已包含

取消撤销端点会将索引中给定版本的 crate 的 yank 字段设置为 false

成功响应包括 JSON 对象

{
    // Indicates the unyank succeeded, always true.
    "ok": true,
}

所有者

Cargo 本身没有用户和所有者的概念,但它确实提供了 owner 命令来帮助管理谁有权控制 crate。由注册表决定如何处理用户和所有者。有关 crates.io 如何通过 GitHub 用户和团队处理所有者的说明,请参阅发布文档

所有者:列表

  • 端点:/api/v1/crates/{crate_name}/owners
  • 方法:GET
  • 授权:已包含

所有者端点返回 crate 的所有者列表。

成功响应包括 JSON 对象

{
    // Array of owners of the crate.
    "users": [
        {
            // Unique unsigned 32-bit integer of the owner.
            "id": 70,
            // The unique username of the owner.
            "login": "github:rust-lang:core",
            // Name of the owner.
            // This is optional and may be null.
            "name": "Core",
        }
    ]
}

所有者:添加

  • 端点:/api/v1/crates/{crate_name}/owners
  • 方法:PUT
  • 授权:已包含

PUT 请求将向注册表发送请求,以将新所有者添加到 crate。由注册表决定如何处理请求。例如,crates.io 会向用户发送邀请,用户必须先接受邀请才能被添加。

请求应包含以下 JSON 对象

{
    // Array of `login` strings of owners to add.
    "users": ["login_name"]
}

成功响应包括 JSON 对象

{
    // Indicates the add succeeded, always true.
    "ok": true,
    // A string to be displayed to the user.
    "msg": "user ehuss has been invited to be an owner of crate cargo"
}

所有者:删除

  • 端点:/api/v1/crates/{crate_name}/owners
  • 方法:DELETE
  • 授权:已包含

DELETE 请求将从 crate 中移除所有者。请求应包含以下 JSON 对象

{
    // Array of `login` strings of owners to remove.
    "users": ["login_name"]
}

成功响应包括 JSON 对象

{
    // Indicates the remove succeeded, always true.
    "ok": true
    // A string to be displayed to the user. Currently ignored by cargo.
    "msg": "owners successfully removed",
}
  • 端点:/api/v1/crates
  • 方法:GET
  • 查询参数
    • q:搜索查询字符串。
    • per_page:结果数量,默认为 10,最大值为 100。

搜索请求将使用服务器上定义的条件执行 crate 搜索。

成功响应包括 JSON 对象

{
    // Array of results.
    "crates": [
        {
            // Name of the crate.
            "name": "rand",
            // The highest version available.
            "max_version": "0.6.1",
            // Textual description of the crate.
            "description": "Random number generators and other randomness functionality.\n",
        }
    ],
    "meta": {
        // Total number of results available on the server.
        "total": 119
    }
}

登录

  • 端点:/me

“登录”端点不是实际的 API 请求。它的存在仅仅是为了让 cargo login 命令显示一个 URL,指示用户在 Web 浏览器中访问该 URL 以登录并检索 API 令牌。