- Python Microservices Development
- Tarek Ziadé
- 480字
- 2021-07-02 18:54:21
How Flask handles requests
The framework entry point is the Flask class in the flask.app module. Running a Flask application means running one single instance of this class, which will take care of handling incoming Web Server Gateway Interface (WSGI) requests, dispatch them to the right code, and then return a response.
WSGI is a specification that defines the interface between web servers and Python applications. The incoming request is described in a single mapping, and frameworks such as Flask take care of routing the call to the right callable.
The class offers a route method, which can decorate your functions. When you decorate a function with it, it becomes a view, and it's registered into Werkzeug's routing system. That system uses a small rule engine to match views with incoming requests, and will be described later in this chapter.
Here's a very basic example of a fully functional Flask application:
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/api')
def my_microservice():
return jsonify({'Hello': 'World!'})
if __name__ == '__main__':
app.run()
That app returns a JSON mapping when called on /api. Every other endpoint would return a 404 Error.
The __name__ variable, whose value will be __main__ when you run that single Python module, is the name of the application package. It's used by Flask to instantiate a new logger with that name, and to find where the file is located on the disk. Flask will use the directory as the root for helpers like the config that's associated with your app, and to determine default locations for the static and templates directories.
If you run that module in a shell, the Flask app will run its web server, and start listen to incoming connections on the 5000 port:
$ python flask_basic.py
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Calling /api with the curl command will return a valid JSON response with the right headers, thanks to the jsonify() function, which takes care of converting the Python dict into a valid JSON response with the proper Content-Type header.
$ curl -v http://127.0.0.1:5000/api
* Trying 127.0.0.1...
...
< HTTP/1.0 200 OK
< Content-Type: application/json
< Content-Length: 24
< Server: Werkzeug/0.11.11 Python/3.5.2
< Date: Thu, 22 Dec 2016 13:54:41 GMT
<
{
"Hello": "World!"
}
The jsonify() function creates a Response object, and dumps the mapping in its body.
While many web frameworks explicitly pass a request object to your code, Flask provides an implicit global request variable, which points to the current Request object it built with the incoming call by parsing the HTTP call into a WSGI environment dictionary.
This design decision makes the simpler views code very concise: like in our example, if you don't have to look at the request content to reply, there's no need to have it around. As long as your view returns what the client should get and Flask can serialize it, everything is pretty much transparent.
For other views, they can just import that variable and use it.
Let's add some print method calls here and there so that we can see what's happening under the hood:
from flask import Flask, jsonify, request
app = Flask(__name__)
@app.route('/api')
def my_microservice():
print(request)
print(request.environ)
response = jsonify({'Hello': 'World!'})
print(response)
print(response.data)
return response
if __name__ == '__main__':
print(app.url_map)
app.run()
Running that new version and hitting it with the curl command in another shell, you get a lot of details, like the following:
$ python flask_details.py
Map([<Rule '/api' (GET, OPTIONS, HEAD) -> my_microservice>,
<Rule '/static/<filename>' (GET, OPTIONS, HEAD) -> static>])
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
<Request 'http://127.0.0.1:5000/api' [GET]>
{'wsgi.url_scheme': 'http', 'HTTP_ACCEPT': '*/*',
'wsgi.run_once': False, 'PATH_INFO': '/api', 'SCRIPT_NAME': '',
'wsgi.version': (1, 0), 'SERVER_SOFTWARE': 'Werkzeug/0.11.11',
'REMOTE_ADDR': '127.0.0.1',
'wsgi.input': <_io.BufferedReader name=5>,
'SERVER_NAME': '127.0.0.1', 'CONTENT_LENGTH': '',
'werkzeug.request': <Request 'http://127.0.0.1:5000/api' [GET]>,
'SERVER_PORT': '5000', 'HTTP_USER_AGENT': 'curl/7.51.0',
'wsgi.multiprocess': False, 'REQUEST_METHOD': 'GET',
'SERVER_PROTOCOL': 'HTTP/1.1', 'REMOTE_PORT': 22135,
'wsgi.multithread': False, 'werkzeug.server.shutdown': <function
WSGIRequestHandler.make_environ.<locals>.shutdown_server at
0x1034e12f0>,
'HTTP_HOST': '127.0.0.1:5000', 'QUERY_STRING': '',
'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w'
encoding='UTF-8'>, 'CONTENT_TYPE': ''}
<Response 24 bytes [200 OK]>
b'{n "Hello": "World!"n}n'
127.0.0.1 - - [22/Dec/2016 15:07:01] "GET /api HTTP/1.1" 200
Let's explore what's happening here on the call:
- Routing: Flask creates the Map class
- Request: Flask passes a Request object to the view
- Response: A Response object is sent back with the response content
- Cocos2d Cross-Platform Game Development Cookbook(Second Edition)
- 自己動手寫搜索引擎
- 實戰Java程序設計
- Learning AWS Lumberyard Game Development
- Python高效開發實戰:Django、Tornado、Flask、Twisted(第3版)
- Expert Android Programming
- 編譯系統透視:圖解編譯原理
- 零基礎入門學習Python(第2版)
- Create React App 2 Quick Start Guide
- Python從入門到精通
- 后臺開發:核心技術與應用實踐
- Laravel Application Development Blueprints
- 數據分析與挖掘算法:Python實戰
- Java EE 8 and Angular
- PHP項目開發全程實錄(第4版)