fix(version-service+gateway+app): fix APK download 404 and SHA-256 false failure
Three coordinated fixes to make in-app APK download work end-to-end:
1. version-service/main.ts: serve uploaded files as static assets via
NestExpressApplication.useStaticAssets('/data/versions', prefix:
'/downloads/versions'), so GET /downloads/versions/{platform}/{file}
returns the actual APK stored in the Docker volume.
2. kong.yml: add /downloads/versions route to Kong so requests from
the Flutter app can reach version-service through the API gateway.
Previously only /api/v1/versions and /api/app/version were routed;
the download URL returned by the check endpoint was unreachable (404).
3. download_manager.dart: skip SHA-256 verification when sha256Expected
is empty string. The check endpoint always returns sha256:"" because
version-service doesn't store file hashes. The previous code compared
actual_hash == "" which always failed, causing the downloaded file to
be deleted after a successful download.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0f328b9794
commit
e6f864d409
|
|
@ -118,9 +118,10 @@ class DownloadManager {
|
||||||
await tempFile.rename(savePath);
|
await tempFile.rename(savePath);
|
||||||
|
|
||||||
debugPrint('Download completed');
|
debugPrint('Download completed');
|
||||||
_status = DownloadStatus.verifying;
|
|
||||||
|
|
||||||
// 校验 SHA-256
|
// 校验 SHA-256(仅在服务器提供了哈希值时校验)
|
||||||
|
if (sha256Expected.isNotEmpty) {
|
||||||
|
_status = DownloadStatus.verifying;
|
||||||
final isValid = await _verifySha256(file, sha256Expected);
|
final isValid = await _verifySha256(file, sha256Expected);
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
debugPrint('SHA-256 verification failed');
|
debugPrint('SHA-256 verification failed');
|
||||||
|
|
@ -128,8 +129,11 @@ class DownloadManager {
|
||||||
_status = DownloadStatus.failed;
|
_status = DownloadStatus.failed;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
debugPrint('SHA-256 verified');
|
debugPrint('SHA-256 verified');
|
||||||
|
} else {
|
||||||
|
debugPrint('SHA-256 not provided, skipping verification');
|
||||||
|
}
|
||||||
|
|
||||||
_status = DownloadStatus.completed;
|
_status = DownloadStatus.completed;
|
||||||
return file;
|
return file;
|
||||||
} on DioException catch (e) {
|
} on DioException catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,10 @@ services:
|
||||||
paths:
|
paths:
|
||||||
- /api/app/version
|
- /api/app/version
|
||||||
strip_path: false
|
strip_path: false
|
||||||
|
- name: app-version-download-route
|
||||||
|
paths:
|
||||||
|
- /downloads/versions
|
||||||
|
strip_path: false
|
||||||
|
|
||||||
- name: billing-service
|
- name: billing-service
|
||||||
url: http://billing-service:3010
|
url: http://billing-service:3010
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { NestFactory } from '@nestjs/core';
|
import { NestFactory } from '@nestjs/core';
|
||||||
|
import { NestExpressApplication } from '@nestjs/platform-express';
|
||||||
import { Logger } from '@nestjs/common';
|
import { Logger } from '@nestjs/common';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { VersionModule } from './version.module';
|
import { VersionModule } from './version.module';
|
||||||
|
|
@ -13,9 +14,13 @@ process.on('uncaughtException', (error) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const app = await NestFactory.create(VersionModule);
|
const app = await NestFactory.create<NestExpressApplication>(VersionModule);
|
||||||
const config = app.get(ConfigService);
|
const config = app.get(ConfigService);
|
||||||
const port = config.get<number>('VERSION_SERVICE_PORT', 3009);
|
const port = config.get<number>('VERSION_SERVICE_PORT', 3009);
|
||||||
|
// Serve uploaded APK/IPA files as static assets
|
||||||
|
// Files are stored at /data/versions/{platform}/filename
|
||||||
|
// Accessible via GET /downloads/versions/{platform}/filename
|
||||||
|
app.useStaticAssets('/data/versions', { prefix: '/downloads/versions' });
|
||||||
await app.listen(port);
|
await app.listen(port);
|
||||||
logger.log(`version-service running on port ${port}`);
|
logger.log(`version-service running on port ${port}`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue