feat: allow GET for some endpoints

Resolve #8263
This commit is contained in:
syuilo
2022-06-25 18:26:31 +09:00
parent 7be4b2145b
commit 58e83f8e4f
24 changed files with 146 additions and 46 deletions

View File

@ -6,7 +6,11 @@ import call from './call.js';
import { ApiError } from './error.js';
export default (endpoint: IEndpoint, ctx: Koa.Context) => new Promise<void>((res) => {
const body = ctx.request.body;
const body = ctx.is('multipart/form-data')
? (ctx.req as any).body
: ctx.method === 'GET'
? ctx.query
: ctx.request.body;
const reply = (x?: any, y?: ApiError) => {
if (x == null) {
@ -33,6 +37,9 @@ export default (endpoint: IEndpoint, ctx: Koa.Context) => new Promise<void>((res
authenticate(body['i']).then(([user, app]) => {
// API invoking
call(endpoint.name, user, app, body, ctx).then((res: any) => {
if (ctx.method === 'GET' && endpoint.meta.cacheSec && !body['i'] && !user) {
ctx.set('Cache-Control', `public, max-age=${endpoint.meta.cacheSec}`);
}
reply(res);
}).catch((e: ApiError) => {
reply(e.httpStatusCode ? e.httpStatusCode : e.kind === 'client' ? 400 : 500, e);

View File

@ -94,7 +94,7 @@ export default async (endpoint: string, user: CacheableLocalUser | null | undefi
}
// Cast non JSON input
if (ep.meta.requireFile && ep.params.properties) {
if ((ep.meta.requireFile || ctx?.method === 'GET') && ep.params.properties) {
for (const k of Object.keys(ep.params.properties)) {
const param = ep.params.properties![k];
if (['boolean', 'number', 'integer'].includes(param.type ?? '') && typeof data[k] === 'string') {

View File

@ -701,6 +701,16 @@ export interface IEndpointMeta {
readonly kind?: string;
readonly description?: string;
/**
* GETでのリクエストを許容するか否か
*/
readonly allowGet?: boolean;
/**
* 正常応答をキャッシュ (Cache-Control: public) する秒数
*/
readonly cacheSec?: number;
}
export interface IEndpoint {

View File

@ -1,11 +1,14 @@
import define from '../../define.js';
import { getJsonSchema } from '@/services/chart/core.js';
import { activeUsersChart } from '@/services/chart/index.js';
import define from '../../define.js';
export const meta = {
tags: ['charts', 'users'],
res: getJsonSchema(activeUsersChart.schema),
allowGet: true,
cacheSec: 60 * 60,
} as const;
export const paramDef = {

View File

@ -1,11 +1,14 @@
import define from '../../define.js';
import { getJsonSchema } from '@/services/chart/core.js';
import { apRequestChart } from '@/services/chart/index.js';
import define from '../../define.js';
export const meta = {
tags: ['charts'],
res: getJsonSchema(apRequestChart.schema),
allowGet: true,
cacheSec: 60 * 60,
} as const;
export const paramDef = {

View File

@ -1,11 +1,14 @@
import define from '../../define.js';
import { getJsonSchema } from '@/services/chart/core.js';
import { driveChart } from '@/services/chart/index.js';
import define from '../../define.js';
export const meta = {
tags: ['charts', 'drive'],
res: getJsonSchema(driveChart.schema),
allowGet: true,
cacheSec: 60 * 60,
} as const;
export const paramDef = {

View File

@ -1,11 +1,14 @@
import define from '../../define.js';
import { getJsonSchema } from '@/services/chart/core.js';
import { federationChart } from '@/services/chart/index.js';
import define from '../../define.js';
export const meta = {
tags: ['charts'],
res: getJsonSchema(federationChart.schema),
allowGet: true,
cacheSec: 60 * 60,
} as const;
export const paramDef = {

View File

@ -1,11 +1,14 @@
import define from '../../define.js';
import { getJsonSchema } from '@/services/chart/core.js';
import { hashtagChart } from '@/services/chart/index.js';
import define from '../../define.js';
export const meta = {
tags: ['charts', 'hashtags'],
res: getJsonSchema(hashtagChart.schema),
allowGet: true,
cacheSec: 60 * 60,
} as const;
export const paramDef = {

View File

@ -1,11 +1,14 @@
import define from '../../define.js';
import { getJsonSchema } from '@/services/chart/core.js';
import { instanceChart } from '@/services/chart/index.js';
import define from '../../define.js';
export const meta = {
tags: ['charts'],
res: getJsonSchema(instanceChart.schema),
allowGet: true,
cacheSec: 60 * 60,
} as const;
export const paramDef = {

View File

@ -1,11 +1,14 @@
import define from '../../define.js';
import { getJsonSchema } from '@/services/chart/core.js';
import { notesChart } from '@/services/chart/index.js';
import define from '../../define.js';
export const meta = {
tags: ['charts', 'notes'],
res: getJsonSchema(notesChart.schema),
allowGet: true,
cacheSec: 60 * 60,
} as const;
export const paramDef = {

View File

@ -1,11 +1,14 @@
import define from '../../../define.js';
import { getJsonSchema } from '@/services/chart/core.js';
import { perUserDriveChart } from '@/services/chart/index.js';
import define from '../../../define.js';
export const meta = {
tags: ['charts', 'drive', 'users'],
res: getJsonSchema(perUserDriveChart.schema),
allowGet: true,
cacheSec: 60 * 60,
} as const;
export const paramDef = {

View File

@ -6,6 +6,9 @@ export const meta = {
tags: ['charts', 'users', 'following'],
res: getJsonSchema(perUserFollowingChart.schema),
allowGet: true,
cacheSec: 60 * 60,
} as const;
export const paramDef = {

View File

@ -1,11 +1,14 @@
import define from '../../../define.js';
import { getJsonSchema } from '@/services/chart/core.js';
import { perUserNotesChart } from '@/services/chart/index.js';
import define from '../../../define.js';
export const meta = {
tags: ['charts', 'users', 'notes'],
res: getJsonSchema(perUserNotesChart.schema),
allowGet: true,
cacheSec: 60 * 60,
} as const;
export const paramDef = {

View File

@ -1,11 +1,14 @@
import define from '../../../define.js';
import { getJsonSchema } from '@/services/chart/core.js';
import { perUserReactionsChart } from '@/services/chart/index.js';
import define from '../../../define.js';
export const meta = {
tags: ['charts', 'users', 'reactions'],
res: getJsonSchema(perUserReactionsChart.schema),
allowGet: true,
cacheSec: 60 * 60,
} as const;
export const paramDef = {

View File

@ -1,11 +1,14 @@
import define from '../../define.js';
import { getJsonSchema } from '@/services/chart/core.js';
import { usersChart } from '@/services/chart/index.js';
import define from '../../define.js';
export const meta = {
tags: ['charts', 'users'],
res: getJsonSchema(usersChart.schema),
allowGet: true,
cacheSec: 60 * 60,
} as const;
export const paramDef = {

View File

@ -8,6 +8,8 @@ import multer from '@koa/multer';
import bodyParser from 'koa-bodyparser';
import cors from '@koa/cors';
import { Instances, AccessTokens, Users } from '@/models/index.js';
import config from '@/config/index.js';
import endpoints from './endpoints.js';
import handler from './api-handler.js';
import signup from './private/signup.js';
@ -16,8 +18,6 @@ import signupPending from './private/signup-pending.js';
import discord from './service/discord.js';
import github from './service/github.js';
import twitter from './service/twitter.js';
import { Instances, AccessTokens, Users } from '@/models/index.js';
import config from '@/config/index.js';
// Init app
const app = new Koa();
@ -56,11 +56,24 @@ for (const endpoint of endpoints) {
if (endpoint.meta.requireFile) {
router.post(`/${endpoint.name}`, upload.single('file'), handler.bind(null, endpoint));
} else {
// 後方互換性のため
if (endpoint.name.includes('-')) {
// 後方互換性のため
router.post(`/${endpoint.name.replace(/-/g, '_')}`, handler.bind(null, endpoint));
if (endpoint.meta.allowGet) {
router.get(`/${endpoint.name.replace(/-/g, '_')}`, handler.bind(null, endpoint));
} else {
router.get(`/${endpoint.name.replace(/-/g, '_')}`, async ctx => { ctx.status = 405; });
}
}
router.post(`/${endpoint.name}`, handler.bind(null, endpoint));
if (endpoint.meta.allowGet) {
router.get(`/${endpoint.name}`, handler.bind(null, endpoint));
} else {
router.get(`/${endpoint.name}`, async ctx => { ctx.status = 405; });
}
}
}