mirror of
https://github.com/gnh1201/welsonjs.git
synced 2025-11-27 10:00:57 +00:00
Merge pull request #334 from gnh1201/dev
Add CORS support to ResourceServer
This commit is contained in:
commit
93b12d2134
|
|
@ -331,6 +331,15 @@ namespace WelsonJS.Launcher.Properties {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 과(와) 유사한 지역화된 문자열을 찾습니다.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ResourceServerAllowOrigins {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ResourceServerAllowOrigins", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// true과(와) 유사한 지역화된 문자열을 찾습니다.
|
/// true과(와) 유사한 지역화된 문자열을 찾습니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -220,4 +220,7 @@
|
||||||
<data name="IpQueryApiPrefix2" xml:space="preserve">
|
<data name="IpQueryApiPrefix2" xml:space="preserve">
|
||||||
<value>https://api.abuseipdb.com/api/v2/</value>
|
<value>https://api.abuseipdb.com/api/v2/</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ResourceServerAllowOrigins" xml:space="preserve">
|
||||||
|
<value />
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -34,12 +34,16 @@ namespace WelsonJS.Launcher
|
||||||
|
|
||||||
private static readonly HttpClient _httpClient = new HttpClient();
|
private static readonly HttpClient _httpClient = new HttpClient();
|
||||||
private static readonly string _defaultMimeType = "application/octet-stream";
|
private static readonly string _defaultMimeType = "application/octet-stream";
|
||||||
|
private static string[] _allowedOrigins;
|
||||||
|
|
||||||
static ResourceServer()
|
static ResourceServer()
|
||||||
{
|
{
|
||||||
// Set timeout
|
// Set timeout
|
||||||
int timeout = int.TryParse(Program.GetAppConfig("HttpClientTimeout"), out timeout) ? timeout : 90;
|
int timeout = int.TryParse(Program.GetAppConfig("HttpClientTimeout"), out timeout) ? timeout : 90;
|
||||||
_httpClient.Timeout = TimeSpan.FromSeconds(timeout);
|
_httpClient.Timeout = TimeSpan.FromSeconds(timeout);
|
||||||
|
|
||||||
|
// Set allowed origins (CORS policy)
|
||||||
|
TryParseAllowedOrigins();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceServer(string prefix, string resourceName, ICompatibleLogger logger = null)
|
public ResourceServer(string prefix, string resourceName, ICompatibleLogger logger = null)
|
||||||
|
|
@ -353,6 +357,11 @@ namespace WelsonJS.Launcher
|
||||||
|
|
||||||
public async Task ServeResource(HttpListenerContext context, byte[] data, string mimeType = "text/html", int statusCode = 200)
|
public async Task ServeResource(HttpListenerContext context, byte[] data, string mimeType = "text/html", int statusCode = 200)
|
||||||
{
|
{
|
||||||
|
if (HandleCorsPreflight(context))
|
||||||
|
return;
|
||||||
|
|
||||||
|
TryApplyCors(context);
|
||||||
|
|
||||||
string xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
|
string xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
|
||||||
|
|
||||||
if (data == null)
|
if (data == null)
|
||||||
|
|
@ -461,6 +470,92 @@ namespace WelsonJS.Launcher
|
||||||
_logger?.Error($"Failed to fetch a blob config. Exception: {ex}");
|
_logger?.Error($"Failed to fetch a blob config. Exception: {ex}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void TryParseAllowedOrigins(ICompatibleLogger logger = null)
|
||||||
|
{
|
||||||
|
var raw = Program.GetAppConfig("ResourceServerAllowOrigins");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(raw))
|
||||||
|
{
|
||||||
|
_allowedOrigins = raw.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
|
||||||
|
.Select(s => s.Trim())
|
||||||
|
.Where(s => !string.IsNullOrEmpty(s))
|
||||||
|
.ToArray();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var prefix = Program.GetAppConfig("ResourceServerPrefix");
|
||||||
|
if (!string.IsNullOrEmpty(prefix))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var uri = new Uri(prefix);
|
||||||
|
_allowedOrigins = new[] { uri.GetLeftPart(UriPartial.Authority) }; // protocol + host + port
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger?.Warn($"Invalid ResourceServerPrefix '{prefix}'. It must be a valid absolute URI. Error: {ex.Message}");
|
||||||
|
// fall through to set empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_allowedOrigins = Array.Empty<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryApplyCors(HttpListenerContext context)
|
||||||
|
{
|
||||||
|
var origin = context.Request.Headers["Origin"];
|
||||||
|
if (string.IsNullOrEmpty(origin))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var allowed = _allowedOrigins;
|
||||||
|
if (allowed.Length == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var respHeaders = context.Response.Headers;
|
||||||
|
|
||||||
|
if (allowed.Any(a => a == "*"))
|
||||||
|
{
|
||||||
|
respHeaders["Access-Control-Allow-Origin"] = "*";
|
||||||
|
respHeaders["Vary"] = "Origin";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only perform a single, case-sensitive origin check
|
||||||
|
if (allowed.Contains(origin, StringComparer.Ordinal))
|
||||||
|
{
|
||||||
|
respHeaders["Access-Control-Allow-Origin"] = origin;
|
||||||
|
respHeaders["Access-Control-Allow-Credentials"] = "true";
|
||||||
|
respHeaders["Vary"] = "Origin";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool HandleCorsPreflight(HttpListenerContext context)
|
||||||
|
{
|
||||||
|
if (!string.Equals(context.Request.HttpMethod, "OPTIONS", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(context.Request.Headers["Origin"]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Apply CORS headers once here
|
||||||
|
TryApplyCors(context);
|
||||||
|
|
||||||
|
var respHeaders = context.Response.Headers;
|
||||||
|
respHeaders["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS";
|
||||||
|
respHeaders["Access-Control-Allow-Headers"] = "Content-Type, Authorization, X-Requested-With";
|
||||||
|
respHeaders["Access-Control-Max-Age"] = "600";
|
||||||
|
|
||||||
|
context.Response.StatusCode = 204;
|
||||||
|
context.Response.ContentLength64 = 0;
|
||||||
|
context.Response.Close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[XmlRoot("blobConfig")]
|
[XmlRoot("blobConfig")]
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<appSettings>
|
<appSettings>
|
||||||
<add key="ResourceServerPrefix" value="http://localhost:3000/"/>
|
<add key="ResourceServerAllowOrigins" value=""/>
|
||||||
<add key="ResourceServerAutoStart" value="true"/>
|
<add key="ResourceServerAutoStart" value="true"/>
|
||||||
|
<add key="ResourceServerPrefix" value="http://localhost:3000/"/>
|
||||||
<add key="RepositoryUrl" value="https://github.com/gnh1201/welsonjs"/>
|
<add key="RepositoryUrl" value="https://github.com/gnh1201/welsonjs"/>
|
||||||
<add key="CopilotUrl" value="https://copilot.microsoft.com/"/>
|
<add key="CopilotUrl" value="https://copilot.microsoft.com/"/>
|
||||||
<add key="ChromiumDevToolsPrefix" value="http://localhost:9222/"/>
|
<add key="ChromiumDevToolsPrefix" value="http://localhost:9222/"/>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user