(三) Input 和 Output 理论 - Build API For Your Company 系列

介绍

这一节主要是简单梳理一下在 HTTP 的世界中 Input、Output理论,特别是为了新手朋友(像我一样)。这些知识非常简单,简而言之,就是 HTTP RequestResponse 这两个概念。

Request

一个简单的 HTTP 请求大家应该不会陌生吧:

GET /places?lat=40.7592&lon=-73.9846 HTTP/1.1
Host: api.example.com

客服端发送一个 GET 请求并且使用 HTTP 1.1 的协议,携带着需要的查询参数,指向 /places 这个URI(Uniform Resource Identifier), 服务器的主机名也被定义好了。这也是我们在上网中,浏览器(客户端)所处理的最基本的事务。

下面是一个稍微复杂的请求:

POST /places/1 HTTP/1.1
Host: api.example.com
Authorization: Basic Y2VpY2htYW5uQHNpbW9uaXMuY29tOnBhc3N3b3Jk
Content-Type: application/json

{ "user_id": 2 }

这里面并没有什么新鲜的东西,并且这些头信息在我们日常使用Web时已经司空见惯,不过我还是稍微解释一下:

Header Information 说明
POST /places/1 HTTP/1.1 发起一个POST请求,并指向 /places/1
Host: api.example.com 表示提供服务的主机名
Content-Type: application/json 希望被服务器当作JSON格式的信息使用
Authorization: Basic ... 基本的认证Token

HTTP 其实非常简单(但是很强大),你可以用你任何熟知的编程语言或者框架来快速实现一个 HTTP 客服端。

作为 PHP 程序员, 你或许听过或者使用过 Guzzle:

Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and trivial to integrate with web services.

--- guzzlephp.org

使用 Guzzle 来快速实现一下上面的 POST 请求:


use Guzzle\Http\Client;

$headers = [
    'Authorization' => 'Basic Y2VpY2htYW5uQHNpbW9uaXMuY29tOnBhc3N3b3Jk',
    'Content-Type' => 'application/json',
];

$payload = [
    'user_id' => 2
];

// 创建一个客户端请求
$client = new Client('http://api.example.com');

$req = $client->post('/places/1', $headers, json_encode($payload));

当然你可以用 Python 或者 Ruby 来快速制作一个 HTTP 请求,curl 也是一个不错的工具。

Response

和 HTTP Request 一样,HTTP Responses 也有着相似的格式:

HTTP/1.1 200 OK
Server: nginx
Host: api.example.com
Connection: close
X-Powered-By: PHP/5.5.15
Cache-Control: no-cache
Date: Sun, 26 Oct 2014 04:27:46 GMT
Content-Type: application/json; charset=UTF-8

[{"id":"e7bd6160-4cf2-11e4-b398-9380ce905f1c","userId":"e43f48e0-4cf2-11e4-9a09-75c59b58eb6d","content":"Id consequatur animi rerum sunt vero vel soluta accusantium minima sit molestiae nihil consequatur in nisi omnis labore.","imageList":null,"mainImage":null,"sourceBlogId":null,"bookId":"e7744bf0-4cf2-11e4-b425-797896315f23","createTime":"2014-10-06 00:52:32","repostsCount":0,"commentsCount":0,"favorCount":0}],"userList":[{"id":"e43f48e0-4cf2-11e4-9a09-75c59b58eb6d","nickname":"Ebba Wyman II","avatar":"IMG_Test.png"}],"sourceBlogList":[],"bookList":[{"id":"e7744bf0-4cf2-11e4-b425-797896315f23","volumNum":"2","userId":"e6f730e0-4cf2-11e4-9fd2-c545ee9bbdee","coverPortrait":"IMG_Test.png","updatedTime":"2014-10-06 08:51:27"}]

这是一个包含JSON数据的一个Response示例,简单的分析一下:

Header Information 说明
HTTP/1.1 200 OK 目前而言,我们的请求很快乐的被服务器接受了,没有出现网络协议失败的问题,或者抛出异常
Server: nginx 处理该请求的Web服务器的类型
X-Powered-By 这里会显示你服务器的使用的 PHP 的版本号,但这是不安全的操作,你应该修改 php.ini 配置文件: expose_php = off
Content-Type: application/json 说明返回的数据类型
Cache-Control: no-cache 缓存控制
Date: Sun, 26 Oct 2014 04:27:46 GMT 生成响应时的时间戳

这些,就是API如何工作的一些主要的基础知识。

JSON And XML

现在应该所有的 API 都会支持 JSON 格式的数据输出, 除非这是一个金融服务的API或者开发者是一个 moron 才会继续输出 XML 格式的数据。XML 曾经辉煌过一段时间,为不同平台之间的集成提供了一个非常好的基础,但是他的很多弊端也导致了它注定要走向历史。对于大多数开发工作来说,JSON IS FINE,或者如果你是一个Ruby开发者,你可能想输出 YAML 格式。

Response 的数据结构(数据格式)

怎么说呢,Response 的数据结构其实没有必须要遵循的一个标准,很难去评价这种格式的对与错,如果你使用过的框架或者语言比较多,你会发现很多机构和公司的API接口,并没有一致的数据结构。但是看看这些人是如何格式化输出的,你会对自己的API设计有一个更好的想法:

JSON API

A standard for building APIs in JSON. 是JSON API的目标,或许你可以使用这套标准来构建你的API响应的数据结构。

JSON API 文档: http://jsonapi.org/format/

论坛里面有人翻译了中文版:http://phphub.org/topics/179

不过有点不理解的是,这套标准为什么要用 posts 来表示单个资源,以及一个资源集合,这个有时候让人很费解?

Twitter-style

个人挺喜欢 Twitter 的数据返回格式,Ask for one user get one user :

{
    "name": "Jobs Long",
    "id": "12332874234"
}

Ask for a collection of things and get a collection of things :

[
    {
        "name": "Jobs Long",
        "id": "12332874234"
    },
    {
        "name": "Steven Jobs",
        "id": "10002334"
    },
]

优势:

  • 最简化的信息输出
  • 几乎可以被任何框架/工具理解

劣势:

  • 没有命名空间来处理分页以及其他的meta数据信息;

    很好奇Twitter是如何实现分页这些信息的返回的(暂时没时间看。。。)

Facebook-style

Facebook 的数据样式和 twitter有类似的地方,但是当请求一个数据集合的时候:

{
    "data": [
        {
            "name": "Jobs Long",
            "id": "12332874234"
        },
        {
            "name": "Steven Jobs",
            "id": "10002334"
        },
    ]
}

优势:

  • 在数据集合的返回中可以放置更多的分页信息和其他元数据;
  • 拥有额外的命名空间的简洁响应格式

Github-style

看看Github 的数据响应格式:

$ curl -i https://api.github.com/users/octocat/orgs

响应结果:

HTTP/1.1 200 OK
Server: GitHub.com
Date: Sun, 26 Oct 2014 14:39:36 GMT
Content-Type: application/json; charset=utf-8

// omitted for brevity ...

{
  "login": "JobsLong",
  "id": 4585899,
  "gravatar_id": "",
  "url": "https://api.github.com/users/JobsLong",

  // omitted for brevity ...
}

可以把 Github 的API技术文档当作一个参考,详细阅读一下文档是一个不错的选择。在这块内容并没有太多的个人看法,只是把一些大家熟知的公司的API技术文档的链接给摆在这里,大家如果有兴趣可以自己去多看看,个人经历尚浅,没办法对这块内容做一个比较详细的分析,可以留着以后更新。

NExT Articles

下一章的内容包括 Status Code, 错误信息的返回,以及 POST MAN 的使用;

Remote. Open. Engineer.
本帖已被设为精华帖!
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 7
Summer

文章不错. :+1:

我小小修改了 header 和加了代码高亮.

9年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!