惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
I
InfoQ
The Cloudflare Blog
人人都是产品经理
人人都是产品经理
博客园 - Franky
T
Tailwind CSS Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
量子位
博客园_首页
罗磊的独立博客
V
V2EX
李成银的技术随笔
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
True Tiger Recordings
Vercel News
Vercel News
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
F
Fox-IT International blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
M
Microsoft Research Blog - Microsoft Research
Know Your Adversary
Know Your Adversary
爱范儿
爱范儿
The Register - Security
The Register - Security
G
Google Developers Blog
The Hacker News
The Hacker News
Malwarebytes
Malwarebytes
S
Securelist
博客园 - 三生石上(FineUI控件)
Jina AI
Jina AI
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
S
SegmentFault 最新的问题
博客园 - 叶小钗
F
Fortinet All Blogs
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
博客园 - 聂微东
T
Threatpost
博客园 - 【当耐特】
D
Docker
P
Privacy & Cybersecurity Law Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
G
GRAHAM CLULEY
V
Visual Studio Blog
C
Cisco Blogs
IT之家
IT之家
S
Security Archives - TechRepublic
Latest news
Latest news
阮一峰的网络日志
阮一峰的网络日志

jdhao's digital space

Manage uv.lock file with Renovate Set up Python Provider for Neovim Ripgrep Config to Search Hidden Files Pre-commit Setup for Your Project I read the nvim v0.12 release note so you don't have to Return Different Values for Each Call of A Mock Migrate Python Project from Pip to Uv 德语常用不规则动词 葱油鸡腿制作 Check Trailing White Spaces in Your Project 菜谱:茄子肉丁 object vs nested type in data mapping in Elasticsearch Node, Index, Shard in Elasticsearch Logging setup for Pytest Select fields in Elasticsearch: _source, fields and stored_fields 中式葱花饼制作 菜谱: 凉拌苤蓝(卜留克/kohlrabi) 我也有高考 PTSD Garmin Course Syncing Not Working? Prevent Accidental Index Delete in Elasticsearch How to Import GPX File into Garmin Watch Python system PATH issues When We Use Pytest 菜谱:泰式打抛牛肉 菜谱:烤箱羊肉串 How to Filter Warnings in Python/pytest 家常烤箱烤鸡腿 Comparison between Several Desktop Speakers How to Use LuaRocks Package in Neovim Macbook 外接显示器 家常萝卜炖羊排 Run the Job Immediately after Starting Scheduler in Python APScheduler Retry for Google Cloud Client 菜谱:土豆金枪鱼沙拉 菜谱:椰香咖喱鸡 凉拌绿豆宽粉制作 Make Python logging Work in GCP Liveness and Readiness Check in Kubernetes Notes on Using GCP Logging 西班牙土豆饼制作 Elasticsearch Version Conflict Error How to Use the Elasticsearch task API Speed up document indexing in Elasticsearch via bulk indexing Index refresh issue in Elasticsearch Google Cloud Storage Usage 家常煎羊排制作 凉拌茄子制作 Configure Python logging with dictConfig Debugging Wezterm Issues Black Formatter Setup for Python Project Git line ending config Garmin Forerunner 965 Essential Tips and Setups How to Download Files from Google Cloud Storage in the Databricks Workspace Notebook Databricks Cli Usage Working with Databricks Workspace Files 手抓羊肉饭制作 Databricks Init Scripts Using Virutal Environment in Python with venv File Systems in Databricks LATERAL VIEW EXPLODE in Spark 菜谱:麻婆豆腐 在德国做台湾卤肉饭 FastAPI testing and OpenAPI doc generation Change Timezone in Databricks Spark How to Profile Your Python Script/Module 菜谱:茄子肉沫 Migrating from Packer.nvim to Lazy.nvim How to Extract PDF file on macOS How to Deploy Fastapi Application with Docker Nerdfont Icon Missing after Wezterm Upgrade Pylsp setup for Neovim in 2023 How to Parse Query Param With Multiple Values in FastAPI 菜谱:土豆胡萝卜烧牛肉 Zsh Startup Files in macOS PATH Variable Changed inside Tmux on macOS? Work with JSON File in Neovim Running/importing Python code/module in Databricks Agile and Scrum 菜谱:凉拌牛肉 Awesome Command Line Tools Written in Rust How to get or set Databricks spark configuration Set Up German Version macOS Add A Custom Search Engine for Vimium 中国大陆小米手机如何使用 Google Pay 春节回乡记 滇西之行 2023 贵阳行 2023 程序员海外工作---语言篇 2023 长沙行 2023 西安行 德国工签申请指南 2022 年博客回顾 感染 omicron 记录 How to Override Default Options in Neovim Variadic Arguments in Lua How to Enable Method Autocompletion for OpenCV How to Read Local CSV File to Table in MySQL I read the nvim v0.8 release note so you do not have to Creating A Trigger in PostgreSQL Cost of Living in Shenzhen You Do Not Need a Plugin for This Feature
Build A Web API Service Using Flask -- The Basics
2020-04-06 · via jdhao's digital space

Web API is a kind of web application. Simply put, web APIs are built for other applications to get info from the web server. For Python, Flask can be used to build web applications. In this post, I want to share how to build web APIs with Flask.

A simple web API#

Supposing that we want to build a simple web API that returns the square root a number, the following code shows how to do that:

import math
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/sqrt', methods=["POST"])
def sqrt():
    num = request.form.get('num', type=int)

    return jsonify({'result': math.sqrt(num), 'msg': 'success'})

In the above code, we first create a flask application using Flask(__name__), which lets Flask know that we are building an application. We then use the @app.route() decorator to define a URL path that we can later incorparate with IP and port number to access our web API. The methods parameter is used to specify what kinds of HTTP requests the server can process from the client.

Below the app decorator, we define a view function to process the client request, the actual name of this view function does not matter. The view function name does not have be the same as app.route path (ref here).

Processing the client request#

To process the client requests in the server side, Flask provides the request module. When a client is using a POST request to post a JSON object, the posted data will be available in request.form, which is like a Python dictionary. Note that by default, the value for a key is of string type. You have to specify the type parameter to convert the value to desired type:

num = request.form.get('num', type=int)

If you do not use type=int, num will be a string instead of an integer..

Return JSON object to client#

Flask provides the jsonify method to serialize any compatible data type to JSON format. Finally, we return the result in JSON format.

Running the development server#

After we build the simple web API, we need to test if it works. First, we need to run the web server. Flask ships with a simple web server for testing purposes. There are two ways that we can run the web server: via app.run() or via the Flask command line interface.

Run the HTTP server via app.run()#

Add the following code to the Flask application module:

if __name__ == "__main__":
    # the server will listen on port 1234. Default is port 5000.
    app.run(port=1234)

If we do not specify the host address, the default will be 127.0.0.1, which means that we can only access the service in our machine. To use the IP address of our machine, we can specify the host parameter in app.run:

app.run(host="0.0.0.0", port=1234)

Then other machines in the same network can access the web service.

Finally, we can start the HTTP server with python application.py (suppose that our module is named application.py). We will see the following message on command line:

 * Serving Flask app "application" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:1234/ (Press CTRL+C to quit)

Run the server via Flask command line interface#

The second and officially-recommended way to run Flask application is via the Flask command line interface (flask run).

When we run the application using flask run, the following settings does not work:

if __name__ == "__main__":
    # when debug is True, flask will reload app once code changes.
    app.run(host="0.0.0.0", port=8081)

The correct way to run the application is to run the following command:

export FLASK_APP=application
FLASK_ENV=development flask run --host=0.0.0.0 --port 1234

FLASK_APP variable is used to specify which file our flask application resides. FLASK_ENV is used to specify the flask running environment. The default is production. If you use development, Flask will activate debug mode, i.e., it will reload the application once the code changes.

--host is used to specify the host address. --port is used to specify the listening port. We can also change the port number via FLASK_RUN_PORT env variable:

export FLASK_APP=application
export FLASK_RUN_PORT=1234
FLASK_ENV=development flask run --host=0.0.0.0

Auto reloading on code changes#

Flask provides a debug mode where the app will be reloaded once the code changes, so we do not need to manually stop the server and run it again.

If we run the server via app.run(), we can activate debug mode via debug=True:

if __name__ == "__main__":
    # when debug is True, flask will reload app once code changes.
    app.run(host="0.0.0.0", port=1234, debug=True)

We may encounter following errors when we run python application.py:

OSError: [Errno 8] Exec format error

The reason for this error can be found here. To put it simply, if application.py has execution right, then Flaks assumes that the script can be run via ./application.py. So we must add shebang at the beginning of the module:

!#/usr/bin/env python

Or we must disable the execution right of this module. When the application is reloaded, it will be run via python application.py.

Another way is to run the app via Flask command line interface, as we have mentioned earlier. Set the FLASK_ENV variable to development or set FLASK_DEBUG to 1:

export FLASK_APP=application
FLASK_ENV=development flask run --host=0.0.0.0 --port 1234

# or the following
# FLASK_DEBUG=1 flask run --host=0.0.0.0 --port 1234

Test the web API#

The full URL for the web API is: http://127.0.0.1:1234/sqrt.

We can test the web API via curl:

curl -XPOST -d num=4 "http://127.0.0.1:1234/sqrt"

It is more convenient to test the API via requests package using the following code:

import requests


def post_data():
    url = "http://127.0.0.1:1234/sqrt"

    payload = {'num': 4}
    response = requests.post(url, data=payload)

    return response.json()


def main():
    result = post_data()
    print(result)


if __name__ == "__main__":
    main()

If everything is OK, you will see the following output:

{'msg': 'success', 'result': 2.0}

References#