Commit 8def6514 authored by nanahira's avatar nanahira

refactor

parent 78b7a65a
import { Body, Get, Patch, Post, ValidationPipe } from '@nestjs/common';
import {
ApiBody,
ApiCreatedResponse,
ApiOkResponse,
ApiOperation,
} from '@nestjs/swagger';
import {
MiddlewareInfoReturnMessageDto,
ReturnMessageDto,
StringReturnMessageDto,
} from '../dto/ReturnMessage.dto';
import { PostUrlDto } from '../dto/PostUrl.dto';
import { MiddlewareService } from './service';
import { MirrorDto } from '../dto/Mirror.dto';
export class MiddlewareController {
constructor(protected middlewareService: MiddlewareService) {}
@Get()
@ApiOperation({ summary: '中间件信息' })
@ApiOkResponse({ type: MiddlewareInfoReturnMessageDto })
async jsdInfo() {
return new ReturnMessageDto(
200,
'success',
await this.middlewareService.info(),
);
}
@Post()
@ApiOperation({ summary: '上传中间件文件' })
@ApiBody({ type: PostUrlDto })
@ApiCreatedResponse({ type: StringReturnMessageDto })
async upload(
@Body(new ValidationPipe({ transform: true })) urlDto: PostUrlDto,
) {
return new ReturnMessageDto(
201,
'success',
await this.middlewareService.upload(urlDto),
);
}
@Patch()
@ApiOperation({ summary: '获取文件下载地址' })
@ApiBody({ type: MirrorDto })
@ApiOkResponse({ type: StringReturnMessageDto })
async download(
@Body(new ValidationPipe({ transform: true })) mirrorDto: MirrorDto,
) {
return new ReturnMessageDto(
200,
'success',
await this.middlewareService.download(mirrorDto),
);
}
}
import { HttpService } from '@nestjs/axios';
import { BlankReturnMessageDto } from '../dto/ReturnMessage.dto';
import { MiddlewareInfoDto } from '../dto/MiddlewareInfo.dto';
import { PostUrlDto } from '../dto/PostUrl.dto';
import { MirrorDto } from '../dto/Mirror.dto';
import { ConsoleLogger } from '@nestjs/common';
export class MiddlewareService extends ConsoleLogger {
constructor(name: string, protected http: HttpService) {
super(name);
}
async info(): Promise<MiddlewareInfoDto> {
throw new BlankReturnMessageDto(404, 'Not Implemented').toException();
}
async upload(urlDto: PostUrlDto): Promise<string> {
throw new BlankReturnMessageDto(404, 'Not Implemented').toException();
}
async download(mirror: MirrorDto): Promise<string> {
return mirror.url;
}
}
import { Test, TestingModule } from '@nestjs/testing';
import { AppController } from './app.controller';
import { AppService } from './app.service';
describe('AppController', () => {
let appController: AppController;
beforeEach(async () => {
const app: TestingModule = await Test.createTestingModule({
controllers: [AppController],
providers: [AppService],
}).compile();
appController = app.get<AppController>(AppController);
});
describe('root', () => {
it('should be defined', () => {
expect(appController).toBeDefined();
});
});
});
import { Body, Controller, Get, Post, ValidationPipe } from '@nestjs/common';
import { AppService } from './app.service';
import {
ApiBody,
ApiCreatedResponse,
ApiOkResponse,
ApiOperation,
} from '@nestjs/swagger';
import { PostUrlDto } from './dto/PostUrl.dto';
import {
MiddlewareInfoReturnMessageDto,
StringReturnMessageDto,
} from './dto/ReturnMessage.dto';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get('jsd')
@ApiOperation({ summary: 'JSDelivr', description: '需要配置 JSD_URL' })
@ApiOkResponse({ type: MiddlewareInfoReturnMessageDto })
jsdInfo() {
return this.appService.jsdInfo();
}
@Post('jsd')
@ApiOperation({ summary: 'JSDelivr', description: '需要配置 JSD_URL' })
@ApiBody({ type: PostUrlDto })
@ApiCreatedResponse({ type: StringReturnMessageDto })
jsd(@Body(new ValidationPipe({ transform: true })) urlDto: PostUrlDto) {
return this.appService.jsd(urlDto);
}
}
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule } from '@nestjs/config'; import { ConfigModule } from '@nestjs/config';
import { HttpModule } from '@nestjs/axios'; import { HttpModule } from '@nestjs/axios';
import { UtilityModule } from './utility/utility.module';
const configModule = ConfigModule.forRoot(); import { JsdModule } from './jsd/jsd.module';
@Module({ @Module({
imports: [configModule, HttpModule], imports: [
controllers: [AppController], ConfigModule.forRoot({ isGlobal: true }),
providers: [AppService], {
...HttpModule.register({}),
global: true,
},
UtilityModule,
JsdModule,
],
}) })
export class AppModule {} export class AppModule {}
import { IsString } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
export class MirrorDto {
@IsString()
@ApiProperty({ description: '文件标识路径。' })
path: string;
@IsString()
@ApiProperty({ description: '文件地址,middleware 曾经返回的。' })
url: string;
@IsString()
@ApiProperty({ description: 'middleware 标识符' })
middleware: string;
}
import { Controller } from '@nestjs/common';
import { MiddlewareController } from '../abstract/controller';
import { JsdService } from './jsd.service';
@Controller('jsd')
export class JsdController extends MiddlewareController {
constructor(s: JsdService) {
super(s);
}
}
import { Module } from '@nestjs/common';
import { JsdController } from './jsd.controller';
import { JsdService } from './jsd.service';
@Module({
controllers: [JsdController],
providers: [JsdService],
})
export class JsdModule {}
import { Injectable, ConsoleLogger } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config'; import { ConfigService } from '@nestjs/config';
import { HttpService } from '@nestjs/axios'; import { HttpService } from '@nestjs/axios';
import internal from 'stream';
import { lastValueFrom } from 'rxjs'; import { lastValueFrom } from 'rxjs';
import { import { BlankReturnMessageDto, ReturnMessage } from '../dto/ReturnMessage.dto';
BlankReturnMessageDto,
ReturnMessage,
ReturnMessageDto,
} from './dto/ReturnMessage.dto';
import FormData from 'form-data'; import FormData from 'form-data';
import { PostUrlDto } from './dto/PostUrl.dto'; import { PostUrlDto } from '../dto/PostUrl.dto';
import { MiddlewareInfoDto } from './dto/MiddlewareInfo.dto'; import { MiddlewareInfoDto } from '../dto/MiddlewareInfo.dto';
import { UtilityService } from '../utility/utility/utility.service';
import { MiddlewareService } from '../abstract/service';
@Injectable() @Injectable()
export class AppService extends ConsoleLogger { export class JsdService extends MiddlewareService {
private jsdUrl: string; private jsdUrl: string;
private jsdIdentifier: string; private jsdIdentifier: string;
constructor(config: ConfigService, private http: HttpService) { constructor(
super('app'); config: ConfigService,
http: HttpService,
private utility: UtilityService,
) {
super('jsd', http);
this.jsdUrl = config.get('JSD_URL'); this.jsdUrl = config.get('JSD_URL');
this.jsdIdentifier = config.get('JSD_IDENTIFIER') || `jsd-${this.jsdUrl}`; this.jsdIdentifier = config.get('JSD_IDENTIFIER') || `jsd-${this.jsdUrl}`;
} }
private async getStreamFromUrl(url: string) { async info() {
try {
const ret = await lastValueFrom(
await this.http.get<internal.Readable>(url, {
responseType: 'stream',
timeout: 30000,
maxBodyLength: 4 * 1024 ** 3,
maxContentLength: 4 * 1024 ** 3,
}),
);
return ret;
} catch (e) {
throw new BlankReturnMessageDto(404, 'URL not available').toException();
}
}
jsdInfo() {
if (!this.jsdUrl) { if (!this.jsdUrl) {
throw new BlankReturnMessageDto( throw new BlankReturnMessageDto(
404, 404,
...@@ -48,17 +33,17 @@ export class AppService extends ConsoleLogger { ...@@ -48,17 +33,17 @@ export class AppService extends ConsoleLogger {
const info = new MiddlewareInfoDto(); const info = new MiddlewareInfoDto();
info.identifier = this.jsdIdentifier; info.identifier = this.jsdIdentifier;
info.maxSize = 50 * 1024 * 1024; info.maxSize = 50 * 1024 * 1024;
return new ReturnMessageDto(200, 'success', info); return info;
} }
async jsd(urlDto: PostUrlDto) { async upload(urlDto: PostUrlDto) {
if (!this.jsdUrl) { if (!this.jsdUrl) {
throw new BlankReturnMessageDto( throw new BlankReturnMessageDto(
404, 404,
'JSDelivr is not configured.', 'JSDelivr is not configured.',
).toException(); ).toException();
} }
const streamData = await this.getStreamFromUrl(urlDto.url); const streamData = await this.utility.getStreamFromUrl(urlDto.url);
//streamData.data.pause(); //streamData.data.pause();
const form = new FormData(); const form = new FormData();
form.append('file', streamData.data, { form.append('file', streamData.data, {
...@@ -77,7 +62,7 @@ export class AppService extends ConsoleLogger { ...@@ -77,7 +62,7 @@ export class AppService extends ConsoleLogger {
maxContentLength: 4 * 1024 ** 3, maxContentLength: 4 * 1024 ** 3,
}), }),
); );
return new ReturnMessageDto(201, 'success', data.data); return data.data;
} catch (e) { } catch (e) {
this.error(`Failed uploading ${urlDto.url}: ${e.toString()} ${e.data}`); this.error(`Failed uploading ${urlDto.url}: ${e.toString()} ${e.data}`);
throw new BlankReturnMessageDto(500, 'upload fail').toException(); throw new BlankReturnMessageDto(500, 'upload fail').toException();
......
import { Global, Module } from '@nestjs/common';
import { UtilityService } from './utility/utility.service';
@Global()
@Module({
providers: [UtilityService],
exports: [UtilityService],
})
export class UtilityModule {}
import { Test, TestingModule } from '@nestjs/testing';
import { UtilityService } from './utility.service';
describe('UtilityService', () => {
let service: UtilityService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [UtilityService],
}).compile();
service = module.get<UtilityService>(UtilityService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
import { Injectable } from '@nestjs/common';
import { lastValueFrom } from 'rxjs';
import internal from 'stream';
import { BlankReturnMessageDto } from '../../dto/ReturnMessage.dto';
import { HttpService } from '@nestjs/axios';
@Injectable()
export class UtilityService {
constructor(private http: HttpService) {}
async getStreamFromUrl(url: string) {
try {
return await lastValueFrom(
await this.http.get<internal.Readable>(url, {
responseType: 'stream',
timeout: 30000,
maxBodyLength: 4 * 1024 ** 3,
maxContentLength: 4 * 1024 ** 3,
}),
);
} catch (e) {
throw new BlankReturnMessageDto(404, 'URL not available').toException();
}
}
}
...@@ -3,7 +3,7 @@ import { INestApplication } from '@nestjs/common'; ...@@ -3,7 +3,7 @@ import { INestApplication } from '@nestjs/common';
import * as request from 'supertest'; import * as request from 'supertest';
import { AppModule } from './../src/app.module'; import { AppModule } from './../src/app.module';
describe('AppController (e2e)', () => { describe('JsdController (e2e)', () => {
let app: INestApplication; let app: INestApplication;
beforeEach(async () => { beforeEach(async () => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment