Featured image of post 怎样给 Hugo 增加一个 RSS 边栏小工具

怎样给 Hugo 增加一个 RSS 边栏小工具

今天上午本来想给 Hugo 主页边栏添加一个 RSS 小工具,用来展示其他跨站动态。本来也很简单,我甚至已经在本站 2025 页面将主要过程记了下来。结果没想到,一提交到 Github 就出了问题,不管是 Github 还是 Vercel 均部署失败。这里只好再详细记录下后续情况。

为 Hugo 添加一个 RSS 边栏小工具

在 Wordpress 中默认的小工具里边可以很方便添加 RSS 插件,但在 Hugo 上就得稍微麻烦点。不过,我的目的是将我的 WordPress 最新文章列表输出到 Hugo 上,倒也不必然使用 RSS 格式,直接调用 Wordpress API 即可。但与 RSS 相比,方法都是相同的。

  1. 在 Hugo 的边栏模板中添加调用模块

    • 方法 A:RSS 调用

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      
      {{ $rssUrl := "https://news.lawtee.com/feed/" }} <!-- 替换为你的 RSS 地址 -->
      {{ $rss := resources.GetRemote $rssUrl }}
      {{ $items := $rss | transform.Unmarshal }}
      <h2>RSS</h2>
      <ul>
          {{ range first 7 $items.channel.item }} 
              <li>
                  <a href="{{ .link }}" target="_blank">{{ .title }}</a>
              </li>
          {{ end }}
      </ul>
      
    • 方法 B:WordPress API 调用

      1
      2
      3
      4
      5
      6
      7
      8
      
      {{ $url := "https://news.lawtee.com/wp-json/wp/v2/posts?per_page=5" }} <!-- 替换为你的 WordPress 地址 -->
      {{ $posts := getJSON $url }}
      <h2>最新文章</h2>
      <ul>
          {{ range $posts }}
              <li><a href="{{ .link }}" target="_blank">{{ .title.rendered }}</a></li>
          {{ end }}
      </ul>
      
  2. 设置必要的 CSS。例如,我为了省事直接套了另一个 Hugo 边栏插件 archives 的 CSS。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    <section class="widget archives">
                <div class="widget-icon">
                    {{ partial "helper/icon" "rss" }}
                </div>
                <h2 class="widget-title section-title">
                    <a href="https://news.lawtee.com/" target="_blank">News</a>
                </h2>
                <div class="widget-archive--list">
                    <ul>
                        {{ range $posts }}
                        <li><a href="{{ .link }}" target="_blank">{{ .title.rendered }}</a></li>
                        {{ end }}
                    </ul>
              </div>
            </section>
    

事情到这里本来就结束了,因为我在本地使用 Hugo Server 命令调试时发现一切运作正常。但没想到在提交 Github 后却出了问题。

Github 和 Vercel 无法正常构建远程调用的 RSS 源

  1. 错误情况。Github Actions 和 Vercel 在 npm run build 后均出现如下错误:
1
ERROR render of "home" failed: "/home/runner/work/lawtee.github.io/lawtee.github.io/themes/hugo-theme-stack/layouts/index.html:18:7": execute of template failed: template: index.html:18:7: executing "right-sidebar" at <partial "sidebar/right.html" (dict "Context" . "Scope" "homepage")>: error calling partial: "/home/runner/work/lawtee.github.io/lawtee.github.io/themes/hugo-theme-stack/layouts/partials/sidebar/right.html:30:36": execute of template failed: template: partials/sidebar/right.html:30:36: executing "partials/sidebar/right.html" at <.link>: can't evaluate field link in type interface {}

简单说就是在我修改后的模板中读取 .link 失败,导致模板无法渲染。而这个 .link 应当是 RSS 中输出的文章固定链接。

我反复确认了一下源 RSS 格式,发现并没问题。于是怀疑是不是 Github 无法拉取 RSS 文件导致的。

  1. 在 Workflow 中添加网络测试
1
2
3
      - name: Test Network
        run: |
          curl -v "https://news.lawtee.com/feed/"

接着,我在 .github/workflow 的部署模板中添加如上测试,想看看是不是 Github 无法访问链接。但结果似乎没问题。

  1. 四处查找问题原因

也是奇了怪了,我接下来又调试了多次,包括重新指定 Hugo 版本,修正一些环境差异;将原来模板中远程调用 RSS 文件修改为 Hugo 构建前预先拉取远程文件到构建服务器,构建时再改用本地文件构建;在 RSS 与 Wordpress API 之间切换等等。试了个把小时,除了收到一堆部署失败邮件,毫无头绪。

  1. 重新确认为网络问题

后来,我又仔细查看确认了一下 Actions 在部署过程中的网络测试结果。这一看不要紧,在第 60 多行还真发现有个 403 。原因也很清晰,就是在构建过程中,Github Vercel 的服务器 IP 被 Cloudflare 当作网络攻击给自动防御了。

更改 Cloudflare WAF 设置,确保 Github Vercel 服务器能够访问到 RSS 地址

知道问题就好解决,在 Cloudflare 中添加 WAF 自定义规则,绕过 RSS 地址即可。

然而,这并没有啥用。仔细查看 Cloudflare 才发现,WAF 规则只对零散访问生效,而 Cloudflare 的自动程序防御优先级是高于 WAF 规则的。想要调整 WAF 自定义规则的优先级,必须充值为 PRO 用户才行。

好在 Cloudflare 还有一堆配置规则可以设置,像“页面规则”,优先级都是高过防火墙的。

于是在配置规则里将构建过程中需要访问的链接的安全级别改成禁用。

结果依然没用。这才发现,Cloudflare 的自动程序攻击模式根本绕不过去。

要么充值成 PRO 用户,要么只能添加 IP 规则,然而 Github 和 Vercel 在部署时都是随机 Microsoft 和 Amazon 地址,添加 IP 规则几乎没有可行性。

最后唯一方法就是把这个 Cloudflare 的自动程序攻击模式给关掉。

Cloudflare 文档说明
You cannot bypass or skip Bot Fight Mode using the Skip action in WAF custom rules or using Page Rules. Skip, Bypass, and Allow actions apply to rules or rulesets running on the Ruleset Engine. While Super Bot Fight Mode rules are implemented in the Ruleset Engine, Bot Fight Mode checks are not. This is why you can skip Super Bot Fight Mode, but not Bot Fight Mode. If you need to skip Bot Fight Mode, consider using Super Bot Fight Mode.
Bot Fight Mode can still trigger if you have IP Access rules, but it cannot trigger if an IP Access rule matches the request. For example, the IP Access rule matches the connecting IP.

不使用 Cloudflare 的方案

如果 RSS 源站没有使用 Cloudflare 等防火墙,只需要第一步即可完成。也就没有后边这么多啰嗦事。

正如本站目前所现,由于关闭 Cloudflare 的自动程序攻击模式会给我其他子服务带来影响,所以我干脆换了个免费域名指向一台 Serv00 免费服务器,刚好在这台服务器早已配置好 Wordpress 闲置在那里,只需要添加一个 RSS 插件即解决问题。

All textual works on this website are protected by copyright, and the authors reserve all rights. The photos on this website, unless specifically stated, licensed under the CC BY-NC-ND 4.0 license.
Built with Hugo, Powered by Github.
全站约 317 篇文章 合计约 870611 字
本站已加入BLOGS·CN