fix response pipe, remove multipart

This commit is contained in:
undefined committed 2020-08-20 17:29:46 +08:00
1 parent 65a50275b1
commit af9a8fb206
13 files changed
+70 -46

No files matched your search

+2 -1
View File
@@ -138,8 +138,8 @@ Content: 内容
Contest scoreboard is not visible.: 当前比赛成绩表隐藏,暂不可显示。
Contest Scoreboard: 比赛成绩表
contest_create: 创建比赛
contest_detail: 比赛详情
contest_detail_problem_submit: 递交比赛题目
contest_detail: 比赛详情
contest_edit: 编辑比赛
contest_main: 比赛
contest_scoreboard: 比赛成绩表
@@ -238,6 +238,7 @@ Domain ID: 域 ID
domain_dashboard: 管理域
domain_discussion: 讨论节点
domain_edit: 编辑域资料
domain_file: 我的文件
domain_join_applications: 加域申请
domain_join: 加入域
domain_main: 首页
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "hydrooj",
"version": "2.12.19",
"version": "2.12.20",
"bin": "bin/hydrooj.js",
"main": "dist/loader.js",
"typings": "dist/loader.d.ts",
@@ -25,7 +25,7 @@
"lodash": "^4.17.20",
"lru-cache": "^6.0.0",
"moment-timezone": "^0.5.31",
"mongodb": "^3.5.9",
"mongodb": "^3.6.0",
"nodemailer": "^6.4.10",
"ps-list": "^7.2.0",
"serialize-javascript": "^4.0.0",
@@ -55,4 +55,4 @@
"build": "tsc",
"build:watch": "tsc --watch"
}
}
}
+3 -1
View File
@@ -6,6 +6,7 @@ import {
} from '../error';
import * as user from '../model/user';
import * as domain from '../model/domain';
import * as system from '../model/system';
import { DOMAIN_SETTINGS, DOMAIN_SETTINGS_BY_KEY } from '../model/setting';
import { PERM, PERMS_BY_FAMILY, PRIV } from '../model/builtin';
import { gravatar } from '../lib/misc';
@@ -199,6 +200,7 @@ class DomainJoinApplicationsHandler extends ManageHandler {
if (!this.response.body.joinSettings) {
delete this.response.body.expirations[domain.JOIN_EXPIRATION_KEEP_CURRENT];
}
this.response.body.url_prefix = await system.get('server.url');
this.response.body.path = [
['Hydro', 'homepage'],
['domain', null],
@@ -207,7 +209,7 @@ class DomainJoinApplicationsHandler extends ManageHandler {
this.response.template = 'domain_join_applications.html';
}
@param('method', Types.Range(domain.JOIN_METHOD_RANGE))
@param('method', Types.Range([domain.JOIN_METHOD_NONE, domain.JOIN_METHOD_ALL, domain.JOIN_METHOD_CODE]))
@param('role', Types.String, true)
@param('expire', Types.UnsignedInt, true)
@param('invitationCode', Types.String, true)
+3 -4
View File
@@ -7,7 +7,7 @@ import * as file from '../model/file';
import * as user from '../model/user';
import * as db from '../service/db';
import {
Route, Handler, Types, param, multipart,
Route, Handler, Types, param,
} from '../service/server';
import { BadRequestError } from '../error';
@@ -19,8 +19,8 @@ class FileDownloadHandler extends Handler {
@param('name', Types.String, true)
async get(domainId: string, fileId: ObjectID, secret: string, name: string) {
if (name) name = Buffer.from(name, 'base64').toString();
this.response.attachment(name || fileId.toHexString());
this.response.body = await file.getWithSecret(fileId, secret);
const doc = await file.getWithSecret(fileId, secret);
this.response.attachment(name || fileId.toHexString(), doc);
}
}
@@ -38,7 +38,6 @@ class FileUploadHandler extends Handler {
this.response.body = { fdoc: null, usage: this.user.usage, quota: await this.getQuota() };
}
@multipart(256 * 1024)
@param('title', Types.String)
async post(domainId: string, title: string) {
if (!this.request.files.file) throw new BadRequestError();
+1 -2
View File
@@ -22,7 +22,7 @@ import * as solution from '../model/solution';
import { PERM, PRIV, CONSTANT } from '../model/builtin';
import * as bus from '../service/bus';
import {
Route, Connection, Handler, ConnectionHandler, Types, param, multipart,
Route, Connection, Handler, ConnectionHandler, Types, param,
} from '../service/server';
const parseCategory = (value: string) => flatten(value.split('+').map((e) => e.split(','))).map((e) => e.trim());
@@ -422,7 +422,6 @@ class ProblemDataUploadHandler extends ProblemManageHandler {
this.response.template = 'problem_upload.html';
}
@multipart(256 * 1024)
async post({ domainId }) {
if (!this.request.files.file) throw new ValidationError('file');
this.pdoc = await problem.setTestdata(
+1
View File
@@ -237,6 +237,7 @@ export interface DomainDoc extends Dictionary<any> {
gravatar: string,
bulletin: string,
pidCounter: number,
join?: any,
}
// Message
+1 -1
View File
@@ -74,7 +74,7 @@ export async function getList(domainIds: string[]): Promise<Dictionary<DomainDoc
}
export function setUserRole(domainId: string, uid: number, role: string) {
return collUser.updateOne({ uid, domainId }, { role }, { upsert: true });
return collUser.updateOne({ uid, domainId }, { $set: { role } }, { upsert: true });
}
export async function getRoles(domainId: string): Promise<any[]>
+2 -2
View File
@@ -60,7 +60,7 @@ export async function getWithSecret(_id: ObjectID, secret: string, reject?: Func
const stream = gridfs.openDownloadStream(_id);
stream.on('error', (err) => {
console.error(err);
if (reject) reject();
if (reject) reject(err);
});
return stream;
}
@@ -71,7 +71,7 @@ export async function get(_id: ObjectID, reject?: Function) {
const stream = gridfs.openDownloadStream(_id);
stream.on('error', (err) => {
console.error(err);
if (reject) reject();
if (reject) reject(err);
});
return stream;
}
+9 -2
View File
@@ -10,12 +10,19 @@ mongourl += `${opts.host}:${opts.port}/${opts.name}`;
// eslint-disable-next-line import/no-mutable-exports
export let db: mongodb.Db = null;
// eslint-disable-next-line import/no-mutable-exports
export let db2: mongodb.Db = null;
mongodb.MongoClient.connect(mongourl, { useNewUrlParser: true, useUnifiedTopology: true })
.then((Client) => {
db = Client.db(opts.name);
global.Hydro.service.db.db = db;
bus.publish('system_database_connected', null);
mongodb.MongoClient.connect(mongourl, { useNewUrlParser: true, useUnifiedTopology: true })
.then((Client1) => {
db2 = Client1.db(opts.name);
global.Hydro.service.db.db2 = db2;
bus.publish('system_database_connected', null);
});
});
export function collection(c: string) {
@@ -23,4 +30,4 @@ export function collection(c: string) {
return db.collection(c);
}
global.Hydro.service.db = { collection, db };
global.Hydro.service.db = { collection, db, db2 };
+3 -3
View File
@@ -1,8 +1,8 @@
import { GridFSBucket } from 'mongodb';
import { db } from './db';
import { db2 } from './db';
export const fs = new GridFSBucket(db);
const fs = new GridFSBucket(db2);
global.Hydro.service.gridfs = fs;
export default fs;
export = fs;
+40 -25
View File
@@ -1,5 +1,6 @@
/* eslint-disable prefer-destructuring */
import assert from 'assert';
import { PassThrough } from 'stream';
import path from 'path';
import os from 'os';
import http from 'http';
@@ -99,7 +100,16 @@ export const Types: Types = {
},
],
Range: (range) => [
null,
(v) => {
if (range instanceof Array) {
for (const item of range) {
if (typeof item === 'number') {
if (item === parseInt(v, 10)) return parseInt(v, 10);
} else if (item === v) return v;
}
}
return v;
},
(v) => {
if (range instanceof Array) {
for (const item of range) {
@@ -181,22 +191,6 @@ export function param(name: string, ...args: any): MethodDecorator {
};
}
export function multipart(maxSizeKiB: number): MethodDecorator {
return function multipartDecorator(target: any, funcName: string, obj: any) {
const originalMethod = obj.value;
obj.value = async function checkCsrfToken(...args: any[]) {
const body = Body({
multipart: true,
formidable: {
maxFileSize: maxSizeKiB * 1024,
},
});
return await body.call(this.ctx, this.ctx, () => originalMethod.call(this, ...args));
};
return obj;
};
}
export function requireCsrfToken(target: any, funcName: string, obj: any) {
const originalMethod = obj.value;
obj.value = async function checkCsrfToken(...args: any[]) {
@@ -219,7 +213,12 @@ export async function prepare() {
maxAge: 365 * 24 * 60 * 60,
}));
}
app.use(Body());
app.use(Body({
multipart: true,
formidable: {
maxFileSize: 256 * 1024 * 1024,
},
}));
}
export class Handler {
@@ -251,7 +250,7 @@ export class Handler {
template?: string,
redirect?: string,
disposition?: string,
attachment: (name: string) => void,
attachment: (name: string, stream?: any) => void,
};
session: any;
@@ -288,7 +287,13 @@ export class Handler {
status: null,
template: null,
redirect: null,
attachment: (name) => ctx.attachment(name),
attachment: (name, stream) => {
ctx.attachment(name);
if (stream) {
this.response.body = null;
ctx.body = stream.pipe(new PassThrough());
}
},
disposition: null,
};
this.UIContext = {
@@ -344,9 +349,13 @@ export class Handler {
if (!this.user.hasPriv(...args)) throw new PrivilegeError(...args);
}
url(name: string, kwargs = {}) {
url(name: string, kwargs: any = {}) {
let res = '#';
const args: any = { ...kwargs };
const args: any = {};
for (const key in kwargs) {
if (kwargs[key] instanceof ObjectID) args[key] = kwargs[key].toHexString();
else args[key] = kwargs[key].toString();
}
try {
if (this.args.domainId !== 'system' || args.domainId) {
name += '_with_domainId';
@@ -422,6 +431,7 @@ export class Handler {
}
async finish() {
if (!this.response.body) return;
try {
await this.renderBody();
} catch (error) {
@@ -468,6 +478,8 @@ export class Handler {
async putResponse() {
if (this.response.disposition) this.ctx.set('Content-Disposition', this.response.disposition);
console.log(this.response);
if (!this.response.body) return;
if (this.response.redirect && !this.request.json) {
this.ctx.response.type = 'application/octet-stream';
this.ctx.response.status = 302;
@@ -677,9 +689,13 @@ export class ConnectionHandler {
if (!this.user.hasPriv(...args)) throw new PrivilegeError(...args);
}
url(name: string, kwargs = {}) {
url(name: string, kwargs: any = {}) {
let res = '#';
const args: any = { ...kwargs };
const args: any = {};
for (const key in kwargs) {
if (kwargs[key] instanceof ObjectID) args[key] = kwargs[key].toHexString();
else args[key] = kwargs[key].toString();
}
try {
if (this.args.domainId !== 'system' || args.domainId) {
name += '_with_domainId';
@@ -803,7 +819,6 @@ global.Hydro.service.server = {
server,
router,
param,
multipart,
requireCsrfToken,
Handler,
ConnectionHandler,
+1 -1
View File
@@ -18,4 +18,4 @@
"js-yaml": "^3.14.0",
"mongodb": "^3.6.0"
}
}
}