Al03's blog

API对接调试

在使用网络API时,总会遇到不少问题,觉得自己的参数没有传错,可就是得不到正确的响应。问题可能出现在自己,也有可能出现在API。花费很多精力找出问题后,是自己的问题,自己fix掉,是API的问题,还被API设计者要求提供请求参数等,配合重现问题。

这里总结下我在使用网络API对接时的一些思想和工具。

利用好Unit Test

使用好单元测试,在定义好一个网络请求接口后,我会先使用Unit Test单独测试一下,这样就无需让app跳转到具体的页面,点击具体的按钮去触发要调试的网络请求,多次调试就会需要重复的跳转操作。而Unit Test一键解决了这个痛苦。

更好的验证和查找问题

在调试某个API时,如果实在找不出问题所在,觉得请求参数没有出错,那么如何验证我们的请求呢?请API设计者协助?NO!这样又会影响到别人的工作,成本太大。既然只是验证请求,那自己搭个HTTPSever打印下请求不就OK了吗。

reflect.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from optparse import OptionParser

class RequestHandler(BaseHTTPRequestHandler):

def do_GET(self):

request_path = self.path

print("\n----- Request Start ----->\n")
print(request_path)
print(self.headers)
print("<----- Request End -----\n")

self.send_response(200)
self.send_header("Set-Cookie", "foo=bar")

def do_POST(self):

request_path = self.path

print("\n----- Request Start ----->\n")
print(request_path)

request_headers = self.headers
content_length = request_headers.getheaders('content-length')
length = int(content_length[0]) if content_length else 0

print(request_headers)
print(self.rfile.read(length))
print("<----- Request End -----\n")

self.send_response(200)

do_PUT = do_POST
do_DELETE = do_GET

def main():
port = 8080
print('Listening on localhost:%s' % port)
server = HTTPServer(('', port), RequestHandler)
server.serve_forever()


if __name__ == "__main__":
parser = OptionParser()
parser.usage = ("Creates an http-server that will echo out any GET or POST parameters\n"
"Run:\n\n"
" reflect")
(options, args) = parser.parse_args()

main()

启动

1
2
$ python reflect.py
Listening on localhost:8080

请求localhost:8080/user?id=123

打印

1
2
3
4
5
6
7
8
9
10
11
12
----- Request Start ----->

/user?id=123
Host: localhost:8080
User-Agent: HTTPie/0.9.6
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive

<----- Request End -----

127.0.0.1 - - [21/Oct/2016 13:29:52] "GET /user?id=123 HTTP/1.1" 200 -

好,到这一步已经基本确认问题所在了,如果问题是自己的,自己去fix,不是的,向API设计者反馈。

如何将出问题的请求打包给API设计者?

cURL?可是cURL好难用,尤其涉及到HEAD信息时。

推荐工具HTTPie,对比cURLHTTPie使用起来更加方便,响应结果也更加Human readable。

安装

$ brew install httpie

使用

$ http --form POST api.example.org/person/1 name='John Smith' User-Agent:Bacon/1.0

请求方式 :POST

参数: name='John Smith'

HEAD:User-Agent:Bacon/1.0

具体的使用说明去看官方说明

更快的开发效率

API使用者一定要等API设计完成才去对接吗?NO。自己搭建个server吧。

json-server是一个很好的搭建REST API的工具。这是个Node.js包,安装使用npm

$ npm install json-server -g

只需定义好数据模型,数据模型定义为JSON格式。

例子 db.json

1
2
3
4
5
6
{
"posts": [{ "id": 1, "title": "json-server", "author": "typicode" },{ "id": 2, "title": "json-server", "author": "typicode" },{ "id": 4, "title": "json-server", "author": "typicode" }],
"comments": [ { "id": 1, "body": "some comment", "postId": 1 } ],
"profile": { "name": "typicode" },
"user": { "car":{"type":"o"}, "info":{"name":"albert"}, "status":0}
}

启动服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ json-server db.json

\{^_^}/ hi!

Loading db.json
Done

Resources
http://localhost:3000/posts
http://localhost:3000/comments
http://localhost:3000/profile
http://localhost:3000/user

Home
http://localhost:3000

Type s + enter at any time to create a snapshot of the database

产生了4个路径的API

试着访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$http http://localhost:3000/posts
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 77
Content-Type: application/json; charset=utf-8
Date: Fri, 21 Oct 2016 02:37:36 GMT
ETag: W/"4d-UcPUu5h974QTqEeR2UT3BA"
Expires: -1
Pragma: no-cache
Vary: Origin, Accept-Encoding
X-Content-Type-Options: nosniff
X-Powered-By: Express

[
{
"author": "typicode",
"id": 1,
"title": "json-server"
},
{
"author": "typicode",
"id": 2,
"title": "json-server"
},
{
"author": "typicode",
"id": 4,
"title": "json-server"
}
]

既然是REST APIhttp://localhost:3000/posts是请求post列表

获取id为4的post

http://localhost:3000/posts/4

然后API使用者就先可以利用这个API进行自己的开发了。但前提是一定要和API设计者对数据定义达成一致

最后

在日常的开发中还有不少问题需要重复地解决,这时候需要思考,我们遇到的问题并没有特殊性,同样的问题一定会出现在很多人身上,所以不要解决完某个具体问题就结束了,还要去试着找下解决这一类问题的解决方案或工具。而这些方案或工具会在你以后遇到类似的问题时给予很大的帮助。