相同url根据nginx判断终端返回不同页面

前言

因业务需要,要根据nginx判断终端类型并返回响应的页面,且使用同一套url,在配置nginx的过程中,踩了一些坑方才配置完成,最后将本次配置的过程和处理方案记录下来

需求背景

  1. 项目采用laravel+react的前后端分离结构,且为同一个项目,其中api目录为接口目录,由laravel处理,其他目录交由react处理
  2. 前端分为移动端和pc端,因业务逻辑类似,故而没有分为两个项目,而是生成了两个页面pc.html和mobile.html,且在同一目录下
  3. 移动端和pc端使用同一个地址,根据服务器端判断终端类型返回不同的页面

确定解决方案

服务器端可以写一个php入口文件,在判断终端类型从而加载不同的html文件,这是最简单的方案
但原本是静态资源文件,却多绕了一层php处理,影响性能
所以只得通过nginx判断终端,并返回相应的页面
于是我这个nginx半吊子只得踏上了采坑之路

说明

  • 项目根目录为/www/public,下面有以下文件(夹)
    • statics:静态资源目录
    • index.php:laravel的入口文件
    • pc.html:pc端的入口文件
    • mobile.html:移动端的入口文件
  • 以下的配置文件只涉及路径及不同终端的处理,对于域名等其他无关配置均没有显示

内心独白:这个应该挺简单的吧,开搞开搞

正常的laravel+react配置

采坑第一次 —— 配置一

测试结果:

  • 接口:没问题(淡定)
  • pc端:没问题(微笑)
  • 移动端:403(纳尼??)

难道,set在if里面没有生效,那干脆直接把try_files写在if里面吧

采坑第二次 —— 配置二

重启Nginx,才发现if中不能写try_files

既然不能写try_files,那只能研究下配置一为啥不生效了
经过一番探索发现,nginx的if还是比较坑的,里面能写的东西有限,如果写了别的,可能导致不可预期的行为

采坑第三次

既然if里面只能写rewrite和return,那要不就用rewrite?
emmm…不行,用rewrite地址就变了

采坑第四次

如果要保证地址不变,try_files不行,那要不用反向代理吧,这个地址不变,而且肯定能解决问题
可是这个想法刚刚冒出来就被否了,为了保证效率,我连最简单的php中转都没用,咋能用同样损耗性能的反向代理呢

迈向曙光第一步 —— 配置四

又经过一番探索,找到了一个类似需求的可行配置,如下:

上述的配置适用于两个目录,而我的需求是两个文件,依样画葫芦,画一画吧

测试后发现都木有问题
只不过这带来一个新问题,不是用rewrite地址就变了嘛?这个问题稍后再议
此时的配置已经满足了需求,只是还有些小瑕疵:
当使用pc访问mobile.html,出来的还是手机页面,但手机访问pc.html则没有问题,因为手机无论访问的地址是什么,都会转发到/mobile.html
那pc也可以使用这种方式啊,就变成了如下的配置

雏形 —— 配置五

到了这一步基本完美了,但是,如果rewrite可以使url不变,那还要fuckurl干嘛,于是我进行了最后的尝试

最终方案 —— 配置六

看到这个版本,我真是欲哭无泪,仰天长叹一声fuck

知识点

通过这次,又对nginx的配置熟悉了一些,本次配置用到了以下知识,将其记录一下

root和alias

虚拟服务器可拥有一个宿主目录和任意数量的其它目录,这些其它目录通常被称为虚拟目录。

nginx没有虚拟目录的说法,因为nginx本来就根据目录设计并工作的,如果要把nginx强硬插上一个虚拟目录的说法,那只有alias标签比较像

还有一个和alias相似的标签root,它们的区别如下:

  • root:指定根目录,该根目录下要含有locatoin指定名称的同名目录
  • alias:指定一个真实存在的目录,与locatoin指定名称不一定一致, 作用可以理解为linux的ln,给location链接到一个目录

alias的注意事项

  1. 使用alias时,目录名后面一定要加”/“
  2. 使用alias标签的目录块中不能使用rewritebreak
  3. alias在使用正则匹配时,必须捕捉要匹配的内容并在指定的内容处使用
  4. alias只能位于location块中

例子

一般情况下,在server中配置root,在location中配置alias是一个好习惯

rewrite

本次闹出的乌龙坑,全因为对rewrite认识不足,一直认为rewrite会改变url地址,谁知道。。。

用法: rewrite [正则] [替换] 标志位

rewrite是实现URL重写的关键指令,根据regex(正则表达式)部分内容,重定向到replacement,结尾是flag标记

flag标记分为下面4仲:

  1. last :本条规则匹配完成后,继续向下匹配新的location URI规则
  2. break :本条规则匹配完成即终止,不再匹配后面的任何规则
  3. redirect :返回302临时重定向,浏览器地址会显示跳转后的URL地址
  4. permanent :返回301永久重定向,浏览器地址栏会显示跳转后的URL地址

通过上面的flag标记来看,只有设置了redirect或permanent地址才会改变

last和break的使用

区别上面已经说明,在本文中,有几个配置用到了这两个关键词

在配置五中,只能使用last,而不能使用break,是因为如果使用了break,则终止了后面的任何规则匹配,那么fuckurl就无法解析了

在配置六中,只能使用break,是因为如果使用last,会造成死循环,报500错误,所以必须使用break将其终止

总结

  1. 只能相信手册,如果是从非官方给出的解释,亲自证实后才能相信
  2. 珍爱生命,远离百度

 

转自:https://www.caijw.com/p/9e6t34l2.html

发表回复