飞翔飞翔
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
  • 学习路径
  • HTTP 基础

    • 认识HTTP协议与应用层定位
    • HTTP消息格式与报文结构
    • HTTP请求方法与幂等性
    • HTTP状态码详解
  • 连接与缓存

    • HTTP持久连接与版本演进
    • HTTP缓存机制
  • 状态与协商

    • Cookie与Session状态管理
    • HTTP重定向与内容协商
    • HTTP条件请求与范围请求
  • 安全与加密

    • HTTP认证机制
    • HTTPS与TLS握手
  • 协议演进

    • HTTP2核心特性
    • HTTP3与QUIC
  • 架构与实战

    • HTTP代理服务器与Web缓存
    • HTTP常见攻击与防御
    • HTTP实践工具与抓包分析

HTTP重定向与内容协商

概念引入

想象你去飞翔公司找航仔(后端),前台告诉你:"航仔搬到18楼了,请去那边找他。"这就是重定向——你问的是A地址,被告知要去B地址。

再想象你去飞翔餐厅点餐,服务员问:"您要粤式口味还是川式口味?要大厅还是包间?"这就是内容协商——双方沟通,确定最合适的方案。

HTTP协议中的重定向和内容协商,就是这两种生活场景的数字化表达。今天,我们以飞翔公司官网多语言版本和架构升级的故事,彻底搞懂它们。


核心内容

重定向状态码

当资源位置发生变化,服务器无法直接响应时,会返回重定向状态码,并在Location头中告知新地址。

常见重定向状态码:

状态码含义方法是否改变SEO影响飞翔公司场景
301永久重定向可能变为GET权重转移给新URL官网从http://升级到https://
302临时重定向可能变为GET权重保留在原URL活动页临时维护,跳转到公告页
307临时重定向严格保持原方法权重保留在原URLPOST提交表单,临时换服务器处理
308永久重定向严格保持原方法权重转移给新URLAPI端点永久迁移,POST还是POST

Location:HTTP响应头,用于重定向时指定资源的新URI。

// 301 永久重定向示例:飞翔官网强制HTTPS
GET http://www.feixiang.net/ HTTP/1.1

HTTP/1.1 301 Moved Permanently
Location: https://www.feixiang.net/

// 浏览器自动跟随Location发起新请求
GET https://www.feixiang.net/ HTTP/1.1

301 vs 302 对SEO的影响

鸣哥(内容运营)很关心这个问题:飞翔博客的旧文章链接被大量外部网站引用,如果换域名,流量会不会丢?

  • 301 永久重定向:搜索引擎会把旧URL的"权重"(PageRank)大部分传递给新URL。适合域名变更、URL结构调整。
  • 302 临时重定向:搜索引擎认为旧URL只是暂时不可用,权重保留在旧URL。适合临时维护、A/B测试。
// 飞翔博客迁移:旧域名 → 新域名,用301传递SEO权重
GET https://blog.feixiang.net/old-article HTTP/1.1

HTTP/1.1 301 Moved Permanently
Location: https://www.feixiang.net/blog/new-article

雁姐(用户运营)提醒:"302用多了会让搜索引擎困惑,该用301的时候别偷懒!"


307和308:方法保持的严谨重定向

302/301有个历史遗留问题:部分浏览器会把POST重定向变成GET请求,导致表单数据丢失。

307/308明确规定:重定向后的请求必须使用与原始请求相同的方法。

// 308 永久重定向:POST保持POST
POST https://api.feixiang.net/v1/login HTTP/1.1
Content-Type: application/json

{"username":"hangzai","password":"***"}

HTTP/1.1 308 Permanent Redirect
Location: https://api.feixiang.net/v2/login

// 浏览器自动用POST请求新地址,Body不变
POST https://api.feixiang.net/v2/login HTTP/1.1
Content-Type: application/json

{"username":"hangzai","password":"***"}

翼王(架构师)在API升级时统一使用308:"v1接口永久下线,全部导向v2,而且用户的POST请求不能变成GET!"


内容协商:找到最合适的资源版本

内容协商(Content Negotiation):客户端和服务器通过HTTP头部交换偏好信息,由服务器选择最合适的资源版本返回。

飞翔公司官网服务全球用户,需要支持中文、英文、日文等多语言。用户访问www.feixiang.net,服务器怎么知道该返回哪个语言版本?

客户端驱动的内容协商:浏览器通过请求头告诉服务器自己的偏好。

请求头说明飞翔公司示例
Accept可接受的MIME类型Accept: text/html, application/json
Accept-Language偏好的语言Accept-Language: zh-CN, en-US;q=0.9
Accept-Encoding支持的压缩格式Accept-Encoding: gzip, deflate, br
Accept-Charset支持的字符集Accept-Charset: utf-8
// 浏览器告诉服务器:我要中文,支持gzip压缩
GET / HTTP/1.1
Host: www.feixiang.net
Accept-Language: zh-CN, zh;q=0.9, en;q=0.8
Accept-Encoding: gzip, deflate
Accept: text/html

// 服务器返回中文页面,并用gzip压缩
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Language: zh-CN
Content-Encoding: gzip

服务端驱动 vs 客户端驱动 vs 透明协商

三种方式对比:

方式决策方优点缺点飞翔应用
客户端驱动服务器根据请求头选择标准、灵活请求头可能过长官网多语言版本
服务端驱动服务器根据IP/UA判断用户无感知可能判断错误早期飞翔官网自动跳转
透明协商中间代理/CDN决策减轻服务器负担实现复杂阿里云CDN智能调度

星宇(产品助理)建议:"飞翔官网用客户端驱动+语言切换按钮兜底。如果Accept-Language识别错了,用户还能手动切换。"


gzip压缩协商实战

凌叔(运维)发现飞翔官网的main.js有500KB,传输很慢。启用gzip压缩后降到150KB,速度提升3倍!

// 请求:浏览器声明支持gzip
GET /static/js/main.js HTTP/1.1
Host: www.feixiang.net
Accept-Encoding: gzip, deflate, br

// 响应:服务器返回gzip压缩内容
HTTP/1.1 200 OK
Content-Type: application/javascript
Content-Encoding: gzip
Content-Length: 153600
// 原始500KB → 压缩后150KB

风速(算法)补充:"Brotli(br)压缩比gzip更高,飞翔官网对支持br的浏览器优先返回br格式,能再省20%流量。"


飞翔公司官网多语言与压缩实战

// 中国用户访问飞翔官网
GET / HTTP/1.1
Host: www.feixiang.net
Accept-Language: zh-CN,zh;q=0.9
Accept-Encoding: br,gzip
Accept: text/html

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Language: zh-CN
Content-Encoding: br
Vary: Accept-Encoding, Accept-Language

// 返回中文首页,Brotli压缩

Vary响应头:告诉缓存服务器,哪些请求头会影响响应内容。缓存必须根据这些头的不同值分别存储。

凌叔在Nginx配置了Vary: Accept-Encoding, Accept-Language,确保CDN不会把中文版缓存错发给美国用户。


重定向与内容协商结合场景

飞翔公司收购了一个海外域名feixiang.com,需要把流量引导到主站:

// 场景1:域名合并,301传递权重
GET https://feixiang.com/ HTTP/1.1

HTTP/1.1 301 Moved Permanently
Location: https://www.feixiang.net/

// 场景2:根据语言协商跳转到对应路径
GET https://www.feixiang.net/ HTTP/1.1
Accept-Language: en-US,en;q=0.9

HTTP/1.1 302 Found
Location: https://www.feixiang.net/en/

// 场景3:API版本升级,308保持POST方法
POST https://api.feixiang.net/v1/order HTTP/1.1

HTTP/1.1 308 Permanent Redirect
Location: https://api.feixiang.net/v2/order

本篇小结

  • 重定向通过3xx状态码和Location头将客户端引导到新地址
  • 301(永久)传递SEO权重,适合域名/路径永久变更;302(临时)保留原URL权重,适合临时跳转
  • 307/308严格保持原始请求方法,解决302/301可能将POST变为GET的问题
  • 内容协商让客户端和服务器通过Accept-*请求头和Content-*响应头协商最合适的资源版本
  • Accept-Language决定语言版本,Accept-Encoding决定压缩格式,Accept决定MIME类型
  • 飞翔官网通过Vary: Accept-Encoding, Accept-Language确保CDN正确缓存多语言和多压缩版本
  • 服务端驱动、客户端驱动、透明协商三种方式各有适用场景

动手实践

温馨提示: 以下实践示例中涉及的域名(如 www.feixiang.net)、公司场景和接口均为虚构数据,仅用于演示协议原理,实际执行时可能不会产生文档中描述的效果。建议将命令中的域名替换为你自己可访问的真实地址进行练习。

实践:用curl观察重定向

# 跟随重定向,查看完整跳转链
curl -L -I http://www.feixiang.net

# 不跟随重定向,只看第一个响应
curl -I http://www.feixiang.net

# 观察返回的是301还是302,以及Location头

实践:测试内容协商头部

# 请求英文版本
curl -H "Accept-Language: en-US" -I https://www.feixiang.net

# 请求中文版本
curl -H "Accept-Language: zh-CN" -I https://www.feixiang.net

# 观察Content-Language和可能的重定向Location

实践:测试gzip压缩协商

# 不带Accept-Encoding
curl -I https://www.feixiang.net/static/js/main.js

# 带gzip
curl -H "Accept-Encoding: gzip" -I https://www.feixiang.net/static/js/main.js

# 观察Content-Encoding和Content-Length的变化

实践:思考题

靓晴(UI设计)把飞翔官网的图片资源从/images/迁移到了/static/images/。她使用了302临时重定向。三个月后,搜索引擎收录的还是旧路径,新路径没有权重。请分析原因,并给出正确的重定向方案。

查看思考题答案

上一页
Cookie与Session状态管理
下一页
HTTP条件请求与范围请求