在中国做国外网站,网络营销类网站,怎么设置网站关键字,wordpress图片模版Tornado 特点 Tornado是一个用Python写的相对简单的、不设障碍的Web服务器架构#xff0c;用以处理上万的同时的连接口#xff0c;让实时的Web服务通畅起来。虽然跟现在的一些用Python写的Web架构相似#xff0c;比如Django#xff0c;但Tornado更注重速度#xff0c;能够…Tornado 特点 Tornado是一个用Python写的相对简单的、不设障碍的Web服务器架构用以处理上万的同时的连接口让实时的Web服务通畅起来。虽然跟现在的一些用Python写的Web架构相似比如Django但Tornado更注重速度能够处理海量的同时发生的流量。 FriendFeed的联合创始人Bret Taylor的博客里介绍了更多他说把Tornado开源FriendFeed和Facebook期望第三方能够用以建筑实时的Web服务。其具体的工作原理如上图看起来很像是FriendFeed的评论系统。 Taylor认为Tornado的三个关键部分是 完整的用以构建网站的基础模块。Tornado包含内置的用以解决网络开发最难和最烦的功能模块包括模板、signed cookies、用户认证、地方化localization、aggressive static file caching, cross-site request forgery protection以及类似Facebook Connect的第三方认证。开发者可以随取所需并且自由组合甚至把Tornado与其他架构组合。 实时服务。Tornado支持大量的同时发生的信息连接。用Tornado能够通过HTTP或者Long Polling方便的书写实时服务。要知道每一个FriendFeed的活跃用户都保持有一个连通FriendFeed服务器的开放通路。 高效能。Tornado比大多数用Python写的Web架构更快。根据一些实验Tornado的速度是一般架构的4倍。 Tornado 支持二种模式 一种是串行访问处理异步非阻塞。当客户端访问webtornado 可以自行定义前面2个的处理方式。天生支持RESTful 安装 pip install tornado 官方http://www.tornadoweb.org/en/stable/ 一 、HELLO word 1 import tornado.ioloop2 import tornado.web3 4 class MainHandler(tornado.web.RequestHandler):5 def get(self):6 self.write(Hello, world)7 8 def make_app():9 return tornado.web.Application([
10 (r/index, MainHandler),
11 ])
12
13 if __name__ __main__:
14 app make_app()
15 app.listen(8888)
16 tornado.ioloop.IOLoop.current().start() 访问 ip:8888/index 测试内容 配置模板 返回html页面 #_*_coding:utf-8_*_
import tornado.ioloop
import tornado.web#通过字典定义的方式定义配置文件属性
settings {template_path:template,
}class MainHandler(tornado.web.RequestHandler):def get(self):#self.write(Hello, world)#返回模板中的页面self.render(index.html)def make_app():#把setting这个配置参数带入到方法中return tornado.web.Application([(r/index, MainHandler),],**settings)if __name__ __main__:app make_app()app.listen(8888)tornado.ioloop.IOLoop.current().start() 然后就可以测试页面了非常的简单 这里介绍render都做了什么class MainHandler(tornado.web.RequestHandler): def get(self): 1先找到template的路径 2根据路径找到对应的html页面拼接 3python open方法读取这个html页面内容将内容读取到了内存中。实际上读出来的其实就是一个字符串 4 self.write(open(html).read()) 读出这个文件然后写回(self.write方法) 5self.write用socket的send方法将字符串发送给客户端用户(这里会将这个字符串塞进一个双向队列里面send方法回去队列中去数据然后发送给客户端)用户就可以看见web页面了这个就是一个简单的过程 dic { nameaaaa } 这里在说一下模板渲染上面定义了一个字典dic。那过程就需要多加一步了。 在上面4步 4open(html).read() 先把文件读取出来 5渲染html页面(实际就是一个很长的字符串)替换字符串中的特殊模板语言(在html文件中也会有模板语言{{ name }},这个key可以dic中的key对应上) 6self.write self.render(index.html) #self.render(index.html,**dic) 渲染必须将字典当参数一起传递 路由系统 #_*_coding:utf-8_*_
import tornado.ioloop
import tornado.web#通过字典定义的方式定义配置文件属性
settings {template_path:template,
}class MainHandler(tornado.web.RequestHandler):def get(self):dic{name:abc}self.render(index.html,**dic)class Home(tornado.web.RequestHandler):def get(self):self.render(home.html)class news(tornado.web.RequestHandler):#接受从url传递过来的参数nid是从url中传递过来的def get(self,nid):self.write(str(nid))
(r/news/(\d),news),这里也可以用正则匹配.想要当参数传递必须()中写表达式def make_app():#把setting这个配置参数带入到方法中return tornado.web.Application([(r/index, MainHandler),(r/home,Home),(r/news/(\d),news),],**settings)if __name__ __main__:app make_app()app.listen(8888)tornado.ioloop.IOLoop.current().start() 匹配二级域名这个是Tornado独有的一般都是匹配xxx.xxxx.xxx/后面的参数现在要匹配 psp.xxx.com/index ,匹配psp 这个前缀 #_*_coding:utf-8_*_
import tornado.ioloop
import tornado.web#通过字典定义的方式定义配置文件属性
settings {template_path:template,
}class MainHandler(tornado.web.RequestHandler):def get(self):dic{name:abc}self.render(index.html,**dic)class psphandler(tornado.web.RequestHandler):def get(self):self.write(psp.tb.com/index)
apptornado.web.Application([(r/index, MainHandler),],**settings)#对app的add_handlers方法在增加一个匹配项如果匹配上就掉对应的方法。当url过来的时候如果psp.tb.com匹配不上还是回去其它定义的规则中继续匹配
app.add_handlers(psp.tb.com,[(r/index,psphandler),
])if __name__ __main__:app.listen(8888)tornado.ioloop.IOLoop.current().start() 测试结果 路由psp 路由正常规则 静态文件 !DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/titlelink href{{static_url(commons.css)}} relstylesheet /
/head
body
h1index.html/h1
h1{{ name }}/h1
/body
/html index.html 1 #_*_coding:utf-8_*_2 import tornado.ioloop3 import tornado.web4 5 6 必须定义static_path:static,否则static_path_prefix:/static/,会报错误。7 现在不定义static_path_prefix:/static/,前端html文件{{static_url(commons.css)}} 也会对文件添加md5码。8 当文件更新的时候就会非常方便了客户端也可以发现静态文件更新再也不用手动强制更新ie缓存了9
10 settings {
11 template_path:template,
12 static_path:static,
13 static_path_prefix:/static/,
14 }
15
16 class MainHandler(tornado.web.RequestHandler):
17 def get(self):
18 dic{
19 name:abc
20 }
21 self.render(index.html,**dic)
22 apptornado.web.Application([
23 (r/index, MainHandler),
24 ],**settings)
25
26 if __name__ __main__:
27 app.listen(8888)
28 tornado.ioloop.IOLoop.current().start() 访问展示 主要看静态文件后面的自己生成的md5值然后自己改一下样式重启服务器客户端刷新就会直接刷新缓存了。 这里还有一个好处是前端不用管后端static文件夹的改变后端更改路径不会影响前端 cookie操作 #_*_coding:utf-8_*_
import tornado.ioloop
import tornado.web#cookie_secret这个配置的是加盐的值
settings {template_path:template,static_path:static,static_path_prefix:/static/,cookie_secret:asdasdasda,}
class HomeHandler(tornado.web.RequestHandler):def get(self):#读取客户端cookie,k1就是客户端cookie的一个字符串#self.set_cookie(k1)#设置cookie (参数):name, value, domainNone, expiresNone, path/,expires_daysNone, **kwargs#path/ 这个参数是设置cookie的作用域范围。www.xxx.com/home 如果这样写就说明这个cookie只作用在home这个url上别的url无法使用#set_cookie是不加密的 直接明文就传递给客户端可以用调试工具查看到self.set_cookie(name,abc)#加密cookie 进行签名#self.set_secure_cookie(name,123)self.render(home.html)def make_app():return tornado.web.Application([(r/home, HomeHandler),],**settings)if __name__ __main__:app make_app()app.listen(8888)tornado.ioloop.IOLoop.current().start() 演示 因为这里无法同时开启self.set_cookie和self.set_secure_cookie。所以这个实验是执行完一个在换另一个。加密的还是相对比较安全的 。 看源码是如何处理加密 源码 def set_secure_cookie(self, name, value, expires_days30, versionNone,**kwargs):# 这里默认将超时时间设置了expires_days30,注意看它这直接调用了不加密码的cookie方法self.set_cookie()。 #self.create_signed_value(name, value,ersionversion)加密方法self.set_cookie(name, self.create_signed_value(name, value,ersionversion),xpires_daysexpires_days, **kwargs) create_signed_value加密方法 def create_signed_value(self, name, value, versionNone):#获取加盐的方法self.require_setting(cookie_secret, secure cookies)#在前面的setting增加这几个key就可以self.require_setting(cookie_secret, secure cookies)secret self.application.settings[cookie_secret]key_version Noneif isinstance(secret, dict):if self.application.settings.get(key_version) is None:raise Exception(key_version setting must be used for secret_key dicts)key_version self.application.settings[key_version]#这个是全局的变量虽然跟这个类中的方法名字相同。但是这个不是传给自己的 create_signed_valuereturn create_signed_value(secret, name, value, versionversion,key_versionkey_version) create_signed_value def create_signed_value(secret, name, value, versionNone, clockNone,key_versionNone):if version is None:version DEFAULT_SIGNED_VALUE_VERSIONif clock is None:clock time.time#生成时间戳timestamp utf8(str(int(clock())))#用base64.b64encode加密base64是可以反解回来的value base64.b64encode(utf8(value))#有2个版本加密一个是v1一个v2if version 1:signature _create_signature_v1(secret, name, value, timestamp)value b|.join([value, timestamp, signature])return valueelif version 2:# The v2 format consists of a version number and a series of# length-prefixed fields %d:%s, the last of which is a# signature, all separated by pipes. All numbers are in# decimal format with no leading zeros. The signature is an# HMAC-SHA256 of the whole string up to that point, including# the final pipe.## The fields are:# - format version (i.e. 2; no length prefix)# - key version (integer, default is 0)# - timestamp (integer seconds since epoch)# - name (not encoded; assumed to be ~alphanumeric)# - value (base64-encoded)# - signature (hex-encoded; no length prefix)def format_field(s):return utf8(%d: % len(s)) utf8(s)to_sign b|.join([b2,format_field(str(key_version or 0)),format_field(timestamp),format_field(name),format_field(value),b])if isinstance(secret, dict):assert key_version is not None, Key version must be set when sign key dict is usedassert version 2, Version must be at least 2 for key version supportsecret secret[key_version]signature _create_signature_v2(secret, to_sign)return to_sign signatureelse:raise ValueError(Unsupported version %d % version) 全局create_signed_value def _create_signature_v1(secret, *parts):hash hmac.new(utf8(secret), digestmodhashlib.sha1)for part in parts:hash.update(utf8(part))return utf8(hash.hexdigest())def _create_signature_v2(secret, s):hash hmac.new(utf8(secret), digestmodhashlib.sha256)hash.update(utf8(s))return utf8(hash.hexdigest()) 加密V1和V2 这样做比较安全当黑客如果知道你的加密过程伪造cookieTornado会根据它的cookie先去做签名如果签名跟服务器上的一致那么就OK。但是这里有一个重要的因素是 secret self.application.settings[cookie_secret] 这个值是定在服务器这边的 很难获取到。如果这值知道了那么久没有任何办法了。 反解过程可以看self.get_secure_cookie() 过程都在这里面了。 转载于:https://www.cnblogs.com/menkeyi/p/5961103.html