# DNS

通过 HTTP Basic Authentication 进行权限鉴定，每个业务方需要预先申请用户名、密码才能使用如下 API。默认每个用户对 DNS 的操作 QPS 被限制在 100 以内，如有特殊需要可以申请提高限制上限，当请求超过 QPS 限制后会被阻塞住。

大部分对 DNS 的操作 API 同时提供同步和异步的操作方式，我们推荐大部分的业务使用异步 API 来更新 DNS 记录。
1. 异步 API 的 DNS 记录存储到数据库后 API 直接返回，后续再异步更新记录到所有的 DNS 权威服务器。大部分情况下异步更新的延迟在 50ms 以下，我们也设置了在 DNS 权威服务器的间隔 5s 的定时任务跟数据库记录进行同步，我们保证异步更新成功的记录能达到最终一致。
2. 我们对同步操作提供强一致性保证，当 API 返回时保证记录已成功更新到所有的 DNS 权威服务器。但会损失一些可靠性，目前如果有权威 DNS 宕机可能存在使用同步 API 一直无法成功添加记录的风险。

## [DNS Zone 使用约定](http://wiki.in.zhihu.com/pages/viewpage.action?pageId=58590859)


### 获取域

* 请求地址: /api/v1/zones
* 请求方法: GET
* 响应状态码:
    * 200 OK
* 响应 JSON 结构:
  [{
  "id": 1,
  "name":"bj01.rack.zhihu.com",
  "description": "北京 1 区"
  }]

### 获取记录列表
* 请求地址: /api/v3/zones/{zone_name}/records
* 请求方法: GET
* Query 参数:
    * id 可选，记录唯一 ID
    * keyword 可选，在记录名称和结果中检索关键词
    * exact 可选，是否模糊匹配，当 exact 存在时 keyword 必选，当 exact 为 true 时 keyword 精确匹配记录名称
    * type 可选，指定类型，须为 host/a/cname 之一，比如 host
    * format 可选，输出格式，须为 json/zonefile 之一，默认 json。当 type 为 host，format 为 zonefile 时输出反解记录。
    * limit 可选，输出固定个数数据
    * offset 可选，输出时使用的偏移量，从 offset 个之后开始输出
* 响应 JSON 结构:
  [
  {
  "id": 1,
  "name": "faceair",
  "target": "10.3.2.1",
  "ttl": 300,
  "type": "host",
  "owner": "faceair",
  "comment": "just for test",
  }
  ]
* 响应 zonefile

### 添加指定域的记录

* 请求地址: /api/v3/zones/{zone_name}/records
* 请求方法: POST
* Query 参数:
    * mode 可选，同步还是异步操作，须为 async/sync 之一，默认 async
* 请求体 JSON 字段:
    * name 必填，记录的名称，比如 www
    * type 必填，记录类型, 须为 host/a/cname 之一 (其中host是a记录和ptr记录综合)
    * target 必填，解析地址，比如 10.0.0.1 (**对于cname记录，必须以 . 结尾**)
    * ttl 必填，整数类型，记录刷新时间
    * comment 必填，注释信息
    * owner 必填，该记录所属的用户，大部分情况下 owner 只能填自己，高级管理员能创建属于别人的记录
* 响应状态码:
    * 201 添加成功

### 修改单条记录

注意现在单条记录的修改必须要已知之前的记录内容，否则无法更改。之前的 dnspod API 设计有歧义，只有 name 和 type 无法定位到单个记录，比如当一个 name 下有多个 a 记录时修改可能会把多个 a 记录全修改成一个地址，不符合业务场景。

这种修改场景可以有三种操作方式：
1. 指定 target 和 type 定位到单条记录修改
2. 先删掉现有 name 的所有记录再添加一条新纪录
3. 直接尝试修改，当 API 返回 400 时再使用 1 或 2 方式修改

我们推荐使用指定 target 和 type 的方式修改。

* 请求地址: /api/v3/zones/{zone_name}/records/{record_name}
* 请求方法: PATCH
* Query 参数:
    * mode 可选，同步还是异步操作，须为 async/sync 之一，默认 async
    * type 可选，指定类型，须为 host/a/cname 之一，比如 a
    * target 可选，解析地址，比如 10.0.0.1
* 请求体 JSON 字段:
    * target 可选，解析地址，比如 10.0.0.1 (**对于cname记录，必须以“.”结尾**)
    * ttl 可选，生存时间，比如 60
    * comment 可选，注释信息
    * owner 可选，该记录所属的用户
* 响应状态码:
    * 200 OK
    * 400 Bad Request 无法修改少于或超过一条记录

### 删除记录

* 请求地址: /api/v3/zones/{zone_name}/records/{record_name}
* 请求方法: DELETE
* Query 参数:
    * mode 可选，同步还是异步操作，须为 async/sync 之一，默认 async
    * type 可选，指定类型，须为 host/a/cname 之一，比如 a
    * target 可选，解析地址，比如 10.0.0.1
* 响应状态码:
    * 200 OK
    * 404 Not Found 记录不存在

## 迁移指南

1. 新增 DNS 记录。修改原有 URL 路径，由 /api/v2/record/add/ 改为 /api/v3/zones/{zone_name}/records，还是 POST 方法。
   comment 和 owner 改为必选参数，移除 zone，app_url 参数。
2. 删除 DNS 记录。修改原有 URL 路径，由 /api/v2/record/delete/ 改为 /api/v3/zones/{zone_name}/records/{record_name}，由 POST 方法改为 DELETE 方法。
   移除 zone 参数。
3. 修改单条 DNS 记录。注意事项上述 README 已写清楚，不再赘述。
