Tornado WEB Framework

Source: Internet
Author: User
Tags configuration settings oauth openid ajax chat

First, Introduction

Tornado is an open-source version of the extensible, non-blocking Web server and its associated tools used by FriendFeed. The web framework looks somewhat like web.py or Google's WebApp, but the web framework contains some useful tools and optimizations to make efficient use of the non-blocking server environment.

There is a significant difference between the Tornado and the current mainstream WEB server framework, including most Python frameworks: It's a non-blocking server and it's pretty fast. With its non-blocking approach and its use of epoll, Tornado can handle thousands of connections per second, which means that Tornado is an ideal web framework for real-time Web services. The main purpose of developing this WEB server is to deal with the real-time functionality of FriendFeed, where every active user maintains a server connection in the FriendFeed application. (For questions about how to scale up the server to handle the connections of thousands of clients, see c10k problem.) )

See the Tornado documentation or Tornado original document (mirroring) For more information on the WEB framework.

Download and install
Pip install PIP3 install Tornado Source Installation tar Xvzf tornado-4.4.1.tar.gzcd tornado-4.4.1python setup.py buildsudo python setup.py Inst All

SOURCE download: tornado-1.2.1.tar.gz, tornado-4.4.1.tar.gz

Tornado main modules Web-friendfeed uses the underlying WEB framework that contains most of Tornado's important features escape-xhtml, JSON, URL encoding/decoding method database-Simple for MYSQLDB  encapsulation, making it easier to use template-Python-based Web Template system HttpClient-non-blocking HTTP client, which is designed to work with web and Httpserver auth-third-party authentication implementations (including Google Openid/oauth, Facebook Platform, Yahoo Bbauth, FriendFeed Openid/oauth, Twitter OAuth) locale-support options for localization and translation- command line and Profile resolution tool optimized for the server environment the underlying module Httpserver-a very simple HTTP server implementation that serves the Web module iostream-A simple encapsulation of a non-blocking socket to facilitate common read and write operations Ioloop-core The I/O loop
Second, Hello, world

"Hello, World" and application settings Basic configuration:

Import tornado.ioloopimport tornado.web# import uimodules as md# import uimethods as Mtclass MainHandler (tornado.web.Requ Esthandler):    def get (self):        self.write ("Hello, World") settings = {    ' template_path ': ' Views ',        # HTML file    ' Static_path ': ' statics ',        # static file (css,js,img)    ' static_url_prefix ': '/statics/', # static file prefix    ' Cookie_secret ': ' suoning ',      # Cookie Custom string Add salt    # ' xsrf_cookies ': True,          # Prevent cross-site forgery    # ' Ui_methods ': MT,              # custom Uimethod function    # ' Ui_modules ': MD,              # custom uimodule Class}application = Tornado.web.Application ([    R "/ ", MainHandler),], **settings) if __name__ = =" __main__ ":    application.listen (8888)    Tornado.ioloop.IOLoop.instance (). Start ()

1. Processing procedures and Parameters

When the request comes, the program matches the corresponding routing address with a regular match and is delivered to the subclass of the Tornado.web.RequestHandler, and the subclass is based on the requested method (Post/get/delete ... ) and executes the appropriate method, which returns the string contents and sends it to the browser.

Self.write ("

2, overriding the method function of RequestHandler

The process code for a request is called in the following order:

    1. The program creates a RequestHandler object for each request;
    2. Program Call initialize() function, the parameter of this function is the Application definition of the keyword parameter in the configuration. (The initialize method is newly added in Tornado 1.1, you need to rewrite in the old version __init__ to achieve the same purpose) the initialize method generally simply saves the passed in parameter to the member variable, without producing some output or calling send_error methods like.
    3. Program calls prepare() . Regardless of which HTTP method is used, it prepare is called, so this method is usually defined in a base class and then reused in subclasses. prepareoutput information can be generated. If it calls finish (or Send_error '), then the entire process ends.
    4. The program calls an HTTP method: For example get() , post() ,, and put() so on. If there is a grouping match in the regular expression pattern of the URL, then the correlation match is passed as a parameter to the method.

overriding initialize() function (called after the RequestHandler object is created):

Class Profilehandler (Tornado.web.RequestHandler):    def Initialize (self,database):        self.database = Database    def get (self):        self.write ("Result:" + self.database) application = Tornado.web.Application ([    R "/init", Profilehandler, Dict (database= "database")])
Four, template engine

The template language in Tornao is similar to Django, where the template engine loads the template file into memory and then embeds the data in it, eventually acquiring a complete string and returning the string to the requestor.

The Tornado template supports "control statements" and "expression statements", which are used {% and %} wrapped for example by control statements {% if len(items) > 2 %} . Expression statements are used {{ and }} wrapped, for example {{items[0]}}.

The format of the control statement and the corresponding Python statement is basically exactly the same. We support if , for while and try , where these statements logically end, they need to {% end %} be labeled. extendstemplate inheritance is also implemented through and block statements. These are template described in detail in the code documentation for the module.

Note: You need to set the template path in setting before using the template: "Template_path": "Views"

1, basic use app.py index.html other methods 2, master (template inheritance) layout.html extends.html3, import header.html index.html4, custom Uimethod to Uimodule

A. Definition

uimethods.py uimodules.py

B. Registration

app.py

C. Use

Index.html v. Static files and active file caching

Specify options in the application configuration settings static_path to provide static file services;

Specify options in the application configuration settings static_url_prefix to provide the static file prefix service;

{{static_url(‘XX.css‘)}}implement proactive caching of static files when importing static files

Settings = {    ' template_path ': ' Views ',    ' static_path ': ' Static ',    ' static_url_prefix ': '/static/',}
Vi. Cookie1, basic cookies

set_cookiemethod to set the cookie in the user's browsing;

get_cookiemethod to obtain a cookie in the user's browsing.

Class MainHandler (Tornado.web.RequestHandler):    def get (self):        if not Self.get_cookie ("MyCookie"):            Self.set_cookie ("MyCookie", "myvalue")            self.write ("Your cookie is not set yet!")        else:            self.write ("Your cookie was set!")
2. Encrypted cookie (signature)

Cookies can easily be forged by malicious clients. To add information that you would like to have in your cookie to keep the current logged-in user's ID, you need to sign the cookie to prevent forgery. Tornado set_secure_cookie get_secure_cookie supports this function directly through and through the method. To use these methods, you need to provide a key when the app is created, named cookie_secret . You can pass it as a keyword parameter into the app's settings:

Class MainHandler (Tornado.web.RequestHandler):    def get (self):        if not Self.get_secure_cookie ("MyCookie"):            Self.set_secure_cookie ("MyCookie", "myvalue")            self.write ("Your cookie is not set yet!")        else:            self.write ("Your cookie was set!")             application = Tornado.web.Application ([    (R "/", MainHandler),], cookie_secret= " 61oetzkxqagaydkl5gemgejjfuyh7eqnp2xdtp1o/vo= ")
Internal algorithm source code interpretation

The nature of cryptographic Cookice:

Write Cookie process:

  • To encrypt a value base64
  • Hash algorithm (cannot be parsed backwards) to sign content other than value
  • Stitching Signature + Encrypted value

Read the cookie process:

  • Read Signature + encrypted value
  • Verifying a signature
  • Base64 decrypt, Get value content

Note: Many API validation mechanisms and security cookies implement the same mechanism.

User authentication based on cookie-demo user authentication based on signature cookie-demo3, JavaScript action cookie

Because cookies are stored on the browser side, JavaScript can also be used to manipulate cookies on the browser side.

/* Set the cookie to specify the number of seconds to expire */function Setcookie (name,value,expires) {    var temp = [];    var current_date = new Date ();    Current_date.setseconds (Current_date.getseconds () + 5);    Document.cookie = name + "=" + Value + "; expires=" + current_date.toutcstring ();}

For parameters:

    • Cookies under domain-specific domains
    • The cookie in the specified URL under path domain name
    • Secure HTTPS use

Note: jquery also has the specified plugin jquery cookie specifically for manipulating cookies, bash here

Seven, user authentication

Currently authenticated user information is stored in each request processor self.current_user , and also in the template current_user . By default, the current_user None .

To implement user authentication in an application, you need to rewrite this method in the request processing get_current_user() , where the current user's state is determined, such as through a cookie. The following example allows the user to simply use a nickname login application, which will be saved in a cookie:

 class Basehandler (Tornado.web.RequestHandler): def get_current_user (self): return Self.get_secure_cookie ("U             Ser ") class MainHandler (Basehandler): Def get (self): If not Self.current_user:self.redirect ("/login ") return name = Tornado.escape.xhtml_escape (self.current_user) self.write ("Hello," + Name) class L Oginhandler (Basehandler): Def get (self): Self.write (' auth to the code documentation for the module for more information. For more details. Check auth module to learn more details. In Tornado's source code there is a Blog example, you can also see the user authentication method (and how to save the user data in the MySQL database).

EightCSRFPrevention of cross-site forgery requests

Cross-site forgery requests (Cross-site request forgery), referred to as XSRF, are a common security issue in personalized WEB applications. The previous link also details how the XSRF attack was implemented.

A common way to prevent XSRF is to record an unpredictable cookie data for each user, and then request that all submitted requests have this cookie data. If this data does not match, then the request may have been forged.

Tornado has built-in XSRF defense mechanism, to use this mechanism, you need to add settings in the application configuration xsrf_cookies :

Settings = {    "Cookie_secret": "61oetzkxqagaydkl5gemgejjfuyh7eqnp2xdtp1o/vo=",    "Login_url": "/login",    " Xsrf_cookies ": true,}application = Tornado.web.Application ([R    "/", MainHandler),    (R"/login ", Loginhandler) ,], **settings)

If set xsrf_cookies , then the Tornado Web app will set a cookie value for all users _xsrf , and if the POST PUT DELET cookie value is not in the request, the request will be rejected directly. If you start this mechanism, you will need to add a field to provide this value in all the submitted forms. You can do this by using specialized functions in the template xsrf_form_html() :

<form action= "/new_message" method= "POST" >  {{xsrf_form_html ()}}  <input type= "text" name= "message" />  <input type= "Submit" value= "Post"/></form>

If you are submitting an AJAX POST request, you still need to add this value to each request through a script _xsrf . Here is the AJAX request in FriendFeed POST , which uses the JQuery function to add values for all request group East _xsrf :

function GetCookie (name) {    var r = document.cookie.match ("\\b" + name + "= ([^;] *) \\b ");    Return r? R[1]: undefined;} Jquery.postjson = function (URL, args, callback) {    args._xsrf = GetCookie ("_xsrf");    $.ajax ({url:url, data: $.param (args), DataType: "Text", type: "POST",        success:function (response) {        callback ( Eval ("(" + Response + ")");});};    

PUT DELETE POST You can also X-XSRFToken pass XSRF tokens with this parameter in the HTTP header for and requests (and for requests that do not use the form content as parameters).

If you need to customize the XSRF behavior for each request processor, you can rewrite it RequestHandler.check_xsrf_cookie() . For example, if you need to use an API that does not support cookies, you can check_xsrf_cookie() disable the XSRF protection mechanism by setting empty functions. However, if you need to support both cookies and non-cookie authentication methods, it is important that you use the XSRF protection mechanism as long as the current request is authenticated by a cookie.

Nine, file upload 1, form form upload HTML Python2, Ajax upload (mainly using the first two ways) html-xmlhttprequest-xhr html-jquery html-iframe Python extension: IFRAME-based implementation Ajax Upload Example ten, verification code

To install the image processing module:pip3 install pillow

Instance:

Verification Code Demo source download: Punch Here, note the path of the import module

Verification code Instance Python file Authenticode instance HTML file 11, non-blocking asynchronous request

When a request is processed, the request ends automatically. Because a non-blocking I/O model is used in the Tornado, you can change this default processing behavior--keeping a request in a connected state instead of returning immediately until a primary processing behavior returns. To implement this approach, you only need to use tornado.web.asynchronous the adorner.

After using this adorner, you must call the self.finish() completed htttp request, or the user's browser will remain in the state waiting for the server to respond:

Class MainHandler (Tornado.web.RequestHandler):    @tornado. web.asynchronous    def get (self):        self.write (" Hello, World ")        Self.finish ()

Here is an example of an API that uses the Tornado built-in asynchronous request HTTP client to invoke FriendFeed:

Class MainHandler (Tornado.web.RequestHandler):    @tornado. web.asynchronous    def get (self):        http = Tornado.httpclient.AsyncHTTPClient ()        http.fetch ("Http://friendfeed-api.com/v2/feed/bret",                   callback= Self.on_response)    def on_response (self, Response):        if Response.error:raise tornado.web.HTTPError ($)        JSON = Tornado.escape.json_decode (response.body)        self.write ("fetched" + str (len (json["Entries"]) + "entries"                   "from the FriendFeed API")        Self.finish ()

Example, when the get() method returns, the request processing is not completed. When the HTTP client executes its callback function on_response() , the request from the browser still exists, and the self.finish() response is returned to the browser only after the explicit invocation.

For a high-level example of more asynchronous requests, you can refer to this example in the demo chat . It is an AJAX chat room that uses a long polling method. If you use a long polling, you may need to make a copy on_connection_close() so that you can do the cleanup after the client connection is closed.

12. Custom Web Component A. Session

What is a Session? What is the difference between a session and a cookie?

A session is a server-side mechanism (a cookie exists on the browser side) that stores the information needed for a particular user session (the session is built on demand and the cookie is the system's own); The session must rely on Cookice.

Tornado does not provide a Session mechanism by default, we can customize the following:

Demob. Form validation

In web programs, it often involves a lot of work on forms validation, such as: judging if the input is empty, and whether it conforms to the rules.

HTML Python

Because validation rules can be reused in code, they can be defined like this:

Demo

Tornado WEB Framework

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.