整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Nginx 实现 Rewrite 跳转

Nginx 实现 Rewrite 跳转

章原创于公众号:程序猿周先森。本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号。

上一篇文章对Nginx的Location配置进行了讲解,本篇主要对于Nginx中的Rewrite跳转进行讲解。因为目前很多工作前端开发都会选择使用Nginx作为反向代理服务器,但是平时业务需要难免碰到重写URL,Nginx的Rewrite跳转有什么使用场景呢?

  • 公司更换域名需要访问旧域名时跳转到新域名
  • 请求静态文件跳转到CDN
  • 根据用户设备不同跳转到不同站点(pc端,移动端)

不得不说的是Apache服务器规则库很强大,做跳转也很简单,但是Nginx使用Rewrite实现跳转效率更高,所以这也是我们需要学习Nginx的Rewrite模块的目的所在。Rewrite是Nginx的静态重写模块,跳转的使用场景有以下几种情形:

  • 可以改变用户访问的URL
  • 可以将动态URL伪装成静态URL提供服务
  • 可以访问旧域名时跳转到新域名
  • 可以根据变量,目录,客户端信息等跳转不同的URL

Rewrite如何实现跳转?

Nginx利用ngxhttprewrite_module模块解析和处理rewrite请求。Rewrite用于实现URL重写,其实有点类似于重定向功能,可以将用户的请求重写至别的目录,在一定程度上提高了网站安全性。Rewrite支持if条件判断,但不支持else判断。而且Rewrite需要PCRE支持,一次重定向最多可以跳转10次,超过10次将返回500错误。Rewrite模块包含set命令,可以创建变量用来记录条件标识或者传递变量到其他的Location中。Rewrite实际上就是使用Nginx已有的全局变量或者通过set命令设置的变量结合正则表达式实现URL重写。

Rewrite使用场景

在Nginx中使用Rewrite实现跳转有以下三种场景:

  • 直接用Rewrite进行匹配跳转
  • 使用if匹配全局变量进行跳转
  • 使用location匹配再进行跳转

所以说rewrite语句只允许放在server{ },if{ },location{ }中。接下来我们先看看if指令。

if指令

if指令用于条件匹配判断,根据判断结果选择不同的Nginx配置,在server或location中配置。Nginx中的if指令只支持单重判断,不支持多重判断。我们简单看个例子:

location /test{
 index index.html;

 if ( $scheme=http ){
 rewrite / https://www.niyueling.cn permanent;
 }
 
 if ($scheme=https ){
 echo "if ---> $scheme";
 }
}

location上篇文章讲过了,这里不再细讲,接下来我们看下rewrite语法.

rewrite语法

rewrite regex replacement [flag]

rewrite将用户请求的URL基于正则表达式regex进行检查,匹配到时将其替换为正则表达式对应的新的URL。若在同一级配置模块中存在多个rewrite规则,则会自顶向下检查。replacement则为跳转后的内容。[flag]作为标识符用于控制循环机制,如果替换后的URL是以http或者https开头,则会直接301永久重定向。

flag参数介绍

rewrite语句有四种flag状态:redirect、permanent、break、last。前两种属于客户浏览器重新发起对新地址的请求,后两种是在WEB服务器内部实现跳转。

  • redirect #临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端,有客户端重新发起请求,使用相对路径,http://或https://开头,状态码:302
  • permanent #永久重定向,以永久重定向的方式直接返回重写后生成的新URL给客户端,由客户端重新发起新的请求,状态码:301
  • last #重写完成后停止对当前location中后续的其他重写操作,而后对新的URL启动新一轮重写检查,不建议在location中使用
  • break #重写完成后停止对当前URL在当前location中后续的其他重写操作,而后直接跳转至重写规则匹配块之后的其他配置;结束循环,建议在location中使用


rewrite语法讲完了我们可以一起来看看如何实现几种方式跳转:

(1) 在location中将旧域名永久重定向到新域名

location / {

root /data/html;index index.html;rewrite / http://www.niyueling.cn permanent;

}

这里有必要提下临时重定向与永久重定向的区别:

临时重定向不会缓存新域名的解析记录,但是永久重定向会缓存新域名的解析记录。

(2) http自动跳转https

有时候公司项目需要,会要求整个网站皆使用https,这时候为了用户体验,我们需要在用户访问http站点的时候自动跳转到https站点中。

location / {

root /opt/blog;index index.html;
if ( $scheme=http ){rewrite / https://www.niyueling.cn permanent;}

}

上面配置其实就是如果用户请求协议为http的时候使用rewrite跳转到对应的https站点。但是if语句不能去掉,否则就会陷入死循环。

(3) 如果用户请求URL不存在跳转首页

location / {
 root /opt/blog;
 index index.html;

 if ( !-f $request_filename ){
 rewrite (.*) http://www.niyueling.cn;
 }
}

(4) 实现防盗链

防盗链实际上是基于前端携带的referer实现,referer可以记录用户从哪个界面跳转而来的标志信息。Nginx可以通过ungxhttpreferrer_module模块来检查请求的referer信息是否有效实现防盗链功能

location ^~ /test {
 root /opt/blog;
 index index.html;

 valid_referers none blocked server_names *.niyueling.cn www.niyueling.*
 api.online.test/v1/hostlist ~\.google\. ~\.baidu\.; #定义有效的referer
 if ($invalid_referer) { #假如是使用其他的无效的referer访问:
 return 403; #返回状态码403
 }
}

如果喜欢我的文章,欢迎关注我的个人公众号

很多其它语言一样,Go也支持goto跳转语句。 在一个goto跳转语句中,goto关键字后必须跟随一个表明跳转到何处的跳转标签。 我们使用LabelName:这样的形式来声明一个名为LabelName的跳转标签,其中LabelName必须为一个标识符。 一个不为空标识符的跳转标签声明后必须被使用至少一次。

一条跳转标签声明之后必须立即跟随一条语句。 如果此声明的跳转标签使用在一条goto语句中,则当此条goto语句被执行的时候,执行将跳转到此跳转标签声明后跟随的语句。

一个跳转标签必须声明在一个函数体内,此跳转标签的使用可以在此跳转标签的声明之后或者之前,但是此跳转标签的使用不能出现在此跳转标签声明所处的最内层代码块之外。

下面这个例子使用跳转标签声明和goto跳转语句来实现了一个循环:

package main

import "fmt"

func main() {
    i :=0

Next: // 跳转标签声明
    fmt.Println(i)
    i++
    if i < 5 {
        goto Next // 跳转
    }
}

上面刚提到了一个跳转标签的使用不能出现在此跳转标签声明所处的最内层代码块之外,所以下面的代码片段中的跳转标签使用都是不合法的。

package main

func main() {
goto Label1 // error
    {
        Label1:
        goto Label2 // error
    }
    {
        Label2:
    }
}

另外要注意的一点是,如果一个跳转标签声明在某个变量的作用域内,则此跳转标签的使用不能出现在此变量的声明之前。 关于变量的作用域,请阅读后面的文章代码块和作用域

下面这个程序编译不通过:

package main

import "fmt"

func main() {
    i :=0
Next:
    if i >=5 {
        // error: goto Exit jumps over declaration of k
        goto Exit
    }

    k :=i + i
    fmt.Println(k)
    i++
    goto Next
Exit: // 此标签声明在k的作用域内,但
      // 它的使用在k的作用域之外。
}

刚提到的这条规则可能会在今后放宽。 目前,有两种途径可以对上面的程序略加修改以使之编译通过。

第一种途径是缩小变量k的作用域:

func main() {
    i :=0
Next:
    if i >=5 {
        goto Exit
    }
    // 创建一个显式代码块以缩小k的作用域。
    {
        k :=i + i
        fmt.Println(k)
    }
    i++
    goto Next
Exit:
}

第二种途径是放大变量k的作用域:

func main() {
    var k int // 将变量k的声明移到此处。
    i :=0
Next:
    if i >=5 {
        goto Exit
    }

    k=i + i
    fmt.Println(k)
    i++
    goto Next
Exit:
}

包含跳转标签的break和continue语句

一个goto语句必须包含一个跳转标签名。 一个break或者continue语句也可以包含一个跳转标签名,但此跳转标签名是可选的。 包含跳转标签名的break语句一般用于跳出外层的嵌套可跳出流程控制代码块。 包含跳转标签名的continue语句一般用于提前结束外层的嵌套循环流程控制代码块的当前循环步。

如果一条break语句中包含一个跳转标签名,则此跳转标签必须刚好声明在一个包含此break语句的可跳出流程控制代码块之前。 我们可以把此跳转标签名看作是其后紧跟随的可跳出流程控制代码块的名称。 此break语句将立即结束此可跳出流程控制代码块的执行。

如果一条continue语句中包含一个跳转标签名,则此跳转标签必须刚好声明在一个包含此continue语句的循环流程控制代码块之前。 我们可以把此跳转标签名看作是其后紧跟随的循环流程控制代码块的名称。 此continue语句将提前结束此循环流程控制代码块的当前步的执行。

下面是一个使用了包含跳转标签名的break和continue语句的例子。

package main

import "fmt"

func FindSmallestPrimeLargerThan(n int) int {
Outer:
    for n++; ; n++{
        for i :=2; ; i++ {
            switch {
            case i * i > n:
                break Outer
            case n % i==0:
                continue Outer
            }
        }
    }
    return n
}

func main() {
    for i :=90; i < 100; i++ {
        n :=FindSmallestPrimeLargerThan(i)
        fmt.Print("最小的比", i, "大的素数为", n)
        fmt.Println()
    }
}

本文来自博客园,作者:孙龙-程序员,转载请注明原文链接:https://www.cnblogs.com/sunlong88/p/17652663.html

读本文约需要10分钟,您可以先关注我们,避免下次无法找到。

JavaScript基础教程(上)成哥为大家介绍了JavaScript的基础知识、数据类型及常用方法,本编文章主要介绍JavaScript的的控制语句、函数编程及异常处理等相关知识,下面成哥就为大家一一介绍这些内容。

01 JavaScript控制结构

(1)if-else语句

如下所示,使用if-else语句根据不同的三个年龄条件在页面上打印不同的输出

1. <!DOCTYPE html>  
2. <html lang="en">  
3. <head>  
4.     <meta charset="UTF-8">  
5.     <title>JavaScript基础教程</title>  
6. </head>  
7. <body>  
8.     <script type="text/javascript">  
9.         // 通过if-else语句判断年龄应该去什么教育  
10.         let age = 10;  
11.         if (age > 3 && age < 6) {  
12.             document.write("Age : " + age + "<b>应该上学前教育</b>");  
13.         } else if (age >= 6 && age < 18) {  
14.             document.write("Age : " + age + "<b>应该上义务教育</b>");  
15.         } else {  
16.             document.write("Age : " + age + "<b>应该上高等教育</b>");  
17.         }  
18.     </script>  
19. </body>  
20. </html>  

(2)Switch-case-default语句

1. <!DOCTYPE html>  
2. <html lang="en">  
3. <head>  
4.     <meta charset="UTF-8">  
5.     <title>JavaScript基础教程</title>  
6. </head>  
7. <body>  
8.     <script type="text/javascript">  
9.         // 通过switch-case语句控制输出,这边注意每个case后面要接break不然程序不会退出会自动执行下面语句  
10.         let age = 35;  
11.         switch(age){  
12.             case 10:  
13.                 document.write('未成年');  
14.                 break;  
15.             case 18:  
16.                 document.write('成年');  
17.                 break;  
18.             case 35:  
19.                 document.write('淘汰边缘的程序员');  
20.                 break;  
21.             default:  
22.                 document.write('不知道什么人');  
23.         }  
24.     </script>  
25. </body>  
26. </html>  

(3)For循环语句

1. <!DOCTYPE html>  
2. <html lang="en">  
3. <head>  
4.     <meta charset="UTF-8">  
5.     <title>JavaScript基础教程</title>  
6. </head>  
7. <body>  
8. <script type="text/javascript">  
9.     // 通过for循环实现数字倒序输出  
10.     for (var i = 10; i >= 0; i--) {  
11.         document.write(i + " ");  
12.     }  
13. </script>  
14. </body>  
15. </html>  

(4)While循环语句

1. <!DOCTYPE html>  
2. <html lang="en">  
3. <head>  
4.     <meta charset="UTF-8">  
5.     <title>JavaScript基础教程</title>  
6. </head>  
7. <body>  
8. <script type="text/javascript">  
9.     // 通过while循环实现数字正序输出  
10.     x = 0;  
11.     while (x < 10) {  
12.         document.write(x + " ");  
13.         x++;  
14.     }  
15. </script>  
16. </body>  
17. </html>  

(5)do-while循环语句

do-while与while的区别是,do-while是先执行循环体再判断循环条件,而while是先判断循环条件在执行循环体。

1. <!DOCTYPE html>  
2. <html lang="en">  
3. <head>  
4.     <meta charset="UTF-8">  
5.     <title>JavaScript基础教程</title>  
6. </head>  
7. <body>  
8. <script type="text/javascript">  
9.     // 通过do while循环实现数字正序输出  
10.     x = 0;  
11.     do {  
12.         document.write(x + " ");  
13.         x++;  
14.     } while (x < 10);  
15. </script>  
16. </body>  
17. </html>  

(6)for-in循环语句

for-in一般用来遍历数组或者对象,遍历数组时遍历的是数组的索引,遍历对象时是对象的key,下面我们来看看for-in语句的示例

1. <!DOCTYPE html>  
2. <html lang="en">  
3. <head>  
4.     <meta charset="UTF-8">  
5.     <title>JavaScript基础教程</title>  
6. </head>  
7. <body>  
8. <script type="text/javascript">  
9.     // 遍历数组  
10.     let arr = [10, 12, 31];  
11.     for (let a in arr){  
12.         document.write(arr[a] + " ");  
13.     }  
14.     document.write("<br>");  
15.   
16.     // 遍历对象  
17.     let obj = {a: 1, b: 2, c: 3};  
18.     for (let key in obj){  
19.         document.write("key为: ", key, "值为: ", obj[key], "; ");  
20.     }  
21. </script>  
22. </body>  
23. </html>  

(7)Continue与Break语句

continue与break一般都是用在循环语句中,其中continue表示执行到当前不往下再执行而是从下一个循环继续执行,而break是表示退出当前循环,后面的循环语句都不执行了,具体示例如下所示:

1. <!DOCTYPE html>  
2. <html lang="en">  
3. <head>  
4.     <meta charset="UTF-8">  
5.     <title>JavaScript基础教程</title>  
6. </head>  
7. <body>  
8. <script type="text/javascript">  
9.     // continue示例这边输出除了3都打印输出  
10.     for (let i=5; i>=0; i--){  
11.         if (i===3){  
12.             continue;  
13.         }  
14.         document.write(i + " ");  
15.         }  
16.         document.write("<br>");  
17.   
18.     // break示例,这边当循环到3时退出,所以3之前数字(包含3)都不打印  
19.     for (let i=5; i>=0; i--){  
20.         if (i===3){  
21.             break;  
22.         }  
23.         document.write(i + " ");  
24.     }  
25. </script>  
26. </body>  
27. </html>  

02 JavaScript异常处理

在实际开发过程中程序经常会遇见各种异常,为了解决该问题JavaScript使用try-catch来捕获异常,其语法结构如下:

1. try {  
2.   // 这里写可能出现异常的代码  
3. } catch (err) {  
4.   // 在这里写,出现异常后的处理代码  
5. } finally {  
6.   //无论try中代码是否有异常抛出(甚至是try代码块中有return语句),finally代码块中始终会被执行。  
7. }  

try-catch语句有如下几点要注意:

1)语句 try 和 catch 是成对出现的,finally可以写也可以不写。

2)如果在 try 中出现了错误,try 里面出现错误的语句后面的代码都不再执行,直接跳转到 catch 中,catch 处理错误信息,finally的内容则不论有没有异常都会执行。

3)如果 try 中没有出现错误,则不会执行 catch 中的代码,执行完 try 中的代码后直接执行后面的代码。

03 JavaScript函数

JavaScript中的函数可以简要分为以下三类:

1)普通函数

普通函数的语句格式如下

1. function common(age){  
2.   return age + 10;  
3. }  

2)匿名函数

匿名函数也就是没有名称的函数一般当参数使用,如在定时器中调用,具体语法格式如下

1. function (args){  
2.     return args + 1;  
3. }  
4. // 一般用于当做参数使用,例如:设置定时器 setInterval(function(){},5000)  

3)自执行函数

自执行函数是当HTML页面加载完自动执行的函数,具体示例如下

1. <!DOCTYPE html>  
2. <html lang="en">  
3. <head>  
4.     <meta charset="UTF-8">  
5.     <title>JavaScript基础教程</title>  
6. </head>  
7. <body>  
8. <script type="text/javascript">  
9.     // 自执行函数在HTML加载完自动把'成哥的javascript教程'作为变量传给函数然后执行  
10.     (function(arg){  
11.         document.write(arg);  
12.     })('成哥的javascript教程')  
13. </script>  
14. </body>  
15. </html>  

04 JavaScript事件处理

JavaScript主要就是用于HTML页面的事件处理。如鼠标点击或者点击键盘某个按键触发函数调用执行,如下所示alert一般用于在浏览器页面弹出一个小窗口并插入内容。

1. <!DOCTYPE html>  
2. <html lang="en">  
3. <head>  
4.     <meta charset="UTF-8">  
5.     <title>JavaScript基础教程</title>  
6. </head>  
7. <body>  
8.   
9.    <button onclick="alertMessage('alert使用展示')">点击我</button>  
10.   
11. <script type="text/javascript">  
12.    function alertMessage(message){  
13.      alert(message)  
14.    }  
15. </script>  
16. </body>  
17. </html>  

JavaScript的函数事件处理还可以绑定其它常用的触发事件具体如下所示:

1. <!DOCTYPE html>  
2. <html lang="en">  
3. <head>  
4.     <meta charset="UTF-8">  
5.     <title>JavaScript基础教程</title>  
6. </head>  
7. <body>  
8.     // onmouseover鼠标在这标签上时设置标签为红色  
9.     // onmouseleave鼠标离开这标签时设置标签为蓝色  
10.     // onmouseup鼠标没有点击时标签文字设置为'没有点击'  
11.     // onmousedown鼠标点击时设置标签为'被点击'  
12.     <a href="JavaScript:void(0)"  
13.        onmouseover="this.style.color='red'"  
14.        onmouseleave="this.style.color='blue'"  
15.        onmouseup="this.text='没有点击'"  
16.        onmousedown="this.text='被点击'">没有点击</a><br>  
17. </body>  
18. </html>  

JavaScript还有如下常用的事件,我们这边就不一一示例了

1. onLoad :当页面加载完毕后触发,常用于body元素

2. onUnload :当页面关闭后触发,常用于body元素

3. onBlur :当失去焦点时触发,常用于input表单元素

4. onFocus :当获得焦点时触发,常用于input表单元素

5. onClick :当点击时触发,可以用于任何元素

6. onMouseOver :当鼠标悬浮时触发

7. onMouseOut :当鼠标离开时触发

8. onMouseDown :当鼠标按下时触发

9. onMouseUp :当鼠标弹起时触发

10. onMouseMove :当鼠标移动时触发

11. onChange :当状态改变时触发,常用于select下拉选框

12. onSelect :当文本框中的文本选中时触发

13. onkeypress :当键盘按下时触发(要快于onkeydown)

14. onkeydown :当键盘按下时触发(可能捕获功能键,如上下左右)

15. onkeyup :当键盘弹起时触发

16. onSubmit :当表单提交时触发,常用于form表单元素

17. onReset :当表单重置时触发,常用于form表单元素

05 总结

至此我们《JavaScript基础教程》就讲完了,如有任何问题欢迎在文章后面进行留言。最后如果喜欢本篇文章不要忘了点赞、关注与转发哦!

-END-

@IT管理局专注计算机领域技术、大学生活、学习方法、求职招聘、职业规划、职场感悟等类型的原创内容。期待与你相遇,和你一同成长。

文章推荐:

  • 程序员都必掌握的前端教程之HTML基础教程(上)