- 后端
- API设计
【免费下载链接】SpaceX-API
:rocket: Open Source REST API for SpaceX launch, rocket, core, capsule, starlink, launchpad, and landing pad data.
本文以开源仓库 SpaceX-API 的官方文档 docs/launches/v5/next.md 为核心,带你完整掌握GET /v5/launches/next这一便捷端点:它用于查询距离当前时间最近的即将发射任务,无需任何认证即可调用。读完本文,你将理解该端点的请求/响应结构、每个响应字段的业务含义、其背后的 MongoDB 查询与 Redis 缓存实现,并能直接在自己的应用或脚本中安全地消费这一接口。
接口概览
/next是 Launches 路由族中的“便捷端点”(Convenience Endpoints)之一,与/latest、/past、/upcoming并列。它的核心价值在于:调用方无需自行排序或过滤,API 直接返回"下一次发射"的单条完整记录。
| 项目 | 值 |
|---|---|
| Method | GET |
| URL | https://api.spacexdata.com/v5/launches/next |
| Auth required | False |
| 成功响应 | 200 OK |
| 数据源 | MongoDB 中upcoming: true且flight_number最小的发射记录 |
在文档 docs/README.md 中定义了全局基础地址https://api.spacexdata.com,因此该端点实际请求路径为/v5/launches/next。此外 API 支持将版本固定为latest(即/latest/launches/next),但官方文档提示该别名可能引入破坏性变更,生产环境建议显式锁定v5版本。
端点背后的源码实现
路由定义位于 routes/launches/v5/index.js:
// Get next launch router.get('/next', cache(20), async (ctx) => { try { const result = await Launch.findOne({ upcoming: true, }, null, { sort: { flight_number: 'asc', }, }); ctx.status = 200; ctx.body = result; } catch (error) { ctx.throw(400, error.message); } });从源码结构看,该端点的查询逻辑可以拆解为三步:
- 筛选:
Launch.findOne({ upcoming: true })只查询upcoming字段为true的记录,即尚未发射的任务; - 排序:
sort: { flight_number: 'asc' }按飞行编号升序排列,取升序后的第一条,即编号最小的那次未发射任务——也就是时间上最近的下一次发射; - 缓存:路由通过
cache(20)中间件启用 20 秒的响应缓存。
值得注意的是,/next使用的是findOne而非find,返回的是单个对象而非数组;同时与/one端点不同,它不需要:id路径参数,也无需显式处理 404——从代码结构可以推断,若数据库中不存在upcoming: true的记录,响应体将可能为null(状态码仍为 200),消费方代码应做好空值容错。
与兄弟端点的差异
在同文件 routes/launches/v5/index.js 中,另外几个便捷端点的查询条件形成对照:
| 端点 | 查询条件 | 排序 |
|---|---|---|
/next | upcoming: true | flight_number: 'asc',取第一条 |
/latest | upcoming: false | flight_number: 'desc',取第一条 |
/past | upcoming: false | flight_number: 'asc',返回全部 |
/upcoming | upcoming: true | flight_number: 'asc',返回全部 |
其中/latest取已发射记录中flight_number最大的一条,与/next正好形成"已完成的最后一次"与"待执行的第一次"的对偶关系。若需要更灵活的筛选、分页或字段投影,则应改用POST /v5/launches/query端点,参考 docs/queries.md。
成功响应与完整示例
文档 docs/launches/v5/next.md 给出了200 OK的完整响应示例。该示例对应 SpaceX 的 CRS-20 任务(Flight Number 91),是 NASA 原始 CRS 合同下的第 20 次也是最后一次货运补给任务。完整响应如下:
{ "fairings": null, "links": { "patch": { "small": "https://images2.imgbox.com/53/22/dh0XSLXO_o.png", "large": "https://images2.imgbox.com/15/2b/NAcsTEB6_o.png" }, "reddit": { "campaign": "https://www.reddit.com/r/spacex/comments/ezn6n0/crs20_launch_campaign_thread", "launch": "https://www.reddit.com/r/spacex/comments/fe8pcj/rspacex_crs20_official_launch_discussion_updates/", "media": "https://www.reddit.com/r/spacex/comments/fes64p/rspacex_crs20_media_thread_videos_images_gifs/", "recovery": null }, "flickr": { "small": [], "original": [ "https://live.staticflickr.com/65535/49635401403_96f9c322dc_o.jpg", "https://live.staticflickr.com/65535/49636202657_e81210a3ca_o.jpg", "https://live.staticflickr.com/65535/49636202572_8831c5a917_o.jpg", "https://live.staticflickr.com/65535/49635401423_e0bef3e82f_o.jpg", "https://live.staticflickr.com/65535/49635985086_660be7062f_o.jpg" ] }, "presskit": "https://www.spacex.com/sites/spacex/files/crs-20_mission_press_kit.pdf", "webcast": "https://youtu.be/1MkcWK2PnsU", "youtube_id": "1MkcWK2PnsU", "article": "https://spaceflightnow.com/2020/03/07/late-night-launch-of-spacex-cargo-ship-marks-end-of-an-era/", "wikipedia": "https://en.wikipedia.org/wiki/SpaceX_CRS-20" }, "static_fire_date_utc": "2020-03-01T10:20:00.000Z", "static_fire_date_unix": 1583058000, "tdb": false, "net": false, "window": 0, "rocket": "5e9d0d95eda69973a809d1ec", "success": true, "failures": [], "details": "SpaceX's 20th and final Crew Resupply Mission under the original NASA CRS contract, this mission brings essential supplies to the International Space Station using SpaceX's reusable Dragon spacecraft. It is the last scheduled flight of a Dragon 1 capsule. (CRS-21 and up under the new Commercial Resupply Services 2 contract will use Dragon 2.) The external payload for this mission is the Bartolomeo ISS external payload hosting platform. Falcon 9 and Dragon will launch from SLC-40, Cape Canaveral Air Force Station and the booster will land at LZ-1. The mission will be complete with return and recovery of the Dragon capsule and down cargo.", "crew": [], "ships": [], "capsules": [ "5e9e2c5cf359185d753b266f" ], "payloads": [ "5eb0e4d0b6c3bb0006eeb253" ], "launchpad": "5e9e4501f509094ba4566f84", "auto_update": true, "flight_number": 91, "name": "CRS-20", "date_utc": "2020-03-07T04:50:31.000Z", "date_unix": 1583556631, "date_local": "2020-03-06T23:50:31-05:00", "date_precision": "hour", "upcoming": false, "cores": [ { "core": "5e9e28a7f359187afd3b2662", "flight": 2, "gridfins": true, "legs": true, "reused": true, "landing_attempt": true, "landing_success": true, "landing_type": "RTLS", "landpad": "5e9e3032383ecb267a34e7c7" } ], "id": "5eb87d42ffd86e000604b384" }提示:示例中的
upcoming: false是因为该文档基于当时的历史数据编写(CRS-20 任务在文档编写时恰好是"下一次",现已执行完毕)。实际调用/next时,返回的将始终是数据库当前状态下upcoming: true的记录。示例中的对象 ID(如5eb87d42ffd86e000604b384)为真实数据的 MongoDB 文档 ID。
响应字段逐一解读
/next返回的对象与 v5 发射记录 Schema 完全一致,定义于 models/launches.js 与 docs/launches/v5/schema.md。以下按功能分组说明:
任务标识与时间字段
| 字段 | 类型 | 说明 |
|---|---|---|
id | String | MongoDB 文档 ID |
flight_number | Number | 任务飞行编号(必填) |
name | String | 任务名称,Schema 中标记为unique(唯一索引) |
date_utc | String | UTC 发射时间,ISO 8601 格式(必填) |
date_unix | Number | UTC 发射时间的 UNIX 时间戳(秒,必填) |
date_local | String | 带时区偏移的本地发射时间,ISO 8601 格式(必填) |
date_precision | String | 日期精度枚举:half、quarter、year、month、day、hour |
static_fire_date_utc | String/null | 静态点火时间(UTC),默认null |
static_fire_date_unix | Number/null | 静态点火时间 UNIX 时间戳,默认null |
tbd | Boolean | 为true表示日期"待定"(To Be Determined),默认false |
net | Boolean | 为true表示日期为"不早于"(No Earlier Than),默认false |
window | Number/null | 发射窗口时长,默认null |
关于日期字段,官方文档 docs/README.md 特别提醒:部分发射只有不完整的日期(例如2020 July会表示为2020-07-01T00:00:00.000Z,同时date_precision为month),此时日期仅精确到月份级别,消费方不应按完整时间解读。
火箭与载荷关联字段
这些字段在 Schema 中均为 MongoDB ObjectId 引用(外键式关联),指向对应资源文档:
| 字段 | 类型 | 引用资源 |
|---|---|---|
rocket | ObjectId/null | Rockets |
launchpad | ObjectId/null | Launchpads |
payloads | ObjectId[] | Payloads |
capsules | ObjectId[] | Capsules |
ships | ObjectId[] | Ships |
crew | Array | Crew 引用数组,v5 中为对象数组(详见下文 v5 变更) |
一子级核芯数据(cores)
cores是核心级联对象的数组,记录每个一子级(Booster)的飞行履历与回收情况:
| 字段 | 类型 | 说明 |
|---|---|---|
core | ObjectId/null | 关联的 Core 文档 ID |
flight | Number/null | 该 Core 的第几次飞行 |
gridfins | Boolean/null | 是否搭载栅格舵 |
legs | Boolean/null | 是否搭载着陆腿 |
reused | Boolean/null | 是否为复用芯级 |
landing_attempt | Boolean/null | 是否尝试回收 |
landing_success | Boolean/null | 回收是否成功 |
landing_type | String/null | 回收方式,如RTLS(返回发射场)、ASDS(海上驳船)等 |
landpad | ObjectId/null | 关联的着陆场/回收船 ID |
在示例响应中,CRS-20 使用的 Core 是第 2 次飞行(flight: 2)、复用芯级(reused: true),并成功完成RTLS陆地回收(landing_type: "RTLS")。
媒体与任务链接(links)
links聚合了任务相关的全部外部资源,覆盖补丁图、社区讨论、照片、直播与报道:
| 字段 | 类型 | 说明 |
|---|---|---|
patch.small/patch.large | String/null | 任务补丁图(小/大尺寸) |
reddit.campaign/reddit.launch/reddit.media/reddit.recovery | String/null | Reddit 上的战役讨论、发射直播、媒体、回收线程 |
flickr.small/flickr.original | String[] | Flickr 照片(缩略图/原图) |
presskit | String/null | 官方新闻资料包(PDF)链接 |
webcast | String/null | 发射直播视频链接 |
youtube_id | String/null | 直播视频的 YouTube ID |
article | String/null | 第三方任务报道链接 |
wikipedia | String/null | 任务的维基百科词条 |
其他状态字段
| 字段 | 类型 | 说明 |
|---|---|---|
success | Boolean/null | 发射是否成功;未发射前为null |
failures | Array | 失败事件数组,每项含time(失败时刻)、altitude(失败高度)、reason(失败原因) |
fairings | Object/null | 整流罩信息(reused、recovery_attempt、recovered、ships) |
details | String/null | 任务详情描述 |
auto_update | Boolean | 是否由数据抓取任务自动更新,默认true,见 jobs/launches.js |
v5 与 v4 的差异说明
文档 docs/launches/v5/README.md 记录了 v4 到 v5 的关键变化:crew字段从字符串数组变更为对象数组,以便为单个任务的每位乘员提供更多结构化信息(如角色role)。从 Schema(models/launches.js)可以看到 v5 中每个crew元素包含crew(引用 Crew 文档的 ObjectId)与role(乘员角色)两个字段。调用方若从 v4 迁移到 v5,需要对crew的解析逻辑做相应调整。
缓存与性能特征
根据 docs/README.md 与 middleware/cache.js,所有 Launches 相关端点(包括/next)的响应缓存 TTL 为20 秒。其实现要点如下:
- 缓存中间件仅在
NODE_ENV=production且 Redis 可用时生效;非生产环境下直接放行到业务逻辑; - 缓存键由
METHOD + URL + 请求体拼接后经BLAKE3哈希生成,键前缀为spacex-cache:; - 命中缓存时响应头会携带
spacex-api-cache: HIT,未命中则为MISS,便于调试观测; - Redis 不可用时请求会绕过缓存直连数据库,并通过
spacex-api-cache-online响应头标明状态; - 成功响应会设置
Cache-Control: max-age=20,客户端与 CDN 也可据此做本地缓存。
这意味着/next的数据最多有 20 秒的延迟窗口,频繁轮询时无需担心对上游数据库造成压力。对实时性要求较高的场景(如发射倒计时展示),建议以 20 秒为最小轮询间隔。
调用示例
使用curl一行即可获取下一次发射:
curl -s https://api.spacexdata.com/v5/launches/next配合jq提取关键字段,例如任务名、发射时间与火箭 ID:
curl -s https://api.spacexdata.com/v5/launches/next | jq '{name, flight_number, date_utc, rocket, launchpad}'前端或服务端代码中,可将其封装为如下结构(以 JavaScript 为例):
const res = await fetch('https://api.spacexdata.com/v5/launches/next'); const nextLaunch = await res.json(); console.log(nextLaunch.name, nextLaunch.date_utc); // 注意:nextLaunch 可能为 null,需做空值容错使用注意事项
- 空结果容错:当数据库中不存在
upcoming: true的发射记录时,从源码结构推断/next可能返回null响应体,调用方务必处理该情况; - 固定版本号:生产环境使用
v5而非latest别名,避免破坏性变更影响线上服务; - 日期精度:
date_precision不是hour时,date_utc仅表示近似时间,不要用于精确倒计时; - 关联 ID 需要二次请求:
rocket、launchpad、payloads等字段返回的是对象 ID,如需完整信息应分别调用对应的 One 端点 或各资源文档查询接口; - 缓存延迟:数据最多滞后 20 秒,超高频实时场景需结合
auto_update数据抓取周期综合评估。
延伸阅读
- Launches v5 全部端点文档 与 单次发射查询
- launches 查询与分页指南
- Launch Schema 完整定义 与 模型源码
- v5 路由实现 与 Redis 缓存中间件
- r/SpaceX API 总文档
- 后端
- API设计
【免费下载链接】SpaceX-API
:rocket: Open Source REST API for SpaceX launch, rocket, core, capsule, starlink, launchpad, and landing pad data.
相关推荐
SpaceX-API v5 单次发射查询指南:深入解析 GET /v5/launches/:id 端点
SpaceX API v5 单次发射查询指南:深入解析 GET /v5/launches/:id 端点 本文以 SpaceX API 开源仓库中的 docs/l
后端API设计SpaceX-API v5 即将发射查询指南:GET /v5/launches/upcoming 端点全解析
SpaceX API v5 即将发射查询指南:GET /v5/launches/upcoming 端点全解析 本篇技术指南以开源仓库 gh_mirrors/sp
后端API设计SpaceX-API 实战指南:使用 v5 Launches 接口获取全部发射记录(GET /v5/launches)
SpaceX API 实战指南:使用 v5 Launches 接口获取全部发射记录(GET /v5/launches) 导读:本文围绕 SpaceX API 开
后端API设计
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考