[C#] 解決 GitHub 圖片 429 錯誤:轉換 jsDelivr CDN 網址

  • 6
  • 0

最近我遇到一個 GitHub 圖片載入的問題

我習慣把 Blog 使用的一些圖片放在 GitHub Repository,網站直接使用 GitHub Raw URL 顯示圖片

原本一直都正常,但最近在單一 Client 一次讀取比較多圖片時,突然開始出現下面的錯誤

429: Too Many Requests For more on scraping GitHub and how it may affect your rights, please review our Terms of Service

(https://docs.github.com/en/site-policy/github-terms/github-terms-of-service).

最後我的處理方式很簡單,也是 AI 提示我的 就是改走 jsDelivr CDN 不要讓 Client 直接讀取 GitHub Raw

另外 GitHub 在點擊 Raw 或取得圖片網址時,也可能拿到這種格式:

https://github.com/donma/BlogResource/blob/main/2569/264203.png?raw=true

這兩種網址直接丟到瀏覽器都可以正常顯示圖片

所以一開始我也沒有特別處理

但問題就在於,GitHub Raw 可以讀取圖片,不代表適合直接拿來當網站的圖片 CDN
 

當同一個 Client 在短時間內載入大量圖片時,就有機會直接收到:

429: Too Many Requests,可能最近因為 vibe coding 問一下 AI 好像再 2025 下半年開始陸續出現這問題..

1. 簡單的說就是改寫網址把網址改成

網址格式如下:

https://cdn.jsdelivr.net/gh/{owner}/{repo}@{branch}/{path}

例如原本:

https://raw.githubusercontent.com/donma/BlogResource/refs/heads/main/2569/0331-03-42.jfif

轉換後:

https://cdn.jsdelivr.net/gh/donma/BlogResource@main/2569/0331-03-42.jfif

另一種 GitHub Blob URL:

https://github.com/donma/BlogResource/blob/main/2569/264203.png?raw=true

轉換後:

https://cdn.jsdelivr.net/gh/donma/BlogResource@main/2569/264203.png

其實規則不複雜。

GitHub Raw:

/{owner}/{repo}/refs/heads/{branch}/{path}

GitHub Blob:

/{owner}/{repo}/blob/{branch}/{path}

最後統一轉成:

/{owner}/{repo}@{branch}/{path}


2. 這邊提供一個 C# function ,之後你就可以無腦使用

using System;
using System.Linq;

public static string ToJsDelivrUrl(string url)
{
    if (string.IsNullOrWhiteSpace(url))
    {
        return url;
    }

    Uri uri;

    if (!Uri.TryCreate(url, UriKind.Absolute, out uri))
    {
        return url;
    }

    string[] segments = uri.AbsolutePath
        .Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);

    string owner;
    string repository;
    string branch;
    string filePath;

    if (uri.Host.Equals(
        "raw.githubusercontent.com",
        StringComparison.OrdinalIgnoreCase))
    {
        if (segments.Length < 4)
        {
            return url;
        }

        owner = segments[0];
        repository = segments[1];

        if (segments.Length >= 6 &&
            segments[2].Equals(
                "refs",
                StringComparison.OrdinalIgnoreCase) &&
            segments[3].Equals(
                "heads",
                StringComparison.OrdinalIgnoreCase))
        {
            branch = segments[4];
            filePath = string.Join("/", segments.Skip(5));
        }
        else
        {
            branch = segments[2];
            filePath = string.Join("/", segments.Skip(3));
        }
    }
    else if (uri.Host.Equals(
        "github.com",
        StringComparison.OrdinalIgnoreCase))
    {
        if (segments.Length < 5 ||
            !segments[2].Equals(
                "blob",
                StringComparison.OrdinalIgnoreCase))
        {
            return url;
        }

        owner = segments[0];
        repository = segments[1];
        branch = segments[3];
        filePath = string.Join("/", segments.Skip(4));
    }
    else
    {
        return url;
    }

    if (string.IsNullOrWhiteSpace(filePath))
    {
        return url;
    }

    return string.Format(
        "https://cdn.jsdelivr.net/gh/{0}/{1}@{2}/{3}",
        owner,
        repository,
        branch,
        filePath);
}

記得加入:

using System;

using System.Linq;

這個 function 目前支援:

https://raw.githubusercontent.com/{owner}/{repo}/refs/heads/{branch}/{path}

https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{path}

以及:

https://github.com/{owner}/{repo}/blob/{branch}/{path}?raw=true

如果不是 Github 圖片網址,就直接回傳原本的 URL

最後說個結論,其實一值把圖片在 Github 上不一定是好事,但是之前就這樣規畫了

所以這目前是一個快速解決的方法,最好的方式還是自己 own 圖片但是就是得自己扛流量

這次遇到 GitHub Raw 回傳 429: Too Many Requests,才發現原本一直可以正常讀取

不代表這個使用方式就適合網站長期使用,改到 jsdelivr 應該是目前最簡單的解法

紀錄一下,給之後遇到有需要的人 :)

 

---

The bug existed in all possible states.
Until I ran the code.