官术网_书友最值得收藏!

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.

The curl command is going to be used a lot in this book. If you are under Linux or macOS, it should be pre-installed; refer to https://curl.haxx.se/.
 
$ 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.

The request variable is global, but unique, to each incoming request and is thread safe. Flask uses a mechanism called context locals, which we will explain later .

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
主站蜘蛛池模板: 开江县| 云和县| 黎川县| 慈溪市| 孟津县| 普定县| 定边县| 喀喇| 牙克石市| 永安市| 德昌县| 道孚县| 中江县| 嘉黎县| 玉门市| 麟游县| 正宁县| 祁东县| 宁都县| 万全县| 嘉峪关市| 曲麻莱县| 长沙县| 邢台市| 吉首市| 南召县| 阜南县| 财经| 驻马店市| 资溪县| 若羌县| 寿宁县| 察雅县| 梅河口市| 西贡区| 定襄县| 上蔡县| 麻江县| 和政县| 长沙县| 天峻县|