前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Nginx36】Nginx学习:SSI静态文件服务器端包含模块

【Nginx36】Nginx学习:SSI静态文件服务器端包含模块

作者头像
硬核项目经理
发布2023-10-30 17:09:24
1620
发布2023-10-30 17:09:24
举报

Nginx学习:SSI静态文件服务器端包含模块

这个模块让我想到了 2009 年刚刚工作的时候。最早我是做 .NET 的,而第一家公司其实是从 ASP 向 ASP.NET 转型中,因此,还是有不少的 ASP 做的页面。在那个时候,就用到了 SSI 。

这么一说,大家估计也猜到了,这个功能其实是很早的技术了。现在的年轻大佬们可能很多都不知道这个功能。它可以让静态文件,也就是 HTML 文件实现一些简单的文件包含、定义变量、条件判断之类的功能。

这个模块的名称是 ngx_http_ssi_module 模块,它是一个过滤器,用于处理通过它的响应中的 SSI(服务器端包含)命令。目前,支持的 SSI 命令列表不完整。

SSI 模块的指令都可以在 http、server、location 下进行配置。SSI 模块是默认添加的模块,直接就可以使用。我们先来看看它的配置指令。这些配置不是今天的重点,今天的是重点是演示一下如何使用 SSI 。

ssi

启用或禁用响应中 SSI 命令的处理。

代码语言:javascript
复制
ssi on | off;

默认值是 off 。要使用 SSI 当然要把这个打开啦。

ssi_last_modified

允许在 SSI 处理期间保留原始响应中的“Last-Modified”标头字段,以促进响应缓存。

代码语言:javascript
复制
ssi_last_modified on | off;

默认值是 off 。默认情况下,当响应的内容在处理过程中被修改时,标头字段会被删除,并且可能包含动态生成的元素或部分,这些元素或部分会独立于原始响应而更改。

ssi_min_file_chunk

设置存储在磁盘上的响应部分的最小大小,从这里开始使用 sendfile 发送它们是有意义的。

代码语言:javascript
复制
ssi_min_file_chunk size;

默认值是 1k 。

ssi_silent_errors

如果启用,则在 SSI 处理期间发生错误时抑制“[an error occurred while processing the directive]”字符串的输出。

代码语言:javascript
复制
ssi_silent_errors on | off;

默认值是 off 。

ssi_types

除了“text/html”之外,还可以处理具有指定 MIME 类型的响应中的 SSI 命令。

代码语言:javascript
复制
ssi_types mime-type ...;

默认值是 text/html 。特殊值“*”匹配任何 MIME 类型 (0.8.29)。

ssi_value_length

设置 SSI 命令中参数值的最大长度。

代码语言:javascript
复制
ssi_value_length length;

默认值是 256 。

变量

  • $date_local 本地时区的当前时间。格式由带有 timefmt 参数的 config 命令设置。
  • $date_gmt 格林威治标准时间的当前时间。格式由带有 timefmt 参数的 config 命令设置。

SSI 语法

对于上面配置指令和变量的内容咱们就不多说了,直接配置一个服务器来学习 SSI 的使用吧。

代码语言:javascript
复制
server{
  listen 8036;
  root html;

  location /ssi/ {
    ssi on;
  }
  
  location ~ \.php$ {
    root html;
    fastcgi_pass unix:/var/sock/php-fpm/www.sock;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
  }
}

非常简单,就是监听了 8036 端口,然后定义了一个 /ssi/ 目录,然后再打开 ssi 功能。因为我们还会用到 PHP ,所以也加上了一个 PHP 的 FastCGI 配置。然后我们去 html 目录下创建一个 ssi 目录,在这个目录下面创建一个 index.html 文件。

代码语言:javascript
复制
<!--# include file="header.html" -->
<!--# include file="/ssi/header.php?title=testssi" -->

<!--# set var="name" value="zyblog" -->
<!--# set var="age" value="37" -->

<!--# echo var="name" -->
<!--# echo var="age" -->
<!--# echo var="id" default="123456" -->


<!--# if expr="$age = 37" -->
37
<!--# elif expr="$age != 40" -->
young
<!--# else -->
old
<!--# endif -->

<!--# block name="one" -->
this is block one.<br/>
<!--# endblock -->
<!--# include virtual="/ssi/abc.html" stub="one" -->
<!--# include file="/ssi/123.html" stub="one" -->

看出来这个 SSI 的语法了吧。

代码语言:javascript
复制
<!--# command parameter1=value1 parameter2=value2 ... -->

它直接使用 HTML 中的注释,但是在注释中添加了一个 # 符号作为开始符号。接着就是命令以及命令相关的参数 。上面代码中,我们使用 include 命令加载文件,使用 set 定义变量,使用 echo 输出变量。使用 if 命令进行逻辑判断,最后的 block 命令是定义一个块,如果 include 加载的文件不存在时,就使用一个 stub 参数指定一个 block 显示 block 里面的内容。

接下来,准备最上面两个 include 需要加载的文件。

代码语言:javascript
复制
<!-- header.html -->
this is header.html!<br/>

header.html 就是显示一句话。

代码语言:javascript
复制
<?php
// header.php
$title = $_GET['title'];
?>
title is '<?php echo $title;?>'!<br/>

header.php 文件里面则是接收一个 title 参数 ,然后再把这个 title 参数打印出来。

好了,咱们访问一下这个页面试下吧。

代码语言:javascript
复制
➜  ~ curl http://192.168.56.88:8036/ssi/
this is header.html!<br/>



title is 'testssi'!<br/>






zyblog
37
123456



37




this is block one.<br/>


this is block one.<br/>





中间的空行我故意没有去掉,从这里可以看出,SSI 的命令行以及 PHP 代码在解析完成之后是会变成空行的。最下面的两个使用 block 的 include ,在错误日志文件中可以看到相应的错误信息。

代码语言:javascript
复制
2022/09/21 23:20:28 [error] 1513#0: *38 open() "/usr/local/nginx/html/ssi/abc.html" failed (2: No such file or directory), client: 192.168.56.1, server: , request: "GET /ssi/index.html HTTP/1.1", subrequest: "/ssi/abc.html", host: "192.168.56.88:8036", referrer: "http://xxx"
2022/09/21 23:20:28 [error] 1513#0: *38 open() "/usr/local/nginx/html/ssi/123.html" failed (2: No such file or directory), client: 192.168.56.1, server: , request: "GET /ssi/index.html HTTP/1.1", subrequest: "/ssi/123.html", host: "192.168.56.88:8036", referrer: "http://xxx"

上面例子中,if 判断貌似没啥用呀,毕竟我们的变量是写死的。然后 SSI 又不能动态接收参数,其实呀,使用 PHP 套上静态页面就可以接收参数了嘛。还是先准备一个 lcoation 来进行测试。

代码语言:javascript
复制
location ^~ /ssiphp/ {
  alias html/ssi/;
  fastcgi_pass unix:/var/sock/php-fpm/www.sock;
  fastcgi_index  index.php;
  fastcgi_param  SCRIPT_FILENAME $request_filename;
  include        fastcgi_params;
  ssi on;
}

然后,准备一个 if.php 文件。

代码语言:javascript
复制
<?php
$age = $_GET['age'];
?>
<!--# set var="age" value="<?php echo $age;?>" -->
<!--# if expr="$age = 37" -->
37
<!--# elif expr="$age != 40" -->
not 40
<!--# else -->
old or young? old!
<!--# endif -->

测试一下吧,看看 if 的效果怎么样。

代码语言:javascript
复制
➜  ~ curl "http://192.168.56.88:8036/ssiphp/if.php?age=37"


37


➜  ~ curl "http://192.168.56.88:8036/ssiphp/if.php?age=49"


not 40


➜  ~ curl "http://192.168.56.88:8036/ssiphp/if.php?age=40"


old or young? old!

返回的结果和我们 if 条件的预期一样。不过需要注意的是,这里的 if 判断条件没有大于、小于,只有等于、不等于、空或非空判断,但判断值可以是正则表达式。

总结

有意思吧,哈哈,早期的我们就是靠这个,实现 ASP 开发中头文件和脚文件的拆分的。不过现在真的很少见到了,毕竟一是纯静态网站已经很少了,二是各种语言框架都已经自带这些功能了。即使是做文章站那种生成纯静态页面的,也是直接去生成整张页面,和这个嵌套也没啥关系。

因此,它的应用场景现在确实很有限了。大家了解一下就好,特别是各位年轻的大佬,如果没见过的话,自己试试,其实也挺好玩的。

参考文档:

http://nginx.org/en/docs/http/ngx_http_ssi_module.html

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-10-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农老张 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Nginx学习:SSI静态文件服务器端包含模块
    • ssi
      • ssi_last_modified
        • ssi_min_file_chunk
          • ssi_silent_errors
            • ssi_types
              • ssi_value_length
                • 变量
                  • SSI 语法
                    • 总结
                    相关产品与服务
                    腾讯云服务器利旧
                    云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档