<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Angus-fw🥝</title>
  
  
  <link href="https://blog.sihan.fun/atom.xml" rel="self"/>
  
  <link href="https://blog.sihan.fun/"/>
  <updated>2026-04-11T00:34:03.505Z</updated>
  <id>https://blog.sihan.fun/</id>
  
  <author>
    <name>Angus-fw🥝</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Cloudflare部署Snippets项目教程</title>
    <link href="https://blog.sihan.fun/posts/fa0a9ca2.html"/>
    <id>https://blog.sihan.fun/posts/fa0a9ca2.html</id>
    <published>2026-03-27T02:00:00.000Z</published>
    <updated>2026-04-11T00:34:03.505Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Cloudflare部署Snippets项目教程"><a href="#Cloudflare部署Snippets项目教程" class="headerlink" title="Cloudflare部署Snippets项目教程"></a>Cloudflare部署Snippets项目教程</h1><p>本教程将详细介绍如何在Cloudflare中使用Snippets功能部署GitHub反代、Docker反代以及随机图项目。</p><h2 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h2><ol><li>拥有一个已添加到Cloudflare的域名</li><li>登录Cloudflare账户</li></ol><h2 id="步骤一：进入Cloudflare-Snippets页面"><a href="#步骤一：进入Cloudflare-Snippets页面" class="headerlink" title="步骤一：进入Cloudflare Snippets页面"></a>步骤一：进入Cloudflare Snippets页面</h2><ol><li>登录Cloudflare账户</li><li>选择你要使用的域名</li><li>在左侧菜单中找到”规则”选项并点击</li><li>在规则页面中选择”Snippets”选项卡</li></ol><p><img src="/assets/updata/Snippets-1.jpg" alt="Cloudflare Snippets页面"></p><h2 id="步骤二：创建Snippets片段"><a href="#步骤二：创建Snippets片段" class="headerlink" title="步骤二：创建Snippets片段"></a>步骤二：创建Snippets片段</h2><h1 id="代码由于2x-nz博客提供的，感谢2x-nz博客的贡献"><a href="#代码由于2x-nz博客提供的，感谢2x-nz博客的贡献" class="headerlink" title="代码由于2x.nz博客提供的，感谢2x.nz博客的贡献"></a>代码由于2x.nz博客提供的，感谢2x.nz博客的贡献</h1><p><img src="/assets/updata/Snippets-2.jpg" alt="创建片段页面"></p><div class="tabs" id="片段代码"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#片段代码-1">GitHub反代片段</button></li><li class="tab"><button type="button" data-href="#片段代码-2">Docker反代片段</button></li><li class="tab"><button type="button" data-href="#片段代码-3">随机图项目片段</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="片段代码-1"><h3 id="1-创建GitHub反代片段"><a href="#1-创建GitHub反代片段" class="headerlink" title="1. 创建GitHub反代片段"></a>1. 创建GitHub反代片段</h3><ol><li>点击”创建片段”按钮</li><li>在名称输入框中输入一个描述性名称，例如”GitHub反代”</li><li>在编辑框中粘贴以下代码：</li></ol><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 域名白名单配置（仅保留需要的原生域名）</span></span><br><span class="line"><span class="keyword">const</span> domain_whitelist = [</span><br><span class="line">  <span class="string">&#x27;github.com&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;avatars.githubusercontent.com&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;github.githubassets.com&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;collector.github.com&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;api.github.com&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;raw.githubusercontent.com&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;gist.githubusercontent.com&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;github.io&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;assets-cdn.github.com&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;cdn.jsdelivr.net&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;securitylab.github.com&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;www.githubstatus.com&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;npmjs.com&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;git-lfs.github.com&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;githubusercontent.com&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;github.global.ssl.fastly.net&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;api.npms.io&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;github.community&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;desktop.github.com&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;central.github.com&#x27;</span></span><br><span class="line">];</span><br><span class="line"></span><br><span class="line"><span class="comment">// 由白名单自动生成映射</span></span><br><span class="line"><span class="keyword">const</span> domain_mappings = <span class="title class_">Object</span>.<span class="title function_">fromEntries</span>(</span><br><span class="line">  domain_whitelist.<span class="title function_">map</span>(<span class="function"><span class="params">domain</span> =&gt;</span> [domain, domain.<span class="title function_">replace</span>(<span class="regexp">/\./g</span>, <span class="string">&#x27;-&#x27;</span>) + <span class="string">&#x27;-&#x27;</span>])</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 需要重定向的路径（屏蔽海外后可以不填写）</span></span><br><span class="line"><span class="keyword">const</span> redirect_paths = [];</span><br><span class="line"></span><br><span class="line"><span class="comment">// 中国大陆以外的地区重定向到原始GitHub域名</span></span><br><span class="line"><span class="keyword">const</span> enable_geo_redirect = <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="keyword">async</span> <span class="title function_">fetch</span>(<span class="params">request, env, ctx</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">handleRequest</span>(request);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">handleRequest</span>(<span class="params">request</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> url = <span class="keyword">new</span> <span class="title function_">URL</span>(request.<span class="property">url</span>);</span><br><span class="line">  <span class="comment">// 统一转小写</span></span><br><span class="line">  <span class="keyword">const</span> current_host = url.<span class="property">host</span>.<span class="title function_">toLowerCase</span>();</span><br><span class="line">  <span class="keyword">const</span> host_header = request.<span class="property">headers</span>.<span class="title function_">get</span>(<span class="string">&#x27;Host&#x27;</span>);</span><br><span class="line">  <span class="keyword">const</span> effective_host = (host_header || current_host).<span class="title function_">toLowerCase</span>();</span><br><span class="line">  </span><br><span class="line">  <span class="comment">// 检查是否需要重定向到原始GitHub（非中国用户）</span></span><br><span class="line">  <span class="keyword">if</span> (enable_geo_redirect) &#123;</span><br><span class="line">    <span class="keyword">const</span> country = request.<span class="property">headers</span>.<span class="title function_">get</span>(<span class="string">&#x27;CF-IPCountry&#x27;</span>) || <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">    <span class="keyword">if</span> (country &amp;&amp; country !== <span class="string">&#x27;CN&#x27;</span>) &#123;</span><br><span class="line">      <span class="keyword">const</span> host_prefix = <span class="title function_">getProxyPrefix</span>(effective_host);</span><br><span class="line">      <span class="keyword">if</span> (host_prefix) &#123;</span><br><span class="line">        <span class="keyword">let</span> target_host = <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">if</span> (host_prefix &amp;&amp; host_prefix.<span class="title function_">endsWith</span>(<span class="string">&#x27;-gh.&#x27;</span>)) &#123;</span><br><span class="line">          <span class="keyword">const</span> prefix_part = host_prefix.<span class="title function_">slice</span>(<span class="number">0</span>, -<span class="number">4</span>);</span><br><span class="line">          <span class="keyword">for</span> (<span class="keyword">const</span> original <span class="keyword">of</span> <span class="title class_">Object</span>.<span class="title function_">keys</span>(domain_mappings)) &#123;</span><br><span class="line">            <span class="keyword">const</span> normalized_original = original.<span class="title function_">trim</span>().<span class="title function_">toLowerCase</span>();</span><br><span class="line">            <span class="keyword">if</span> (normalized_original.<span class="title function_">replace</span>(<span class="regexp">/\./g</span>, <span class="string">&#x27;-&#x27;</span>) === prefix_part) &#123;</span><br><span class="line">              target_host = original;</span><br><span class="line">              <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (target_host) &#123;</span><br><span class="line">          <span class="keyword">const</span> domain_suffix = effective_host.<span class="title function_">substring</span>(host_prefix.<span class="property">length</span>);</span><br><span class="line">          <span class="keyword">const</span> original_url = <span class="keyword">new</span> <span class="title function_">URL</span>(request.<span class="property">url</span>);</span><br><span class="line">          original_url.<span class="property">host</span> = target_host;</span><br><span class="line">          original_url.<span class="property">protocol</span> = <span class="string">&#x27;https:&#x27;</span>;</span><br><span class="line">          <span class="keyword">return</span> <span class="title class_">Response</span>.<span class="title function_">redirect</span>(original_url.<span class="property">href</span>, <span class="number">302</span>);</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line">  <span class="comment">// 检查特殊路径，返回正常错误</span></span><br><span class="line">  <span class="keyword">if</span> (redirect_paths.<span class="title function_">includes</span>(url.<span class="property">pathname</span>)) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="string">&#x27;Not Found&#x27;</span>, &#123; <span class="attr">status</span>: <span class="number">404</span> &#125;);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 强制使用 HTTPS</span></span><br><span class="line">  <span class="keyword">if</span> (url.<span class="property">protocol</span> === <span class="string">&#x27;http:&#x27;</span>) &#123;</span><br><span class="line">    url.<span class="property">protocol</span> = <span class="string">&#x27;https:&#x27;</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">Response</span>.<span class="title function_">redirect</span>(url.<span class="property">href</span>);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 从有效主机名中提取前缀</span></span><br><span class="line">  <span class="keyword">const</span> host_prefix = <span class="title function_">getProxyPrefix</span>(effective_host);</span><br><span class="line">  <span class="keyword">if</span> (!host_prefix) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="string">`Domain not configured for proxy. Host: <span class="subst">$&#123;effective_host&#125;</span>, Prefix check failed`</span>, &#123; <span class="attr">status</span>: <span class="number">404</span> &#125;);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 根据前缀找到对应的原始域名</span></span><br><span class="line">  <span class="keyword">let</span> target_host = <span class="literal">null</span>;</span><br><span class="line">  </span><br><span class="line">  <span class="comment">// 解析 *-gh. 模式</span></span><br><span class="line">  <span class="keyword">if</span> (host_prefix &amp;&amp; host_prefix.<span class="title function_">endsWith</span>(<span class="string">&#x27;-gh.&#x27;</span>)) &#123;</span><br><span class="line">    <span class="keyword">const</span> prefix_part = host_prefix.<span class="title function_">slice</span>(<span class="number">0</span>, -<span class="number">4</span>); <span class="comment">// 移除 -gh.</span></span><br><span class="line">    <span class="comment">// 尝试找到对应的原始域名</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">const</span> original <span class="keyword">of</span> <span class="title class_">Object</span>.<span class="title function_">keys</span>(domain_mappings)) &#123;</span><br><span class="line">      <span class="keyword">const</span> normalized_original = original.<span class="title function_">trim</span>().<span class="title function_">toLowerCase</span>();</span><br><span class="line">      <span class="keyword">if</span> (normalized_original.<span class="title function_">replace</span>(<span class="regexp">/\./g</span>, <span class="string">&#x27;-&#x27;</span>) === prefix_part) &#123;</span><br><span class="line">        target_host = original;</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (!target_host) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="string">`Domain not configured for proxy. Host: <span class="subst">$&#123;effective_host&#125;</span>, Prefix: <span class="subst">$&#123;host_prefix&#125;</span>, Target lookup failed`</span>, &#123; <span class="attr">status</span>: <span class="number">404</span> &#125;);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 直接使用正则表达式处理最常见的嵌套URL问题</span></span><br><span class="line">  <span class="keyword">let</span> pathname = url.<span class="property">pathname</span>;</span><br><span class="line">  </span><br><span class="line">  <span class="comment">// 修复特定的嵌套URL模式 - 直接移除嵌套URL部分</span></span><br><span class="line">  <span class="comment">// 匹配 /xxx/xxx/latest-commit/main/https%3A//gh.xxx.xxx/ 或 /xxx/xxx/tree-commit-info/main/https%3A//gh.xxx.xxx/</span></span><br><span class="line">  pathname = pathname.<span class="title function_">replace</span>(<span class="regexp">/(\/[^\/]+\/[^\/]+\/(?:latest-commit|tree-commit-info)\/[^\/]+)\/https%3A\/\/[^\/]+\/.*/</span>, <span class="string">&#x27;$1&#x27;</span>);</span><br><span class="line">  </span><br><span class="line">  <span class="comment">// 同样处理非编码版本</span></span><br><span class="line">  pathname = pathname.<span class="title function_">replace</span>(<span class="regexp">/(\/[^\/]+\/[^\/]+\/(?:latest-commit|tree-commit-info)\/[^\/]+)\/https:\/\/[^\/]+\/.*/</span>, <span class="string">&#x27;$1&#x27;</span>);</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 构建新的请求URL</span></span><br><span class="line">  <span class="keyword">const</span> new_url = <span class="keyword">new</span> <span class="title function_">URL</span>(url);</span><br><span class="line">  new_url.<span class="property">host</span> = target_host;</span><br><span class="line">  new_url.<span class="property">pathname</span> = pathname;</span><br><span class="line">  new_url.<span class="property">protocol</span> = <span class="string">&#x27;https:&#x27;</span>;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 设置新的请求头</span></span><br><span class="line">  <span class="keyword">const</span> new_headers = <span class="keyword">new</span> <span class="title class_">Headers</span>(request.<span class="property">headers</span>);</span><br><span class="line">  new_headers.<span class="title function_">set</span>(<span class="string">&#x27;Host&#x27;</span>, target_host);</span><br><span class="line">  new_headers.<span class="title function_">set</span>(<span class="string">&#x27;Referer&#x27;</span>, new_url.<span class="property">href</span>);</span><br><span class="line">  <span class="comment">// 强制要求源站返回未压缩的内容，确保我们可以正常修改文本</span></span><br><span class="line">  new_headers.<span class="title function_">delete</span>(<span class="string">&#x27;accept-encoding&#x27;</span>);</span><br><span class="line">  </span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">    <span class="comment">// 发起请求</span></span><br><span class="line">    <span class="keyword">const</span> response = <span class="keyword">await</span> <span class="title function_">fetch</span>(new_url.<span class="property">href</span>, &#123;</span><br><span class="line">      <span class="attr">method</span>: request.<span class="property">method</span>,</span><br><span class="line">      <span class="attr">headers</span>: new_headers,</span><br><span class="line">      <span class="attr">body</span>: request.<span class="property">method</span> !== <span class="string">&#x27;GET&#x27;</span> ? request.<span class="property">body</span> : <span class="literal">undefined</span>,</span><br><span class="line">      <span class="attr">redirect</span>: <span class="string">&#x27;manual&#x27;</span> <span class="comment">// 处理重定向，避免自动跟随导致的问题</span></span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 处理重定向</span></span><br><span class="line">    <span class="keyword">if</span> ([<span class="number">301</span>, <span class="number">302</span>, <span class="number">303</span>, <span class="number">307</span>, <span class="number">308</span>].<span class="title function_">includes</span>(response.<span class="property">status</span>)) &#123;</span><br><span class="line">      <span class="keyword">const</span> location = response.<span class="property">headers</span>.<span class="title function_">get</span>(<span class="string">&#x27;location&#x27;</span>);</span><br><span class="line">      <span class="keyword">if</span> (location) &#123;</span><br><span class="line">        <span class="keyword">const</span> modified_location = <span class="title function_">modifyUrl</span>(location, host_prefix, effective_host);</span><br><span class="line">        <span class="keyword">const</span> new_res_headers = <span class="keyword">new</span> <span class="title class_">Headers</span>(response.<span class="property">headers</span>);</span><br><span class="line">        new_res_headers.<span class="title function_">set</span>(<span class="string">&#x27;location&#x27;</span>, modified_location);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="literal">null</span>, &#123;</span><br><span class="line">          <span class="attr">status</span>: response.<span class="property">status</span>,</span><br><span class="line">          <span class="attr">headers</span>: new_res_headers</span><br><span class="line">        &#125;);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 设置新的响应头</span></span><br><span class="line">    <span class="keyword">const</span> new_response_headers = <span class="keyword">new</span> <span class="title class_">Headers</span>(response.<span class="property">headers</span>);</span><br><span class="line">    new_response_headers.<span class="title function_">set</span>(<span class="string">&#x27;access-control-allow-origin&#x27;</span>, <span class="string">&#x27;*&#x27;</span>);</span><br><span class="line">    new_response_headers.<span class="title function_">set</span>(<span class="string">&#x27;access-control-allow-credentials&#x27;</span>, <span class="string">&#x27;true&#x27;</span>);</span><br><span class="line">    new_response_headers.<span class="title function_">set</span>(<span class="string">&#x27;cache-control&#x27;</span>, <span class="string">&#x27;public, max-age=14400&#x27;</span>);</span><br><span class="line">    new_response_headers.<span class="title function_">delete</span>(<span class="string">&#x27;content-security-policy&#x27;</span>);</span><br><span class="line">    new_response_headers.<span class="title function_">delete</span>(<span class="string">&#x27;content-security-policy-report-only&#x27;</span>);</span><br><span class="line">    new_response_headers.<span class="title function_">delete</span>(<span class="string">&#x27;clear-site-data&#x27;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 只处理 200 OK 且是文本类型的响应内容</span></span><br><span class="line">    <span class="keyword">const</span> content_type = response.<span class="property">headers</span>.<span class="title function_">get</span>(<span class="string">&#x27;content-type&#x27;</span>) || <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">    <span class="keyword">const</span> is_text = content_type.<span class="title function_">includes</span>(<span class="string">&#x27;text/&#x27;</span>) || </span><br><span class="line">                    content_type.<span class="title function_">includes</span>(<span class="string">&#x27;application/json&#x27;</span>) || </span><br><span class="line">                    content_type.<span class="title function_">includes</span>(<span class="string">&#x27;application/javascript&#x27;</span>) || </span><br><span class="line">                    content_type.<span class="title function_">includes</span>(<span class="string">&#x27;application/xml&#x27;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (response.<span class="property">status</span> === <span class="number">200</span> &amp;&amp; is_text) &#123;</span><br><span class="line">      <span class="comment">// 如果要修改内容，必须移除这些头，因为内容会被解压且长度会变化</span></span><br><span class="line">      new_response_headers.<span class="title function_">delete</span>(<span class="string">&#x27;content-encoding&#x27;</span>);</span><br><span class="line">      new_response_headers.<span class="title function_">delete</span>(<span class="string">&#x27;content-length&#x27;</span>);</span><br><span class="line">      </span><br><span class="line">      <span class="keyword">let</span> text = <span class="keyword">await</span> response.<span class="title function_">text</span>();</span><br><span class="line">      text = <span class="keyword">await</span> <span class="title function_">modifyText</span>(text, host_prefix, effective_host);</span><br><span class="line">      </span><br><span class="line">      <span class="comment">// 注入统计脚本</span></span><br><span class="line">      <span class="keyword">if</span> (content_type.<span class="title function_">includes</span>(<span class="string">&#x27;text/html&#x27;</span>)) &#123;</span><br><span class="line">        <span class="keyword">const</span> inject_script = <span class="string">&#x27;&lt;script defer src=&quot;https://u.2x.nz/script.js&quot; data-website-id=&quot;e20f6781-b518-4bab-96be-35afe24cd0cf&quot;&gt;&lt;/script&gt;&#x27;</span>;</span><br><span class="line">        <span class="keyword">if</span> (text.<span class="title function_">includes</span>(<span class="string">&#x27;&lt;/head&gt;&#x27;</span>)) &#123;</span><br><span class="line">          text = text.<span class="title function_">replace</span>(<span class="string">&#x27;&lt;/head&gt;&#x27;</span>, <span class="string">`<span class="subst">$&#123;inject_script&#125;</span>&lt;/head&gt;`</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (text.<span class="title function_">includes</span>(<span class="string">&#x27;&lt;/body&gt;&#x27;</span>)) &#123;</span><br><span class="line">          text = text.<span class="title function_">replace</span>(<span class="string">&#x27;&lt;/body&gt;&#x27;</span>, <span class="string">`<span class="subst">$&#123;inject_script&#125;</span>&lt;/body&gt;`</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">          text = text + inject_script;</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">      </span><br><span class="line">      <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(text, &#123;</span><br><span class="line">        <span class="attr">status</span>: response.<span class="property">status</span>,</span><br><span class="line">        <span class="attr">headers</span>: new_response_headers</span><br><span class="line">      &#125;);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 对于非文本或非 200 响应，直接返回原始流</span></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(response.<span class="property">body</span>, &#123;</span><br><span class="line">      <span class="attr">status</span>: response.<span class="property">status</span>,</span><br><span class="line">      <span class="attr">headers</span>: new_response_headers</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="string">`Proxy Error: <span class="subst">$&#123;err.message&#125;</span>`</span>, &#123; <span class="attr">status</span>: <span class="number">502</span> &#125;);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 获取当前主机名的前缀，用于匹配反向映射</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">getProxyPrefix</span>(<span class="params">host</span>) &#123;</span><br><span class="line">  <span class="comment">// 检查 *-gh. 模式</span></span><br><span class="line">  <span class="keyword">const</span> ghMatch = host.<span class="title function_">match</span>(<span class="regexp">/^([a-z0-9-]+-gh\.)/</span>);</span><br><span class="line">  <span class="keyword">if</span> (ghMatch) &#123;</span><br><span class="line">    <span class="keyword">return</span> ghMatch[<span class="number">1</span>];</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 修改文本中的域名引用</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">modifyText</span>(<span class="params">text, host_prefix, effective_hostname</span>) &#123;</span><br><span class="line">  <span class="comment">// 使用有效主机名获取域名后缀部分（用于构建完整的代理域名）</span></span><br><span class="line">  <span class="keyword">const</span> domain_suffix = effective_hostname.<span class="title function_">substring</span>(host_prefix.<span class="property">length</span>);</span><br><span class="line">  </span><br><span class="line">  <span class="comment">// 替换所有域名引用</span></span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">const</span> [original_domain, _] <span class="keyword">of</span> <span class="title class_">Object</span>.<span class="title function_">entries</span>(domain_mappings)) &#123;</span><br><span class="line">    <span class="keyword">const</span> escaped_domain = original_domain.<span class="title function_">replace</span>(<span class="regexp">/\./g</span>, <span class="string">&#x27;\\.&#x27;</span>);</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 统一为 [原生域名]-github.com</span></span><br><span class="line">    <span class="keyword">const</span> current_prefix = original_domain.<span class="title function_">replace</span>(<span class="regexp">/\./g</span>, <span class="string">&#x27;-&#x27;</span>) + <span class="string">&#x27;-gh.&#x27;</span>;</span><br><span class="line">    <span class="keyword">const</span> full_proxy_domain = <span class="string">`<span class="subst">$&#123;current_prefix&#125;</span><span class="subst">$&#123;domain_suffix&#125;</span>`</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 替换完整URLs</span></span><br><span class="line">    text = text.<span class="title function_">replace</span>(</span><br><span class="line">      <span class="keyword">new</span> <span class="title class_">RegExp</span>(<span class="string">`https?://<span class="subst">$&#123;escaped_domain&#125;</span>(?=/|&quot;|&#x27;|\\s|$)`</span>, <span class="string">&#x27;g&#x27;</span>),</span><br><span class="line">      <span class="string">`https://<span class="subst">$&#123;full_proxy_domain&#125;</span>`</span></span><br><span class="line">    );</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 替换协议相对URLs</span></span><br><span class="line">    text = text.<span class="title function_">replace</span>(</span><br><span class="line">      <span class="keyword">new</span> <span class="title class_">RegExp</span>(<span class="string">`//<span class="subst">$&#123;escaped_domain&#125;</span>(?=/|&quot;|&#x27;|\\s|$)`</span>, <span class="string">&#x27;g&#x27;</span>),</span><br><span class="line">      <span class="string">`//<span class="subst">$&#123;full_proxy_domain&#125;</span>`</span></span><br><span class="line">    );</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> text;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 修改 URL（用于重定向等）</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">modifyUrl</span>(<span class="params">url_str, host_prefix, effective_hostname</span>) &#123;</span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> url = <span class="keyword">new</span> <span class="title function_">URL</span>(url_str);</span><br><span class="line">    <span class="keyword">const</span> domain_suffix = effective_hostname.<span class="title function_">substring</span>(host_prefix.<span class="property">length</span>);</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">const</span> [original_domain, _] <span class="keyword">of</span> <span class="title class_">Object</span>.<span class="title function_">entries</span>(domain_mappings)) &#123;</span><br><span class="line">      <span class="keyword">if</span> (url.<span class="property">host</span> === original_domain) &#123;</span><br><span class="line">        <span class="keyword">const</span> current_prefix = original_domain.<span class="title function_">replace</span>(<span class="regexp">/\./g</span>, <span class="string">&#x27;-&#x27;</span>) + <span class="string">&#x27;-gh.&#x27;</span>;</span><br><span class="line">        url.<span class="property">host</span> = <span class="string">`<span class="subst">$&#123;current_prefix&#125;</span><span class="subst">$&#123;domain_suffix&#125;</span>`</span>;</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> url.<span class="property">href</span>;</span><br><span class="line">  &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">    <span class="keyword">return</span> url_str;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol><li>点击”保存”按钮、</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="片段代码-2"><h3 id="2-创建Docker反代片段"><a href="#2-创建Docker反代片段" class="headerlink" title="2. 创建Docker反代片段"></a>2. 创建Docker反代片段</h3><ol><li>点击”创建片段”按钮</li><li>在名称输入框中输入一个描述性名称，例如”Docker反代”</li><li>在编辑框中粘贴以下代码：</li></ol><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br><span class="line">421</span><br><span class="line">422</span><br><span class="line">423</span><br><span class="line">424</span><br><span class="line">425</span><br><span class="line">426</span><br><span class="line">427</span><br><span class="line">428</span><br><span class="line">429</span><br><span class="line">430</span><br><span class="line">431</span><br><span class="line">432</span><br><span class="line">433</span><br><span class="line">434</span><br><span class="line">435</span><br><span class="line">436</span><br><span class="line">437</span><br><span class="line">438</span><br><span class="line">439</span><br><span class="line">440</span><br><span class="line">441</span><br><span class="line">442</span><br><span class="line">443</span><br><span class="line">444</span><br><span class="line">445</span><br><span class="line">446</span><br><span class="line">447</span><br><span class="line">448</span><br><span class="line">449</span><br><span class="line">450</span><br><span class="line">451</span><br><span class="line">452</span><br><span class="line">453</span><br><span class="line">454</span><br><span class="line">455</span><br><span class="line">456</span><br><span class="line">457</span><br><span class="line">458</span><br><span class="line">459</span><br><span class="line">460</span><br><span class="line">461</span><br><span class="line">462</span><br><span class="line">463</span><br><span class="line">464</span><br><span class="line">465</span><br><span class="line">466</span><br><span class="line">467</span><br><span class="line">468</span><br><span class="line">469</span><br><span class="line">470</span><br><span class="line">471</span><br><span class="line">472</span><br><span class="line">473</span><br><span class="line">474</span><br><span class="line">475</span><br><span class="line">476</span><br><span class="line">477</span><br><span class="line">478</span><br><span class="line">479</span><br><span class="line">480</span><br><span class="line">481</span><br><span class="line">482</span><br><span class="line">483</span><br><span class="line">484</span><br><span class="line">485</span><br><span class="line">486</span><br><span class="line">487</span><br><span class="line">488</span><br><span class="line">489</span><br><span class="line">490</span><br><span class="line">491</span><br><span class="line">492</span><br><span class="line">493</span><br><span class="line">494</span><br><span class="line">495</span><br><span class="line">496</span><br><span class="line">497</span><br><span class="line">498</span><br><span class="line">499</span><br><span class="line">500</span><br><span class="line">501</span><br><span class="line">502</span><br><span class="line">503</span><br><span class="line">504</span><br><span class="line">505</span><br><span class="line">506</span><br><span class="line">507</span><br><span class="line">508</span><br><span class="line">509</span><br><span class="line">510</span><br><span class="line">511</span><br><span class="line">512</span><br><span class="line">513</span><br><span class="line">514</span><br><span class="line">515</span><br><span class="line">516</span><br><span class="line">517</span><br><span class="line">518</span><br><span class="line">519</span><br><span class="line">520</span><br><span class="line">521</span><br><span class="line">522</span><br><span class="line">523</span><br><span class="line">524</span><br><span class="line">525</span><br><span class="line">526</span><br><span class="line">527</span><br><span class="line">528</span><br><span class="line">529</span><br><span class="line">530</span><br><span class="line">531</span><br><span class="line">532</span><br><span class="line">533</span><br><span class="line">534</span><br><span class="line">535</span><br><span class="line">536</span><br><span class="line">537</span><br><span class="line">538</span><br><span class="line">539</span><br><span class="line">540</span><br><span class="line">541</span><br><span class="line">542</span><br><span class="line">543</span><br><span class="line">544</span><br><span class="line">545</span><br><span class="line">546</span><br><span class="line">547</span><br><span class="line">548</span><br><span class="line">549</span><br><span class="line">550</span><br><span class="line">551</span><br><span class="line">552</span><br><span class="line">553</span><br><span class="line">554</span><br><span class="line">555</span><br><span class="line">556</span><br><span class="line">557</span><br><span class="line">558</span><br><span class="line">559</span><br><span class="line">560</span><br><span class="line">561</span><br><span class="line">562</span><br><span class="line">563</span><br><span class="line">564</span><br><span class="line">565</span><br><span class="line">566</span><br><span class="line">567</span><br><span class="line">568</span><br><span class="line">569</span><br><span class="line">570</span><br><span class="line">571</span><br><span class="line">572</span><br><span class="line">573</span><br><span class="line">574</span><br><span class="line">575</span><br><span class="line">576</span><br><span class="line">577</span><br><span class="line">578</span><br><span class="line">579</span><br><span class="line">580</span><br><span class="line">581</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="variable constant_">DEFAULT_HUB_HOST</span> = <span class="string">&#x27;registry-1.docker.io&#x27;</span></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">AUTH_URL</span> = <span class="string">&#x27;https://auth.docker.io&#x27;</span></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">DEFAULT_BLOCKED_UA</span> = [<span class="string">&#x27;netcraft&#x27;</span>]</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">SNIPPET_CONFIG</span> = &#123;</span><br><span class="line">  <span class="title class_">URL302</span>: <span class="string">&#x27;&#x27;</span>,</span><br><span class="line">  <span class="attr">URL</span>: <span class="string">&#x27;&#x27;</span>,</span><br><span class="line">  <span class="attr">UA</span>: <span class="string">&#x27;&#x27;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">routeByHosts</span>(<span class="params">host, defaultHubHost</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> routes = &#123;</span><br><span class="line">    <span class="attr">quay</span>: <span class="string">&#x27;quay.io&#x27;</span>,</span><br><span class="line">    <span class="attr">gcr</span>: <span class="string">&#x27;gcr.io&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;k8s-gcr&#x27;</span>: <span class="string">&#x27;k8s.gcr.io&#x27;</span>,</span><br><span class="line">    <span class="attr">k8s</span>: <span class="string">&#x27;registry.k8s.io&#x27;</span>,</span><br><span class="line">    <span class="attr">ghcr</span>: <span class="string">&#x27;ghcr.io&#x27;</span>,</span><br><span class="line">    <span class="attr">cloudsmith</span>: <span class="string">&#x27;docker.cloudsmith.io&#x27;</span>,</span><br><span class="line">    <span class="attr">nvcr</span>: <span class="string">&#x27;nvcr.io&#x27;</span>,</span><br><span class="line">    <span class="attr">test</span>: <span class="string">&#x27;registry-1.docker.io&#x27;</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">if</span> (host <span class="keyword">in</span> routes) <span class="keyword">return</span> [routes[host], <span class="literal">false</span>]</span><br><span class="line">  <span class="keyword">return</span> [defaultHubHost, <span class="literal">true</span>]</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">PREFLIGHT_INIT</span> = &#123;</span><br><span class="line">  <span class="attr">headers</span>: <span class="keyword">new</span> <span class="title class_">Headers</span>(&#123;</span><br><span class="line">    <span class="string">&#x27;access-control-allow-origin&#x27;</span>: <span class="string">&#x27;*&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;access-control-allow-methods&#x27;</span>: <span class="string">&#x27;GET,POST,PUT,PATCH,TRACE,DELETE,HEAD,OPTIONS&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;access-control-max-age&#x27;</span>: <span class="string">&#x27;1728000&#x27;</span></span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">makeRes</span>(<span class="params">body, status = <span class="number">200</span>, headers = &#123;&#125;</span>) &#123;</span><br><span class="line">  headers[<span class="string">&#x27;access-control-allow-origin&#x27;</span>] = <span class="string">&#x27;*&#x27;</span></span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(body, &#123; status, headers &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">newUrl</span>(<span class="params">urlStr, base</span>) &#123;</span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title function_">URL</span>(urlStr, base)</span><br><span class="line">  &#125; <span class="keyword">catch</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">nginx</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="string">`</span></span><br><span class="line"><span class="string">  &lt;!DOCTYPE html&gt;</span></span><br><span class="line"><span class="string">  &lt;html&gt;</span></span><br><span class="line"><span class="string">  &lt;head&gt;</span></span><br><span class="line"><span class="string">  &lt;title&gt;Welcome to nginx!&lt;/title&gt;</span></span><br><span class="line"><span class="string">  &lt;style&gt;</span></span><br><span class="line"><span class="string">    body &#123;</span></span><br><span class="line"><span class="string">      width: 35em;</span></span><br><span class="line"><span class="string">      margin: 0 auto;</span></span><br><span class="line"><span class="string">      font-family: Tahoma, Verdana, Arial, sans-serif;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">  &lt;/style&gt;</span></span><br><span class="line"><span class="string">  &lt;/head&gt;</span></span><br><span class="line"><span class="string">  &lt;body&gt;</span></span><br><span class="line"><span class="string">  &lt;h1&gt;Welcome to nginx!&lt;/h1&gt;</span></span><br><span class="line"><span class="string">  &lt;p&gt;If you see this page, the nginx web server is successfully installed and</span></span><br><span class="line"><span class="string">  working. Further configuration is required.&lt;/p&gt;</span></span><br><span class="line"><span class="string">  &lt;p&gt;For online documentation and support please refer to</span></span><br><span class="line"><span class="string">  &lt;a href=&quot;http://nginx.org/&quot;&gt;nginx.org&lt;/a&gt;.&lt;br/&gt;</span></span><br><span class="line"><span class="string">  Commercial support is available at</span></span><br><span class="line"><span class="string">  &lt;a href=&quot;http://nginx.com/&quot;&gt;nginx.com&lt;/a&gt;.&lt;/p&gt;</span></span><br><span class="line"><span class="string">  &lt;p&gt;&lt;em&gt;Thank you for using nginx.&lt;/em&gt;&lt;/p&gt;</span></span><br><span class="line"><span class="string">  &lt;/body&gt;</span></span><br><span class="line"><span class="string">  &lt;/html&gt;</span></span><br><span class="line"><span class="string">  `</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">searchInterface</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="string">`</span></span><br><span class="line"><span class="string">  &lt;!DOCTYPE html&gt;</span></span><br><span class="line"><span class="string">  &lt;html&gt;</span></span><br><span class="line"><span class="string">  &lt;head&gt;</span></span><br><span class="line"><span class="string">    &lt;title&gt;Docker Hub 镜像搜索&lt;/title&gt;</span></span><br><span class="line"><span class="string">    &lt;meta charset=&quot;UTF-8&quot;&gt;</span></span><br><span class="line"><span class="string">    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;</span></span><br><span class="line"><span class="string">    &lt;style&gt;</span></span><br><span class="line"><span class="string">    :root &#123;</span></span><br><span class="line"><span class="string">      --github-color: rgb(27,86,198);</span></span><br><span class="line"><span class="string">      --github-bg-color: #ffffff;</span></span><br><span class="line"><span class="string">      --primary-color: #0066ff;</span></span><br><span class="line"><span class="string">      --primary-dark: #0052cc;</span></span><br><span class="line"><span class="string">      --gradient-start: #1a90ff;</span></span><br><span class="line"><span class="string">      --gradient-end: #003eb3;</span></span><br><span class="line"><span class="string">      --text-color: #ffffff;</span></span><br><span class="line"><span class="string">      --shadow-color: rgba(0,0,0,0.1);</span></span><br><span class="line"><span class="string">      --transition-time: 0.3s;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    </span></span><br><span class="line"><span class="string">    * &#123;</span></span><br><span class="line"><span class="string">      box-sizing: border-box;</span></span><br><span class="line"><span class="string">      margin: 0;</span></span><br><span class="line"><span class="string">      padding: 0;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    body &#123;</span></span><br><span class="line"><span class="string">      font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, &quot;Helvetica Neue&quot;, Arial, sans-serif;</span></span><br><span class="line"><span class="string">      display: flex;</span></span><br><span class="line"><span class="string">      flex-direction: column;</span></span><br><span class="line"><span class="string">      justify-content: center;</span></span><br><span class="line"><span class="string">      align-items: center;</span></span><br><span class="line"><span class="string">      min-height: 100vh;</span></span><br><span class="line"><span class="string">      margin: 0;</span></span><br><span class="line"><span class="string">      background: linear-gradient(135deg, var(--gradient-start) 0%, var(--gradient-end) 100%);</span></span><br><span class="line"><span class="string">      padding: 20px;</span></span><br><span class="line"><span class="string">      color: var(--text-color);</span></span><br><span class="line"><span class="string">      overflow-x: hidden;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    .container &#123;</span></span><br><span class="line"><span class="string">      text-align: center;</span></span><br><span class="line"><span class="string">      width: 100%;</span></span><br><span class="line"><span class="string">      max-width: 800px;</span></span><br><span class="line"><span class="string">      padding: 20px;</span></span><br><span class="line"><span class="string">      margin: 0 auto;</span></span><br><span class="line"><span class="string">      display: flex;</span></span><br><span class="line"><span class="string">      flex-direction: column;</span></span><br><span class="line"><span class="string">      justify-content: center;</span></span><br><span class="line"><span class="string">      min-height: 60vh;</span></span><br><span class="line"><span class="string">      animation: fadeIn 0.8s ease-out;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    @keyframes fadeIn &#123;</span></span><br><span class="line"><span class="string">      from &#123; opacity: 0; transform: translateY(20px); &#125;</span></span><br><span class="line"><span class="string">      to &#123; opacity: 1; transform: translateY(0); &#125;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    .github-corner &#123;</span></span><br><span class="line"><span class="string">      position: fixed;</span></span><br><span class="line"><span class="string">      top: 0;</span></span><br><span class="line"><span class="string">      right: 0;</span></span><br><span class="line"><span class="string">      z-index: 999;</span></span><br><span class="line"><span class="string">      transition: transform var(--transition-time) ease;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    .github-corner:hover &#123;</span></span><br><span class="line"><span class="string">      transform: scale(1.08);</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    .github-corner svg &#123;</span></span><br><span class="line"><span class="string">      fill: var(--github-bg-color);</span></span><br><span class="line"><span class="string">      color: var(--github-color);</span></span><br><span class="line"><span class="string">      position: absolute;</span></span><br><span class="line"><span class="string">      top: 0;</span></span><br><span class="line"><span class="string">      border: 0;</span></span><br><span class="line"><span class="string">      right: 0;</span></span><br><span class="line"><span class="string">      width: 80px;</span></span><br><span class="line"><span class="string">      height: 80px;</span></span><br><span class="line"><span class="string">      filter: drop-shadow(0 2px 5px rgba(0, 0, 0, 0.2));</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    .logo &#123;</span></span><br><span class="line"><span class="string">      margin-bottom: 20px;</span></span><br><span class="line"><span class="string">      transition: transform var(--transition-time) ease;</span></span><br><span class="line"><span class="string">      animation: float 6s ease-in-out infinite;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    @keyframes float &#123;</span></span><br><span class="line"><span class="string">      0%, 100% &#123; transform: translateY(0); &#125;</span></span><br><span class="line"><span class="string">      50% &#123; transform: translateY(-10px); &#125;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    .logo:hover &#123;</span></span><br><span class="line"><span class="string">      transform: scale(1.08) rotate(5deg);</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    .logo svg &#123;</span></span><br><span class="line"><span class="string">      filter: drop-shadow(0 5px 15px rgba(0, 0, 0, 0.2));</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    .title &#123;</span></span><br><span class="line"><span class="string">      color: var(--text-color);</span></span><br><span class="line"><span class="string">      font-size: 2.3em;</span></span><br><span class="line"><span class="string">      margin-bottom: 10px;</span></span><br><span class="line"><span class="string">      text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);</span></span><br><span class="line"><span class="string">      font-weight: 700;</span></span><br><span class="line"><span class="string">      letter-spacing: -0.5px;</span></span><br><span class="line"><span class="string">      animation: slideInFromTop 0.5s ease-out 0.2s both;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    @keyframes slideInFromTop &#123;</span></span><br><span class="line"><span class="string">      from &#123; opacity: 0; transform: translateY(-20px); &#125;</span></span><br><span class="line"><span class="string">      to &#123; opacity: 1; transform: translateY(0); &#125;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    .subtitle &#123;</span></span><br><span class="line"><span class="string">      color: rgba(255, 255, 255, 0.9);</span></span><br><span class="line"><span class="string">      font-size: 1.1em;</span></span><br><span class="line"><span class="string">      margin-bottom: 25px;</span></span><br><span class="line"><span class="string">      max-width: 600px;</span></span><br><span class="line"><span class="string">      margin-left: auto;</span></span><br><span class="line"><span class="string">      margin-right: auto;</span></span><br><span class="line"><span class="string">      line-height: 1.4;</span></span><br><span class="line"><span class="string">      animation: slideInFromTop 0.5s ease-out 0.4s both;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    .search-container &#123;</span></span><br><span class="line"><span class="string">      display: flex;</span></span><br><span class="line"><span class="string">      align-items: stretch;</span></span><br><span class="line"><span class="string">      width: 100%;</span></span><br><span class="line"><span class="string">      max-width: 600px;</span></span><br><span class="line"><span class="string">      margin: 0 auto;</span></span><br><span class="line"><span class="string">      height: 55px;</span></span><br><span class="line"><span class="string">      position: relative;</span></span><br><span class="line"><span class="string">      animation: slideInFromBottom 0.5s ease-out 0.6s both;</span></span><br><span class="line"><span class="string">      box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);</span></span><br><span class="line"><span class="string">      border-radius: 12px;</span></span><br><span class="line"><span class="string">      overflow: hidden;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    @keyframes slideInFromBottom &#123;</span></span><br><span class="line"><span class="string">      from &#123; opacity: 0; transform: translateY(20px); &#125;</span></span><br><span class="line"><span class="string">      to &#123; opacity: 1; transform: translateY(0); &#125;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    #search-input &#123;</span></span><br><span class="line"><span class="string">      flex: 1;</span></span><br><span class="line"><span class="string">      padding: 0 20px;</span></span><br><span class="line"><span class="string">      font-size: 16px;</span></span><br><span class="line"><span class="string">      border: none;</span></span><br><span class="line"><span class="string">      outline: none;</span></span><br><span class="line"><span class="string">      transition: all var(--transition-time) ease;</span></span><br><span class="line"><span class="string">      height: 100%;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    #search-input:focus &#123;</span></span><br><span class="line"><span class="string">      padding-left: 25px;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    #search-button &#123;</span></span><br><span class="line"><span class="string">      width: 60px;</span></span><br><span class="line"><span class="string">      background-color: var(--primary-color);</span></span><br><span class="line"><span class="string">      border: none;</span></span><br><span class="line"><span class="string">      cursor: pointer;</span></span><br><span class="line"><span class="string">      transition: all var(--transition-time) ease;</span></span><br><span class="line"><span class="string">      height: 100%;</span></span><br><span class="line"><span class="string">      display: flex;</span></span><br><span class="line"><span class="string">      align-items: center;</span></span><br><span class="line"><span class="string">      justify-content: center;</span></span><br><span class="line"><span class="string">      position: relative;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    #search-button svg &#123;</span></span><br><span class="line"><span class="string">      transition: transform 0.3s ease;</span></span><br><span class="line"><span class="string">      stroke: white;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    #search-button:hover &#123;</span></span><br><span class="line"><span class="string">      background-color: var(--primary-dark);</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    #search-button:hover svg &#123;</span></span><br><span class="line"><span class="string">      transform: translateX(2px);</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    #search-button:active svg &#123;</span></span><br><span class="line"><span class="string">      transform: translateX(4px);</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    .tips &#123;</span></span><br><span class="line"><span class="string">      color: rgba(255, 255, 255, 0.8);</span></span><br><span class="line"><span class="string">      margin-top: 20px;</span></span><br><span class="line"><span class="string">      font-size: 0.9em;</span></span><br><span class="line"><span class="string">      animation: fadeIn 0.5s ease-out 0.8s both;</span></span><br><span class="line"><span class="string">      transition: transform var(--transition-time) ease;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    .tips:hover &#123;</span></span><br><span class="line"><span class="string">      transform: translateY(-2px);</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    @media (max-width: 768px) &#123;</span></span><br><span class="line"><span class="string">      .container &#123;</span></span><br><span class="line"><span class="string">        padding: 20px 15px;</span></span><br><span class="line"><span class="string">        min-height: 60vh;</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string">      .title &#123;</span></span><br><span class="line"><span class="string">        font-size: 2em;</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string">      .subtitle &#123;</span></span><br><span class="line"><span class="string">        font-size: 1em;</span></span><br><span class="line"><span class="string">        margin-bottom: 20px;</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string">      .search-container &#123;</span></span><br><span class="line"><span class="string">        height: 50px;</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    @media (max-width: 480px) &#123;</span></span><br><span class="line"><span class="string">      .container &#123;</span></span><br><span class="line"><span class="string">        padding: 15px 10px;</span></span><br><span class="line"><span class="string">        min-height: 60vh;</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string">      .github-corner svg &#123;</span></span><br><span class="line"><span class="string">        width: 60px;</span></span><br><span class="line"><span class="string">        height: 60px;</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string">      .search-container &#123;</span></span><br><span class="line"><span class="string">        height: 45px;</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string">      #search-input &#123;</span></span><br><span class="line"><span class="string">        padding: 0 15px;</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string">      #search-button &#123;</span></span><br><span class="line"><span class="string">        width: 50px;</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string">      #search-button svg &#123;</span></span><br><span class="line"><span class="string">        width: 18px;</span></span><br><span class="line"><span class="string">        height: 18px;</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string">      .title &#123;</span></span><br><span class="line"><span class="string">        font-size: 1.7em;</span></span><br><span class="line"><span class="string">        margin-bottom: 8px;</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string">      .subtitle &#123;</span></span><br><span class="line"><span class="string">        font-size: 0.95em;</span></span><br><span class="line"><span class="string">        margin-bottom: 18px;</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    &lt;/style&gt;</span></span><br><span class="line"><span class="string">  &lt;/head&gt;</span></span><br><span class="line"><span class="string">  &lt;body&gt;</span></span><br><span class="line"><span class="string">    &lt;a href=&quot;https://github.com/cmliu/CF-Workers-docker.io&quot; target=&quot;_blank&quot; class=&quot;github-corner&quot; aria-label=&quot;View source on Github&quot;&gt;</span></span><br><span class="line"><span class="string">      &lt;svg viewBox=&quot;0 0 250 250&quot; aria-hidden=&quot;true&quot;&gt;</span></span><br><span class="line"><span class="string">        &lt;path d=&quot;M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z&quot;&gt;&lt;/path&gt;</span></span><br><span class="line"><span class="string">        &lt;path d=&quot;M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2&quot; fill=&quot;currentColor&quot; style=&quot;transform-origin: 130px 106px;&quot; class=&quot;octo-arm&quot;&gt;&lt;/path&gt;</span></span><br><span class="line"><span class="string">        &lt;path d=&quot;M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z&quot; fill=&quot;currentColor&quot; class=&quot;octo-body&quot;&gt;&lt;/path&gt;</span></span><br><span class="line"><span class="string">      &lt;/svg&gt;</span></span><br><span class="line"><span class="string">    &lt;/a&gt;</span></span><br><span class="line"><span class="string">    &lt;div class=&quot;container&quot;&gt;</span></span><br><span class="line"><span class="string">      &lt;div class=&quot;logo&quot;&gt;</span></span><br><span class="line"><span class="string">        &lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 24 18&quot; fill=&quot;#ffffff&quot; width=&quot;110&quot; height=&quot;85&quot;&gt;</span></span><br><span class="line"><span class="string">          &lt;path d=&quot;M23.763 6.886c-.065-.053-.673-.512-1.954-.512-.32 0-.659.03-1.01.087-.248-1.703-1.651-2.533-1.716-2.57l-.345-.2-.227.328a4.596 4.596 0 0 0-.611 1.433c-.23.972-.09 1.884.403 2.666-.596.331-1.546.418-1.744.42H.752a.753.753 0 0 0-.75.749c-.007 1.456.233 2.864.692 4.07.545 1.43 1.355 2.483 2.409 3.13 1.181.725 3.104 1.14 5.276 1.14 1.016 0 2.03-.092 2.93-.266 1.417-.273 2.705-.742 3.826-1.391a10.497 10.497 0 0 0 2.61-2.14c1.252-1.42 1.998-3.005 2.553-4.408.075.003.148.005.221.005 1.371 0 2.215-.55 2.68-1.01.505-.5.685-.998.704-1.053L24 7.076l-.237-.19Z&quot;&gt;&lt;/path&gt;</span></span><br><span class="line"><span class="string">          &lt;path d=&quot;M2.216 8.075h2.119a.186.186 0 0 0 .185-.186V6a.186.186 0 0 0-.185-.186H2.216A.186.186 0 0 0 2.031 6v1.89c0 .103.083.186.185.186Zm2.92 0h2.118a.185.185 0 0 0 .185-.186V6a.185.185 0 0 0-.185-.186H5.136A.185.185 0 0 0 4.95 6v1.89c0 .103.083.186.186.186Zm2.964 0h2.118a.186.186 0 0 0 .185-.186V6a.186.186 0 0 0-.185-.186H8.1A.185.185 0 0 0 7.914 6v1.89c0 .103.083.186.186.186Zm2.928 0h2.119a.185.185 0 0 0 .185-.186V6a.185.185 0 0 0-.185-.186h-2.119a.186.186 0 0 0-.185.186v1.89c0 .103.083.186.185.186Zm-5.892-2.72h2.118a.185.185 0 0 0 .185-.186V3.28a.186.186 0 0 0-.185-.186H5.136a.186.186 0 0 0-.186.186v1.89c0 .103.083.186.186.186Zm2.964 0h2.118a.186.186 0 0 0 .185-.186V3.28a.186.186 0 0 0-.185-.186H8.1a.186.186 0 0 0-.186.186v1.89c0 .103.083.186.186.186Zm2.928 0h2.119a.185.185 0 0 0 .185-.186V3.28a.185.185 0 0 0-.185-.186h-2.119a.186.186 0 0 0-.185.186v1.89c0 .103.083.186.185.186Zm0-2.72h2.119a.186.186 0 0 0 .185-.186V.56a.185.185 0 0 0-.185-.186h-2.119a.186.186 0 0 0-.185.186v1.89c0 .103.083.186.185.186Zm2.955 5.44h2.118a.185.185 0 0 0 .186-.186V6a.185.185 0 0 0-.186-.186h-2.118a.185.185 0 0 0-.185.186v1.89c0 .103.083.186.185.186Z&quot;&gt;&lt;/path&gt;</span></span><br><span class="line"><span class="string">        &lt;/svg&gt;</span></span><br><span class="line"><span class="string">      &lt;/div&gt;</span></span><br><span class="line"><span class="string">      &lt;h1 class=&quot;title&quot;&gt;Docker Hub 镜像搜索&lt;/h1&gt;</span></span><br><span class="line"><span class="string">      &lt;p class=&quot;subtitle&quot;&gt;快速查找、下载和部署 Docker 容器镜像&lt;/p&gt;</span></span><br><span class="line"><span class="string">      &lt;div class=&quot;search-container&quot;&gt;</span></span><br><span class="line"><span class="string">        &lt;input type=&quot;text&quot; id=&quot;search-input&quot; placeholder=&quot;输入关键词搜索镜像，如: nginx, mysql, redis...&quot;&gt;</span></span><br><span class="line"><span class="string">        &lt;button id=&quot;search-button&quot; title=&quot;搜索&quot;&gt;</span></span><br><span class="line"><span class="string">          &lt;svg width=&quot;20&quot; height=&quot;20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; viewBox=&quot;0 0 24 24&quot;&gt;</span></span><br><span class="line"><span class="string">            &lt;path d=&quot;M13 5l7 7-7 7M5 5l7 7-7 7&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;/path&gt;</span></span><br><span class="line"><span class="string">          &lt;/svg&gt;</span></span><br><span class="line"><span class="string">        &lt;/button&gt;</span></span><br><span class="line"><span class="string">      &lt;/div&gt;</span></span><br><span class="line"><span class="string">      &lt;p class=&quot;tips&quot;&gt;基于 Cloudflare Workers / Pages 构建，利用全球边缘网络实现毫秒级响应。&lt;/p&gt;</span></span><br><span class="line"><span class="string">    &lt;/div&gt;</span></span><br><span class="line"><span class="string">    &lt;script&gt;</span></span><br><span class="line"><span class="string">    function performSearch() &#123;</span></span><br><span class="line"><span class="string">      const query = document.getElementById(&#x27;search-input&#x27;).value;</span></span><br><span class="line"><span class="string">      if (query) &#123;</span></span><br><span class="line"><span class="string">        window.location.href = &#x27;/search?q=&#x27; + encodeURIComponent(query);</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">    document.getElementById(&#x27;search-button&#x27;).addEventListener(&#x27;click&#x27;, performSearch);</span></span><br><span class="line"><span class="string">    document.getElementById(&#x27;search-input&#x27;).addEventListener(&#x27;keypress&#x27;, function(event) &#123;</span></span><br><span class="line"><span class="string">      if (event.key === &#x27;Enter&#x27;) &#123;</span></span><br><span class="line"><span class="string">        performSearch();</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string">    &#125;);</span></span><br><span class="line"><span class="string">    window.addEventListener(&#x27;load&#x27;, function() &#123;</span></span><br><span class="line"><span class="string">      document.getElementById(&#x27;search-input&#x27;).focus();</span></span><br><span class="line"><span class="string">    &#125;);</span></span><br><span class="line"><span class="string">    &lt;/script&gt;</span></span><br><span class="line"><span class="string">  &lt;/body&gt;</span></span><br><span class="line"><span class="string">  &lt;/html&gt;</span></span><br><span class="line"><span class="string">  `</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">httpHandler</span>(<span class="params">req, pathname, baseHost</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> reqHdrRaw = req.<span class="property">headers</span></span><br><span class="line">  <span class="keyword">if</span> (req.<span class="property">method</span> === <span class="string">&#x27;OPTIONS&#x27;</span> &amp;&amp; reqHdrRaw.<span class="title function_">has</span>(<span class="string">&#x27;access-control-request-headers&#x27;</span>)) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="literal">null</span>, <span class="variable constant_">PREFLIGHT_INIT</span>)</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">const</span> reqHdrNew = <span class="keyword">new</span> <span class="title class_">Headers</span>(reqHdrRaw)</span><br><span class="line">  reqHdrNew.<span class="title function_">delete</span>(<span class="string">&#x27;Authorization&#x27;</span>)</span><br><span class="line">  <span class="keyword">const</span> urlObj = <span class="title function_">newUrl</span>(pathname, <span class="string">`https://<span class="subst">$&#123;baseHost&#125;</span>`</span>)</span><br><span class="line">  <span class="keyword">const</span> reqInit = &#123;</span><br><span class="line">    <span class="attr">method</span>: req.<span class="property">method</span>,</span><br><span class="line">    <span class="attr">headers</span>: reqHdrNew,</span><br><span class="line">    <span class="attr">redirect</span>: <span class="string">&#x27;follow&#x27;</span>,</span><br><span class="line">    <span class="attr">body</span>: req.<span class="property">body</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> <span class="title function_">proxy</span>(urlObj, reqInit, <span class="string">&#x27;&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">proxy</span>(<span class="params">urlObj, reqInit, rawLen</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> res = <span class="keyword">await</span> <span class="title function_">fetch</span>(urlObj.<span class="property">href</span>, reqInit)</span><br><span class="line">  <span class="keyword">const</span> resHdrOld = res.<span class="property">headers</span></span><br><span class="line">  <span class="keyword">const</span> resHdrNew = <span class="keyword">new</span> <span class="title class_">Headers</span>(resHdrOld)</span><br><span class="line">  <span class="keyword">if</span> (rawLen) &#123;</span><br><span class="line">    <span class="keyword">const</span> newLen = resHdrOld.<span class="title function_">get</span>(<span class="string">&#x27;content-length&#x27;</span>) || <span class="string">&#x27;&#x27;</span></span><br><span class="line">    <span class="keyword">if</span> (rawLen !== newLen) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="title function_">makeRes</span>(res.<span class="property">body</span>, <span class="number">400</span>, &#123;</span><br><span class="line">        <span class="string">&#x27;--error&#x27;</span>: <span class="string">`bad len: <span class="subst">$&#123;newLen&#125;</span>, except: <span class="subst">$&#123;rawLen&#125;</span>`</span>,</span><br><span class="line">        <span class="string">&#x27;access-control-expose-headers&#x27;</span>: <span class="string">&#x27;--error&#x27;</span></span><br><span class="line">      &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  resHdrNew.<span class="title function_">set</span>(<span class="string">&#x27;access-control-expose-headers&#x27;</span>, <span class="string">&#x27;*&#x27;</span>)</span><br><span class="line">  resHdrNew.<span class="title function_">set</span>(<span class="string">&#x27;access-control-allow-origin&#x27;</span>, <span class="string">&#x27;*&#x27;</span>)</span><br><span class="line">  resHdrNew.<span class="title function_">set</span>(<span class="string">&#x27;Cache-Control&#x27;</span>, <span class="string">&#x27;max-age=1500&#x27;</span>)</span><br><span class="line">  resHdrNew.<span class="title function_">delete</span>(<span class="string">&#x27;content-security-policy&#x27;</span>)</span><br><span class="line">  resHdrNew.<span class="title function_">delete</span>(<span class="string">&#x27;content-security-policy-report-only&#x27;</span>)</span><br><span class="line">  resHdrNew.<span class="title function_">delete</span>(<span class="string">&#x27;clear-site-data&#x27;</span>)</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(res.<span class="property">body</span>, &#123;</span><br><span class="line">    <span class="attr">status</span>: res.<span class="property">status</span>,</span><br><span class="line">    <span class="attr">headers</span>: resHdrNew</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">parseCsvInput</span>(<span class="params">input</span>) &#123;</span><br><span class="line">  <span class="keyword">let</span> text = input.<span class="title function_">replace</span>(<span class="regexp">/[\t |&quot;&#x27;\r\n]+/g</span>, <span class="string">&#x27;,&#x27;</span>).<span class="title function_">replace</span>(<span class="regexp">/,+/g</span>, <span class="string">&#x27;,&#x27;</span>)</span><br><span class="line">  <span class="keyword">if</span> (text.<span class="title function_">charAt</span>(<span class="number">0</span>) === <span class="string">&#x27;,&#x27;</span>) text = text.<span class="title function_">slice</span>(<span class="number">1</span>)</span><br><span class="line">  <span class="keyword">if</span> (text.<span class="title function_">charAt</span>(text.<span class="property">length</span> - <span class="number">1</span>) === <span class="string">&#x27;,&#x27;</span>) text = text.<span class="title function_">slice</span>(<span class="number">0</span>, text.<span class="property">length</span> - <span class="number">1</span>)</span><br><span class="line">  <span class="keyword">return</span> text ? text.<span class="title function_">split</span>(<span class="string">&#x27;,&#x27;</span>) : []</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="keyword">async</span> <span class="title function_">fetch</span>(<span class="params">request</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">getReqHeader</span> = (<span class="params">key</span>) =&gt; request.<span class="property">headers</span>.<span class="title function_">get</span>(key)</span><br><span class="line">    <span class="keyword">const</span> originalUrl = <span class="keyword">new</span> <span class="title function_">URL</span>(request.<span class="property">url</span>)</span><br><span class="line">    <span class="keyword">let</span> url = <span class="keyword">new</span> <span class="title function_">URL</span>(request.<span class="property">url</span>)</span><br><span class="line">    <span class="keyword">const</span> userAgentHeader = request.<span class="property">headers</span>.<span class="title function_">get</span>(<span class="string">&#x27;User-Agent&#x27;</span>)</span><br><span class="line">    <span class="keyword">const</span> userAgent = userAgentHeader ? userAgentHeader.<span class="title function_">toLowerCase</span>() : <span class="string">&#x27;null&#x27;</span></span><br><span class="line">    <span class="keyword">const</span> workersUrl = <span class="string">`https://<span class="subst">$&#123;originalUrl.hostname&#125;</span>`</span></span><br><span class="line">    <span class="keyword">const</span> ns = url.<span class="property">searchParams</span>.<span class="title function_">get</span>(<span class="string">&#x27;ns&#x27;</span>)</span><br><span class="line">    <span class="keyword">const</span> hostname = url.<span class="property">searchParams</span>.<span class="title function_">get</span>(<span class="string">&#x27;hubhost&#x27;</span>) || originalUrl.<span class="property">hostname</span></span><br><span class="line">    <span class="keyword">const</span> hostTop = hostname.<span class="title function_">split</span>(<span class="string">&#x27;.&#x27;</span>)[<span class="number">0</span>]</span><br><span class="line">    <span class="keyword">let</span> blockedUA = [...<span class="variable constant_">DEFAULT_BLOCKED_UA</span>]</span><br><span class="line">    <span class="keyword">if</span> (<span class="variable constant_">SNIPPET_CONFIG</span>.<span class="property">UA</span>) blockedUA = blockedUA.<span class="title function_">concat</span>(<span class="title function_">parseCsvInput</span>(<span class="variable constant_">SNIPPET_CONFIG</span>.<span class="property">UA</span>))</span><br><span class="line">    <span class="keyword">let</span> checkHost</span><br><span class="line">    <span class="keyword">let</span> hubHost = <span class="variable constant_">DEFAULT_HUB_HOST</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (ns) &#123;</span><br><span class="line">      hubHost = ns === <span class="string">&#x27;docker.io&#x27;</span> ? <span class="string">&#x27;registry-1.docker.io&#x27;</span> : ns</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      checkHost = <span class="title function_">routeByHosts</span>(hostTop, <span class="variable constant_">DEFAULT_HUB_HOST</span>)</span><br><span class="line">      hubHost = checkHost[<span class="number">0</span>]</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> fakePage = checkHost ? checkHost[<span class="number">1</span>] : <span class="literal">false</span></span><br><span class="line">    url.<span class="property">hostname</span> = hubHost</span><br><span class="line">    <span class="keyword">const</span> hubParams = [<span class="string">&#x27;/v1/search&#x27;</span>, <span class="string">&#x27;/v1/repositories&#x27;</span>]</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (blockedUA.<span class="title function_">some</span>(<span class="function">(<span class="params">ua</span>) =&gt;</span> userAgent.<span class="title function_">includes</span>(ua)) &amp;&amp; blockedUA.<span class="property">length</span> &gt; <span class="number">0</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="keyword">await</span> <span class="title function_">nginx</span>(), &#123;</span><br><span class="line">        <span class="attr">headers</span>: &#123; <span class="string">&#x27;Content-Type&#x27;</span>: <span class="string">&#x27;text/html; charset=UTF-8&#x27;</span> &#125;</span><br><span class="line">      &#125;)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> ((userAgent &amp;&amp; userAgent.<span class="title function_">includes</span>(<span class="string">&#x27;mozilla&#x27;</span>)) || hubParams.<span class="title function_">some</span>(<span class="function">(<span class="params">param</span>) =&gt;</span> url.<span class="property">pathname</span>.<span class="title function_">includes</span>(param))) &#123;</span><br><span class="line">      <span class="keyword">if</span> (url.<span class="property">pathname</span> === <span class="string">&#x27;/&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="variable constant_">SNIPPET_CONFIG</span>.<span class="property">URL302</span>) <span class="keyword">return</span> <span class="title class_">Response</span>.<span class="title function_">redirect</span>(<span class="variable constant_">SNIPPET_CONFIG</span>.<span class="property">URL302</span>, <span class="number">302</span>)</span><br><span class="line">        <span class="keyword">if</span> (<span class="variable constant_">SNIPPET_CONFIG</span>.<span class="property">URL</span>) &#123;</span><br><span class="line">          <span class="keyword">if</span> (<span class="variable constant_">SNIPPET_CONFIG</span>.<span class="property">URL</span>.<span class="title function_">toLowerCase</span>() === <span class="string">&#x27;nginx&#x27;</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="keyword">await</span> <span class="title function_">nginx</span>(), &#123;</span><br><span class="line">              <span class="attr">headers</span>: &#123; <span class="string">&#x27;Content-Type&#x27;</span>: <span class="string">&#x27;text/html; charset=UTF-8&#x27;</span> &#125;</span><br><span class="line">            &#125;)</span><br><span class="line">          &#125;</span><br><span class="line">          <span class="keyword">return</span> <span class="title function_">fetch</span>(<span class="keyword">new</span> <span class="title class_">Request</span>(<span class="variable constant_">SNIPPET_CONFIG</span>.<span class="property">URL</span>, request))</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (fakePage) &#123;</span><br><span class="line">          <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="keyword">await</span> <span class="title function_">searchInterface</span>(), &#123;</span><br><span class="line">            <span class="attr">headers</span>: &#123; <span class="string">&#x27;Content-Type&#x27;</span>: <span class="string">&#x27;text/html; charset=UTF-8&#x27;</span> &#125;</span><br><span class="line">          &#125;)</span><br><span class="line">        &#125;</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (url.<span class="property">pathname</span>.<span class="title function_">startsWith</span>(<span class="string">&#x27;/v1/&#x27;</span>)) url.<span class="property">hostname</span> = <span class="string">&#x27;index.docker.io&#x27;</span></span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span> (fakePage) url.<span class="property">hostname</span> = <span class="string">&#x27;hub.docker.com&#x27;</span></span><br><span class="line">        <span class="keyword">if</span> (url.<span class="property">searchParams</span>.<span class="title function_">get</span>(<span class="string">&#x27;q&#x27;</span>)?.<span class="title function_">includes</span>(<span class="string">&#x27;library/&#x27;</span>) &amp;&amp; url.<span class="property">searchParams</span>.<span class="title function_">get</span>(<span class="string">&#x27;q&#x27;</span>) !== <span class="string">&#x27;library/&#x27;</span>) &#123;</span><br><span class="line">          <span class="keyword">const</span> search = url.<span class="property">searchParams</span>.<span class="title function_">get</span>(<span class="string">&#x27;q&#x27;</span>)</span><br><span class="line">          url.<span class="property">searchParams</span>.<span class="title function_">set</span>(<span class="string">&#x27;q&#x27;</span>, search.<span class="title function_">replace</span>(<span class="string">&#x27;library/&#x27;</span>, <span class="string">&#x27;&#x27;</span>))</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_">fetch</span>(<span class="keyword">new</span> <span class="title class_">Request</span>(url, request))</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (!<span class="regexp">/%2F/</span>.<span class="title function_">test</span>(url.<span class="property">search</span>) &amp;&amp; <span class="regexp">/%3A/</span>.<span class="title function_">test</span>(url.<span class="title function_">toString</span>())) &#123;</span><br><span class="line">      <span class="keyword">const</span> modifiedUrl = url.<span class="title function_">toString</span>().<span class="title function_">replace</span>(<span class="regexp">/%3A(?=.*?&amp;)/</span>, <span class="string">&#x27;%3Alibrary%2F&#x27;</span>)</span><br><span class="line">      url = <span class="keyword">new</span> <span class="title function_">URL</span>(modifiedUrl)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (url.<span class="property">pathname</span>.<span class="title function_">includes</span>(<span class="string">&#x27;/token&#x27;</span>)) &#123;</span><br><span class="line">      <span class="keyword">const</span> tokenParameter = &#123;</span><br><span class="line">        <span class="attr">headers</span>: &#123;</span><br><span class="line">          <span class="title class_">Host</span>: <span class="string">&#x27;auth.docker.io&#x27;</span>,</span><br><span class="line">          <span class="string">&#x27;User-Agent&#x27;</span>: <span class="title function_">getReqHeader</span>(<span class="string">&#x27;User-Agent&#x27;</span>),</span><br><span class="line">          <span class="title class_">Accept</span>: <span class="title function_">getReqHeader</span>(<span class="string">&#x27;Accept&#x27;</span>),</span><br><span class="line">          <span class="string">&#x27;Accept-Language&#x27;</span>: <span class="title function_">getReqHeader</span>(<span class="string">&#x27;Accept-Language&#x27;</span>),</span><br><span class="line">          <span class="string">&#x27;Accept-Encoding&#x27;</span>: <span class="title function_">getReqHeader</span>(<span class="string">&#x27;Accept-Encoding&#x27;</span>),</span><br><span class="line">          <span class="title class_">Connection</span>: <span class="string">&#x27;keep-alive&#x27;</span>,</span><br><span class="line">          <span class="string">&#x27;Cache-Control&#x27;</span>: <span class="string">&#x27;max-age=0&#x27;</span></span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">const</span> tokenUrl = <span class="variable constant_">AUTH_URL</span> + url.<span class="property">pathname</span> + url.<span class="property">search</span></span><br><span class="line">      <span class="keyword">return</span> <span class="title function_">fetch</span>(<span class="keyword">new</span> <span class="title class_">Request</span>(tokenUrl, request), tokenParameter)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (hubHost === <span class="string">&#x27;registry-1.docker.io&#x27;</span> &amp;&amp; <span class="regexp">/^\/v2\/[^/]+\/[^/]+\/[^/]+$/</span>.<span class="title function_">test</span>(url.<span class="property">pathname</span>) &amp;&amp; !<span class="regexp">/^\/v2\/library/</span>.<span class="title function_">test</span>(url.<span class="property">pathname</span>)) &#123;</span><br><span class="line">      url.<span class="property">pathname</span> = <span class="string">&#x27;/v2/library/&#x27;</span> + url.<span class="property">pathname</span>.<span class="title function_">split</span>(<span class="string">&#x27;/v2/&#x27;</span>)[<span class="number">1</span>]</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (</span><br><span class="line">      url.<span class="property">pathname</span>.<span class="title function_">startsWith</span>(<span class="string">&#x27;/v2/&#x27;</span>) &amp;&amp;</span><br><span class="line">      (url.<span class="property">pathname</span>.<span class="title function_">includes</span>(<span class="string">&#x27;/manifests/&#x27;</span>) ||</span><br><span class="line">        url.<span class="property">pathname</span>.<span class="title function_">includes</span>(<span class="string">&#x27;/blobs/&#x27;</span>) ||</span><br><span class="line">        url.<span class="property">pathname</span>.<span class="title function_">includes</span>(<span class="string">&#x27;/tags/&#x27;</span>) ||</span><br><span class="line">        url.<span class="property">pathname</span>.<span class="title function_">endsWith</span>(<span class="string">&#x27;/tags/list&#x27;</span>))</span><br><span class="line">    ) &#123;</span><br><span class="line">      <span class="keyword">let</span> repo = <span class="string">&#x27;&#x27;</span></span><br><span class="line">      <span class="keyword">const</span> v2Match = url.<span class="property">pathname</span>.<span class="title function_">match</span>(<span class="regexp">/^\/v2\/(.+?)(?:\/(manifests|blobs|tags)\/)/</span>)</span><br><span class="line">      <span class="keyword">if</span> (v2Match) repo = v2Match[<span class="number">1</span>]</span><br><span class="line">      <span class="keyword">if</span> (repo) &#123;</span><br><span class="line">        <span class="keyword">const</span> tokenUrl = <span class="string">`<span class="subst">$&#123;AUTH_URL&#125;</span>/token?service=registry.docker.io&amp;scope=repository:<span class="subst">$&#123;repo&#125;</span>:pull`</span></span><br><span class="line">        <span class="keyword">const</span> tokenRes = <span class="keyword">await</span> <span class="title function_">fetch</span>(tokenUrl, &#123;</span><br><span class="line">          <span class="attr">headers</span>: &#123;</span><br><span class="line">            <span class="string">&#x27;User-Agent&#x27;</span>: <span class="title function_">getReqHeader</span>(<span class="string">&#x27;User-Agent&#x27;</span>),</span><br><span class="line">            <span class="title class_">Accept</span>: <span class="title function_">getReqHeader</span>(<span class="string">&#x27;Accept&#x27;</span>),</span><br><span class="line">            <span class="string">&#x27;Accept-Language&#x27;</span>: <span class="title function_">getReqHeader</span>(<span class="string">&#x27;Accept-Language&#x27;</span>),</span><br><span class="line">            <span class="string">&#x27;Accept-Encoding&#x27;</span>: <span class="title function_">getReqHeader</span>(<span class="string">&#x27;Accept-Encoding&#x27;</span>),</span><br><span class="line">            <span class="title class_">Connection</span>: <span class="string">&#x27;keep-alive&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;Cache-Control&#x27;</span>: <span class="string">&#x27;max-age=0&#x27;</span></span><br><span class="line">          &#125;</span><br><span class="line">        &#125;)</span><br><span class="line">        <span class="keyword">const</span> tokenData = <span class="keyword">await</span> tokenRes.<span class="title function_">json</span>()</span><br><span class="line">        <span class="keyword">const</span> parameter = &#123;</span><br><span class="line">          <span class="attr">headers</span>: &#123;</span><br><span class="line">            <span class="title class_">Host</span>: hubHost,</span><br><span class="line">            <span class="string">&#x27;User-Agent&#x27;</span>: <span class="title function_">getReqHeader</span>(<span class="string">&#x27;User-Agent&#x27;</span>),</span><br><span class="line">            <span class="title class_">Accept</span>: <span class="title function_">getReqHeader</span>(<span class="string">&#x27;Accept&#x27;</span>),</span><br><span class="line">            <span class="string">&#x27;Accept-Language&#x27;</span>: <span class="title function_">getReqHeader</span>(<span class="string">&#x27;Accept-Language&#x27;</span>),</span><br><span class="line">            <span class="string">&#x27;Accept-Encoding&#x27;</span>: <span class="title function_">getReqHeader</span>(<span class="string">&#x27;Accept-Encoding&#x27;</span>),</span><br><span class="line">            <span class="title class_">Connection</span>: <span class="string">&#x27;keep-alive&#x27;</span>,</span><br><span class="line">            <span class="string">&#x27;Cache-Control&#x27;</span>: <span class="string">&#x27;max-age=0&#x27;</span>,</span><br><span class="line">            <span class="title class_">Authorization</span>: <span class="string">`Bearer <span class="subst">$&#123;tokenData.token&#125;</span>`</span></span><br><span class="line">          &#125;,</span><br><span class="line">          <span class="attr">cacheTtl</span>: <span class="number">3600</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (request.<span class="property">headers</span>.<span class="title function_">has</span>(<span class="string">&#x27;X-Amz-Content-Sha256&#x27;</span>)) &#123;</span><br><span class="line">          parameter.<span class="property">headers</span>[<span class="string">&#x27;X-Amz-Content-Sha256&#x27;</span>] = <span class="title function_">getReqHeader</span>(<span class="string">&#x27;X-Amz-Content-Sha256&#x27;</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">const</span> originalResponse = <span class="keyword">await</span> <span class="title function_">fetch</span>(<span class="keyword">new</span> <span class="title class_">Request</span>(url, request), parameter)</span><br><span class="line">        <span class="keyword">const</span> newResponseHeaders = <span class="keyword">new</span> <span class="title class_">Headers</span>(originalResponse.<span class="property">headers</span>)</span><br><span class="line">        <span class="keyword">if</span> (newResponseHeaders.<span class="title function_">get</span>(<span class="string">&#x27;Www-Authenticate&#x27;</span>)) &#123;</span><br><span class="line">          <span class="keyword">const</span> re = <span class="keyword">new</span> <span class="title class_">RegExp</span>(<span class="variable constant_">AUTH_URL</span>, <span class="string">&#x27;g&#x27;</span>)</span><br><span class="line">          newResponseHeaders.<span class="title function_">set</span>(</span><br><span class="line">            <span class="string">&#x27;Www-Authenticate&#x27;</span>,</span><br><span class="line">            originalResponse.<span class="property">headers</span>.<span class="title function_">get</span>(<span class="string">&#x27;Www-Authenticate&#x27;</span>).<span class="title function_">replace</span>(re, workersUrl)</span><br><span class="line">          )</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (newResponseHeaders.<span class="title function_">get</span>(<span class="string">&#x27;Location&#x27;</span>)) &#123;</span><br><span class="line">          <span class="keyword">const</span> location = newResponseHeaders.<span class="title function_">get</span>(<span class="string">&#x27;Location&#x27;</span>)</span><br><span class="line">          <span class="keyword">return</span> <span class="title function_">httpHandler</span>(request, location, hubHost)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(originalResponse.<span class="title function_">clone</span>().<span class="property">body</span>, &#123;</span><br><span class="line">          <span class="attr">status</span>: originalResponse.<span class="property">status</span>,</span><br><span class="line">          <span class="attr">headers</span>: newResponseHeaders</span><br><span class="line">        &#125;)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> parameter = &#123;</span><br><span class="line">      <span class="attr">headers</span>: &#123;</span><br><span class="line">        <span class="title class_">Host</span>: hubHost,</span><br><span class="line">        <span class="string">&#x27;User-Agent&#x27;</span>: <span class="title function_">getReqHeader</span>(<span class="string">&#x27;User-Agent&#x27;</span>),</span><br><span class="line">        <span class="title class_">Accept</span>: <span class="title function_">getReqHeader</span>(<span class="string">&#x27;Accept&#x27;</span>),</span><br><span class="line">        <span class="string">&#x27;Accept-Language&#x27;</span>: <span class="title function_">getReqHeader</span>(<span class="string">&#x27;Accept-Language&#x27;</span>),</span><br><span class="line">        <span class="string">&#x27;Accept-Encoding&#x27;</span>: <span class="title function_">getReqHeader</span>(<span class="string">&#x27;Accept-Encoding&#x27;</span>),</span><br><span class="line">        <span class="title class_">Connection</span>: <span class="string">&#x27;keep-alive&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;Cache-Control&#x27;</span>: <span class="string">&#x27;max-age=0&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="attr">cacheTtl</span>: <span class="number">3600</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (request.<span class="property">headers</span>.<span class="title function_">has</span>(<span class="string">&#x27;Authorization&#x27;</span>)) &#123;</span><br><span class="line">      parameter.<span class="property">headers</span>.<span class="property">Authorization</span> = <span class="title function_">getReqHeader</span>(<span class="string">&#x27;Authorization&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (request.<span class="property">headers</span>.<span class="title function_">has</span>(<span class="string">&#x27;X-Amz-Content-Sha256&#x27;</span>)) &#123;</span><br><span class="line">      parameter.<span class="property">headers</span>[<span class="string">&#x27;X-Amz-Content-Sha256&#x27;</span>] = <span class="title function_">getReqHeader</span>(<span class="string">&#x27;X-Amz-Content-Sha256&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> originalResponse = <span class="keyword">await</span> <span class="title function_">fetch</span>(<span class="keyword">new</span> <span class="title class_">Request</span>(url, request), parameter)</span><br><span class="line">    <span class="keyword">const</span> newResponseHeaders = <span class="keyword">new</span> <span class="title class_">Headers</span>(originalResponse.<span class="property">headers</span>)</span><br><span class="line">    <span class="keyword">if</span> (newResponseHeaders.<span class="title function_">get</span>(<span class="string">&#x27;Www-Authenticate&#x27;</span>)) &#123;</span><br><span class="line">      <span class="keyword">const</span> re = <span class="keyword">new</span> <span class="title class_">RegExp</span>(<span class="variable constant_">AUTH_URL</span>, <span class="string">&#x27;g&#x27;</span>)</span><br><span class="line">      newResponseHeaders.<span class="title function_">set</span>(</span><br><span class="line">        <span class="string">&#x27;Www-Authenticate&#x27;</span>,</span><br><span class="line">        originalResponse.<span class="property">headers</span>.<span class="title function_">get</span>(<span class="string">&#x27;Www-Authenticate&#x27;</span>).<span class="title function_">replace</span>(re, workersUrl)</span><br><span class="line">      )</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (newResponseHeaders.<span class="title function_">get</span>(<span class="string">&#x27;Location&#x27;</span>)) &#123;</span><br><span class="line">      <span class="keyword">const</span> location = newResponseHeaders.<span class="title function_">get</span>(<span class="string">&#x27;Location&#x27;</span>)</span><br><span class="line">      <span class="keyword">return</span> <span class="title function_">httpHandler</span>(request, location, hubHost)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(originalResponse.<span class="title function_">clone</span>().<span class="property">body</span>, &#123;</span><br><span class="line">      <span class="attr">status</span>: originalResponse.<span class="property">status</span>,</span><br><span class="line">      <span class="attr">headers</span>: newResponseHeaders</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol><li>点击”保存”按钮</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="片段代码-3"><h3 id="3-创建随机图项目片段"><a href="#3-创建随机图项目片段" class="headerlink" title="3. 创建随机图项目片段"></a>3. 创建随机图项目片段</h3><ol><li>点击”创建片段”按钮</li><li>在名称输入框中输入一个描述性名称，例如”随机图”</li><li>在编辑框中粘贴以下代码：</li></ol><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> countsCache = <span class="literal">null</span>;</span><br><span class="line"><span class="keyword">let</span> lastFetch = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">CACHE_TTL</span> = <span class="number">10</span> * <span class="number">60</span> * <span class="number">1000</span>; <span class="comment">// 10分钟缓存</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">getCounts</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="comment">// 简单缓存，避免每次请求都 fetch</span></span><br><span class="line">    <span class="keyword">if</span> (countsCache &amp;&amp; (<span class="title class_">Date</span>.<span class="title function_">now</span>() - lastFetch &lt; <span class="variable constant_">CACHE_TTL</span>)) &#123;</span><br><span class="line">        <span class="keyword">return</span> countsCache;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> resp = <span class="keyword">await</span> <span class="title function_">fetch</span>(<span class="string">&#x27;https://p.域名/random.js&#x27;</span>);</span><br><span class="line">    <span class="keyword">const</span> text = <span class="keyword">await</span> resp.<span class="title function_">text</span>();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 提取 &#123;&quot;h&quot;:1124,&quot;v&quot;:4382&#125;</span></span><br><span class="line">    <span class="keyword">const</span> match = text.<span class="title function_">match</span>(<span class="regexp">/counts\s*=\s*(\&#123;[^&#125;]+\&#125;)/</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (!match) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&#x27;无法解析 counts&#x27;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    countsCache = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(match[<span class="number">1</span>]);</span><br><span class="line">    lastFetch = <span class="title class_">Date</span>.<span class="title function_">now</span>();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> countsCache;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">randomInt</span>(<span class="params">max</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">Math</span>.<span class="title function_">floor</span>(<span class="title class_">Math</span>.<span class="title function_">random</span>() * max) + <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">    <span class="keyword">async</span> <span class="title function_">fetch</span>(<span class="params">request</span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> url = <span class="keyword">new</span> <span class="title function_">URL</span>(request.<span class="property">url</span>);</span><br><span class="line">        <span class="keyword">const</span> path = url.<span class="property">pathname</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">const</span> counts = <span class="keyword">await</span> <span class="title function_">getCounts</span>();</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (path === <span class="string">&#x27;/h&#x27;</span>) &#123;</span><br><span class="line">                <span class="keyword">const</span> n = <span class="title function_">randomInt</span>(counts.<span class="property">h</span>);</span><br><span class="line">                <span class="keyword">const</span> location = <span class="string">`https://p.域名/ri/h/<span class="subst">$&#123;n&#125;</span>.webp`</span>;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="literal">null</span>, &#123;</span><br><span class="line">                    <span class="attr">status</span>: <span class="number">302</span>,</span><br><span class="line">                    <span class="attr">headers</span>: &#123;</span><br><span class="line">                        <span class="title class_">Location</span>: location</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (path === <span class="string">&#x27;/v&#x27;</span>) &#123;</span><br><span class="line">                <span class="keyword">const</span> n = <span class="title function_">randomInt</span>(counts.<span class="property">v</span>);</span><br><span class="line">                <span class="keyword">const</span> location = <span class="string">`https://p.域名/ri/v/<span class="subst">$&#123;n&#125;</span>.webp`</span>;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="literal">null</span>, &#123;</span><br><span class="line">                    <span class="attr">status</span>: <span class="number">302</span>,</span><br><span class="line">                    <span class="attr">headers</span>: &#123;</span><br><span class="line">                        <span class="title class_">Location</span>: location</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="string">&#x27;Not Found&#x27;</span>, &#123; <span class="attr">status</span>: <span class="number">404</span> &#125;);</span><br><span class="line"></span><br><span class="line">        &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="string">&#x27;Error: &#x27;</span> + e.<span class="property">message</span>, &#123; <span class="attr">status</span>: <span class="number">500</span> &#125;);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><ol><li>点击”保存”按钮</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="步骤三：配置片段规则"><a href="#步骤三：配置片段规则" class="headerlink" title="步骤三：配置片段规则"></a>步骤三：配置片段规则</h2><p><img src="/assets/updata/Snippets-3.jpg" alt="配置片段规则页面"></p><div class="tabs" id="片段规则"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#片段规则-1">GitHub反代片段规则</button></li><li class="tab"><button type="button" data-href="#片段规则-2">Docker反代片段规则</button></li><li class="tab"><button type="button" data-href="#片段规则-3">随机图项目片段规则</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="片段规则-1"><h3 id="1-为GitHub反代配置规则"><a href="#1-为GitHub反代配置规则" class="headerlink" title="1. 为GitHub反代配置规则"></a>1. 为GitHub反代配置规则</h3><ol><li>找到刚创建的”GitHub反代”片段</li><li>点击”添加规则”按钮</li><li>在规则配置页面中：<ul><li>选择”自定义筛选表达式”</li><li>字段选择”主机名”</li><li>运算符选择”通配符”</li><li>值输入<code>*-gh.域名</code>（或者你想要使用的具体子域名，例如<code>github.com</code>）</li></ul></li><li>点击”保存”按钮</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="片段规则-2"><h3 id="2-为Docker反代配置规则"><a href="#2-为Docker反代配置规则" class="headerlink" title="2. 为Docker反代配置规则"></a>2. 为Docker反代配置规则</h3><ol><li>找到刚创建的”Docker反代”片段</li><li>点击”添加规则”按钮</li><li>在规则配置页面中：<ul><li>选择”自定义筛选表达式”</li><li>字段选择”主机名”</li><li>运算符选择”通配符”</li><li>值输入<code>docker.域名</code>（或者你想要使用的具体子域名，例如<code>docker.yourdomain.com</code>）</li></ul></li><li>点击”保存”按钮</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="片段规则-3"><h3 id="3-为随机图项目配置规则"><a href="#3-为随机图项目配置规则" class="headerlink" title="3. 为随机图项目配置规则"></a>3. 为随机图项目配置规则</h3><ol><li>找到刚创建的”随机图”片段</li><li>点击”添加规则”按钮</li><li>在规则配置页面中：<ul><li>选择”自定义筛选表达式”</li><li>字段选择”主机名”</li><li>运算符选择”通配符”</li><li>值输入<code>c-p.域名</code>（或者你想要使用的具体子域名，例如<code>c-p.yourdomain.com</code>）</li></ul></li><li>点击”保存”按钮</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="步骤四：部署和测试"><a href="#步骤四：部署和测试" class="headerlink" title="步骤四：部署和测试"></a>步骤四：部署和测试</h2><ol><li>确保所有片段和规则都已保存</li><li>等待Cloudflare生效（通常需要几分钟时间）</li><li>测试访问：<ul><li>GitHub反代：访问<code>github.com</code>（替换为你的实际域名）</li><li>Docker反代：访问<code>docker.yourdomain.com</code>（替换为你的实际域名）</li><li>随机图：访问<code>c-p.yourdomain.com</code>（替换为你的实际域名）</li></ul></li></ol><h2 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h2><ol><li>确保你的域名已经正确配置了DNS记录，指向Cloudflare</li><li>如果你使用的是子域名，确保已经在DNS中添加了相应的A记录或CNAME记录</li><li>某些地区可能无法访问GitHub或Docker Hub，即使使用反代也可能受到影响</li><li>随机图服务可能会受到外部API的限制，建议使用多个备用API以提高可靠性</li></ol><h2 id="故障排除"><a href="#故障排除" class="headerlink" title="故障排除"></a>故障排除</h2><ul><li>如果访问时出现错误，请检查片段代码是否正确</li><li>确认规则配置中的主机名是否与你的实际域名匹配</li><li>检查Cloudflare的安全设置，确保没有阻止请求</li><li>尝试清除浏览器缓存后再次访问</li></ul><p>通过以上步骤，你应该已经成功在Cloudflare上部署了GitHub反代、Docker反代和随机图项目。如果遇到任何问题，请参考Cloudflare的官方文档或寻求社区支持。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;Cloudflare部署Snippets项目教程&quot;&gt;&lt;a href=&quot;#Cloudflare部署Snippets项目教程&quot; class=&quot;headerlink&quot; title=&quot;Cloudflare部署Snippets项目教程&quot;&gt;&lt;/a&gt;Cloudflare部署Sn</summary>
      
    
    
    
    <category term="网络" scheme="https://blog.sihan.fun/categories/%E7%BD%91%E7%BB%9C/"/>
    
    <category term="Cloudflare" scheme="https://blog.sihan.fun/categories/%E7%BD%91%E7%BB%9C/Cloudflare/"/>
    
    
    <category term="Cloudflare" scheme="https://blog.sihan.fun/tags/Cloudflare/"/>
    
    <category term="Snippets" scheme="https://blog.sihan.fun/tags/Snippets/"/>
    
    <category term="反代" scheme="https://blog.sihan.fun/tags/%E5%8F%8D%E4%BB%A3/"/>
    
    <category term="随机图" scheme="https://blog.sihan.fun/tags/%E9%9A%8F%E6%9C%BA%E5%9B%BE/"/>
    
  </entry>
  
  <entry>
    <title>Cloudflare Pages 国内访问优化 -- 利用「优选 IP」加速</title>
    <link href="https://blog.sihan.fun/posts/98765432.html"/>
    <id>https://blog.sihan.fun/posts/98765432.html</id>
    <published>2026-01-12T16:00:00.000Z</published>
    <updated>2026-01-12T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="🌟-核心方案"><a href="#🌟-核心方案" class="headerlink" title="🌟 核心方案"></a>🌟 核心方案</h2><p><strong>Cloudflare Pages + 华为云国际站 + 第三方 CNAME 优选 IP</strong></p><h2 id="🧠-优化思路"><a href="#🧠-优化思路" class="headerlink" title="🧠 优化思路"></a>🧠 优化思路</h2><h3 id="核心逻辑"><a href="#核心逻辑" class="headerlink" title="核心逻辑"></a>核心逻辑</h3><p>通过 DNS 层分流实现国内外访问优化：</p><ul><li>🌍 <strong>国外访问</strong>：继续使用 Cloudflare 官方线路</li><li>🇨🇳 <strong>国内访问</strong>：通过优选 IP 线路提高访问速度</li></ul><h3 id="技术实现"><a href="#技术实现" class="headerlink" title="技术实现"></a>技术实现</h3><p>实现这个效果需要三个关键步骤：</p><ol><li><strong>Cloudflare 子域名 NS 下沉</strong>：将特定子域名的解析权下放</li><li><strong>华为云国际站线路解析</strong>：实现智能地区分流</li><li><strong>第三方 Cloudflare 优选 IP/CNAME</strong>：使用稳定快速的国内访问节点</li></ol><h3 id="预期效果"><a href="#预期效果" class="headerlink" title="预期效果"></a>预期效果</h3><ul><li>✅ 国内访问速度显著提升</li><li>✅ 国外访问保持原有稳定性</li><li>✅ Pages 项目无需任何代码修改</li><li>✅ 架构清晰，配置简单</li></ul><h2 id="🗺️-架构示意图"><a href="#🗺️-架构示意图" class="headerlink" title="🗺️ 架构示意图"></a>🗺️ 架构示意图</h2><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">用户访问  </span><br><span class="line">  │  </span><br><span class="line">  ├─ 国外 → Cloudflare<span class="built_in"> DNS </span>→ CF Pages  </span><br><span class="line">  │  </span><br><span class="line">  └─ 国内 → 华为云<span class="built_in"> DNS </span>→ 优选<span class="built_in"> IP </span>→ CF Pages</span><br></pre></td></tr></table></figure><p><strong>架构特点</strong>：</p><ul><li>仅在 DNS 层进行智能分流，不影响 Pages 项目本身</li><li>国内流量通过优选 IP 直达 Cloudflare Pages</li><li>国外流量保持原有 Cloudflare 官方路径</li><li>对用户完全透明，无需修改访问方式</li></ul><h2 id="�-准备条件"><a href="#�-准备条件" class="headerlink" title="� 准备条件"></a>� 准备条件</h2><p>在开始配置之前，请确保你已经准备好以下资源：</p><p>✅ <strong>Cloudflare Pages 项目</strong>：已部署的项目（如 logo 库、静态网站等）<br>✅ <strong>自定义二级域名</strong>：已绑定到 Pages 项目的域名<br>✅ <strong>第三方 Cloudflare 优选 IP/CNAME</strong>：稳定的国内加速节点<br>✅ <strong>华为云国际站账号</strong>：无需实名，仅需邮箱注册即可</p><h2 id="🔗-步骤一：确保-Cloudflare-Pages-已绑定域名"><a href="#🔗-步骤一：确保-Cloudflare-Pages-已绑定域名" class="headerlink" title="🔗 步骤一：确保 Cloudflare Pages 已绑定域名"></a>🔗 步骤一：确保 Cloudflare Pages 已绑定域名</h2><h3 id="查看-Pages-分配的-CNAME"><a href="#查看-Pages-分配的-CNAME" class="headerlink" title="查看 Pages 分配的 CNAME"></a>查看 Pages 分配的 CNAME</h3><p>部署 Cloudflare Pages 后，系统会分配一个默认的 CNAME 地址：<br><figure class="highlight q"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xxx.pages.<span class="built_in">dev</span></span><br></pre></td></tr></table></figure></p><p><strong>注意</strong>：这个 CNAME 地址非常重要，后续配置会用到。</p><p><img src="/assets/updata/640.png" alt="cf"></p><h3 id="绑定自定义域名（如已完成可跳过）"><a href="#绑定自定义域名（如已完成可跳过）" class="headerlink" title="绑定自定义域名（如已完成可跳过）"></a>绑定自定义域名（如已完成可跳过）</h3><ol><li>登录 Cloudflare Pages 控制台</li><li>选择目标项目，进入「Settings」→「Custom domains」</li><li>输入自定义二级域名（如 <code>logo.example.com</code>）</li><li>点击「Activate domain」完成绑定</li></ol><p><img src="/assets/updata/641.png" alt="cf"></p><h3 id="测试初始访问速度"><a href="#测试初始访问速度" class="headerlink" title="测试初始访问速度"></a>测试初始访问速度</h3><p>使用 itdog 等工具测试未优化前的访问效果：</p><p><img src="/assets/updata/642.png" alt="cf"></p><h2 id="☁️-步骤二：注册并使用华为云国际站"><a href="#☁️-步骤二：注册并使用华为云国际站" class="headerlink" title="☁️ 步骤二：注册并使用华为云国际站"></a>☁️ 步骤二：注册并使用华为云国际站</h2><h3 id="注册华为云国际站"><a href="#注册华为云国际站" class="headerlink" title="注册华为云国际站"></a>注册华为云国际站</h3><p><strong>重要提示</strong>：请确保注册的是国际站，而非国内站。</p><ol><li><strong>访问注册地址</strong>：<a href="https://www.huaweicloud.com/intl/zh-cn/">https://www.huaweicloud.com/intl/zh-cn/</a></li><li><strong>邮箱注册</strong>：使用任意邮箱即可注册，无需实名认证</li><li><strong>无需手机绑定</strong>：注册过程简单快捷，不需要绑定海外手机号</li></ol><h3 id="进入-DNS-管理控制台"><a href="#进入-DNS-管理控制台" class="headerlink" title="进入 DNS 管理控制台"></a>进入 DNS 管理控制台</h3><p>注册完成后：</p><ol><li>登录华为云国际站控制台</li><li>在「服务列表」中找到并进入 <strong>云解析服务 DNS</strong></li></ol><p><img src="/assets/updata/643.png" alt="cf"></p><h2 id="🧩-步骤三：在华为云添加子域名解析"><a href="#🧩-步骤三：在华为云添加子域名解析" class="headerlink" title="🧩 步骤三：在华为云添加子域名解析"></a>🧩 步骤三：在华为云添加子域名解析</h2><h3 id="📋-3-1-创建公网域名"><a href="#📋-3-1-创建公网域名" class="headerlink" title="📋 3.1 创建公网域名"></a>📋 3.1 创建公网域名</h3><ol><li>登录华为云 DNS 控制台</li><li>点击「创建公网域名」</li><li>输入你的二级域名（如 <code>logo.example.com</code>）</li></ol><p><strong>注意</strong>：这里只需要添加二级域名，不需要添加主域名（因为主域名仍托管在 Cloudflare）。</p><p><img src="/assets/updata/644.png" alt="cf"></p><h3 id="⚙️-3-2-添加关键-DNS-记录（核心步骤）"><a href="#⚙️-3-2-添加关键-DNS-记录（核心步骤）" class="headerlink" title="⚙️ 3.2 添加关键 DNS 记录（核心步骤）"></a>⚙️ 3.2 添加关键 DNS 记录（核心步骤）</h3><h4 id="�-记录一：默认线路（非大陆访问）"><a href="#�-记录一：默认线路（非大陆访问）" class="headerlink" title="� 记录一：默认线路（非大陆访问）"></a>� 记录一：默认线路（非大陆访问）</h4><p>用于处理海外用户的访问请求：</p><ul><li><strong>类型</strong>：CNAME</li><li><strong>主机记录</strong>：留空（表示直接使用域名）</li><li><strong>线路类型</strong>：全网默认</li><li><strong>解析值</strong>：填写 Cloudflare Pages 分配的 <code>xxx.pages.dev</code></li></ul><p>这条记录确保海外用户继续使用 Cloudflare 官方线路访问。</p><p><img src="/assets/updata/645.png" alt="cf"></p><h4 id="�-记录二：中国大陆线路（国内访问）"><a href="#�-记录二：中国大陆线路（国内访问）" class="headerlink" title="� 记录二：中国大陆线路（国内访问）"></a>� 记录二：中国大陆线路（国内访问）</h4><p>用于优化国内用户的访问速度：</p><ul><li><strong>类型</strong>：CNAME</li><li><strong>主机记录</strong>：留空</li><li><strong>线路类型</strong>：地域解析 → 中国大陆</li><li><strong>解析值</strong>：填写第三方提供的 Cloudflare 优选 IP CNAME<br>例如：<code>logo.cf.090227.xyz</code></li></ul><p>这条记录是国内加速的核心，所有中国大陆用户的请求都会通过优选 IP 访问你的 Pages 项目。</p><p><img src="/assets/updata/646.png" alt="cf"></p><h3 id="📝-3-3-记录华为云分配的-NS-服务器"><a href="#📝-3-3-记录华为云分配的-NS-服务器" class="headerlink" title="📝 3.3 记录华为云分配的 NS 服务器"></a>📝 3.3 记录华为云分配的 NS 服务器</h3><p>完成域名添加后，华为云会自动为这个子域名分配一组 NS 服务器地址，类似这样：<br><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">ns1<span class="selector-class">.huaweicloud-dns</span><span class="selector-class">.com</span></span><br><span class="line">ns1<span class="selector-class">.huaweicloud-dns</span><span class="selector-class">.cn</span></span><br><span class="line">ns1<span class="selector-class">.huaweicloud-dns</span><span class="selector-class">.net</span></span><br><span class="line">ns1<span class="selector-class">.huaweicloud-dns</span>.org</span><br></pre></td></tr></table></figure></p><p>请将这些 NS 地址完整记录下来，后续配置需要使用。</p><p><img src="/assets/updata/647.png" alt="cf"></p><h2 id="�-步骤四：在-Cloudflare-设置-NS-下沉"><a href="#�-步骤四：在-Cloudflare-设置-NS-下沉" class="headerlink" title="� 步骤四：在 Cloudflare 设置 NS 下沉"></a>� 步骤四：在 Cloudflare 设置 NS 下沉</h2><h3 id="🎯-核心操作：将子域名解析权下放给华为云"><a href="#🎯-核心操作：将子域名解析权下放给华为云" class="headerlink" title="🎯 核心操作：将子域名解析权下放给华为云"></a>🎯 核心操作：将子域名解析权下放给华为云</h3><ol><li>登录 Cloudflare 控制台，进入「域名管理 → DNS」</li><li>点击「添加记录」</li><li><p>配置以下参数：</p><ul><li><strong>类型</strong>：NS</li><li><strong>名称</strong>：输入二级域名的前缀（如 <code>logo</code>）</li><li><strong>名称服务器</strong>：输入华为云分配的 NS 地址</li><li><strong>TTL</strong>：保持默认自动</li></ul></li><li><p>重复上述步骤，添加华为云分配的所有 NS 服务器记录</p></li></ol><p><img src="/assets/updata/648.png" alt="cf"></p><h3 id="📌-操作含义"><a href="#📌-操作含义" class="headerlink" title="📌 操作含义"></a>📌 操作含义</h3><p>通过 NS 下沉设置，我们将 <code>logo.example.com</code> 这个子域名的 DNS 解析权完全下放给华为云，而主域名 <code>example.com</code> 仍然由 Cloudflare 管理。这样华为云就能根据用户地域智能分配解析结果了。</p><h2 id="📊-步骤五：验证优化效果"><a href="#📊-步骤五：验证优化效果" class="headerlink" title="📊 步骤五：验证优化效果"></a>📊 步骤五：验证优化效果</h2><h3 id="⏳-生效时间"><a href="#⏳-生效时间" class="headerlink" title="⏳ 生效时间"></a>⏳ 生效时间</h3><p>配置完成后，DNS 记录一般需要 <strong>5-30分钟</strong> 生效，具体时间取决于网络环境和 DNS 缓存情况。</p><h3 id="🧪-验证方法"><a href="#🧪-验证方法" class="headerlink" title="🧪 验证方法"></a>🧪 验证方法</h3><p>你可以通过以下方式验证优化效果：</p><ol><li><strong>网络测试工具</strong>：使用 itdog、ping.pe 等工具测试域名访问速度</li><li><strong>浏览器访问</strong>：直接在浏览器中访问优化后的域名</li><li><strong>实际应用场景</strong>：在播放器中测试台标加载速度</li><li><strong>跨网络测试</strong>：使用不同网络环境（大陆/非大陆）测试访问效果</li></ol><p><img src="/assets/updata/649.png" alt="cf"></p><h3 id="✨-预期效果"><a href="#✨-预期效果" class="headerlink" title="✨ 预期效果"></a>✨ 预期效果</h3><p>优化成功后，你应该能观察到：</p><ul><li>✅ 国内访问速度显著提升（通常可提升 30%-70%）</li><li>✅ 台标等静态资源加载更快</li><li>✅ 海外用户访问不受影响</li><li>✅ Pages 项目无需任何代码修改</li></ul><h2 id="🎯-方案总结"><a href="#🎯-方案总结" class="headerlink" title="🎯 方案总结"></a>🎯 方案总结</h2><h3 id="�-核心优势"><a href="#�-核心优势" class="headerlink" title="� 核心优势"></a>� 核心优势</h3><p>通过 <strong>Cloudflare Pages + 华为云国际站 + 第三方 CNAME 优选 IP</strong> 方案，你可以获得：</p><ul><li>🚀 <strong>显著的国内访问加速</strong>：解决 Cloudflare 国内访问慢的问题</li><li>🌍 <strong>全球访问优化</strong>：海外用户继续享受 Cloudflare 全球 CDN 服务</li><li>�️ <strong>零代码修改</strong>：无需修改 Pages 项目代码，配置即可生效</li><li>🔒 <strong>安全稳定</strong>：利用华为云国际站的可靠解析服务</li><li>💡 <strong>低成本高效益</strong>：无需额外服务器成本，仅需 DNS 配置</li></ul><h3 id="📈-适用场景"><a href="#📈-适用场景" class="headerlink" title="📈 适用场景"></a>📈 适用场景</h3><p>这个优化方案特别适合：</p><ul><li>🌐 Logo 图库托管</li><li>📺 直播源订阅服务</li><li>📁 静态资源分发</li><li>🌍 全球访问的个人/企业网站</li></ul><h2 id="⚠️-注意事项与经验分享"><a href="#⚠️-注意事项与经验分享" class="headerlink" title="⚠️ 注意事项与经验分享"></a>⚠️ 注意事项与经验分享</h2><h3 id="📌-优选-IP-选择建议"><a href="#📌-优选-IP-选择建议" class="headerlink" title="📌 优选 IP 选择建议"></a>📌 优选 IP 选择建议</h3><ul><li><strong>质量优先</strong>：优先选择稳定可靠的优选 IP，而非数量</li><li><strong>定期更新</strong>：优选 IP 可能会失效，建议定期检查和更新</li><li><strong>测试验证</strong>：使用前先测试优选 IP 的稳定性和速度</li></ul><h3 id="�️-风险控制"><a href="#�️-风险控制" class="headerlink" title="�️ 风险控制"></a>�️ 风险控制</h3><ul><li>优选 IP 失效不会影响海外线路访问</li><li>子域名 NS 下沉仅影响单个子域名，不会影响主域名</li><li>保持 Cloudflare 主域名配置不变，确保整体稳定性</li></ul><h3 id="�-避免常见错误"><a href="#�-避免常见错误" class="headerlink" title="� 避免常见错误"></a>� 避免常见错误</h3><ul><li>不要在 Cloudflare 再为同一子域名添加额外的 CNAME 记录</li><li>确保华为云的 NS 记录完整添加到 Cloudflare</li><li>配置后耐心等待 DNS 记录生效（通常需要 5-30 分钟）</li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;🌟-核心方案&quot;&gt;&lt;a href=&quot;#🌟-核心方案&quot; class=&quot;headerlink&quot; title=&quot;🌟 核心方案&quot;&gt;&lt;/a&gt;🌟 核心方案&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Cloudflare Pages + 华为云国际站 + 第三方 CNAME 优选 I</summary>
      
    
    
    
    <category term="技术" scheme="https://blog.sihan.fun/categories/%E6%8A%80%E6%9C%AF/"/>
    
    
    <category term="Cloudflare" scheme="https://blog.sihan.fun/tags/Cloudflare/"/>
    
    <category term="网络优化" scheme="https://blog.sihan.fun/tags/%E7%BD%91%E7%BB%9C%E4%BC%98%E5%8C%96/"/>
    
    <category term="访问加速" scheme="https://blog.sihan.fun/tags/%E8%AE%BF%E9%97%AE%E5%8A%A0%E9%80%9F/"/>
    
    <category term="技术教程" scheme="https://blog.sihan.fun/tags/%E6%8A%80%E6%9C%AF%E6%95%99%E7%A8%8B/"/>
    
  </entry>
  
  <entry>
    <title>uptime-kuma 搭建教程和美化教程</title>
    <link href="https://blog.sihan.fun/posts/87654321.html"/>
    <id>https://blog.sihan.fun/posts/87654321.html</id>
    <published>2026-01-11T16:00:00.000Z</published>
    <updated>2026-01-11T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<div class="note info flat"><p>什么是 uptime-kuma？<br>uptime-kuma 是一个自托管的监控工具，用于监控网站、服务器和其他在线服务的可用性。它提供了直观的 Web 界面，支持多种监控方式，如 HTTP、TCP、Ping、DNS 等，并且可以自定义通知方式。</p></div><h2 id="效果展示"><a href="#效果展示" class="headerlink" title="效果展示"></a>效果展示</h2><p><img src="/assets/updata/美化后效果.jpg" alt="uptime-kuma 界面"></p><h2 id="🚀-安装-uptime-kuma"><a href="#🚀-安装-uptime-kuma" class="headerlink" title="🚀 安装 uptime-kuma"></a>🚀 安装 uptime-kuma</h2><h3 id="方法一：使用-Docker-安装（推荐）"><a href="#方法一：使用-Docker-安装（推荐）" class="headerlink" title="方法一：使用 Docker 安装（推荐）"></a>方法一：使用 Docker 安装（推荐）</h3><p>Docker 安装是最简单和推荐的方式：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建数据目录</span></span><br><span class="line"><span class="built_in">mkdir</span> uptime-kuma</span><br><span class="line"></span><br><span class="line"><span class="comment"># 运行容器</span></span><br><span class="line"><span class="built_in">cd</span> uptime-kuma</span><br><span class="line">curl -o compose.yaml https://raw.githubusercontent.com/louislam/uptime-kuma/master/compose.yaml</span><br><span class="line">docker compose up -d</span><br></pre></td></tr></table></figure><h2 id="🎨-基础配置"><a href="#🎨-基础配置" class="headerlink" title="🎨 基础配置"></a>🎨 基础配置</h2><ol><li><strong>访问 Web 界面</strong>：打开浏览器访问 <code>http://服务器IP:3001</code></li><li><strong>创建管理员账户</strong>：首次访问需要设置用户名和密码</li><li><strong>添加监控项</strong>：点击「Add New Monitor」按钮添加需要监控的服务</li></ol><h2 id="🌟-美化代码和自定义"><a href="#🌟-美化代码和自定义" class="headerlink" title="🌟 美化代码和自定义"></a>🌟 美化代码和自定义</h2><details class="folding-tag" cyan><summary> 自用美化配置代码 </summary>              <div class='content'>              <figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">/* ============================</span></span><br><span class="line"><span class="comment">   基础样式重置与全局配置</span></span><br><span class="line"><span class="comment">============================ */</span></span><br><span class="line"><span class="comment">/* LOGO标题样式 - 补充display:flex使其生效 */</span></span><br><span class="line"><span class="selector-class">.title-flex</span> &#123;</span><br><span class="line">  <span class="attribute">font-weight</span>: bold;</span><br><span class="line">  <span class="attribute">display</span>: flex; <span class="comment">/* 关键：flex布局需声明display:flex才生效 */</span></span><br><span class="line">  <span class="attribute">justify-content</span>: center;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* ============================</span></span><br><span class="line"><span class="comment">   1. 自定义字体引入（可替换为自己的字体地址）</span></span><br><span class="line"><span class="comment">============================ */</span></span><br><span class="line"><span class="comment">/* 标题特效字体 */</span></span><br><span class="line"><span class="keyword">@font-face</span> &#123;</span><br><span class="line">  <span class="attribute">font-family</span>: <span class="string">&#x27;CustomTitleFont&#x27;</span>; <span class="comment">/* 语义化命名，替代数字 */</span></span><br><span class="line">  <span class="attribute">src</span>: <span class="built_in">url</span>(<span class="string">&#x27;https://jsd.cdn.zzko.cn/gh/54ayao/ACG@main/static/fonts/1666963922.woff&#x27;</span>) <span class="built_in">format</span>(<span class="string">&#x27;woff&#x27;</span>);</span><br><span class="line">  <span class="attribute">font-weight</span>: normal;</span><br><span class="line">  <span class="attribute">font-style</span>: normal;</span><br><span class="line">  <span class="attribute">font-display</span>: swap; <span class="comment">/* 优化字体加载体验 */</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 正文字体 */</span></span><br><span class="line"><span class="keyword">@font-face</span> &#123;</span><br><span class="line">  <span class="attribute">font-family</span>: <span class="string">&quot;BodyFont&quot;</span>;</span><br><span class="line">  <span class="attribute">src</span>: <span class="built_in">url</span>(<span class="string">&quot;https://cdn.jsdelivr.net/gh/nulijiazaizhong/fonts/saye/saye.woff2&quot;</span>) <span class="built_in">format</span>(<span class="string">&quot;woff2&quot;</span>);</span><br><span class="line">  <span class="attribute">font-weight</span>: normal;</span><br><span class="line">  <span class="attribute">font-style</span>: normal;</span><br><span class="line">  <span class="attribute">font-display</span>: swap;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* ============================</span></span><br><span class="line"><span class="comment">   2. 全局样式设置</span></span><br><span class="line"><span class="comment">============================ */</span></span><br><span class="line"><span class="comment">/* 基础全局样式 */</span></span><br><span class="line"><span class="selector-tag">body</span> &#123;</span><br><span class="line">  <span class="attribute">font-family</span>: <span class="string">&quot;BodyFont&quot;</span>, sans-serif; <span class="comment">/* 正文基础字体 */</span></span><br><span class="line">  <span class="attribute">color</span>: <span class="number">#333</span>;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="comment">/* 背景图样式 - 优化适配 */</span></span><br><span class="line">  <span class="attribute">background-image</span>: <span class="built_in">url</span>(<span class="string">&#x27;https://t.alcy.cc/fj&#x27;</span>);</span><br><span class="line">  <span class="attribute">background-attachment</span>: fixed;</span><br><span class="line">  <span class="attribute">background-size</span>: cover;</span><br><span class="line">  <span class="attribute">background-position</span>: center center;</span><br><span class="line">  <span class="attribute">background-repeat</span>: no-repeat;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 根容器字体（优先级更高） */</span></span><br><span class="line"><span class="selector-id">#app</span> &#123;</span><br><span class="line">  <span class="attribute">font-family</span>: <span class="string">&#x27;CustomTitleFont&#x27;</span>, BlinkMacSystemFont, <span class="string">&#x27;segoe ui&#x27;</span>, Roboto, <span class="string">&#x27;helvetica neue&#x27;</span>,</span><br><span class="line">               Arial, <span class="string">&#x27;noto sans&#x27;</span>, sans-serif, <span class="string">&#x27;apple color emoji&#x27;</span>, <span class="string">&#x27;segoe ui emoji&#x27;</span>,</span><br><span class="line">               <span class="string">&#x27;segoe ui symbol&#x27;</span>, <span class="string">&#x27;noto color emoji&#x27;</span> <span class="meta">!important</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* ============================</span></span><br><span class="line"><span class="comment">   3. 通用组件样式</span></span><br><span class="line"><span class="comment">============================ */</span></span><br><span class="line"><span class="comment">/* 导航栏链接悬停 */</span></span><br><span class="line"><span class="selector-class">.navbar</span> <span class="selector-tag">a</span><span class="selector-pseudo">:hover</span> &#123;</span><br><span class="line">  <span class="attribute">text-decoration</span>: underline;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 卡片基础样式 */</span></span><br><span class="line"><span class="selector-class">.card</span> &#123;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="number">#fff</span>;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">5px</span>;</span><br><span class="line">  <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">2px</span> <span class="number">5px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.1</span>); <span class="comment">/* 修复空格问题 */</span></span><br><span class="line">  <span class="attribute">margin-bottom</span>: <span class="number">20px</span>;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">20px</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 卡片标题 */</span></span><br><span class="line"><span class="selector-class">.card-title</span> &#123;</span><br><span class="line">  <span class="attribute">font-size</span>: <span class="number">18px</span>;</span><br><span class="line">  <span class="attribute">font-weight</span>: bold;</span><br><span class="line">  <span class="attribute">margin-bottom</span>: <span class="number">10px</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 侧边栏样式 */</span></span><br><span class="line"><span class="selector-class">.sidebar</span> &#123;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(<span class="number">255</span>, <span class="number">255</span>, <span class="number">255</span>, <span class="number">0.9</span>);</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">20px</span>;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">10px</span>;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">5px</span>;</span><br><span class="line">  <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">2px</span> <span class="number">5px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.1</span>); <span class="comment">/* 修复空格问题 */</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* ============================</span></span><br><span class="line"><span class="comment">   4. 主题适配样式</span></span><br><span class="line"><span class="comment">============================ */</span></span><br><span class="line"><span class="comment">/* 明亮主题 - 阴影盒子 */</span></span><br><span class="line"><span class="selector-class">.shadow-box</span> &#123;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(<span class="number">255</span>, <span class="number">255</span>, <span class="number">255</span>, <span class="number">0.75</span>);</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">10px</span>;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">5px</span>;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">10px</span>;</span><br><span class="line">  <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">2px</span> <span class="number">5px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.1</span>); <span class="comment">/* 修复空格问题 */</span></span><br><span class="line">  <span class="attribute">text-decoration</span>: none;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 暗色主题 - 阴影盒子（排除alert类） */</span></span><br><span class="line"><span class="selector-class">.dark</span> <span class="selector-class">.shadow-box</span><span class="selector-pseudo">:not</span>(<span class="selector-class">.alert</span>) &#123;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.65</span>);</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">20px</span>;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">10px</span>;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">5px</span>;</span><br><span class="line">  <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">2px</span> <span class="number">5px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.1</span>); <span class="comment">/* 修复空格问题 */</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* ============================</span></span><br><span class="line"><span class="comment">   5. 文字渐变动画特效</span></span><br><span class="line"><span class="comment">============================ */</span></span><br><span class="line"><span class="comment">/* 渐变文字元素 */</span></span><br><span class="line"><span class="selector-tag">span</span><span class="selector-attr">[data-v-7d4a7f28]</span>,</span><br><span class="line"><span class="selector-class">.item-name</span>,</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.description</span><span class="selector-attr">[data-v-7d4a7f28]</span><span class="selector-attr">[data-v-b8247e57]</span><span class="selector-attr">[contenteditable=<span class="string">&quot;true&quot;</span>]</span>,</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-attr">[data-v-7d4a7f28]</span><span class="selector-attr">[data-v-b8247e57]</span><span class="selector-class">.alert-heading</span><span class="selector-class">.p-2</span>,</span><br><span class="line"><span class="selector-class">.refresh-info</span>&gt;<span class="selector-tag">div</span>,</span><br><span class="line"><span class="selector-class">.alert-heading</span><span class="selector-class">.p-2</span>&gt;<span class="selector-tag">div</span>,</span><br><span class="line"><span class="selector-class">.alert-heading</span><span class="selector-class">.p-2</span>&gt;<span class="selector-tag">p</span>,</span><br><span class="line"><span class="selector-class">.alert-heading</span><span class="selector-class">.p-2</span>&gt;<span class="selector-tag">h1</span> &#123;</span><br><span class="line">  <span class="comment">/* 渐变背景 */</span></span><br><span class="line">  <span class="attribute">background-image</span>: <span class="built_in">linear-gradient</span>(<span class="number">90deg</span>, <span class="number">#07c160</span>, <span class="number">#fb6bea</span> <span class="number">25%</span>, <span class="number">#3aedff</span> <span class="number">50%</span>, <span class="number">#fb6bea</span> <span class="number">75%</span>, <span class="number">#28d079</span>);</span><br><span class="line">  <span class="attribute">font-family</span>: <span class="string">&#x27;CustomTitleFont&#x27;</span>, sans-serif;</span><br><span class="line">  <span class="comment">/* 文字渐变核心属性 */</span></span><br><span class="line">  -webkit-<span class="selector-tag">text</span>-<span class="attribute">fill</span>-<span class="attribute">color</span>: transparent;</span><br><span class="line">  -webkit-<span class="attribute">background-clip</span>: text;</span><br><span class="line">  <span class="attribute">background-clip</span>: text; <span class="comment">/* 兼容非webkit内核 */</span></span><br><span class="line">  <span class="attribute">background-size</span>: <span class="number">400%</span> <span class="number">100%</span>;</span><br><span class="line">  <span class="comment">/* 绑定动画 */</span></span><br><span class="line">  <span class="attribute">animation</span>: wzw <span class="number">10s</span> linear infinite;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 渐变动画关键帧 - 修复空格问题 */</span></span><br><span class="line"><span class="keyword">@keyframes</span> wzw &#123;</span><br><span class="line">  <span class="number">0%</span> &#123;</span><br><span class="line">    <span class="attribute">background-position</span>: <span class="number">0%</span> <span class="number">50%</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="number">50%</span> &#123;</span><br><span class="line">    <span class="attribute">background-position</span>: <span class="number">100%</span> <span class="number">50%</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="number">100%</span> &#123;</span><br><span class="line">    <span class="attribute">background-position</span>: <span class="number">0%</span> <span class="number">50%</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>              </div>            </details><h3 id="添加自定义-CSS"><a href="#添加自定义-CSS" class="headerlink" title="添加自定义 CSS"></a>添加自定义 CSS</h3><details class="folding-tag" cyan><summary> 你可以通过自定义 CSS 来美化界面： </summary>              <div class='content'>              <figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 自定义 uptime-kuma 样式 */</span></span><br><span class="line"><span class="selector-tag">body</span> &#123;</span><br><span class="line">  <span class="attribute">font-family</span>: <span class="string">&#x27;Segoe UI&#x27;</span>, Tahoma, Geneva, Verdana, sans-serif;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 美化卡片样式 */</span></span><br><span class="line"><span class="selector-class">.card</span> &#123;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">12px</span>;</span><br><span class="line">  <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">4px</span> <span class="number">15px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.1</span>);</span><br><span class="line">  <span class="attribute">transition</span>: transform <span class="number">0.3s</span> ease, box-shadow <span class="number">0.3s</span> ease;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.card</span><span class="selector-pseudo">:hover</span> &#123;</span><br><span class="line">  <span class="attribute">transform</span>: <span class="built_in">translateY</span>(-<span class="number">5px</span>);</span><br><span class="line">  <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">8px</span> <span class="number">25px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.15</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 自定义状态指示器 */</span></span><br><span class="line"><span class="selector-class">.status-up</span> &#123;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="number">#4CAF50</span>;</span><br><span class="line">  <span class="attribute">animation</span>: pulse <span class="number">2s</span> infinite;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.status-down</span> &#123;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="number">#F44336</span>;</span><br><span class="line">  <span class="attribute">animation</span>: shake <span class="number">0.5s</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">@keyframes</span> pulse &#123;</span><br><span class="line">  <span class="number">0%</span> &#123; <span class="attribute">opacity</span>: <span class="number">1</span>; &#125;</span><br><span class="line">  <span class="number">50%</span> &#123; <span class="attribute">opacity</span>: <span class="number">0.7</span>; &#125;</span><br><span class="line">  <span class="number">100%</span> &#123; <span class="attribute">opacity</span>: <span class="number">1</span>; &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">@keyframes</span> shake &#123;</span><br><span class="line">  <span class="number">0%</span>, <span class="number">100%</span> &#123; <span class="attribute">transform</span>: <span class="built_in">translateX</span>(<span class="number">0</span>); &#125;</span><br><span class="line">  <span class="number">25%</span> &#123; <span class="attribute">transform</span>: <span class="built_in">translateX</span>(-<span class="number">5px</span>); &#125;</span><br><span class="line">  <span class="number">75%</span> &#123; <span class="attribute">transform</span>: <span class="built_in">translateX</span>(<span class="number">5px</span>); &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="3-添加自定义图标"><a href="#3-添加自定义图标" class="headerlink" title="3. 添加自定义图标"></a>3. 添加自定义图标</h3><p>你可以为监控项添加自定义图标：</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 在监控项设置中添加自定义图标 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.jsdelivr.net/gh/simple-icons/simple-icons/icons/github.svg&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;GitHub&quot;</span> <span class="attr">width</span>=<span class="string">&quot;24&quot;</span> <span class="attr">height</span>=<span class="string">&quot;24&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure>              </div>            </details><h2 id="📊-高级配置"><a href="#📊-高级配置" class="headerlink" title="📊 高级配置"></a>📊 高级配置</h2><details class="folding-tag" cyan><summary> 1.设置通知： </summary>              <div class='content'>              <p>uptime-kuma 支持多种通知方式，如电子邮件、Telegram、Discord 等：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 配置 Telegram 通知</span></span><br><span class="line">1. 在 Telegram 中创建 Bot 并获取 Token</span><br><span class="line">2. 获取 Chat ID</span><br><span class="line">3. 在 uptime-kuma 中添加 Telegram 通知，填写 Token 和 Chat ID</span><br></pre></td></tr></table></figure><h3 id="2-使用反向代理"><a href="#2-使用反向代理" class="headerlink" title="2. 使用反向代理"></a>2. 使用反向代理</h3><p>使用 Nginx 作为反向代理，添加 HTTPS 支持：</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">server</span> &#123;</span><br><span class="line">    <span class="attribute">listen</span> <span class="number">80</span>;</span><br><span class="line">    <span class="attribute">server_name</span> monitor.yourdomain.com;</span><br><span class="line">    <span class="attribute">return</span> <span class="number">301</span> https://<span class="variable">$host</span><span class="variable">$request_uri</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="section">server</span> &#123;</span><br><span class="line">    <span class="attribute">listen</span> <span class="number">443</span> ssl http2;</span><br><span class="line">    <span class="attribute">server_name</span> monitor.yourdomain.com;</span><br><span class="line">    </span><br><span class="line">    <span class="attribute">ssl_certificate</span> /path/to/ssl/cert.pem;</span><br><span class="line">    <span class="attribute">ssl_certificate_key</span> /path/to/ssl/key.pem;</span><br><span class="line">    </span><br><span class="line">    <span class="section">location</span> / &#123;</span><br><span class="line">        <span class="attribute">proxy_pass</span> http://localhost:3001;</span><br><span class="line">        <span class="attribute">proxy_http_version</span> <span class="number">1</span>.<span class="number">1</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> Upgrade <span class="variable">$http_upgrade</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> Connection <span class="string">&#x27;upgrade&#x27;</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> Host <span class="variable">$host</span>;</span><br><span class="line">        <span class="attribute">proxy_cache_bypass</span> <span class="variable">$http_upgrade</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> X-Real-IP <span class="variable">$remote_addr</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> X-Forwarded-For <span class="variable">$proxy_add_x_forwarded_for</span>;</span><br><span class="line">        <span class="attribute">proxy_set_header</span> X-Forwarded-Proto <span class="variable">$scheme</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>              </div>            </details><h2 id="🛠️-常见问题解决"><a href="#🛠️-常见问题解决" class="headerlink" title="🛠️ 常见问题解决"></a>🛠️ 常见问题解决</h2><h3 id="1-容器无法启动"><a href="#1-容器无法启动" class="headerlink" title="1. 容器无法启动"></a>1. 容器无法启动</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看容器日志</span></span><br><span class="line">docker logs uptime-kuma</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查端口是否被占用</span></span><br><span class="line">netstat -tuln | grep 3001</span><br></pre></td></tr></table></figure><h3 id="2-数据备份和恢复"><a href="#2-数据备份和恢复" class="headerlink" title="2. 数据备份和恢复"></a>2. 数据备份和恢复</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 备份数据</span></span><br><span class="line">tar -czf uptime-kuma-backup.tar.gz /data/uptime-kuma</span><br><span class="line"></span><br><span class="line"><span class="comment"># 恢复数据</span></span><br><span class="line">tar -xzf uptime-kuma-backup.tar.gz -C /</span><br></pre></td></tr></table></figure><div class="note success flat"><p>恭喜！你已经成功搭建了 uptime-kuma 监控工具，并添加了一些美化代码。现在你可以监控你的网站和服务器，并通过自定义通知及时了解服务状态。</p></div>]]></content>
    
    
      
      
    <summary type="html">&lt;div class=&quot;note info flat&quot;&gt;&lt;p&gt;什么是 uptime-kuma？&lt;br&gt;uptime-kuma 是一个自托管的监控工具，用于监控网站、服务器和其他在线服务的可用性。它提供了直观的 Web 界面，支持多种监控方式，如 HTTP、TCP、Ping、DNS</summary>
      
    
    
    
    <category term="教程" scheme="https://blog.sihan.fun/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="教程" scheme="https://blog.sihan.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="监控" scheme="https://blog.sihan.fun/tags/%E7%9B%91%E6%8E%A7/"/>
    
    <category term="工具" scheme="https://blog.sihan.fun/tags/%E5%B7%A5%E5%85%B7/"/>
    
  </entry>
  
  <entry>
    <title>飞牛NAS远程访问设置教程</title>
    <link href="https://blog.sihan.fun/posts/12345678.html"/>
    <id>https://blog.sihan.fun/posts/12345678.html</id>
    <published>2025-12-22T16:00:00.000Z</published>
    <updated>2025-12-22T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<p>前段时间，在一台工作近20年的老笔记本上安装了飞牛NAS系统，跑得速度还挺快，装了1T的硬盘，平时可自动把手机里的照片视频都备份上去，还能远程离线下载电影，非常不错。</p><p>如何在外面远程访问家里的NAS，这是个难题。现在找宽带运营商要免费的IPV4基本上是不可能的，但是好在各个宽带运营商都提供了免费的IPV6，关键是如何使用。</p><h2 id="一、IPV6查看与检测"><a href="#一、IPV6查看与检测" class="headerlink" title="一、IPV6查看与检测"></a>一、IPV6查看与检测</h2><h3 id="1-Windows电脑查看IPV6"><a href="#1-Windows电脑查看IPV6" class="headerlink" title="1. Windows电脑查看IPV6"></a>1. Windows电脑查看IPV6</h3><p>如果是Windows电脑，依次点击”控制面板”→”网络和 Internet”→”网络和共享中心”→”更改适配器设置”，找到对应的网卡，点击鼠标右键，选择”状态”，点击”详细信息”，即可查看当前网卡的IPV6地址。</p><p><img src="/assets/updata/4.jpg" alt="ipv6图片"></p><p>也可以通过cmd的命令行查看，在cmd窗口中输入<code>ipconfig /all</code>，回车</p><p><img src="/assets/updata/8.jpg" alt="ipv6 cmd"></p><p>向下滚动，找到对应的网卡，即可看到IPV6地址：</p><p><img src="/assets/updata/3.jpg" alt="ipv6 cmd"></p><p>两种方法，我更倾向于使用cmd，因为cmd里面的地址可以直接复制出来。</p><p>另外，每个网卡会有2个IPV6地址，其中：FE80开头的比较短，是局域网的IPV6地址，只能在局域网内部使用；24开头的比较长，是外网可用的地址。</p><h3 id="2-Linux系统查看IPV6"><a href="#2-Linux系统查看IPV6" class="headerlink" title="2. Linux系统查看IPV6"></a>2. Linux系统查看IPV6</h3><p>在shell中输入命令<code>ip -6 addr show</code>即可。</p><h3 id="3-飞牛NAS中查看IPV6"><a href="#3-飞牛NAS中查看IPV6" class="headerlink" title="3. 飞牛NAS中查看IPV6"></a>3. 飞牛NAS中查看IPV6</h3><p>使用手机APP或者是网页登录飞牛NAS，在”系统设置”→”网络设置”中可查看。</p><h3 id="4-判断IPV6能否在外网访问"><a href="#4-判断IPV6能否在外网访问" class="headerlink" title="4. 判断IPV6能否在外网访问"></a>4. 判断IPV6能否在外网访问</h3><p>关闭手机的wifi，然后把飞牛NAS的IPV6复制出来，比如说是：240e:401:<strong><strong>:691e:</strong></strong>:a14:<em>**</em>:81b1</p><p>打开手机浏览器，在地址栏中输入<code>[240e:401:****:691e:****:a14:****:81b1]</code>，看能否打开网页，即可判断该IPV6能否在外网访问。此处要注意，在浏览器中，IPV6地址要使用<code>[]</code>包裹起来。</p><p>如果打不开网页，说明光猫拦截了该外网访问，剩下的就是去光猫中设置。</p><h2 id="二、移动光猫开启IPV6"><a href="#二、移动光猫开启IPV6" class="headerlink" title="二、移动光猫开启IPV6"></a>二、移动光猫开启IPV6</h2><p>之前使用的是移动的宽带，移动的光猫带有路由器和WIFI功能，所以就没有再购买路由器，直接使用光猫的WIFI。</p><p>移动光猫使用管理员用户登录（管理员密码可以找宽带运维工程师要，一般都会给），找到”安全”→”防火墙”，如下图所示，拉到最下面，找到”IPV6防火墙开关”，这个默认是开着的，把它关闭，点击”保存”。</p><p><img src="/assets/updata/1.jpg" alt="ipv6 防火墙"></p><p><img src="/assets/updata/6.jpg" alt="ipv6 防火墙"></p><p>操作完以后，就可以在外网通过IPV6访问家里的设备了。</p><h2 id="三、电信光猫开启IPV6"><a href="#三、电信光猫开启IPV6" class="headerlink" title="三、电信光猫开启IPV6"></a>三、电信光猫开启IPV6</h2><p>电信的光猫同样带有路由和WIFI功能。</p><p>使用电信光猫的普通用户登录（用户名和密码都在光猫背面印着）。</p><p><img src="/assets/updata/7.jpg" alt="ipv6 开启"></p><p>用户名是useradmin，密码是2<strong>*</strong>。</p><h3 id="1-开启Telnet"><a href="#1-开启Telnet" class="headerlink" title="1. 开启Telnet"></a>1. 开启Telnet</h3><p>找宽带运维工程师要管理员密码（用户名是useradmin），然后使用管理员密码登录光猫后台，网址是192.168.1.1，登录后的界面如下：</p><p><img src="/assets/updata/5.jpg" alt="ipv6 Telnet"></p><p>登陆后再打开如下网址：</p><p><code>http://192.168.1.1:8080/enableTelnet.html</code>，启用telnet。（一定要先使用管理员密码登录光猫后台）</p><p><img src="/assets/updata/2.jpg" alt="ipv6 网站"></p><p>在这个网页上，能发现Telnet的开关是关着的，把开关打开，然后点击”保存/应用”即可。</p><h3 id="2-连接Telnet，关闭IPV6防火墙"><a href="#2-连接Telnet，关闭IPV6防火墙" class="headerlink" title="2. 连接Telnet，关闭IPV6防火墙"></a>2. 连接Telnet，关闭IPV6防火墙</h3><p>Win10电脑上默认没有安装Telnet，因此需要去下载一下，就几十KB，下载地址：<code>https://xiazai.zol.com.cn/detail/45/446440.shtml</code></p><p>把下载后的exe放在windows目录下，然后，打开cmd窗口，输入：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">telnet 192.168.1.1</span><br></pre></td></tr></table></figure><p>输入用户名telnetadmin，密码2<em>**</em></p><p>然后依次把以下命令粘贴进去即可：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">ip6tables -F</span><br><span class="line">ip6tables -P INPUT ACCEPT</span><br><span class="line">ip6tables -P FORWARD ACCEPT</span><br><span class="line">ip6tables -P OUTPUT ACCEPT</span><br></pre></td></tr></table></figure><p>以上命令可以关闭ipv6防火墙，但是重启光猫后配置会丢失，只要光猫不重启就可以一直用。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;前段时间，在一台工作近20年的老笔记本上安装了飞牛NAS系统，跑得速度还挺快，装了1T的硬盘，平时可自动把手机里的照片视频都备份上去，还能远程离线下载电影，非常不错。&lt;/p&gt;
&lt;p&gt;如何在外面远程访问家里的NAS，这是个难题。现在找宽带运营商要免费的IPV4基本上是不可能的</summary>
      
    
    
    
    <category term="教程" scheme="https://blog.sihan.fun/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="教程" scheme="https://blog.sihan.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="NAS" scheme="https://blog.sihan.fun/tags/NAS/"/>
    
    <category term="IPV6" scheme="https://blog.sihan.fun/tags/IPV6/"/>
    
  </entry>
  
  <entry>
    <title>H96MAX系统重装教程</title>
    <link href="https://blog.sihan.fun/posts/c549160f.html"/>
    <id>https://blog.sihan.fun/posts/c549160f.html</id>
    <published>2024-01-16T16:00:00.000Z</published>
    <updated>2024-01-16T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="🛠️-系统重装准备工作"><a href="#🛠️-系统重装准备工作" class="headerlink" title="🛠️ 系统重装准备工作"></a>🛠️ 系统重装准备工作</h2><div class="note info flat"><p>准备工具：</p><ul><li>准备&gt;=8g的U盘一个(也许不止一个，有些U盘识别不好时请更换U盘试下)</li><li>局域网 IP扫描工具</li><li>电脑SSH连接服务器工具 SecureCRT | MobaXterm</li><li>镜像烧录工具 usbit | Win32磁盘映像工具 | balenaEtcher (推荐使用balenaEtcher)</li></ul></div><div class="note primary flat"><p>以上所有文件下载地址: 【软件库 -&gt; 系统重装准备工具】</p></div><h2 id="💿-U盘启动盘镜像下载"><a href="#💿-U盘启动盘镜像下载" class="headerlink" title="💿 U盘启动盘镜像下载"></a>💿 U盘启动盘镜像下载</h2><div class="tabs" id="image"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#image-1">注意事项</button></li><li class="tab"><button type="button" data-href="#image-2">下载地址</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="image-1"><ol><li>两种镜像都可以制作U盘启动盘，<strong>与你想要恢复的系统无关，随便选择一个即可</strong></li><li>下载文件后，请提前<strong>解压出img镜像</strong>文件备用</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="image-2"><ul><li>Ubuntu镜像</li><li>下载地址: 【软件库 -&gt; U盘启动盘镜像】</li></ul><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="📥-下载系统镜像"><a href="#📥-下载系统镜像" class="headerlink" title="📥 下载系统镜像"></a>📥 下载系统镜像</h2><div class="note warning flat"><p>下载的系统镜像<strong>无需解压</strong></p></div><p>下载相对应的系统镜像，下载地址: 【软件库 -&gt; 系统盘镜像】</p><h2 id="💽-制作U盘启动盘"><a href="#💽-制作U盘启动盘" class="headerlink" title="💽 制作U盘启动盘"></a>💽 制作U盘启动盘</h2><details class="folding-tag" cyan><summary> 使用usbit(USB Image Tool)制作启动盘步骤 </summary>              <div class='content'>              <ol><li><p>插入大于8g的U盘(需要在windows上格式化，格式化格式NTFS/FAT均可，<strong>重要数据请提前保存</strong>)</p></li><li><p>按下图选择U盘图标<br><img src="/assets/updata/u盘.png" alt="u盘启动图片"></p></li><li><p>点击 <strong>Restore</strong>，选择下载好的系统启动盘镜像</p></li><li><p>选择下载好启动镜像img文件后确认，开始烧录U盘启动盘</p></li><li><p>烧录完成后，会弹出格式化，<strong>不要格式化，不要格式化，不要格式化</strong>，点击取消</p></li><li><p>退出U盘</p></li></ol>              </div>            </details><h2 id="🚀-插入U盘启动盘启动进入U盘系统"><a href="#🚀-插入U盘启动盘启动进入U盘系统" class="headerlink" title="🚀 插入U盘启动盘启动进入U盘系统"></a>🚀 插入U盘启动盘启动进入U盘系统</h2><details class="folding-tag" cyan><summary> 启动步骤 </summary>              <div class='content'>              <ol><li><p>在服务器断电情况下,插入烧录好的U盘启动盘</p><ul><li>usb2.0插入黑色口</li><li>usb3.0插入蓝色口</li><li>不行都试试</li></ul></li><li><p>连接网线</p></li><li><p>插上电源,等待U盘启动盘启动</p></li></ol><div class="note info flat"><p>如果接了电视机或者显示器的,只会显示开机画面logo(不用理会,直接使用ssh工具连接)</p></div><ol><li><p>用IP扫描工具扫描局域网IP(本文是192.168.101.74)<br><img src="/assets/updata/ip.png" alt="ip扫描工具图片"></p></li><li><p>用SSH连接工具连接服务器的IP(端口号默认为<strong>22</strong>) [默认密码是ubuntu系统]</p></li><li><p>SSH连接服务器后,输入: <strong>df -h</strong> 后回车,有显示:<strong>/dev/sda</strong>,则说明当前是USB启动</p></li></ol>              </div>            </details><h2 id="🔄-系统恢复步骤"><a href="#🔄-系统恢复步骤" class="headerlink" title="🔄 系统恢复步骤"></a>🔄 系统恢复步骤</h2><details class="folding-tag" cyan><summary> 手动恢复系统步骤 </summary>              <div class='content'>              <ol><li><p>在SSH中手动输入以下代码:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /</span><br><span class="line"><span class="built_in">mkdir</span> -p /lsddbr</span><br><span class="line"><span class="built_in">chmod</span> 777 /lsddbr</span><br><span class="line">mount /dev/mmcblk2p17 /lsddbr</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;格式化分区内容，请稍候&quot;</span></span><br><span class="line"><span class="built_in">rm</span> -rf /lsddbr/*</span><br><span class="line"><span class="built_in">cd</span> /lsddbr</span><br></pre></td></tr></table></figure></li><li><p>MobaXterm工具左侧切换到 <strong>/lsddbr</strong><br><img src="/assets/updata/ssh.png" alt="ssh链接工具"></p></li><li><p>使用MobaXterm工具上传系统镜像到 /lsddbr中(可点击上传按钮,或直接拖拽到左侧处)</p></li><li><p>等待上传完成后,执行以下代码:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /lsddbr</span><br><span class="line">tar -zxvf ubuntu20.04.tar.gz</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;解压完成&quot;</span></span><br><span class="line"><span class="built_in">rm</span> -rf ubuntu20.04.tar.gz</span><br><span class="line">umount /dev/mmcblk2p17</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;Complete! 请拔下电源后,拔下U盘,再通电开机,启动系统...&quot;</span></span><br></pre></td></tr></table></figure></li><li><p>代码执行完成后,按系统提示输入poweroff关机</p></li><li><p>等待<strong>1分钟</strong>后,拔下电源,取下U盘,重新通电开机</p></li><li><p>系统手动恢复结束</p></li></ol>              </div>            </details>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;🛠️-系统重装准备工作&quot;&gt;&lt;a href=&quot;#🛠️-系统重装准备工作&quot; class=&quot;headerlink&quot; title=&quot;🛠️ 系统重装准备工作&quot;&gt;&lt;/a&gt;🛠️ 系统重装准备工作&lt;/h2&gt;&lt;div class=&quot;note info flat&quot;&gt;&lt;p&gt;准备</summary>
      
    
    
    
    <category term="教程" scheme="https://blog.sihan.fun/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="教程" scheme="https://blog.sihan.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="系统重装" scheme="https://blog.sihan.fun/tags/%E7%B3%BB%E7%BB%9F%E9%87%8D%E8%A3%85/"/>
    
  </entry>
  
  <entry>
    <title>如何安装AList系统</title>
    <link href="https://blog.sihan.fun/posts/70289010.html"/>
    <id>https://blog.sihan.fun/posts/70289010.html</id>
    <published>2024-01-16T16:00:00.000Z</published>
    <updated>2024-01-16T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<div class="note info flat"><p>什么是AList?<br>一个支持多种存储，支持网页浏览和 WebDAV 的文件列表程序，由 gin 和 Solidjs 驱动。</p></div><h2 id="📥-获取-AList"><a href="#📥-获取-AList" class="headerlink" title="📥 获取 AList"></a>📥 获取 AList</h2><details class="folding-tag" cyan><summary> 下载说明 </summary>              <div class='content'>              <ol><li>打开 <strong>AList Release</strong> 下载待部署系统对应的文件(本机需下载arm64版本的)</li><li>最新版的前端已经和后端打包好了，不用再下载前端文件</li><li>xxxx 指的是不同系统/架构对应的名称，一般 Linux-x86/64 为 alist-linux-amd64</li><li>如果你的 glibc 版本太低，建议下载 musl 版本</li></ol>              </div>            </details><div class="note success flat"><p>当你看到 start <strong>server@0.0.0.0:5244</strong> 的输出，之后没有报错，说明操作成功。<br>第一次运行时会输出初始密码。程序默认监听 5244 端口。<br>现在打开 <a href="http://ip:5244">http://ip:5244</a> 可以看到登录页面。</p></div><h2 id="🚀-手动运行"><a href="#🚀-手动运行" class="headerlink" title="🚀 手动运行"></a>🚀 手动运行</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 解压下载的文件，得到可执行文件：</span></span><br><span class="line">tar -zxvf alist-xxxx.tar.gz  <span class="comment">#注意此处 xxxx 改为你下载的文件对应的名称</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 授予程序执行权限：</span></span><br><span class="line"><span class="built_in">chmod</span> +x alist</span><br><span class="line"></span><br><span class="line"><span class="comment"># 运行程序</span></span><br><span class="line">./alist server</span><br><span class="line"></span><br><span class="line"><span class="comment"># 获得管理员信息</span></span><br><span class="line">./alist admin</span><br></pre></td></tr></table></figure><h2 id="⚙️-守护进程"><a href="#⚙️-守护进程" class="headerlink" title="⚙️ 守护进程"></a>⚙️ 守护进程</h2><details class="folding-tag" cyan><summary> 配置守护进程 </summary>              <div class='content'>              <ol><li><p>编辑服务文件:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vi /usr/lib/systemd/system/alist.service</span><br></pre></td></tr></table></figure></li><li><p>添加以下内容:</p><figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">[Unit]</span></span><br><span class="line"><span class="attr">Description</span>=alist</span><br><span class="line"><span class="attr">After</span>=network.target</span><br><span class="line"> </span><br><span class="line"><span class="section">[Service]</span></span><br><span class="line"><span class="attr">Type</span>=simple</span><br><span class="line"><span class="attr">WorkingDirectory</span>=path_alist  <span class="comment">#例如放在地址: /mnt 下 ,即: WorkingDirectory=/mnt</span></span><br><span class="line"><span class="attr">ExecStart</span>=path_alist/alist server   <span class="comment">#WorkingDirectory=/mnt/alist server</span></span><br><span class="line"><span class="attr">Restart</span>=<span class="literal">on</span>-failure</span><br><span class="line"> </span><br><span class="line"><span class="section">[Install]</span></span><br><span class="line"><span class="attr">WantedBy</span>=multi-user.target</span><br></pre></td></tr></table></figure></li><li><p>管理命令:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 重载配置</span></span><br><span class="line">systemctl daemon-reload</span><br><span class="line"></span><br><span class="line"><span class="comment"># 启动</span></span><br><span class="line">systemctl start alist</span><br><span class="line"></span><br><span class="line"><span class="comment"># 关闭</span></span><br><span class="line">systemctl stop alist</span><br><span class="line"></span><br><span class="line"><span class="comment"># 配置开机自启</span></span><br><span class="line">systemctl <span class="built_in">enable</span> alist</span><br><span class="line"></span><br><span class="line"><span class="comment"># 取消开机自启</span></span><br><span class="line">systemctl <span class="built_in">disable</span> alist</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看状态</span></span><br><span class="line">systemctl status alist</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重启</span></span><br><span class="line">systemctl restart alist</span><br></pre></td></tr></table></figure></li></ol>              </div>            </details><h2 id="🔄-反向代理"><a href="#🔄-反向代理" class="headerlink" title="🔄 反向代理"></a>🔄 反向代理</h2><details class="folding-tag" cyan><summary> Nginx配置 </summary>              <div class='content'>              <p>在网站配置文件的 server 字段中添加:<br><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">location</span> / &#123;</span><br><span class="line">  <span class="attribute">proxy_set_header</span> X-Forwarded-For <span class="variable">$proxy_add_x_forwarded_for</span>;</span><br><span class="line">  <span class="attribute">proxy_set_header</span> X-Forwarded-Proto <span class="variable">$scheme</span>;</span><br><span class="line">  <span class="attribute">proxy_set_header</span> Host <span class="variable">$http_host</span>;</span><br><span class="line">  <span class="attribute">proxy_set_header</span> X-Real-IP <span class="variable">$remote_addr</span>;</span><br><span class="line">  <span class="attribute">proxy_set_header</span> Range <span class="variable">$http_range</span>;</span><br><span class="line">  <span class="attribute">proxy_set_header</span> If-Range <span class="variable">$http_if_range</span>;</span><br><span class="line">  <span class="attribute">proxy_redirect</span> <span class="literal">off</span>;</span><br><span class="line">  <span class="attribute">proxy_pass</span> http://127.0.0.1:5244;</span><br><span class="line">  <span class="comment"># the max size of file to upload</span></span><br><span class="line">  <span class="attribute">client_max_body_size</span> <span class="number">20000m</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><div class="note warning flat"><p>如果使用宝塔面板，请务必删除以下默认配置(建议用#注释掉即可):<br><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">location</span> <span class="regexp">~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md</span></span><br><span class="line"><span class="section">location</span> <span class="regexp">~ .\*\.(gif|jpg|jpeg|png|bmp|swf)$</span></span><br><span class="line"><span class="section">location</span> <span class="regexp">~ .\*\.(js|css)?$</span></span><br></pre></td></tr></table></figure></p></div>              </div>            </details>]]></content>
    
    
      
      
    <summary type="html">&lt;div class=&quot;note info flat&quot;&gt;&lt;p&gt;什么是AList?&lt;br&gt;一个支持多种存储，支持网页浏览和 WebDAV 的文件列表程序，由 gin 和 Solidjs 驱动。&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;📥-获取-AList&quot;&gt;&lt;a href=&quot;#📥</summary>
      
    
    
    
    <category term="教程" scheme="https://blog.sihan.fun/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="教程" scheme="https://blog.sihan.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="AList" scheme="https://blog.sihan.fun/tags/AList/"/>
    
  </entry>
  
  <entry>
    <title>泰山派使用教程</title>
    <link href="https://blog.sihan.fun/posts/17a44e88.html"/>
    <id>https://blog.sihan.fun/posts/17a44e88.html</id>
    <published>2024-01-16T16:00:00.000Z</published>
    <updated>2024-01-16T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<div class="note info flat"><p>如果需要安装docker就得用内核5.0以上的镜像，不需要用docker就用官方给的镜像刷入就可以了</p></div><h2 id="🖥️-镜像下载"><a href="#🖥️-镜像下载" class="headerlink" title="🖥️ 镜像下载"></a>🖥️ 镜像下载</h2><div class="tabs" id="image"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#image-1">官方镜像</button></li><li class="tab"><button type="button" data-href="#image-2">Docker镜像</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="image-1"><p>官方刷入链接：<a href="https://wiki.lckfb.com/zh-hans/tspi-rk3566/system-usage/img-download.html#%E3%80%90%E7%AB%8B%E5%88%9B%C2%B7%E6%B3%B0%E5%B1%B1%E6%B4%BErk3566%E5%BC%80%E5%8F%91%E6%9D%BF%E3%80%91%E9%95%9C%E5%83%8F%E7%83%A7%E5%BD%95%E6%95%99%E7%A8%8B">点击下载</a></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="image-2"><p>可用docker镜像：<a href="https://wiki.lckfb.com/zh-hans/tspi-rk3566/system-usage/img-download.html#%E3%80%90%E7%AB%8B%E5%88%9B%C2%B7%E6%B3%B0%E5%B1%B1%E6%B4%BErk3566%E5%BC%80%E5%8F%91%E6%9D%BF%E3%80%91%E9%95%9C%E5%83%8F%E7%83%A7%E5%BD%95%E6%95%99%E7%A8%8B">点击下载</a></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="📶-连接WiFi并使用ssh连接设备"><a href="#📶-连接WiFi并使用ssh连接设备" class="headerlink" title="📶 连接WiFi并使用ssh连接设备"></a>📶 连接WiFi并使用ssh连接设备</h2><details class="folding-tag" cyan><summary> WiFi相关命令 </summary>              <div class='content'>              <p>查看附近可用WiFi命令:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nmcli device wifi list</span><br></pre></td></tr></table></figure></p><p>连接WiFi:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nmcli device wifi connect <span class="string">&quot;名称&quot;</span> password <span class="string">&quot;密码&quot;</span></span><br></pre></td></tr></table></figure></p><p>查看WiFi是否连接:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nmcli con show</span><br></pre></td></tr></table></figure></p>              </div>            </details><h2 id="🔄-添加清华源"><a href="#🔄-添加清华源" class="headerlink" title="🔄 添加清华源"></a>🔄 添加清华源</h2><div class="note warning flat"><p>请确保网络连接正常再执行以下命令</p></div><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">wget https://tuna.moe/oh-my-tuna/oh-my-tuna.py</span><br><span class="line">python3 oh-my-tuna.py</span><br><span class="line">python3 oh-my-tuna.py --global</span><br><span class="line">python3 oh-my-tuna.py -h</span><br></pre></td></tr></table></figure><h2 id="🔒-SSH配置"><a href="#🔒-SSH配置" class="headerlink" title="🔒 SSH配置"></a>🔒 SSH配置</h2><details class="folding-tag" cyan><summary> SSH安装与配置步骤 </summary>              <div class='content'>              <ol><li><p>重设Linux密码:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> passwd root</span><br></pre></td></tr></table></figure></li><li><p>安装ssh:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">apt-get update</span><br><span class="line"><span class="built_in">sudo</span> apt-get install openssh-client</span><br><span class="line"><span class="built_in">sudo</span> apt-get install openssh-server</span><br></pre></td></tr></table></figure></li><li><p>启动ssh服务:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/etc/init.d/ssh start</span><br></pre></td></tr></table></figure></li><li><p>查看是否安装成功:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> ps -e | grep ssh</span><br></pre></td></tr></table></figure></li><li><p>更改ssh配置:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vim /etc/ssh/sshd_config</span><br></pre></td></tr></table></figure></li></ol><div class="note info flat"><p>将 Port 前方的 # 删掉，然后改一个自己想要的端口号，建议端口号不要小于6000！<br>这里我们修改为 8080 端口。<br>默认端口号是：22</p></div><p><img src="/assets/updata/bb2a1732850127.png" alt="SSH配置示意图"></p><div class="note primary flat"><p>将#PermitRootLogin without-password改为PermitRootLogin yes</p></div><p><img src="/assets/updata/c9b01732850269.png" alt="SSH配置修改"></p><ol><li>重启SSH服务使配置生效:<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> /etc/init.d/ssh restart</span><br></pre></td></tr></table></figure></li></ol>              </div>            </details><h2 id="🐳-使用阿里源安装Docker"><a href="#🐳-使用阿里源安装Docker" class="headerlink" title="🐳 使用阿里源安装Docker"></a>🐳 使用阿里源安装Docker</h2><div class="note info flat"><p>因为官方下架了dockerhub的镜像，我们更换一个阿里的镜像源</p></div><details class="folding-tag" cyan><summary> Docker安装步骤 </summary>              <div class='content'>              <ol><li><p>更新apt包索引并安装相关软件包:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> apt-get update</span><br><span class="line"><span class="built_in">sudo</span> apt-get install ca-certificates curl gnupg lsb-release</span><br></pre></td></tr></table></figure></li><li><p>添加阿里云的Docker GPG密钥:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> <span class="built_in">mkdir</span> -p /etc/apt/keyrings</span><br><span class="line">curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | <span class="built_in">sudo</span> gpg --dearmor -o /etc/apt/keyrings/docker.gpg</span><br></pre></td></tr></table></figure></li><li><p>添加阿里云的Docker源:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&quot;deb [arch=<span class="subst">$(dpkg --print-architecture)</span> signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu <span class="subst">$(lsb_release -cs)</span> stable&quot;</span> | <span class="built_in">sudo</span> <span class="built_in">tee</span> /etc/apt/sources.list.d/docker.list &gt; /dev/null</span><br></pre></td></tr></table></figure></li><li><p>安装Docker engine:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> apt-get update</span><br><span class="line"><span class="built_in">sudo</span> apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin</span><br></pre></td></tr></table></figure></li><li><p>验证安装完成:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> docker -v</span><br><span class="line"><span class="comment"># 打印出版本号</span></span><br><span class="line">Docker version 24.0.2, build cb74dfc</span><br></pre></td></tr></table></figure></li><li><p>修复Docker并重启:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> update-alternatives --<span class="built_in">set</span> iptables /usr/sbin/iptables-legacy &amp;&amp; update-alternatives --<span class="built_in">set</span> ip6tables /usr/sbin/ip6tables-legacy</span><br><span class="line"><span class="comment"># 修复好docker后重启一下</span></span><br><span class="line"><span class="built_in">sudo</span> systemctl restart docker</span><br></pre></td></tr></table></figure></li></ol>              </div>            </details>]]></content>
    
    
      
      
    <summary type="html">&lt;div class=&quot;note info flat&quot;&gt;&lt;p&gt;如果需要安装docker就得用内核5.0以上的镜像，不需要用docker就用官方给的镜像刷入就可以了&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;🖥️-镜像下载&quot;&gt;&lt;a href=&quot;#🖥️-镜像下载&quot; class=&quot;he</summary>
      
    
    
    
    <category term="教程" scheme="https://blog.sihan.fun/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="教程" scheme="https://blog.sihan.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="Linux" scheme="https://blog.sihan.fun/tags/Linux/"/>
    
  </entry>
  
  <entry>
    <title>泰山派使用docker安装Home Assistant经验</title>
    <link href="https://blog.sihan.fun/posts/d5d4f67a.html"/>
    <id>https://blog.sihan.fun/posts/d5d4f67a.html</id>
    <published>2024-01-16T16:00:00.000Z</published>
    <updated>2024-01-16T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<div class="note warning modern"><p><i class="fas fa-exclamation-circle"></i> <strong>前置要求</strong><br>请确保已经完成Docker的安装和配置</p></div><h2 id="🔄-修改Docker镜像源"><a href="#🔄-修改Docker镜像源" class="headerlink" title="🔄 修改Docker镜像源"></a>🔄 修改Docker镜像源</h2><div class="tabs" id="docker源配置"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#docker源配置-1">手动编辑配置</button></li><li class="tab"><button type="button" data-href="#docker源配置-2">命令行一键配置</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="docker源配置-1"><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vi /etc/docker/daemon.json</span><br></pre></td></tr></table></figure><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;registry-mirrors&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">        <span class="string">&quot;https://docker.1panelproxy.com&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="string">&quot;https://docker-proxy.741001.xyz&quot;</span><span class="punctuation">,</span> </span><br><span class="line">        <span class="string">&quot;https://registry.docker-cn.com&quot;</span></span><br><span class="line">    <span class="punctuation">]</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="docker源配置-2"><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> <span class="built_in">tee</span> /etc/docker/daemon.json &lt;&lt;-<span class="string">&#x27;EOF&#x27;</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="string">&quot;registry-mirrors&quot;</span>: [</span><br><span class="line">    <span class="string">&quot;https://docker.m.daocloud.io&quot;</span>,</span><br><span class="line">    <span class="string">&quot;https://docker.1panel.live&quot;</span>,</span><br><span class="line">    <span class="string">&quot;https://hub.rat.dev&quot;</span></span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><div class="note info flat"><p>修改后需要重启Docker服务：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">systemctl restart docker</span><br></pre></td></tr></table></figure></p></div><h2 id="📦-Home-Assistant安装"><a href="#📦-Home-Assistant安装" class="headerlink" title="📦 Home Assistant安装"></a>📦 Home Assistant安装</h2><details class="folding-tag" cyan open><summary> 详细安装步骤 </summary>              <div class='content'>              <ol><li><p>拉取镜像：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 最新版</span></span><br><span class="line">docker pull homeassistant/home-assistant</span><br><span class="line"></span><br><span class="line"><span class="comment"># 或指定稳定版</span></span><br><span class="line">docker pull homeassistant/home-assistant:stable</span><br></pre></td></tr></table></figure></li><li><p>创建数据目录：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> -p /data/homeassistant</span><br></pre></td></tr></table></figure></li><li><p>启动容器：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">docker run -d \</span><br><span class="line">  --name homeassistant \</span><br><span class="line">  --privileged \</span><br><span class="line">  --restart=unless-stopped \</span><br><span class="line">  -e TZ=Asia/Shanghai \</span><br><span class="line">  -v /data/homeassistant:/config \</span><br><span class="line">  --network=host \</span><br><span class="line">  homeassistant/home-assistant</span><br></pre></td></tr></table></figure></li></ol><div class="note primary flat"><p><i class="fas fa-folder-open"></i> 目录说明：<br><code>/data/homeassistant</code> 是配置文件存储路径，请根据实际情况修改</p></div>              </div>            </details><h2 id="🔌-HACS安装指南"><a href="#🔌-HACS安装指南" class="headerlink" title="🔌 HACS安装指南"></a>🔌 HACS安装指南</h2><div class="note success flat"><p><i class="fab fa-github"></i> <strong>HACS</strong> 是Home Assistant的第三方插件商店，支持接入主流智能家居平台</p></div><details class="folding-tag" blue><summary> 分步安装流程 </summary>              <div class='content'>              <ol><li><p>创建必要目录结构：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> -p /data/homeassistant/&#123;www,custom_components/hacs&#125;</span><br></pre></td></tr></table></figure></li><li><p>一键安装脚本：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /data/homeassistant</span><br><span class="line">wget -O - https://get.hacs.vip | bash -</span><br></pre></td></tr></table></figure></li><li><p>重启服务生效：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker restart homeassistant</span><br></pre></td></tr></table></figure></li></ol><div class="note warning flat"><p><i class="fas fa-exclamation-triangle"></i> 常见问题：  </p><ul><li>安装失败可尝试旧版：<code>HACS 1.22.0</code> 对应 <code>HA 2021.12.8</code></li><li>确保网络通畅，必要时使用代理</li></ul></div>              </div>            </details><h2 id="📹-Go2RTC流媒体服务"><a href="#📹-Go2RTC流媒体服务" class="headerlink" title="📹 Go2RTC流媒体服务"></a>📹 Go2RTC流媒体服务</h2><details class="folding-tag" orange><summary> 安装配置说明 </summary>              <div class='content'>              <figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">docker run -d \</span><br><span class="line">  --name go2rtc \</span><br><span class="line">  -v /data/go2rtc:/config \</span><br><span class="line">  --net=host \</span><br><span class="line">  --restart=unless-stopped \</span><br><span class="line">  alexxit/go2rtc</span><br></pre></td></tr></table></figure><div class="note info flat"><p><i class="fas fa-info-circle"></i> 功能说明：<br>提供RTSP/RTMP流媒体转换服务，用于摄像头等设备接入</p></div>              </div>            </details>]]></content>
    
    
      
      
    <summary type="html">&lt;div class=&quot;note warning modern&quot;&gt;&lt;p&gt;&lt;i class=&quot;fas fa-exclamation-circle&quot;&gt;&lt;/i&gt; &lt;strong&gt;前置要求&lt;/strong&gt;&lt;br&gt;请确保已经完成Docker的安装和配置&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id</summary>
      
    
    
    
    <category term="教程" scheme="https://blog.sihan.fun/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="教程" scheme="https://blog.sihan.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="Docker" scheme="https://blog.sihan.fun/tags/Docker/"/>
    
    <category term="Home Assistant" scheme="https://blog.sihan.fun/tags/Home-Assistant/"/>
    
  </entry>
  
  <entry>
    <title>玩客云装宝塔（无需焊接）0基础教程</title>
    <link href="https://blog.sihan.fun/posts/f1370e4a.html"/>
    <id>https://blog.sihan.fun/posts/f1370e4a.html</id>
    <published>2024-01-16T16:00:00.000Z</published>
    <updated>2024-01-16T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="🛠️-准备工具"><a href="#🛠️-准备工具" class="headerlink" title="🛠️ 准备工具"></a>🛠️ 准备工具</h2><div class="note info flat"><ol><li>USB公对公（没有的可以自己DIY）</li><li>金属线一段或镊子</li><li>如果你的宽带支持IPV6建议关闭（路由器禁用即可）</li></ol></div><div class="note warning flat"><p>最新提示：固件用5.9的（2022-12-18）<br>刷机工具安装时关闭杀毒软件避免驱动装不上</p></div><h2 id="📥-刷机步骤"><a href="#📥-刷机步骤" class="headerlink" title="📥 刷机步骤"></a>📥 刷机步骤</h2><details class="folding-tag" cyan><summary> 详细刷机步骤 </summary>              <div class='content'>              <ol><li><p>安装刷机工具后，按下图操作，导入下载好的刷机包<br><div class="note primary flat"><p>请仔细对照下图第2步</p></div><br><img src="/assets/updata/4a471731571636.png" alt="刷机工具设置"></p></li><li><p>拆开玩客云，取出主板，USB公对公插入接近HDMI口的那一个，另一端插电脑<br><img src="/assets/updata/fb5c1731571655.png" alt="主板连接"></p></li><li><p>用镊子或者电线短接主板触点插入电源<br><div class="note info flat"><p>2种主板，请对号入座</p></div><br><img src="/assets/updata/10fb1731571667.png" alt="主板类型1"><br><img src="/assets/updata/09dd1731571675.png" alt="主板类型2"></p></li><li><p>这时，电脑能听到插入设备的提示音，并显示如下<br><img src="/assets/updata/82661731571716.png" alt="连接成功"></p></li></ol><div class="note warning flat"><p>如果不显示连接成功，拔掉电源重新操作</p></div><ol><li>软件显示连接成功后即断开触点短接，点击开始即可<br><img src="/assets/updata/f19c1731571723.png" alt="开始刷机"></li></ol><div class="note warning flat"><p>中途如果失败，断开电源重新操作</p></div><p><img src="/assets/updata/9eb91731571731.png" alt="刷机过程"></p><ol><li><p>烧录过程中，可以写U盘了，先把网盘里的下载的U盘文件解压出来，按照下边图示操作<br><img src="/assets/updata/602e1731571740.png" alt="U盘写入"></p></li><li><p>玩客云烧录成功后:</p><ul><li>点击停止、关闭软件</li><li>拔掉USB和电源</li><li>将U盘插到网口边的USB插电启动</li><li>过一会后指示灯红蓝闪烁就是开始刷机</li><li>几分钟后，蓝灯常亮不闪时，断电拔出U盘</li><li>插入网线和电源即可</li></ul></li></ol>              </div>            </details><h2 id="🔐-系统配置"><a href="#🔐-系统配置" class="headerlink" title="🔐 系统配置"></a>🔐 系统配置</h2><details class="folding-tag" cyan><summary> 系统初始配置 </summary>              <div class='content'>              <ol><li><p>通过路由器查看玩客云的IP地址，用putty.exe登陆改密码</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 用户名和密码</span></span><br><span class="line">用户名: root</span><br><span class="line">密码: 1234</span><br></pre></td></tr></table></figure></li><li><p>5.9固件需要写到emmc:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /boot/install/</span><br><span class="line"><span class="built_in">sudo</span> ./install.sh</span><br></pre></td></tr></table></figure></li></ol>              </div>            </details><h2 id="🖥️-登录FinalShell"><a href="#🖥️-登录FinalShell" class="headerlink" title="🖥️ 登录FinalShell"></a>🖥️ 登录FinalShell</h2><details class="folding-tag" cyan><summary> 系统更新配置 </summary>              <div class='content'>              <ol><li><p>修改源:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">wget https://tuna.moe/oh-my-tuna/oh-my-tuna.py</span><br><span class="line">python3 oh-my-tuna.py</span><br><span class="line">python3 oh-my-tuna.py --global</span><br><span class="line">python3 oh-my-tuna.py -h</span><br></pre></td></tr></table></figure></li><li><p>更新源:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> apt update</span><br><span class="line"><span class="built_in">sudo</span> apt upgrade</span><br></pre></td></tr></table></figure></li></ol>              </div>            </details><h2 id="🔧-安装宝塔和初始环境"><a href="#🔧-安装宝塔和初始环境" class="headerlink" title="🔧 安装宝塔和初始环境"></a>🔧 安装宝塔和初始环境</h2><div class="note warning flat"><p>耗时约1小时,出红字错误后执行下方修复代码</p></div><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget -O install.sh http://v820.hostcli.com/install/install-ubuntu_6.0.sh &amp;&amp; <span class="built_in">sudo</span> bash install.sh</span><br></pre></td></tr></table></figure><h3 id="释放空间"><a href="#释放空间" class="headerlink" title="释放空间"></a>释放空间</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">swapoff -a</span><br><span class="line"><span class="built_in">rm</span> -f /www/swap</span><br></pre></td></tr></table></figure><h2 id="💾-手动挂载磁盘"><a href="#💾-手动挂载磁盘" class="headerlink" title="💾 手动挂载磁盘"></a>💾 手动挂载磁盘</h2><details class="folding-tag" cyan><summary> 磁盘挂载步骤 </summary>              <div class='content'>              <ol><li><p>检查磁盘状态:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">df</span> -h</span><br></pre></td></tr></table></figure></li><li><p>插入usb设备</p></li><li><p>查看usb设备号</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">fdisk -l</span><br><span class="line"></span><br><span class="line">blkid</span><br></pre></td></tr></table></figure></li></ol><div class="note info flat"><p>TF卡显示mmcblk0,U盘或移动硬盘会显示sdb或者sda</p></div><p><img src="/assets/updata/1d341731572417.png" alt="硬盘信息"></p><ol><li><p>格式化usb设备:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mkfs -t ext4 /dev/sdb</span><br></pre></td></tr></table></figure></li><li><p>建立挂载文件夹:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /mnt</span><br><span class="line"><span class="built_in">mkdir</span> usb</span><br></pre></td></tr></table></figure></li><li><p>挂载usb设备:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mount /dev/sdb /mnt/usb</span><br></pre></td></tr></table></figure></li><li><p>实现开机自动挂载:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nano /etc/fstab</span><br></pre></td></tr></table></figure></li><li><p>写入:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/dev/sdb /mnt/usb ext4 defaults 0 0</span><br></pre></td></tr></table></figure></li></ol>              </div>            </details><div class="note warning flat"><p>如果您是用于生产环境，数据备份是重点。<br>安装完宝塔再挂载外部介质即可。</p></div><h2 id="📶-WiFi配置参考"><a href="#📶-WiFi配置参考" class="headerlink" title="📶 WiFi配置参考"></a>📶 WiFi配置参考</h2><details class="folding-tag" cyan><summary> WiFi相关命令 </summary>              <div class='content'>              <ol><li><p>查看附近网络:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nmcli device wifi list</span><br></pre></td></tr></table></figure></li><li><p>连接网络:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nmcli device wifi connect <span class="string">&quot;名称&quot;</span> password <span class="string">&quot;密码&quot;</span></span><br></pre></td></tr></table></figure></li><li><p>查看网络是否连接:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nmcli con show</span><br></pre></td></tr></table></figure></li></ol>              </div>            </details>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;🛠️-准备工具&quot;&gt;&lt;a href=&quot;#🛠️-准备工具&quot; class=&quot;headerlink&quot; title=&quot;🛠️ 准备工具&quot;&gt;&lt;/a&gt;🛠️ 准备工具&lt;/h2&gt;&lt;div class=&quot;note info flat&quot;&gt;&lt;ol&gt;
&lt;li&gt;USB公对公（没有的可以</summary>
      
    
    
    
    <category term="教程" scheme="https://blog.sihan.fun/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="教程" scheme="https://blog.sihan.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="玩客云" scheme="https://blog.sihan.fun/tags/%E7%8E%A9%E5%AE%A2%E4%BA%91/"/>
    
    <category term="宝塔面板" scheme="https://blog.sihan.fun/tags/%E5%AE%9D%E5%A1%94%E9%9D%A2%E6%9D%BF/"/>
    
  </entry>
  
</feed>
