-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* chore: 更新 gitignore * feat: demo 包使用 typescript 运行 * feat: 新增路由基准路径的配置项 * refactor: 调整代码中的导出方式 * feat: 添加渲染异常对象的可选配置 * refactor: 路由系统泛型类型重构 * chore: 新增 setup 脚本安装 demo 目录的依赖 * feat: 新增 CommonError 的单元测试 * doc: 更新中间件的文档 * refactor: 统一从 typing 导入公用的接口声明 * fix: 修复配置 base 后没有使用 base path 访问接口也能成功响应的问题 * feat: 导出 CommonError 类供应用层使用 * chore: 同步 @types/node 的版本 * chore: Update package-lock.json * feat: 新增对 HEAD 方法的支持 * fix: 修复 MD5 函数重复 digest 的问题 * fix: 请求 url 前缀不包含 base 时返回空 handler * fix: 消除前导问号,并对 key value 进行 URL 解码
- Loading branch information
1 parent
e24e97f
commit dde2c2c
Showing
40 changed files
with
4,824 additions
and
4,681 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,4 +3,5 @@ dist/ | |
lib/ | ||
public/ | ||
*-debug.log | ||
coverage | ||
coverage | ||
.DS_Store |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"name": "demo", | ||
"version": "1.0.0", | ||
"private": true, | ||
"main": "index.js", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"@types/node": "^17.0.21", | ||
"typescript": "^4.6.2" | ||
}, | ||
"scripts": { | ||
"start": "tsc && node dist/index.js" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
import { Server, Middlewares, Router, RouterMapFactory, CommonError } from '../../packages/auf'; | ||
|
||
const Config = { | ||
chunkSize: 5 * 1024 * 1024, | ||
publicDir: path.resolve(__dirname, '../public') | ||
}; | ||
|
||
const serverTag = '[auf]'; | ||
const errorTag = 'Error:'; | ||
const port = 60000; | ||
const timeout = 5000; | ||
const callback = () => { | ||
console.log(serverTag, 'Server Listening on', port); | ||
} | ||
const errorHandler = (e: Error) => { | ||
console.error(serverTag, errorTag, e.message, '\n', e.stack); | ||
} | ||
const routerMap = RouterMapFactory(/* base= */'/api'); | ||
const fsredirPromise = (path: string) => new Promise<string[]>((resolve, reject) => { | ||
fs.readdir(path, (err, files) => { | ||
if (err) { | ||
reject(new CommonError({ | ||
message: err.message, | ||
statusCode: 500, | ||
statusMessage: 'File not exists' | ||
})); | ||
} | ||
resolve(files); | ||
}); | ||
}); | ||
|
||
const server = new Server({ | ||
port, | ||
assetsRoot: Config.publicDir | ||
}); | ||
|
||
routerMap.get('/', async (ctx, next) => { | ||
ctx.body = ''; | ||
next && await next(ctx); | ||
}); | ||
|
||
routerMap.get('/upload/config', async (ctx, next) => { | ||
ctx.body = JSON.stringify(Object.assign({}, { chunkSize: Config.chunkSize })) | ||
// @ts-ignore | ||
next && await next(ctx); | ||
}); | ||
|
||
routerMap.head('/upload/config', async (ctx, next) => { | ||
ctx.body = JSON.stringify(Object.assign({}, { chunkSize: Config.chunkSize })); | ||
next && await next(ctx); | ||
}); | ||
|
||
routerMap.get('/upload/chunkIndex', async (ctx, next) => { | ||
const res = await fsredirPromise(Config.publicDir); | ||
// const res = []; | ||
const hash = ctx.query.hash; | ||
const fileWithHash = res.filter(file => file.indexOf(hash) === 0) | ||
ctx.body = JSON.stringify({ | ||
success: true, | ||
message: '', | ||
data: fileWithHash.length | ||
}); | ||
next && await next(ctx); | ||
}); | ||
|
||
routerMap.post('/upload', async (ctx, next) => { | ||
const body = ctx.reqBody; | ||
const { files, index, filename: _filename, chunkCount, fileHash } = body; | ||
const _file = files[0]; | ||
const { file } = _file; | ||
const filename = decodeURIComponent(_filename); | ||
|
||
const stream = fs.createWriteStream(path.resolve(Config.publicDir, `${fileHash}-${index}`)); | ||
stream.write(file, 'binary'); | ||
|
||
ctx.body = JSON.stringify({ msg: 'success', success: true, data: (Number(index) + 1) / Number(chunkCount) }); | ||
stream.end(); | ||
stream.on('finish', async () => { | ||
console.log('Writing Finished') | ||
if (Number(chunkCount) === Number(index) + 1) { | ||
const mergeStream = fs.createWriteStream(path.resolve(Config.publicDir, filename)); | ||
// const chunkArr = Array.from({ length: chunkCount }).map((_, index) => index); | ||
|
||
let promise = new Promise<number>((resolve) => { | ||
const fd = path.resolve(Config.publicDir, `${fileHash}-${0}`) | ||
const readData = fs.readFileSync(fd) | ||
|
||
const writable = mergeStream.write(readData, 'binary'); | ||
|
||
if (!writable) { | ||
console.log('Waiting Drain Event For', index); | ||
const drainListener = () => { | ||
resolve(1); | ||
fs.existsSync(fd) && fs.unlink(fd, err => err && console.error(err)); | ||
mergeStream.removeListener('drain', drainListener); | ||
} | ||
mergeStream.on('drain', drainListener) | ||
} | ||
}) | ||
|
||
let q = 0; | ||
while (q < chunkCount - 1) { | ||
promise = promise.then(index => { | ||
return new Promise<number>(resolve => { | ||
const fd = path.resolve(Config.publicDir, `${fileHash}-${index}`) | ||
const readData = fs.readFileSync(fd) | ||
|
||
const writable = mergeStream.write(readData, 'binary'); | ||
|
||
if (!writable) { | ||
console.log('Waiting Drain Event For', index); | ||
const drainListener = () => { | ||
resolve(index + 1); | ||
mergeStream.removeListener('drain', drainListener); | ||
} | ||
mergeStream.on('drain', drainListener) | ||
} else { | ||
resolve(index + 1) | ||
} | ||
|
||
fs.unlink(fd, err => err && console.error(err)) | ||
}) | ||
}) | ||
q ++; | ||
} | ||
|
||
} | ||
}); | ||
next && await next(ctx); | ||
}); | ||
|
||
const CORS = function () { | ||
return async function (ctx, next) { | ||
await next(ctx) | ||
|
||
const { res } = ctx | ||
// console.log(res) | ||
res.setHeader('Access-Control-Allow-Origin', '*') | ||
} | ||
} | ||
|
||
server.applyMiddleware([ | ||
CORS(), | ||
Middlewares.ErrorBoundary({ | ||
errorHandler, | ||
renderError: true | ||
}), | ||
Middlewares.Timeout({ timeout }), | ||
Middlewares.Logger(console), | ||
Middlewares.StaticRoutes({ | ||
fileSystem: fs | ||
}), | ||
Middlewares.BodyParser(), | ||
Router() | ||
]) | ||
|
||
|
||
try { | ||
server.setup(callback); | ||
} catch (e) { | ||
console.error(e.message); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{ | ||
"compilerOptions": { | ||
"target": "es5", | ||
"allowSyntheticDefaultImports": true, // 允许你使用 ES2015 默认的 imports 风格 | ||
"sourceMap": true, // 使 TypeScript 生成 sourcemaps | ||
"strictNullChecks": true, | ||
"moduleResolution": "node", | ||
"noUnusedLocals": true, | ||
"noUnusedParameters": true, | ||
"baseUrl": ".", | ||
"outDir": "./dist", | ||
"declaration": true, | ||
"declarationDir": "./dist/types", | ||
"rootDir": "src" | ||
}, | ||
"include": [ | ||
"src/**/*.ts", | ||
"src/*.ts" | ||
], | ||
"exclude": [ | ||
"node_modules", // 这个目录下的代码不会被 typescript 处理 | ||
"lib", | ||
"webpack", | ||
"es", | ||
"dist" | ||
], | ||
"lib": [ | ||
"esnext", | ||
"es2015", | ||
"dom", | ||
"dom.iterable", | ||
"scripthost" | ||
] | ||
} |
Oops, something went wrong.