部署 davical 到 apache2

Table of Content

缘起于 radicale 的 well-known 自动配置不能与 thunderbird 的 tbsync 插件和平地工作, 以及使用 python 实现的 radicale 在过去的半年中失去响应了 3 次, 所以决定找一个可能更稳定一些, 更加通用一些的支持 caldav 的服务程序, 最终选定了 davical .

这里将在 debian 系统 apache2 上部署 davical , 同时会配置好 well-known 的重定向, 此外还会有一些实现方式的小推测.

关于软件依赖等事项不再赘述, 这里只讨论使用 apache 部署 davical 站点的过程.

部署 davical 站点

部署 davical 有两大类别, 分别是部署为一个新的站点和部署为一个网站的子目录.

部署为新的站点比较方便, 而且不会对未来可能的新目录产生冲突, 但建议配合 DNS 来使用, 以免浪费一个 80 端口, 此外客户端的配置也十分简单.

部署为一个 http 子目录兼容性则会更好一些, 适用于更多场景.

使用 VirtualHost 部署 davical 为一个新的站点

部署为一个新的站点只需要创建一个新的 VirtualHost 条目, 并指定网页根目录 DocumentRoot 即可. 比如将新站点监听在本机所有 IP 的 81 端口, 只需要在 VirualHost 条目中通配指定所有 IP , 再指定端口 81 即可.

需要注意的是那个比较容易被忽略的 Listen 81 的指令, 这个指令要求 apache2 在运行时监听 81 端口, 如果没有这条指令则会发现站点无法正常使用, 表现为无法建立连接, 在服务器主机上也会发现没有任何进程监听 81 端口.

Listen 81
<VirtualHost *:81>
    DocumentRoot /usr/share/davical/htdocs
</VirtualHost>

使用这种方式配置以后, 在客户端的配置中需要指定 caldav/carddav 的目录为根目录或忽略不写路径即可.

使用软链接方式部署 davical 到一个 http 子目录

这种配置方式不需要去为了建立站点或重定向来修改配置文件, 只需要在当前的站点的 DocumentRoot 的文件目录中建立一个指向 davical 的 htdocs 的目录的软链接即可.

# ls -l
total 2
-rw-r--r-- 1 root root 10701 Dec 27 23:39 index.html
lrwxrwxrwx 1 root root    26 Dec 28 02:25 davical-link -> /usr/share/davical/htdocs/

使用别名(Alias)方式部署 davical 到一个 http 子目录

在需要部署的站点 (VirtualHost) 中添加 Alias 指令就可以实现和建立软链接相同的效果.

需要注意是否在第一个参数 URI 中后缀一个斜杠, Alias 对于 URI 后缀斜杠的行为与 Redirect 类似, 具体在关于 Redirect 时有无后缀斜杠的区别中描述.

Alias "/davical" "/usr/share/davical/htdocs/"

well-known 的配置

well-known 是一个将各种可能在网页文档某个路径的服务另外在路径 /.well-known/ 下为指定名称的文档请求返回跳转响应的约定.

比如 caldav 服务部署在 /davical/caldav.php 路径, 若配置好 well-known 则访问 /.well-known/caldav URI 时, 会在得到一个响应头, 其中 location 字段为 /davical/caldav.php, 状态码为任意一个跳转状态码 (如 301 或 302), 随后客户端会根据得到的 URI 去再一次请求服务.

对于 davical 的 well-known 的配置可以参见其 wiki (Well-known URLs) , 下面也会进行简短的复述.

davical 的 well-known 工作机制要求 well-known 的访问被 /davical-base/caldav.php/.well-known/caldav 处理, 处理结果中, GET 请求会直接在此 URI 的网页文档下处理, 而 caldav 中用到的 PROPFIND 等请求会返回一个重定向响应, 响应路径为 /davical-base/caldav.php .

在 apache 的配置当中, 一切配置的目的都是将访问到 /.well-known/caldav 到请求重定向到 /davical-base/caldav.php/.well-known/caldav, 实现这一目的的手段有对用户透明的 Rewrite 和用户可见的 Redirect 两种.

使用 Rewrite 部署 well-known

假设 davical 被部署在 /davical-base/ 下, 使用 Rewrite 需要先引入模块 mod_rewrite, 仅重写 caldav 服务的情况时, 配置如下.

RewriteEngine On
RewriteRule ^/\.well-known/caldav$ /davical-base/caldav.php/.well-known/caldav [NC,L]

客户端的访问体验

Request: PROPFIND http://hostname/.well-known/caldav
Response: 301 location=/davical-base/caldav.php

Request: PROPFIND http://hostname/davical-base/caldav.php
Response: ... ... ... ...

使用 Redirect 部署 well-known

假设 davical 被部署在同一位置, 仅重写 caldav 服务时, 配置如下.

Redirect /.well-known/caldav /davical-base/caldav.php/.well-known/caldav

客户端的访问体验

Request: PROPFIND http://hostname/.well-known/caldav
Response: 302 location=/davical-base/caldav.php/.well-known/caldav

Request: PROPFIND http://hostname/davical-base/caldav.php/.well-known/caldav
Response: 301 location=/davical-base/caldav.php

Request: PROPFIND http://hostname/davical-base/caldav.php
Response: ... ... ... ...

关于 Rewrite 的一些解释

Rewrite 是简单的修改 URI , 然后将修改后的 URI 中的资源作为响应返回给请求, 这一过程对于客户端是透明的.

关于 Redirect 时有无后缀斜杠的区别

Redirect 只是一个普通的查找替换, 相当于将 URI 中特定前缀替换为第二个参数表述的字符串以后, 将修改之后的 URI 作为响应头中的 location 字段值并以 301 作为状态码返回给浏览器.

此外, 对于目录文件, 如果 URI 的目标刚好是一个目录文件, 在匹配唯一的情况下, 是否后缀斜杠以及后缀多少个斜杠对于目录项来说没有区别, 即 /dir/dir/ /dir// 没有区别. 而对于普通文档, 则后缀一个额外的斜杠以后会无法访问该文档.

一个关于 URI 后缀斜杠并在重定向时被替换的例子

所以对于是否加上斜杠, 应考虑是否需要要以斜杠的方式访问. 如网页根目录内容以及目标为 tmp-file 的重定向如下.

# content of the DocumentRoot
-rw-r--r-- 1 root root   9 Jan  2 00:09 tmp-file

# directive in VirtualHost
Redirect /redirect-file/ /tmp-file

浏览器访问 URI 为 http://hostname/redirect-file/ 的网页时, 得到的响应头如下.

HTTP/1.1 302 Found
Date: Sat, 02 Jan 2021 06:43:49 GMT
Server: Apache/2.4.38 (Debian)
Location: http://hostname/tmp-file
Content-Length: 296
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=iso-8859-1

随后浏览器跳转到 http://hostname/tmp-file 最终获取到真正的网页.

请留意 302 跳转时浏览器访问时提供的 URI 中后缀的斜杠, 以及重定向指令中的源 URI 中的斜杠.

当访问的 URI 中没有后缀斜杠时, 即访问时提供的 URI 为 http://hostname/redirect-file 时, 此重定向指令将不会生效, 最终浏览器得到一个 404 的响应.

一个重定向与直接获取网页文档同时工作的例子

# content of the DocumentRoot
-rw-r--r-- 1 root root   9 Jan  2 00:09 redirect-dir
drw-r--r-- 1 root root   9 Jan  2 00:09 tmp-dir

# directive in VirtualHost
Redirect /redirect-dir/ /tmp-dir

当如上配置时, URI 为 http://hostname/redirect-dir 时, 会直接获取到文件 redirect-dir 的内容, 当 URI 为 http://hostname/redirect-dir/ 时, 会访问到目录 tmp-dir 的内容.

Leave a Reply

Your email address will not be published. Required fields are marked *




Enter Captcha Here :