update:阿里云下载
This commit is contained in:
parent
0afa0f8c1a
commit
2fa9d1e29d
@ -1,6 +1,8 @@
|
|||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using YD_Event.Application.Auth;
|
using YD_Event.Application.Auth;
|
||||||
using YD_Event.Application.Common;
|
using YD_Event.Application.Common;
|
||||||
|
using YD_Event.Core.Options;
|
||||||
|
|
||||||
namespace YD_Event.Application.AppUpdate;
|
namespace YD_Event.Application.AppUpdate;
|
||||||
|
|
||||||
@ -16,15 +18,18 @@ public class AppUpdateController : IDynamicApiController
|
|||||||
private readonly AuthManager _auth;
|
private readonly AuthManager _auth;
|
||||||
private readonly IIdGenerator _ids;
|
private readonly IIdGenerator _ids;
|
||||||
private readonly FileService _files;
|
private readonly FileService _files;
|
||||||
|
private readonly IOptionsMonitor<OssConnectionOptions> _ossOptions;
|
||||||
private readonly string _channel;
|
private readonly string _channel;
|
||||||
|
|
||||||
public AppUpdateController(ISqlSugarRepository<JudgeAppRelease> releases,
|
public AppUpdateController(ISqlSugarRepository<JudgeAppRelease> releases,
|
||||||
AuthManager auth, IIdGenerator ids, FileService files)
|
AuthManager auth, IIdGenerator ids, FileService files,
|
||||||
|
IOptionsMonitor<OssConnectionOptions> ossOptions)
|
||||||
{
|
{
|
||||||
_releases = releases;
|
_releases = releases;
|
||||||
_auth = auth;
|
_auth = auth;
|
||||||
_ids = ids;
|
_ids = ids;
|
||||||
_files = files;
|
_files = files;
|
||||||
|
_ossOptions = ossOptions;
|
||||||
_channel = Environment.GetEnvironmentVariable("APP_UPDATE_CHANNEL")?.Trim().ToLowerInvariant() ?? "production";
|
_channel = Environment.GetEnvironmentVariable("APP_UPDATE_CHANNEL")?.Trim().ToLowerInvariant() ?? "production";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,11 +46,43 @@ public class AppUpdateController : IDynamicApiController
|
|||||||
available = true, release.Id, release.PackageName, release.VersionCode,
|
available = true, release.Id, release.PackageName, release.VersionCode,
|
||||||
release.VersionName, release.NotesZh, release.NotesEn,
|
release.VersionName, release.NotesZh, release.NotesEn,
|
||||||
release.IsMandatory, release.FileSize, release.Sha256,
|
release.IsMandatory, release.FileSize, release.Sha256,
|
||||||
release.CertificateSha256, downloadUrl = $"/api/app-updates/download/{release.Id}",
|
release.CertificateSha256, downloadUrl = DownloadUrlFor(release),
|
||||||
release.PublishedTime
|
release.PublishedTime
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>OSS 已启用时直连阿里云/CDN;配置缺失或不安全时仍使用受控下载接口。</summary>
|
||||||
|
private string DownloadUrlFor(JudgeAppRelease release)
|
||||||
|
{
|
||||||
|
var fallback = $"/api/app-updates/download/{release.Id}";
|
||||||
|
// Direct delivery is opt-in: a private bucket without CDN/public-read
|
||||||
|
// must continue using the existing server-side OSS stream.
|
||||||
|
var cdn = Environment.GetEnvironmentVariable("APP_UPDATE_DIRECT_DOWNLOAD_BASE_URL");
|
||||||
|
if (string.IsNullOrWhiteSpace(cdn)) return fallback;
|
||||||
|
var oss = _ossOptions.CurrentValue;
|
||||||
|
if (!oss.Enable || string.IsNullOrWhiteSpace(oss.Domain) ||
|
||||||
|
!Uri.TryCreate(oss.Domain.TrimEnd('/') + "/", UriKind.Absolute, out var ossBase) ||
|
||||||
|
ossBase.Scheme != Uri.UriSchemeHttps ||
|
||||||
|
!Uri.TryCreate(release.FileUrl, UriKind.Absolute, out var fileUri) ||
|
||||||
|
fileUri.Scheme != Uri.UriSchemeHttps ||
|
||||||
|
!fileUri.AbsoluteUri.StartsWith(ossBase.AbsoluteUri, StringComparison.OrdinalIgnoreCase))
|
||||||
|
return fallback;
|
||||||
|
|
||||||
|
// FileUrl comes from the configured OSS domain at upload time. Never turn
|
||||||
|
// an arbitrary stored URL into an untrusted redirect/download host.
|
||||||
|
var objectKey = fileUri.AbsoluteUri[ossBase.AbsoluteUri.Length..];
|
||||||
|
if (!objectKey.StartsWith($"app-releases/{_channel}/", StringComparison.Ordinal) ||
|
||||||
|
objectKey.Contains("..", StringComparison.Ordinal) ||
|
||||||
|
!objectKey.EndsWith(".apk", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return fallback;
|
||||||
|
|
||||||
|
if (!Uri.TryCreate(cdn.TrimEnd('/') + "/", UriKind.Absolute, out var cdnBase) ||
|
||||||
|
cdnBase.Scheme != Uri.UriSchemeHttps || !string.IsNullOrEmpty(cdnBase.UserInfo) ||
|
||||||
|
!string.IsNullOrEmpty(cdnBase.Query) || !string.IsNullOrEmpty(cdnBase.Fragment))
|
||||||
|
return fallback;
|
||||||
|
return new Uri(cdnBase, objectKey).AbsoluteUri;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>只允许下载当前环境已发布的版本,沿用现有文件服务流式返回。</summary>
|
/// <summary>只允许下载当前环境已发布的版本,沿用现有文件服务流式返回。</summary>
|
||||||
[HttpGet("download/{id:long}")]
|
[HttpGet("download/{id:long}")]
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user