<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>文章 on Feng-Chi's Notes</title><link>https://holmeslin.github.io/posts/</link><description>Recent content in 文章 on Feng-Chi's Notes</description><generator>Hugo -- gohugo.io</generator><language>zh-tw</language><lastBuildDate>Mon, 02 Nov 2026 14:00:00 +0800</lastBuildDate><atom:link href="https://holmeslin.github.io/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>用 os.Root 寫一個安全的 Go 檔案儲存</title><link>https://holmeslin.github.io/posts/go-os-root-safe-file-store/</link><pubDate>Mon, 02 Nov 2026 14:00:00 +0800</pubDate><guid>https://holmeslin.github.io/posts/go-os-root-safe-file-store/</guid><description>&lt;p&gt;讓使用者上傳檔案、存在伺服器的某個目錄底下，是很常見的需求。最直覺的寫法只要兩行，但這兩行藏了三個問題：檔名可以跳出目錄、寫到一半當機會留下殘檔、讀檔時可能被一個 FIFO 卡住整個 goroutine。&lt;/p&gt;
&lt;p&gt;這篇從最直覺的寫法開始，逐一修掉這三個問題。主角是 Go 1.24 新增的 &lt;code&gt;os.Root&lt;/code&gt;。&lt;/p&gt;</description></item><item><title>url.Redacted() 遮不住的 token</title><link>https://holmeslin.github.io/posts/go-url-redacted-credential-leak/</link><pubDate>Mon, 02 Nov 2026 13:00:00 +0800</pubDate><guid>https://holmeslin.github.io/posts/go-url-redacted-credential-leak/</guid><description>&lt;p&gt;服務啟動時把連線字串印到 log，方便確認連到哪台機器，這是很常見的寫法。Go 的 &lt;code&gt;net/url&lt;/code&gt; 有一個 &lt;code&gt;Redacted()&lt;/code&gt;，看名字會以為它能把敏感資訊遮掉，但它只遮「密碼」這一格。很多連線字串的祕密根本不放在那一格。&lt;/p&gt;
&lt;p&gt;這篇用實際跑過的測試，整理 &lt;code&gt;Redacted()&lt;/code&gt; 會漏掉的幾種情況，以及 &lt;code&gt;url.Parse&lt;/code&gt; 錯誤訊息的同類問題，最後給一個簡單的替代寫法。&lt;/p&gt;</description></item><item><title>Vite 部署後舊分頁點不動</title><link>https://holmeslin.github.io/posts/vite-preload-error-stale-chunk/</link><pubDate>Mon, 02 Nov 2026 12:00:00 +0800</pubDate><guid>https://holmeslin.github.io/posts/vite-preload-error-stale-chunk/</guid><description>&lt;p&gt;Vite 打包的 SPA 部署新版之後，常會收到這種回報：「選單點了沒反應，重新整理就好了。」原因是使用者的分頁還停在舊版，舊版要載入的 chunk 在伺服器上已經不存在了。&lt;/p&gt;
&lt;p&gt;Vite 官方文件提供了 &lt;code&gt;vite:preloadError&lt;/code&gt; 事件，範例只有一行 &lt;code&gt;window.location.reload()&lt;/code&gt;。這一行能解決大部分情況，但它沒處理無限重整、同一次失敗觸發好幾次，也沒顧慮使用者手上正在進行的工作。這篇從官方範例出發，逐一補上這些狀況。&lt;/p&gt;</description></item><item><title>用 Claude Code hook 擋危險指令</title><link>https://holmeslin.github.io/posts/claude-code-pretooluse-hook-guardrails/</link><pubDate>Mon, 02 Nov 2026 11:00:00 +0800</pubDate><guid>https://holmeslin.github.io/posts/claude-code-pretooluse-hook-guardrails/</guid><description>&lt;p&gt;在 CLAUDE.md 寫「不要 force push」，模型大多會遵守，但「大多」不夠。Claude Code 的 PreToolUse hook 會在每次工具呼叫之前執行你的腳本，由腳本決定放行或擋下，模型沒辦法用說理的方式繞過去。&lt;/p&gt;
&lt;p&gt;寫 hook 時最容易忽略的問題是：&lt;strong&gt;hook 自己出錯的時候該怎麼辦？&lt;/strong&gt; 擋危險指令的護欄，出錯時應該擋下（fail-closed）；只是提醒的 hook，出錯時應該安靜放行（fail-open）。這篇用兩支 bash 腳本說明這兩種設計。&lt;/p&gt;</description></item><item><title>檢查 ?redirect= 防 open redirect</title><link>https://holmeslin.github.io/posts/open-redirect-validation/</link><pubDate>Mon, 02 Nov 2026 10:00:00 +0800</pubDate><guid>https://holmeslin.github.io/posts/open-redirect-validation/</guid><description>&lt;p&gt;使用者在未登入時打開 &lt;code&gt;/orders/42&lt;/code&gt;，前端把他導到 &lt;code&gt;/login?redirect=/orders/42&lt;/code&gt;，登入成功後再導回去。這個流程幾乎每個 SPA 都有，但 &lt;code&gt;redirect&lt;/code&gt; 是網址上的參數，誰都能改。只要改成 &lt;code&gt;?redirect=https://evil.com&lt;/code&gt;，使用者就會在剛輸入完帳號密碼、最信任你的那一刻，被送到攻擊者的頁面。這就是 open redirect。&lt;/p&gt;
&lt;p&gt;這篇從最常見的檢查開始，說明它怎麼被繞過，再一層一層補起來。&lt;/p&gt;</description></item><item><title>JavaScript 筆記</title><link>https://holmeslin.github.io/posts/javascript-note/</link><pubDate>Thu, 15 Oct 2020 15:43:43 +0800</pubDate><guid>https://holmeslin.github.io/posts/javascript-note/</guid><description>&lt;p&gt;紀錄 Javscript 相關筆記&lt;/p&gt;</description></item><item><title>Clean Code 系列 - Javascript</title><link>https://holmeslin.github.io/posts/clean-code-javascript/</link><pubDate>Thu, 30 Jul 2020 08:10:05 +0800</pubDate><guid>https://holmeslin.github.io/posts/clean-code-javascript/</guid><description/></item><item><title>Clean Code 系列 - PHP</title><link>https://holmeslin.github.io/posts/clean-code-php/</link><pubDate>Thu, 30 Jul 2020 08:10:05 +0800</pubDate><guid>https://holmeslin.github.io/posts/clean-code-php/</guid><description/></item><item><title>關於 Web 跨域相關紀錄</title><link>https://holmeslin.github.io/posts/cross-domain/</link><pubDate>Tue, 14 Jul 2020 08:51:19 +0800</pubDate><guid>https://holmeslin.github.io/posts/cross-domain/</guid><description>&lt;h2 id="前言"&gt;前言&lt;/h2&gt;
&lt;p&gt;前段時間公司同事出現了跨域問題 , 雖然我知道了大略的解決方案 , 但是說實在的真實真實的跨域知識及領域 ,&lt;/p&gt;
&lt;p&gt;不是了解得很透徹 , 趁這個機會好好查一下文章記錄下來&lt;/p&gt;</description></item><item><title>Nginx 相關設定</title><link>https://holmeslin.github.io/posts/nginx-setting-record/</link><pubDate>Thu, 09 Jul 2020 14:20:56 +0800</pubDate><guid>https://holmeslin.github.io/posts/nginx-setting-record/</guid><description/></item><item><title>RHEL(CentOS) 離線安裝套件</title><link>https://holmeslin.github.io/posts/server-offline-install-software/</link><pubDate>Thu, 09 Jul 2020 14:14:35 +0800</pubDate><guid>https://holmeslin.github.io/posts/server-offline-install-software/</guid><description/></item><item><title>編譯原始碼安裝 Nginx 在 RHEL / CentOS 環境下</title><link>https://holmeslin.github.io/posts/build-nginx-centos/</link><pubDate>Thu, 09 Jul 2020 14:01:14 +0800</pubDate><guid>https://holmeslin.github.io/posts/build-nginx-centos/</guid><description/></item><item><title>Goroutine 和 Channel 講解</title><link>https://holmeslin.github.io/posts/go-goroutine-channel/</link><pubDate>Wed, 08 Jul 2020 10:36:17 +0800</pubDate><guid>https://holmeslin.github.io/posts/go-goroutine-channel/</guid><description>&lt;h2 id="前言"&gt;前言&lt;/h2&gt;
&lt;p&gt;Go 語言中並發程序可以用兩種方式來實現。&lt;/p&gt;
&lt;p&gt;一種是 &lt;code&gt;goroutine&lt;/code&gt; 和 &lt;code&gt;channel&lt;/code&gt;，其支持 &amp;ldquo;交談循序程式&amp;rdquo;（communicating sequential processes）或被簡稱為 CSP。&lt;/p&gt;
&lt;p&gt;CSP 是一個現代的並發程式模型，在這種程式模型中值會在不同的運行實例(goroutine)中傳遞，儘管大多數情況下被限制在單一實例中。&lt;/p&gt;
&lt;p&gt;另一種是傳統的並發模型，多線程共享內存(基於共享變量的並發) ， 會在後續單獨闡述。&lt;/p&gt;</description></item><item><title>Go 語言 sync 包的應用詳解</title><link>https://holmeslin.github.io/posts/go-sync/</link><pubDate>Tue, 07 Jul 2020 15:07:16 +0800</pubDate><guid>https://holmeslin.github.io/posts/go-sync/</guid><description>&lt;p&gt;並發程式中的同步也就是我們通常說的鎖的主要作用是保證多個線程或者 &lt;code&gt;goroutine&lt;/code&gt; 在訪問同一片內存時不會出現混亂的問題。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Go&lt;/code&gt; 語言的 &lt;code&gt;sync&lt;/code&gt; 包提供了常見的並發程式同步 。 今天的文章裡讓我們回到應用層 ， 聚焦 &lt;code&gt;sync&lt;/code&gt; 包裡這些同步的應用場景 ， 同時也會介紹 &lt;code&gt;sync&lt;/code&gt; 包中的 &lt;code&gt;Pool&lt;/code&gt; 和 &lt;code&gt;Map&lt;/code&gt; 的應用場景和使用方法。&lt;/p&gt;</description></item><item><title>本站建置過程紀錄</title><link>https://holmeslin.github.io/posts/blog-build-process/</link><pubDate>Tue, 07 Jul 2020 14:29:40 +0800</pubDate><guid>https://holmeslin.github.io/posts/blog-build-process/</guid><description>&lt;blockquote&gt;
&lt;p&gt;紀錄建置過程&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;註：本文記錄的是 2020 年的舊架構（hugo-theme-even + peaceiris/actions-gh-pages），本站目前已改用 toha 主題與 GitHub Pages 官方部署流程。&lt;/p&gt;
&lt;/blockquote&gt;</description></item></channel></rss>