Feat: repo api done
This commit is contained in:
@@ -20,16 +20,19 @@
|
||||
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.844.0",
|
||||
"@nestjs/common": "^11.0.1",
|
||||
"@nestjs/config": "^4.0.2",
|
||||
"@nestjs/core": "^11.0.1",
|
||||
"@nestjs/platform-express": "^11.0.1",
|
||||
"@nestjs/swagger": "^11.2.0",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@eslint/js": "^9.18.0",
|
||||
"@nestjs/cli": "^11.0.0",
|
||||
"@nestjs/cli": "^11.0.7",
|
||||
"@nestjs/schematics": "^11.0.0",
|
||||
"@nestjs/testing": "^11.0.1",
|
||||
"@swc/cli": "^0.6.0",
|
||||
|
||||
1294
pnpm-lock.yaml
generated
1294
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -15,8 +15,8 @@ describe('AppController', () => {
|
||||
});
|
||||
|
||||
describe('root', () => {
|
||||
it('should return "Hello World!"', () => {
|
||||
expect(appController.getHello()).toBe('Hello World!');
|
||||
it('should return "OK"', () => {
|
||||
expect(appController.getHealthz()).toBe('OK');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,12 +1,51 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Header,
|
||||
Param,
|
||||
Headers,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
StreamableFile,
|
||||
} from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { GetObjectCommandInput } from '@aws-sdk/client-s3';
|
||||
import { AppService } from './app.service';
|
||||
|
||||
@Controller()
|
||||
export class AppController {
|
||||
constructor(private readonly appService: AppService) {}
|
||||
constructor(
|
||||
private readonly configService: ConfigService,
|
||||
private readonly appService: AppService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
getHello(): string {
|
||||
return this.appService.getHello();
|
||||
@Get('healthz')
|
||||
getHealthz(): string {
|
||||
return this.appService.getHealthz();
|
||||
}
|
||||
|
||||
@Get(`:repo/os/:arch/:pkg`)
|
||||
@Header('Accept-Ranges', 'bytes')
|
||||
async getRepo(
|
||||
@Headers('Range') range: string,
|
||||
@Param('repo') repo: string,
|
||||
@Param('arch') arch: string,
|
||||
@Param('pkg') pkg: string,
|
||||
): Promise<StreamableFile> {
|
||||
if (repo !== this.configService.get<string>('REPO_NAME'))
|
||||
throw new HttpException(`Repo '${repo}' not exist`, HttpStatus.NOT_FOUND);
|
||||
if (arch !== this.configService.get<string>('ARCH_NAME'))
|
||||
throw new HttpException(
|
||||
`Architecture '${arch}' not exist`,
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
|
||||
const stream = await this.appService.getObject({
|
||||
Bucket: this.configService.get<string>('MINIO_BUCKET'),
|
||||
Key: pkg,
|
||||
Range: range,
|
||||
} as GetObjectCommandInput);
|
||||
|
||||
return new StreamableFile(stream);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
imports: [ConfigModule.forRoot()],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
})
|
||||
|
||||
@@ -1,8 +1,41 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Readable } from 'stream';
|
||||
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import {
|
||||
S3Client,
|
||||
S3ClientConfig,
|
||||
GetObjectCommand,
|
||||
GetObjectCommandInput,
|
||||
} from '@aws-sdk/client-s3';
|
||||
|
||||
@Injectable()
|
||||
export class AppService {
|
||||
getHello(): string {
|
||||
return 'Hello World!';
|
||||
private readonly s3Client: S3Client;
|
||||
|
||||
constructor(private readonly configService: ConfigService) {
|
||||
this.s3Client = new S3Client({
|
||||
region: 'us-west-1',
|
||||
endpoint: this.configService.get<string>('MINIO_ENDPOINT'),
|
||||
credentials: {
|
||||
accessKeyId: this.configService.get<string>('MINIO_ACCESSKEY'),
|
||||
secretAccessKey: this.configService.get<string>('MINIO_SECRETKEY'),
|
||||
},
|
||||
forcePathStyle: true,
|
||||
} as S3ClientConfig);
|
||||
}
|
||||
|
||||
getHealthz(): string {
|
||||
return 'OK';
|
||||
}
|
||||
|
||||
async getObject(getObjectConfig: GetObjectCommandInput): Promise<Readable> {
|
||||
const command = new GetObjectCommand(getObjectConfig);
|
||||
const res = await this.s3Client.send(command);
|
||||
if (!res.Body)
|
||||
throw new HttpException(
|
||||
's3 get object failed',
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
return res.Body as Readable;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,4 +5,4 @@ async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule);
|
||||
await app.listen(process.env.PORT ?? 3000);
|
||||
}
|
||||
bootstrap();
|
||||
void bootstrap();
|
||||
|
||||
Reference in New Issue
Block a user