关于 CORS

说起 CORS,就不得不先提到 SOP(Same-origin policy):浏览器打开的网页只可以对该网页的同源网站发起请求。注意,受约束的主要是脚本代码,不包括图片或者 CSS 等资源(字体文件是个例外)。同源的定义包括三部分,即协议、域名和端口都要保持一致。 为了缓解 SOP 带来的严格限制,有几种主流的解决方案可以选择: CORS JSONP:利用 <script> 标签来请求非同源地址的 JSON 响应,同时配合一个预先定义的回调函数来处理响应数据。 WebSocket:WS 连接并不受同源策略的约束,但是在建立连接时服务端也需要判断 headers 中的 Origin 是否可以接受。 其中 CORS 应该是最实用的一种,相比 JSONP 只支持 GET 请求,前者扩展了各种 HTTP 方法的跨域调用。 CORS(Cross-origin resource sharing),是一种跨域共享资源的机制,它利用特定的 Headers 来保证跨域请求的安全性,这些请求分为两类:简单请求和非简单请求。 简单请求,包括 GET、HEAD 和 POST,这里 POST 的 Content-Type 仅限于下面三种: application/x-www-form-urlencoded multipart/form-data text/plain 对于这些请求来说,只需要保证 Access-Control-Allow-Origin 中匹配了当前网页的域名即可,如果是 * 的话表明所有的域名都是允许的。 非简单请求,比如 Content-Type 为 application/json 的 POST,会增加一次额外的 Preflight 请求,即先发送 OPTIONS 请求给服务器,然后通过响应中的一系列 Headers 决定是否可以进行真正的请求。这些 Headers 包括: Access-Control-Allow-Methods:服务器允许的跨域方法,比如 POST。 Access-Control-Allow-Headers:服务器允许的跨域头部,比如 Content-Type。 Access-Control-Max-Age:Preflight 请求结果的缓存时间,默认为 5s。 另外,如果想在 Chrome 中查看 Preflight 请求的话,打开 Network 标签,点击 Other filter 就可以看到了。...

05-17 · 1 min

论独处

最近读完了叔本华的《人生的智慧》,其中关于独处的言论令人印象深刻。作者的观点鲜明,欣赏之余,我也不禁想重新解读下这件事情。 先看看书中的描述: 拘谨、掣肘不可避免地伴随着社交聚会。社交聚会要求人们做出牺牲,而一个人越具备独特的个性,那他就越难做出这样的牺牲。因此,一个人逃避、忍受抑或喜爱独处是和这一个人自身具备的价值恰成比例。因为在独处的时候,一个可怜虫就会感受到自己的全部可怜之处,而一个具有丰富思想的人只会感受到自己丰富的思想。一言以蔽之:一个人只会感觉到自己的自身。进一步而言,一个人在大自然的级别中所处的位置越高,那他就越孤独,这是根本的,同时也是必然的。 首先要承认,作为一名孤独患者,读完后充满了优越感,但又感到有些不对劲:人都生活在社会中,到底怎样才算是独处?如果这才是正确的选择,那还有必要社交吗?独处者真的高人一等么? 要解答这些问题,需要先给独处下个定义。我想它并不等同于独居或独来独往,因为这些造成的是生活中的影响,而没有体现精神层面的差异。从书中来看,作者针对的是上流社会的社交方式: 所谓的上流社会承认一个人在其他方面的优势,却唯独不肯承认一个人在精神思想方面的优势;他们甚至抵制这方面的优势。 另外,由于真正的、精神思想的优势不会见容于社交聚会,并且也着实难得一见,为了代替它,人们就采用了一种虚假的、世俗常规的、建立在相当随意的原则之上的东西作为某种优越的表现——它在高级的社交圈子里传统般地传递着,就像暗语一样地可以随时更改。这也就是人们名之为时尚或时髦的东西。 而并不是所有的聚会场合: 具有深度的交谈和充满思想的话语只能属于由思想丰富的人所组成的聚会。 因此,相比在人群中泛泛而谈,独处看起来是个不错的选择,而真正可以深度交流的机会更是求之不得的。 那么独处是在做什么?抛开实际的活动不谈,我想这包括了思想的创造和心灵的解放。前者指的是思考过程,这一点无论在行动中(散步)还是静止状态下(发呆)都可以完成;后者则要求我们的身体停顿下来,让内心深处的感受浮现,这通常难以做到,除非坚持长期的练习,比如冥想。 如果这样便已足够,社会恐怕不会发展成今天的样子。无论是谁,在生命历程中都需要经验资料来丰富自己的认知。即使独处,我们仍然会不断地从外界获取信息,无论是书籍、网站还是播客。 此时已经可以联想到一些好的生活习惯是如何在底层逻辑上成立的: 复盘 冥想 阅读 必须承认,不论聪明才智还是性格习惯,个体都受限于独立本身,所以与贤为伴是必要的。从父母老师,到同事朋友,甚至是学生晚辈,即使对方没有更好的见解,我们也很可能在交流中反窥出自己的问题。简单来说:三人行,必有我师。 从叔本华的角度看,才智卓越之士在人群之中只会受到拖累,这么说无可厚非,只是如他一般的天才实难多见。对大多数人来说,更实用的做法就是组合成为强大的团队,在合作过程中相互促进。从另一个角度上讲,互利共赢优于闭关锁国。 我更赞赏心灵的独处: 因此,完全、真正的内心平和和感觉宁静——这是在这尘世间仅次于健康的至高无上的恩物–也只有在一个人孤身独处的时候才可觅到;而要长期保持这一心境,则只有深居简出才行。 青年人首上的一课,就是要学会承受孤独,因为孤独是幸福、安乐的源泉。 智商自出生便有高低,有时候再努力也难以跨越天赋的鸿沟。内心则不同,每个人都可以通过足够的修炼让自己达到独立、自由与平和的境界。孤独面前,人人平等,越早接受并适应这一现实,我们就越少受到独处时带来的痛苦煎熬。当然,生活也时而赋予我们陪伴,所以独处更应当作为一种能力,而非状态。 至于自身价值,很明显不能单单通过独处能力来判定,就像按照财富或社会地位将人划分为三六九等一样,对号入座可能会让自己心情好些,但并没有道理。饶是如此,如果不能很好地与自己相处,对未来的人生的确会产生不利影响,因为这意味着大部分的时间我们都是无所适从的,尤其到了老年时期。 遗憾的是,在当今时代,虽然人口和信息都在无限爆炸,但我们与独处更加密不可分了。网络的便利提供足不出户的借口,疫情负责夺走人身自由,孤独感依旧,绝望的情绪却已经悄悄完成了全球化。 物质是有限的,但精神可以不受约束。也许叔本华想象不到今天的世界,但他的话确实打动了我: 谁要是不热爱独处,那他也就是不热爱自由,因为只有当一个人独处的时候,他才是自由的。

05-05 · 1 min

Bottle 框架源码阅读

写这篇文章最开心的一点是终于可以用这张截图了: 相比名声在外的 Django/Flask/FastAPI,Bottle 可以说是非常不起眼了,甚至很多人并不知道它的存在。其实在很多方面,这个框架都极其优秀: 速度:截止到 2022-04-13,Bottle 在一众 Python Web 框架的测评中名列第二,要知道这可是十年以上的老前辈了。 易用性:Bottle 早在 Flask 之前就使用了装饰器来定义路由,此外还有全局可用的 Request/Response 对象。 文档:不仅将框架本身的使用讲得很清楚,还总结了很多 Web 场景下的解决方案。 代码质量:虽然为了 Python 2 做了不少兼容,但是代码很精炼,而且 Pythonic。 其他:Bottle 坚持单模块以及无第三方库依赖;仓库仍然在积极维护中。 换作几年前,我会一开始就使用并将 Bottle 研究透彻,而不是让自己淹没在 Django 浩瀚如烟的文档中。下面开始梳理 Bottle 源码的阅读理解。因为代码量不大,所以就直接看最新的版本了:0.11.1 - 5a6c620。 Web 框架的基本元素 参考 The Hitchhiker’s Guide to Python 的说法,一个 Web 框架要满足的基本功能: URL Routing Request and Response Objects Template Engine Development Web Server 从后端的角度来讲更重要的是 1、2、4 三项,其中 1 负责转发请求到对应的视图函数,2 是对 HTTP 协议元素的解析处理,而 4 决定了服务的部署方式和基础性能。 Bottle 在这几方面都做了很好的实现:路由上提供了通配符匹配和装饰器接口;请求和响应对象作为全局对象存在并保证了线程安全;Server 部署除了 Python 自带的 wsgiref 还支持绝大多数的 WSGI Server。...

04-22 · 6 min

Python 中的 TLS 是如何实现的

TLS(Thread Local Storage),或者说 Threadlocal,可以说是一种并发编程的常用模式,既实现了线程之间的资源隔离,又满足了全局变量的使用。 从 TLS 出发,这篇文章研究了 Python 中的 Threadlocal 是如何实现的,比如自带的 threading.local,再比如 Flask 框架中 Local 对象。 Why Threadlocal 先思考一下为什么要用 Threadlocal,这就不得不提到线程安全。Race condition 说到底是因为数据共享和非原子操作,这可以体现在函数的两种基本写法:一种是显式地传参(参数对象也可能变化?这也是为什么最好不要传递可变对象),没有共享自然安全;另一种就是全局对象,这么写既简化了函数签名,代码也比较清晰,缺点就是很容易出现线程不安全的问题,所以经常会和锁配合使用。 而 Threadlocal 就结合了两者的优点,在共享全局变量的同时,保证每个线程操作的都是自己独有的数据对象。 对比一下 Django 和 Flask 两大框架就会发现,前者总是在视图函数中显式声明 request 参数,而后者的只需要 import 一次就可以到处使用。在 Flask 的文档中,Armin Ronacher 也提及了这一点: For example, Flask uses thread-local objects internally so that you don’t have to pass objects around from function to function within a request in order to stay threadsafe. 不过 Flask 并没有直接使用 Python 内置的 threading....

04-11 · 4 min

Python Logging 源码分析

阅读了源码之后,我对 Python Logging 模块的几大疑惑都得到了解答: 为什么 Logger 和 Handler 都有 setLevel 方法? Logging 中会出现 Race condition 吗?(感觉都是很直接的 write 操作) 正式环境中想看日志又没办法动态调整 logLevel,感觉很鸡肋。 用起来好像还不如 print 方便。 会有性能问题吗? 日常使用 首先要了解下 Logging 的用法。 1. 配置 基本上有三种方式,代码、文件和字典。先看下如何用代码设置: import logging # create logger logger = logging.getLogger('simple_example') logger.setLevel(logging.DEBUG) # create console handler and set level to debug ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) # create formatter formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # add formatter to ch ch....

04-09 · 5 min