(十七)重定向、Cookie 与会话
1. 响应位置与最终地址
# 项目文件:demos/http_redirect.py
# urllib 自动跟随本例的 GET 重定向,geturl 显示最终取得响应的位置。
import json
from urllib.parse import urlsplit
from urllib.request import urlopen
from labserver import running_server
if __name__ == "__main__":
with running_server() as server:
with urlopen(server.base_url + "/api/redirect", timeout=1) as response:
print(
response.status,
urlsplit(response.geturl()).path,
json.load(response)["title"],
)输出 200 /api/books/1 Python。最初的 302 响应带 Location,客户端随后又发出 GET,最后得到的是另一条响应。分析下载结果时,把最初 URL、最终 URL 和中间跳转区分开。
2. 后续请求带回服务器发出的标识
# 项目文件:demos/http_cookie_session.py
# CookieJar 保存响应发来的 Cookie;同一个 opener 在后续请求中按路径等规则带回。
from http.cookiejar import CookieJar
import json
from urllib.error import HTTPError
from urllib.request import build_opener, HTTPCookieProcessor, Request
from labserver import running_server
if __name__ == "__main__":
with running_server() as server:
cookies = CookieJar()
opener = build_opener(HTTPCookieProcessor(cookies))
try:
with opener.open(server.base_url + "/api/me", timeout=1) as response:
print(json.load(response))
except HTTPError as error:
with error:
print("登录前", error.code)
data = json.dumps({"username": "learner"}).encode("utf-8")
request = Request(
server.base_url + "/api/login",
data=data,
method="POST",
headers={"Content-Type": "application/json"},
)
with opener.open(request, timeout=1) as response:
print("收到 Cookie", response.headers.get("Set-Cookie") is not None)
with opener.open(server.base_url + "/api/me", timeout=1) as response:
print("登录后", json.load(response)["username"])输出 登录前 401、收到 Cookie True、登录后 learner。本例登录接口建立一条演示会话,把随机的 session_id 发给客户端;后续 Cookie 带回这个标识,服务器再从会话表查出对应用户。
Cookie 是客户端保存与发送的一种机制,会话是多次请求之间延续身份或状态的安排。这里的用户名没有通过每次请求直接当作“已经登录”的证明。浏览器还会按 HttpOnly、SameSite 等属性处理 Cookie,HTTP 客户端的保存接口不等于浏览器的全部行为。CookieJar、Cookie 与浏览器