API(接口)是什么?
API(Application Programming Interface,应用程序接口)是一些预先定义的接口(如函数、HTTP接口),或指软件系统不同组成部分衔接的约定。 用来提供应用程序与开发人员基于某软件或硬件得以访问的一组例程,而又无需访问源码,或理解内部工作机制的细节。
http接口
HTTP简介:
HTTP协议(HyperText Transfer Protocol,超文本传输协议),是用于从万维网(WWW:World Wide Web)服务器传输超文本到本地浏览器的传送协议。
HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。
HTTP工作原理:
HTTP协议工作于客户端-服务器(C/S)架构上。浏览器作为HTTP客户端通过URL向HTTP服务端即web服务器发送所有请求。
一个HTTP"客户端"是一个应用程序(Web浏览器或其他任何客户端),通过连接到服务器达到向服务器发送一个或多个HTTP的请求的目的。
web服务器有:Apache服务器,IIS服务器(Internet Information Service)等。
web服务器根据接收到的请求,向客户端发送响应信息。
HTTP默认端口为80,也可以改为其它端口。
简单的http实现:
'''
http server
1.多线程并发
2.可以请求简单数据
3.能进行简单请求解析
'''
from socket import *
from threading import Thread
import sys
import traceback
class HTTPServer(object):
def __init__(self,server_addr,static_dir):
self.server_address = server_addr
self.static_dir = static_dir
self.ip = server_addr[0]
self.port = server_addr[1]
self.create_socket()
def create_socket(self):
self.sockfd = socket()
self.sockfd.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
self.sockfd.bind(self.server_address)
def serve_forever(self):
self.sockfd.listen(5)
print("Listen the port %d"%self.port)
while True:
try:
connfd,addr = self.sockfd.accept()
except KeyboardInterrupt:
self.sockfd.close()
sys.exit("服务器退出")
except Exception:
traceback.print_exc()
continue
clientThread = Thread(target = self.handleRequest,args=(connfd,))
clientThread.setDaemon(True)
clientThread.start()
def handleRequest(self,connfd):
request = connfd.recv(4096)
requestHeaders = request.splitlines()
print(connfd.getpeername(),":",requestHeaders[0])
getRequest = str(requestHeaders[0]).split(' ')[1]
if getRequest == '/' or getRequest[-5:] == '.html':
self.get_html(connfd,getRequest)
else:
self.get_data(connfd,getRequest)
connfd.close()
def get_html(self,connfd,getRequest):
if getRequest == '/':
filename = self.static_dir + "/index.html"
else:
filename = self.static_dir + getRequest
try:
f = open(filename, encoding='utf-8')
except Exception:
responseHeaders = "HTTP/1.1 404 NOT FOUND\r\n"
responseHeaders += '\r\n'
responseBody = "Sorry,not found the page"
else:
responseHeaders = "HTTP/1.1 200 OK\r\n"
responseHeaders += '\r\n'
responseBody = f.read()
finally:
response = responseHeaders + responseBody
connfd.send(response.encode())
def get_data(self,connfd,getRequest):
urls = ['/time','/jj_world','/python']
if getRequest in urls:
responseHeaders = "HTTP/1.1 200 OK\r\n"
responseHeaders += '\r\n'
if getRequest == "/time":
import time
responseBody = time.ctime()
elif getRequest == '/jj_world':
responseBody = "Welcome to jj_world"
elif getRequest == '/python':
responseBody = "人生苦短我用Python"
else:
responseHeaders = "HTTP/1.1 404 NOT FOUND\r\n"
responseHeaders += '\r\n'
responseBody = "Sorry,not found the data"
response = responseHeaders + responseBody
connfd.send(response.encode())
if __name__ == "__main__":
server_addr = ('0.0.0.0',8000)
static_dir = './static'
httpd = HTTPServer(server_addr,static_dir)
httpd.serve_forever()
HTTP三点注意事项:
1、HTTP是无连接:现在每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
2、HTTP是媒体独立的:只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。
3、HTTP是无状态协议,指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
浏览器输入一个url中间经历的过程
- 中间涉及到那些过程
dns查询/host文件–>tcp握手–>http请求–>反向代理nginx–>uwsgi/gunicorn–>web app响应–>tcp挥手 获取到ip 应用 WSGI web应用
HTTP消息结构
实际查看可以在fiddle中进行查看数据格式
HTTP请求报文头属性
Accept
请求报文可通过一个“Accept”报文头属性告诉服务端 客户端接受什么类型的响应。 如下报文头相当于告诉服务端,俺客户端能够接受的响应类型仅为纯文本数据啊,你丫别发其它什么图片啊,视频啊过来,那样我会歇菜的~~~
Accept:text/plain
Accept属性的值可以为一个或多个MIME类型的值(描述消息内容类型的因特网标准, 消息能包含文本、图像、音频、视频以及其他应用程序专用的数据)
cookie
客户端的Cookie就是通过这个报文头属性传给服务端的哦!如下所示:
Cookie: $Version=1; Skin=new;jsessionid=5F4771183629C9834F8382E23
服务端是怎么知道客户端的多个请求是隶属于一个Session呢?注意到后台的那个jsessionid = 5F4771183629C9834F8382E23木有?原来就是通过HTTP请求报文头的Cookie属性的jsessionid的值关联起来的!(当然也可以通过重写URL的方式将会话ID附带在每个URL的后面哦)。
Referer
表示这个请求是从哪个URL过来的,假如你通过google搜索出一个商家的广告页面,你对这个广告页面感兴趣,鼠标一点发送一个请求报文到商家的网站,这个请求报文的Referer报文头属性值就是http://www.google.com。
Cache-Control
对缓存进行控制,如一个请求希望响应返回的内容在客户端要被缓存一年,或不希望被缓存就可以通过这个报文头达到目的。
实现一个简单的http接口
FBV
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/', methods=['GET'])
def index():
data = request.get_json()
return jsonify(data)
if __name__ == '__main__':
app.run(host="0.0.0.0", debug=True, threaded=True)
有道翻译接口使用示例
import json
import sys
import uuid
import random
import requests
import hashlib
import time
YOUDAO_URL = 'https://openapi.youdao.com/api'
APP_KEY = '15c5a0d'
APP_SECRET = 'jmG1acQ9PF3WVSGFGVTCFI'
def encrypt(signStr):
hash_algorithm = hashlib.sha256()
hash_algorithm.update(signStr.encode('utf-8'))
return hash_algorithm.hexdigest()
def truncate(q):
if q is None:
return None
size = len(q)
return q if size <= 20 else q[0:10] + str(size) + q[size - 10:size]
def do_request(data):
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
return requests.post(YOUDAO_URL, data=data, headers=headers)
def connect(text):
q = text
data = {}
data['from'] = 'zh-CHS'
data['to'] = 'en'
data['signType'] = 'v3'
curtime = str(int(time.time()))
data['curtime'] = curtime
salt = str(uuid.uuid1())
signStr = APP_KEY + truncate(q) + salt + curtime + APP_SECRET
sign = encrypt(signStr)
data['appKey'] = APP_KEY
data['q'] = q
data['salt'] = salt
data['sign'] = sign
response = do_request(data)
contentType = response.headers['Content-Type']
if contentType == "audio/mp3":
millis = int(round(time.time() * 1000))
filePath = "合成的音频存储路径" + str(millis) + ".mp3"
fo = open(filePath, 'wb')
fo.write(response.content)
fo.close()
else:
print(response.content)
class youdao:
def __init__(self):
self.params = {
'from':'AUTO',
'to':'AUTO',
'smartresult':'dict',
'client':'fanyideskweb',
'salt':'1543198914021',
'sign':'1eb94666d05e93f3221178d89ee7a583',
'doctype':'json',
'version':'2.1',
'keyfrom':'fanyi.web',
'action':'FY_BY_REALTIME',
'typoResult':'false'
}
self.url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule"
self.h_list = [
{"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11"},
{"User-Agent": "Mozilla/4.0"},
{"User-Agent": "Mozilla/3.0"},
{"User-Agent": "Mozilla/2.0"},
{"User-Agent": "Mozilla/1.0"},
]
def reqAip(self,text):
self.params["i"] = text
res = requests.post(self.url, data=self.params, headers=random.choice(self.h_list))
res.encoding = "utf-8"
html = res.text
print(html.strip())
r_dict = json.loads(html)
print(r_dict['translateResult'][0][0]['tgt'])
if __name__ == '__main__':
connect("我要测试")
yd = youdao()
yd.reqAip("我要测试")
restful 接口
什么是Restful:
对应的中文是rest式的;Restful web service是一种常见的rest的应用,是遵守了rest风格的web服务;rest式的web服务是一种ROA(The Resource-Oriented Architecture)(面向资源的架构).
为什么会出现Restful
在Restful之前的操作: http://127.0.0.1/user/query/1 GET 根据用户id查询用户数据 http://127.0.0.1/user/save POST 新增用户 http://127.0.0.1/user/update/1 POST 修改用户信息 http://127.0.0.1/user/delete/1 GET/POST 删除用户信息
RESTful用法: http://127.0.0.1/user/1 GET 根据用户id查询用户数据 http://127.0.0.1/user POST 新增用户 http://127.0.0.1/user/1 PUT 修改用户信息 http://127.0.0.1/user/1 DELETE 删除用户信息
如何使用:
状态码返回
接口示例见myweb
什么是接口测试
接口测试分两种:
- 测试外部接口:系统和外部系统之间的接口。如:电商网站:支付宝支付。
- 测试内部接口:系统内部的模块之间的联调,或者子系统之间的数据交互。
- 测试重点:测试接口参数传递的正确性,接口功能的正确性,输出结果的正确性,以及对各种异常情况的容错性和权限控制。
- 接口测试内容?例如:
XX老师:理发服务。
接口请求内容:
接口地址:门店地址
接口请求方式:理发方式:剪发,烫发
指定请求头:指定:1号技师
请求参数:None
接口响应内容:
响应状态码:1、非常好,2.一般,3.极差。
响应信息:非常好,一般,极差
响应头:单号,顾客编号
响应主体:具体感受的文字描述。
接口测试工具
postman简介: postman一个款功能强大的接口测试工具。专为接口而生。 安装: 两个版本: Postman Chome app(chorme浏览器,翻墙) 不推荐 Postman native app 客户端的安装方式: 下载地址: https://www.getpostman.com/apps 注册,登录。只有登录后才可以使用Postman的云服务的功能。
接口测试流程
1.拿到接口文档。(抓包:F12,fiddler,charles),熟悉接口业务,接口地址,请求参数,请求头信息,请求方式,鉴权方式。 2.编写接口用例编写以及评审。 3.使用接口测试工具执行接口测试。 4.输出接口测试报告。
|