原来我误会了 changeOrigin 那么多年

简介: 前端开发中经常要配置接口代理服务,用来解决开发阶段的跨域问题。有一个常用的 changeOrigin 配置项,它究竟配置了个啥?本文做了一个小小的探究。

changeOrigin 到底改了啥

前端开发中经常要配置接口代理服务,用来解决开发阶段的跨域问题。

无论是 webpack-dev-server 中的 proxy,还是 vite 中的 proxy,内部都是使用了同一个库 node-http-proxy

一个代理的例子

在配置 proxy 时,通常是这样的:

// vite.config.js

import { defineConfig } from 'vite'

export default defineConfig({
  server: {
    // 配置代理服务
    proxy: {
      // 以 /api 开头的请求,全部转发到 target 设置的地址
      '/api': {
        target: 'https://demo.com',
        changeOrigin: true
      }
    }
  }
})

设置 target 目标的同时,有时还会配置一个 changeOrigin 属性。看名字,它好像用来改变 origin 请求头的值,将其改为 target 的值。

真的如此吗?

先看文档

  • changeOrigin: true/false, Default: false - changes the origin of the host header to the target URL

也就是说,changeOrigin 的默认值为 false,用来将 host 请求头修改为 target 的 URL

🌰 通过一个例子演示

准备两个服务:

  • 后端:使用 koa 创建的接口服务
  • 前端:使用 @vue/cli 创建的 vue 项目

示例代码已上传到 Github 仓库

Koa

在本地 3000 端口启动一个接口服务:

// server.js

const Koa = require("koa")
const body = require("koa-body")
const Router = require("@koa/router")

const app = new Koa()
const router = new Router()

app.use(body())

// post请求,携带 origin 头
router.post('/api/list', async ctx => {
    console.log(ctx.headers)
    ctx.body = {
        code: 0,
        msg: 'ok'
    }
})

app.use(router.routes()).use(router.allowedMethods());

app.listen(3000, () => {
    console.log(`服务器已启动: 3000`);
})

Vue

前端使用 axios 访问接口/api/list

// main.js

import axios from 'axios'

axios.post('/api/list').then(res => {
  console.log(res)
})

设置 changeOrigin 为 false

devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: false
      }
    }
}

此时的 originhost 头分别是:

Host: localhost:8080

Origin: http://localhost:8080

image-20221007233456329

可以通过代理解决跨域问题:

image-20221007233601051

服务端接收到的请求头信息是:

origin: 'http://localhost:8080'

host: 'localhost:8080'

image-20221007233800986

设置 changeOrigin 为 true

devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true
      }
    }
}

浏览器端查看请求头信息:

Host: localhost:8080

Origin: http://localhost:8080

image-20221007233901503

服务端接收到的请求头信息:

origin: 'http://localhost:8080'

host: 'localhost:3000'

image-20221007233943164

发现

这一次,host 头的值变为 localhost:3000 ,也就是 target 设置的接口服务器的地址了。

也就是,changeOrigin 这个配置项,修改的不是 origin 头,而是 host 头。

那么,修改 host 有什么特别的作用吗?

答案是没有。起码对于解决跨域问题没有。

换个角度看, changeOrigin 的默认值是 false,也就是不改,说明不改的适用场景更广泛一些。

那如果改了 host ,能发挥出什么作用吗?

那就先看看 host 这个头本身的作用是什么。

host header

Host 请求头表示请求资源的网络主机和端口号, 比如我们访问上面的 localhost:8080 这个页面,那么它的 host 就是:
image-20221008161006384

该请求头在 HTTP/1.1 版本中推出,是为了解决虚拟主机的问题。在 HTTP/1.0 中,一个域名绑定一个 IP 地址,一台服务器对应一个 IP,因此一台服务器只能运行一个站点。随着虚拟主机技术的发展,有时候需要在一台服务器上运行多个虚拟主机,此时服务器就可以通过 host 头来做不同的处理。

在运行 HTTP/1.1 协议的网站中,请求头中要求携带 host 头。现在很多网站都已经支持了 HTTP/2 版本协议,它就不要求携带 host 请求了。

看下百度:

image-20221008004414723

看下主域名:

image-20221008004535987

掘金已经全部采用 HTTP/2 了:

image-20221008004745061

已经没有 host 请求头了:

image-20221008005019850

小结

配置 changeOrigin 修改 host,基本上没什么用。

🎀 关于 changeOrigin 的结论

通过上面的探究,基本可以得出以下结论:

  1. changeOrigin 配置项用来修改 host header,而非 origin header
  2. Host header 用来处理虚拟主机的问题,和跨域无关
  3. 一般情况下,设置代理时可以忽略这个配置项,保持默认即可
  4. 特殊情况下,很可能后端服务就用 host 做校验了,此时根据实际情况去设置

另一个问题:为什么浏览器网络面板观察不到 host 的修改?

因为浏览器运行的 js 代码,发出了一个网络请求,这个请求的 host 就是 localhost:8080

发出去之后,被本地的代理服务拦截到了,在这个地方将 host 修改了,再发往后端服务器。

也就是,host 修改时,浏览器已经将请求发出去了,所以观察不到。

🏁 最后

本文简单探讨了 changeOrigin 这个常见的配置项。用了这么多年,才发现一直“误会”了它。看来正应了那句老话:

纸上得来终觉浅,

绝知此事要躬行。

目录
相关文章
|
6月前
|
机器学习/深度学习 网络架构 开发者
技术领导力之路 - 正反馈
本文主要探讨了技术领导给予员工正负反馈的重要性,以及如何给正负反馈,如何欣赏他人,作者结合自身实际案例做出了总结和思考。
|
消息中间件 运维 Kubernetes
【架构师之路 六】两年期计划
【架构师之路 六】两年期计划
137 0
|
人工智能 运维 安全
职等你来 | 2023春招,牵手阿里云基础设施,期待同行
快~加入阿里云基础设施,一起打开有意思的未来!
职等你来 | 2023春招,牵手阿里云基础设施,期待同行
|
设计模式 运维 架构师
学习笔记 | 技术创业之路: 从架构师走向创业者
学习笔记 | 技术创业之路: 从架构师走向创业者
347 0
|
存储 物联网 编译器
5位资深技术专家畅聊:RISC-V 的发展现状和未来方向
龙蜥社区 RISC-V SIG 会秉持 RISC-V 开源开放的理念,继续联合各大合作伙伴推进 RISC-V 走向繁荣。
5位资深技术专家畅聊:RISC-V 的发展现状和未来方向
|
设计模式 缓存 架构师
架构师技术领导力成长之路(1)
架构师技术领导力成长之路(1)
217 0
架构师技术领导力成长之路(1)
|
架构师 小程序
架构师技术领导力成长之路(3)
架构师技术领导力成长之路(3)
181 0
架构师技术领导力成长之路(3)
|
监控 Dubbo 架构师
架构师技术领导力成长之路(2)
架构师技术领导力成长之路(2)
149 0
架构师技术领导力成长之路(2)
|
移动开发 人工智能 前端开发
素人程序员:如何在技术浪潮更迭中保持较高成长速度?
  技术更迭是有加速度的,一个又一个风口,一波又一波浪潮,昨天火了人工智能,今天已经大谈区块链。普通程序员们在这个进程里,应该怎样找准自己的位置,获得持续的个人成长呢?   技术更迭是有加速度的   从 2010 年开始,被定义为移动互联网的元年,移动开发也是从这一年开始逐渐开始火爆的。笔者也是从毕业之后加入这个浪潮的。据说移动开发火爆之时,理发师通过几个月培训以后也可以拿到月薪 1,2W 的薪水,可见那个时候对移动人才的饥渴程度。但是到了 2014 年底开始,移动开发的入职要求回归理性,要求逐渐提高,到现在基本大公司社招也不再招高级以下的移动开发了。
194 0
|
SQL 缓存 架构师
五年成为阿里技术专家,架构师需要懂哪些技术?
  很早很早之前,我对于架构的概念一点都不理解,依稀记得,架构( architecture)这个词,来自于建筑领域。   这对于我这个没写过几行代码的人来说,瞬间就有了一种“不明觉厉”的崇拜感。   架构,感觉好厉害的样子,从名称上来说,好像是设计根骨,设计底层,设计最核心的东西的人。   架构师,一定很NB,我什么时候能成为架构师呢?   后来懂了一点点代码,去写增删改查,更是体会不出来架构的概念,不就是Sql语句吗?明明DBA更厉害啊,做各种的慢Sql优化,所有的Sql都要让DBA审核,DBA对于Mysql,或者是Oracle的各种性能调忧很厉害,而熟悉业务的开发人员又常常能写出几
241 0