最近将一个很久没有更新的部署在物理机上的一个老服务迁移到k8s时,发现在gitlab ci跑pytest的过程中出现以下报错:
___________________________ HelloTests.test_redirect ___________________________
self = <tests.test_hello.HelloTests testMethod=test_redirect>
def test_redirect(self):
resp = self.get('/api/hello')
> self.assertEqual(http.HTTPStatus.MOVED_PERMANENTLY.value, resp.status_code)
E AssertionError: 301 != 308
tests/test_hello.py:18: AssertionError
按照python系的习惯,一般而言,我们习惯在接口最后加上一个slash,因此会将所有不带slash的接口301重定向到带slash。但是这一次提示重定向的状态码是308。
经排查,发现是使用的WSGI服务器WerkZeug的版本发生了升级由Werkzeug-0.12.0
升级到Werkzeug-0.16.0
,通过查看Werkzeug-0.12.0
的重定向确实是301,源代码如下:
class RequestRedirect(HTTPException, RoutingException):
"""Raise if the map requests a redirect. This is for example the case if
`strict_slashes` are activated and an url that requires a trailing slash.
The attribute `new_url` contains the absolute destination url.
"""
code = 301
def __init__(self, new_url):
RoutingException.__init__(self, new_url)
self.new_url = new_url
def get_response(self, environ):
return redirect(self.new_url, self.code)
而Werkzeug-0.16.0
的重定向却变成了308,源代码如下:
class RequestRedirect(HTTPException, RoutingException):
"""Raise if the map requests a redirect. This is for example the case if
`strict_slashes` are activated and an url that requires a trailing slash.
The attribute `new_url` contains the absolute destination url.
"""
code = 308
def __init__(self, new_url):
RoutingException.__init__(self, new_url)
self.new_url = new_url
def get_response(self, environ):
return redirect(self.new_url, self.code)
查阅Werkzeug代码的更新历史,在https://github.com/pallets/werkzeug/pull/1342/这个pr中将301改成了308。pr中的conversation的讨论主要是有以下观点:
相关pr:https://github.com/pallets/werkzeug/pull/1402/files
介绍3xx之前,再大致过一遍目前的状态码复习一遍
关于3xx的http状态码,简单做一下介绍:
永久重定向:被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个 URI 之一。如果可能,拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址。除非额外指定,否则这个响应也是可缓存的。
临时重定向:请求的资源现在临时从不同的 URI 响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。
对应当前请求的响应可以在另一个 URI 上被找到,而且客户端应当采用 GET 的方式访问那个资源。这个方法的存在主要是为了允许由脚本激活的POST请求输出重定向到一个新的资源。
如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码。304 响应禁止包含消息体,因此始终以消息头后的第一个空行结尾。
被请求的资源必须通过指定的代理才能被访问。Location 域中将给出指定的代理所在的 URI 信息,接收者需要重复发送一个单独的请求,通过这个代理才能访问相应资源。只有原始服务器才能建立305响应。
这个状态最初是指后续请求应使用指定的代理。但是已经被弃用了
临时重定向且不能修改之后的请求方法,302的扩充
永久重定向且不能修改之后的请求方法,301的扩充