3.2 Key Points of API Development
Key Points
- Master the key points of API development
- Understand JSONPath
- Understand intranet penetration
Pre-Class Preparation
None
Course Content
Key points of API Development
Preview of push format
Go to Extension > Webhook > Field Comparison Table and JSON Example.
1. Determine the push type*
op: Push events include data_create(data creating), data_update(data updating), data_remove(data deleting), and data_recover(data recovering).
Use op to distinguish specific push events
from flask import Flask, request
import json
app = Flask(__name__)
@app.route('/test/', methods=['POST']) #Only POST requests are received in Jodoo
def hello_world():
print("params: ",request.args)
print("headers: ",request.headers)
print("Encoded data: ",request.data)
print("Unencoded data: ",json.loads(request.data))
return 'success',200
if __name__ == '__main__':
app.run(host='0.0.0.0',port=10000)
url: http://101.132.103.228:10000/test/?nonce=5932d0×tamp=1585724440
params: ImmutableMultiDict([('nonce', '5932d0'), ('timestamp', '1585724440')])
headers: Content-Type: application/json
X-Jdy-Deliverid: 2b85594d-454a-4063-ac1d-91a2b3318b63
Host: 101.132.103.228:10000
Content-Length: 765
Connection: close
Raw data: b'{"data":{"_id":"5dd6740646357c0006e6eb6e","_widget_1574134687834":"\xe6\xb6\xa1\xe8\xbd\xae\xe5\x87\x8f\xe9\x80\x9f\xe6\x9c\xba1","_widget_1574134687849":"DJSM9K2000","_widget_1574134687894":"2019-11-21T11:24:54.000Z","_widget_1574134688078":345999,"_widget_1574134688093":101,"_widget_1574134688108":3459990,"_widget_1574134688185":"\xe5\x8d\x97\xe4\xba\xac\xe6\x82\x9f\xe5\xb8\x86\xe7\xa7\x91\xe6\x8a\x80\xe8\x82\xa1\xe4\xbb\xbd\xe6\x9c\x89\xe9\x99\x90\xe5\x85\xac\xe5\x8f\xb8","_widget_1574142293244":"TSCJ001574335494","appId":"5dce13f43087860006c70e7a","createTime":"2019-11-21T11:24:54.213Z","creator":{"_id":"5cecd40dd23e194ab0867aab","name":"\xe6\x9f\xa5\xe7\x90\x86","username":"cxt7777"},"deleteTime":null,"deleter":null,"entryId":"5dce145c26aecf00062e7db0","formName":"\xe8\xae\xa2\xe5\x8d\x95\xe6\xb1\x87\xe6\x80\xbb","updateTime":"2020-04-01T07:00:40.876Z","updater":{"_id":"5cecd40dd23e194ab0867aab","name":"\xe6\x9f\xa5\xe7\x90\x86","username":"cxt7777"}},"op":"data_update"}'
The data that are converted into a dictionary in Python: {'data': {'_id': '5dd6740646357c0006e6eb6e', '_widget_1574134687834': 'machine 1', '_widget_1574134687849': 'DJSM9K2000', '_widget_1574134687894': '2019-11-21T11:24:54.000Z', '_widget_1574134688078': 345999, '_widget_1574134688093': 101, '_widget_1574134688108': 3459990, '_widget_1574134688185': 'Jodoo Technology Co., Ltd.', '_widget_1574142293244': 'TSCJ001574335494', 'appId': '5dce13f43087860006c70e7a', 'createTime': '2019-11-21T11:24:54.213Z', 'creator': {'_id': '5cecd40dd23e194ab0867aab', 'name': 'Martin', 'username': 'cxt7777'}, 'deleteTime': None, 'deleter': None, 'entryId': '5dce145c26aecf00062e7db0', 'formName': 'Order Summary', 'updateTime': '2020-04-01T07:00:40.876Z', 'updater': {'_id': '5cecd40dd23e194ab0867aab', 'name': 'Martin', 'username': 'cxt7777'}}, 'op': 'data_update'}
2. Multi-threading processing
Threading: In Python, you need to use the threading module to implement multi-threading programming. Multi-threading is often used to prevent response timeout caused by long processing time.
Multi-threading is a programming technique that allows multiple threads to run concurrently within a single process.
- It can be used to execute tasks in the background that take a long time to complete, freeing up resources for other tasks.
- Multi-threading can also be used to enhance user interfaces by displaying progress bars or other indicators of task completion when an event is triggered by the user.
- In addition, multi-threading can accelerate program execution by running multiple threads simultaneously. This is particularly useful for tasks that involve waiting for user input, file reading and writing, or network data transmission. In these cases, threads can be used to free up resources such as memory usage.
threading.Thread(target=<Function name>).start()
# Multi-threading assignment
threading.Thread(target=<Function name>, args=(<Variable>,).start()
import threading
import time
def handle_a():
for i in range(5):
print("a",time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) )
time.sleep(1)
def handle_b():
for i in range(5):
print("b",time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) )
time.sleep(1)
#Use multi-threading
threading.Thread(target=handle_a).start()
time.sleep(0.1)
handle_b()
#Execute functions in a normal sequential order.
handle_a()
handle_b()
#Import parameters
def printtime(a):
print(a, time.time())
x = 123
threading.Thread(target=print,args=(x,)).start()
3. API encryption
Encryption: To prevent the API from being attacked.
import hashlib
def get_signature(nonce, payload, secret, timestamp):
content = ':'.join([nonce, payload, secret, timestamp]).encode('utf-8')
m = hashlib.sha1()
m.update(content)
return m.hexdigest()
@app.route('/callback', methods=['POST'])
def callback():
payload = request.data.decode('utf-8')
nonce = request.args['nonce']
timestamp = request.args['timestamp']
if request.headers['x-jdy-signature'] != get_signature(nonce, payload, 'test-secret', timestamp):
return 'fail', 401
threading.Thread(target=handle, args=(json.loads(payload), )).start()
return 'success'
JSONPath
Click to test.
{
"data": [
{
"creator": {
"_id": "5cecd40dd23e194ab0867aab",
"name": "Martin",
"username": "cxt7777"
},
"updater": {
"_id": "5cecd40dd23e194ab0867aab",
"name": "Martin",
"username": "cxt7777"
},
"deleter": null,
"createTime": "2020-03-26T02:41:06.491Z",
"updateTime": "2020-03-26T02:46:27.825Z",
"deleteTime": null,
"_widget_1557886562320": "iPhone 11",
"_widget_1557886562335": "5998",
"_widget_1557886562350": "17",
"_id": "5e7c164229e01a00063be284",
"appId": "5e798363b587cc0006b40445",
"entryId": "5cdb765b5a6ae613aeed0f84"
},
{
"creator": {
"_id": "5cecd40dd23e194ab0867aab",
"name": "Martin",
"username": "cxt7777"
},
"updater": {
"_id": "5cecd40dd23e194ab0867aab",
"name": "Martin",
"username": "cxt7777"
},
"deleter": null,
"createTime": "2020-03-26T02:47:02.037Z",
"updateTime": "2020-03-26T02:47:02.037Z",
"deleteTime": null,
"_widget_1557886562320": "iPhone X",
"_widget_1557886562335": "4998",
"_widget_1557886562350": "5",
"_id": "5e7c17a650bccb0006441778",
"appId": "5e798363b587cc0006b40445",
"entryId": "5cdb765b5a6ae613aeed0f84"
},
{
"creator": {
"_id": "5cecd40dd23e194ab0867aab",
"name": "Martin",
"username": "cxt7777"
},
"updater": {
"_id": "5cecd40dd23e194ab0867aab",
"name": "Martin",
"username": "cxt7777"
},
"deleter": null,
"createTime": "2020-03-26T02:47:43.059Z",
"updateTime": "2020-03-26T02:47:43.059Z",
"deleteTime": null,
"_widget_1557886562320": "iPhone 8",
"_widget_1557886562335": "3998",
"_widget_1557886562350": "32",
"_id": "5e7c17cfcd87510006cf8189",
"appId": "5e798363b587cc0006b40445",
"entryId": "5cdb765b5a6ae613aeed0f84"
}
]
}
The extraction rules are similar to those in Python:
Extract the quantity of iPhone 11 products ("_widget_1557886562350")
$.data[0]._widget_1557886562350
$.data[0][‘_widget_1557886562350’]
Intranet Penetration (Demo)
Now, the APIs we have developed can only be accessed locally (your own host, localhost or 127.0.0.1). We need to map the local port to the public network environment before it can be accessed by Jodoo or other people (you only need to know what is intranet penetration, instead of mastering it).
The APIs we have developed can currently only be accessed on the local machine, using the localhost or 127.0.0.1 address. To make these APIs accessible from outside the local machine, we need to map the local port to the public network environment. (You only need to understand the basic concepts and techniques involved, instead of being an expert in intranet penetration.)
Of course, you can also directly deploy the service on a cloud server (ECS) with a public network address. We will introduce it in the next course.
We have written an API, and both the request and response formats are JSON.
from flask import Flask, request
import json
app = Flask(__name__)
@app.route('/test/', methods=['POST']) #Only POST requests are received in Jodoo
def hello_world():
print("params: ",request.args)
print("headers: ",request.headers)
print("Unencoded data: ",request.data)
print("Encoded data: ",json.loads(request.data))
return 'success',200
if __name__ == '__main__':
app.run(host='0.0.0.0',port=3100)