Merge pull request #245 from gnh1201/dev
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled

Add JavaScript CDN servers
This commit is contained in:
Namhyeon Go 2025-05-05 23:44:59 +09:00 committed by GitHub
commit aee5fb22d0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 202 additions and 10 deletions

View File

@ -60,6 +60,15 @@ namespace WelsonJS.Launcher.Properties {
}
}
/// <summary>
/// https://ajax.aspnetcdn.com/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string AspNetCdnPrefix {
get {
return ResourceManager.GetString("AspNetCdnPrefix", resourceCulture);
}
}
/// <summary>
/// 과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
@ -132,6 +141,24 @@ namespace WelsonJS.Launcher.Properties {
}
}
/// <summary>
/// https://esm.run/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string EsmRunPrefix {
get {
return ResourceManager.GetString("EsmRunPrefix", resourceCulture);
}
}
/// <summary>
/// https://esm.sh/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string EsmShPrefix {
get {
return ResourceManager.GetString("EsmShPrefix", resourceCulture);
}
}
/// <summary>
/// (아이콘)과(와) 유사한 System.Drawing.Icon 형식의 지역화된 리소스를 찾습니다.
/// </summary>
@ -142,6 +169,15 @@ namespace WelsonJS.Launcher.Properties {
}
}
/// <summary>
/// https://ajax.googleapis.com/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string GoogleApisPrefix {
get {
return ResourceManager.GetString("GoogleApisPrefix", resourceCulture);
}
}
/// <summary>
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
/// </summary>
@ -232,6 +268,42 @@ namespace WelsonJS.Launcher.Properties {
}
}
/// <summary>
/// https://code.jquery.com/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string JqueryCdnPrefix {
get {
return ResourceManager.GetString("JqueryCdnPrefix", resourceCulture);
}
}
/// <summary>
/// https://cdn.jsdelivr.net/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string JsDeliverPrefix {
get {
return ResourceManager.GetString("JsDeliverPrefix", resourceCulture);
}
}
/// <summary>
/// https://polyfill-fastly.io/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string PolyfillPrefix {
get {
return ResourceManager.GetString("PolyfillPrefix", resourceCulture);
}
}
/// <summary>
/// https://raw.githubusercontent.com/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string RawGitHubPrefix {
get {
return ResourceManager.GetString("RawGitHubPrefix", resourceCulture);
}
}
/// <summary>
/// https://github.com/gnh1201/welsonjs과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
@ -250,6 +322,24 @@ namespace WelsonJS.Launcher.Properties {
}
}
/// <summary>
/// https://www.skypack.dev/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string SkypackPrefix {
get {
return ResourceManager.GetString("SkypackPrefix", resourceCulture);
}
}
/// <summary>
/// https://unpkg.com/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string UnpkgPrefix {
get {
return ResourceManager.GetString("UnpkgPrefix", resourceCulture);
}
}
/// <summary>
/// 141.101.82.1과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>

View File

@ -187,4 +187,34 @@
<data name="CdnJsPrefix" xml:space="preserve">
<value>https://cdnjs.cloudflare.com/</value>
</data>
<data name="EsmRunPrefix" xml:space="preserve">
<value>https://esm.run/</value>
</data>
<data name="EsmShPrefix" xml:space="preserve">
<value>https://esm.sh/</value>
</data>
<data name="JqueryCdnPrefix" xml:space="preserve">
<value>https://code.jquery.com/</value>
</data>
<data name="JsDeliverPrefix" xml:space="preserve">
<value>https://cdn.jsdelivr.net/</value>
</data>
<data name="SkypackPrefix" xml:space="preserve">
<value>https://www.skypack.dev/</value>
</data>
<data name="UnpkgPrefix" xml:space="preserve">
<value>https://unpkg.com/</value>
</data>
<data name="AspNetCdnPrefix" xml:space="preserve">
<value>https://ajax.aspnetcdn.com/</value>
</data>
<data name="GoogleApisPrefix" xml:space="preserve">
<value>https://ajax.googleapis.com/</value>
</data>
<data name="PolyfillPrefix" xml:space="preserve">
<value>https://polyfill-fastly.io/</value>
</data>
<data name="RawGitHubPrefix" xml:space="preserve">
<value>https://raw.githubusercontent.com/</value>
</data>
</root>

View File

@ -1,12 +1,19 @@
using System;
// ResourceServer.cs
// A resource server of WelsonJS Editor (WelsonJS.Launcher)
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
//
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
@ -23,7 +30,25 @@ namespace WelsonJS.Launcher
private string _resourceName;
private List<IResourceTool> _tools = new List<IResourceTool>();
private readonly HttpClient _httpClient = new HttpClient();
private readonly string _defaultMimeType = "application/octet-stream";
private static readonly string _defaultMimeType = "application/octet-stream";
private static readonly Regex _nodePackageRegex = new Regex(@"^[^/@]+@[^/]+/", RegexOptions.Compiled);
private static readonly List<string[]> CDN_PREFIXES = new List<string[]> {
new[] { "ajax/libs/" },
new[] { "npm/", "gh/", "wp/" },
new[] { "jquery/" },
new[] { "polyfill/" },
new[] { "ajax/" }, // https://learn.microsoft.com/en-us/aspnet/ajax/cdn/overview
new[] { "raw/gh/"}
};
private enum CDN_TYPES: int
{
Cloudflare = 0,
JsDeliver = 1,
Jquery = 2,
Polyfill = 3,
Microsoft = 4,
GitHub = 5
};
public ResourceServer(string prefix, string resourceName)
{
@ -182,17 +207,55 @@ namespace WelsonJS.Launcher
}
}
// use the cdn-js
if (path.StartsWith("ajax/libs/"))
// use CDN sources
if (await TryServeFromCdn(context, path))
{
if (await ServeBlob(context, path, Program.GetAppConfig("CdnJsPrefix"))) {
return true;
}
return true;
}
}
return false;
}
private async Task<bool> TryServeFromCdn(HttpListenerContext context, string path)
{
bool isNodePackageExpression = _nodePackageRegex.IsMatch(path);
bool isPrefixMatched(CDN_TYPES type)
{
if (CDN_PREFIXES[(int)type].Any(prefix => path.StartsWith(prefix)))
{
return true;
}
// use the blob stroage
if (await ServeBlob(context, path, Program.GetAppConfig("BlobStoragePrefix"))) {
return true;
return false;
}
var sources = new (bool isMatch, string configKey, Func<string, string> transform)[]
{
(isPrefixMatched(CDN_TYPES.Cloudflare), "CdnJsPrefix", p => p), // Libraries from Cloudflare
(isPrefixMatched(CDN_TYPES.Cloudflare), "GoogleApisPrefix", p => p), // Libraries from Google
(isNodePackageExpression, "UnpkgPrefix", p => p),
(isNodePackageExpression, "SkypackPrefix", p => p),
(isNodePackageExpression, "EsmShPrefix", p => p),
(isNodePackageExpression, "EsmRunPrefix", p => p),
(isPrefixMatched(CDN_TYPES.JsDeliver), "JsDeliverPrefix", p => p),
(isPrefixMatched(CDN_TYPES.Jquery), "JqueryCdnPrefix", p => p.Substring("jquery/".Length)),
(isPrefixMatched(CDN_TYPES.Polyfill), "CdnJsPrefix", p => p), // polyfill.js from Cloudflare
(isPrefixMatched(CDN_TYPES.Polyfill), "PolyfillPrefix", p => p.Substring("polyfill/".Length)), // polyfill.js from Fastly
(isPrefixMatched(CDN_TYPES.Microsoft), "AspNetCdnPrefix", p => p), // Libraries from Microsoft
(isPrefixMatched(CDN_TYPES.GitHub), "RawGitHubPrefix", p => p.Substring("raw/gh/".Length)),
(true, "BlobStoragePrefix", p => p) // fallback
};
foreach (var (isMatch, configKey, transform) in sources)
{
if (isMatch)
{
string prefix = Program.GetAppConfig(configKey);
if (await ServeBlob(context, transform(path), prefix))
{
return true;
}
}
}

View File

@ -14,6 +14,15 @@
<add key="DnsServerAddress" value="1.1.1.1"/>
<add key="BlobStoragePrefix" value="https://catswords.blob.core.windows.net/welsonjs/"/>
<add key="CdnJsPrefix" value="https://cdnjs.cloudflare.com/"/>
<add key="JsDeliverPrefix" value="https://cdn.jsdelivr.net/"/>
<add key="UnpkgPrefix" value="https://unpkg.com/"/>
<add key="SkypackPrefix" value="https://www.skypack.dev/"/>
<add key="EsmShPrefix" value="https://esm.sh/"/>
<add key="EsmRunPrefix" value="https://esm.run/"/>
<add key="JqueryCdnPrefix" value="https://code.jquery.com/"/>
<add key="AspNetCdnPrefix" value="https://ajax.aspnetcdn.com/"/>
<add key="GoogleApisPrefix" value="https://ajax.googleapis.com/"/>
<add key="RawGitHubPrefix" value="https://raw.githubusercontent.com/"/>
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>