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&timestamp=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) 

Was this information helpful?
Yes
NoNo
Need more help? Contact support