起源于 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
的内容.