feat: added RequestHandler

This commit is contained in:
Junseo Park 2021-02-27 15:37:10 +09:00
parent 46f64a7899
commit 5b6a1ff072
12 changed files with 111 additions and 86 deletions

View File

@ -1,9 +1,7 @@
import { NextApiRequest, NextApiResponse } from 'next'
import nc from 'next-connect'
import ResponseWrapper from '@utils/ResponseWrapper' import ResponseWrapper from '@utils/ResponseWrapper'
import RequestHandler from '@utils/RequestHandler'
const NotFound = nc<NextApiRequest, NextApiResponse>() const NotFound = RequestHandler
.all(async(_req, res) => { .all(async(_req, res) => {
return ResponseWrapper(res, { code: 404, message: '요청하신 URL에 페이지가 존재하지 않습니다.' }) return ResponseWrapper(res, { code: 404, message: '요청하신 URL에 페이지가 존재하지 않습니다.' })
}) })

View File

@ -1,5 +1,4 @@
import { NextApiRequest, NextApiResponse } from 'next' import { NextApiRequest } from 'next'
import nc from 'next-connect'
import fetch from 'node-fetch' import fetch from 'node-fetch'
import { serialize } from 'cookie' import { serialize } from 'cookie'
@ -10,9 +9,10 @@ import ResponseWrapper from '@utils/ResponseWrapper'
import { DiscordTokenInfo, DiscordUserInfo } from '@types' import { DiscordTokenInfo, DiscordUserInfo } from '@types'
import { update } from '@utils/Query' import { update } from '@utils/Query'
import { verify } from '@utils/Jwt' import { verify } from '@utils/Jwt'
import RequestHandler from '@utils/RequestHandler'
const Callback = nc<ApiRequest, NextApiResponse>() const Callback = RequestHandler
.get(async(req, res) => { .get(async(req: ApiRequest, res) => {
const validate = await OauthCallbackSchema.validate(req.query).then(r=> r).catch((e) => { const validate = await OauthCallbackSchema.validate(req.query).then(r=> r).catch((e) => {
ResponseWrapper(res, { code: 400, errors: e.errors }) ResponseWrapper(res, { code: 400, errors: e.errors })
return null return null

View File

@ -1,8 +1,10 @@
import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' import { NextApiRequest, NextApiResponse } from 'next'
import { generateOauthURL } from '@utils/Tools' import { generateOauthURL } from '@utils/Tools'
import RequestHandler from '@utils/RequestHandler'
const Discord: NextApiHandler = (_req: NextApiRequest, res: NextApiResponse) => { const Discord = RequestHandler
res.redirect(301, generateOauthURL('discord', process.env.DISCORD_CLIENT_ID, process.env.DISCORD_SCOPE)) .get(async (_req: NextApiRequest, res: NextApiResponse) => {
} res.redirect(301, generateOauthURL('discord', process.env.DISCORD_CLIENT_ID, process.env.DISCORD_SCOPE))
})
export default Discord export default Discord

View File

@ -1,9 +1,8 @@
import { NextApiRequest, NextApiResponse } from 'next'
import nc from 'next-connect'
import { serialize } from 'cookie' import { serialize } from 'cookie'
import RequestHandler from '@utils/RequestHandler'
const Logout = nc<NextApiRequest, NextApiResponse>() const Logout = RequestHandler
.get(async(req, res) => { .get(async(req, res) => {
res.setHeader('Cache-control', 'no-cache') res.setHeader('Cache-control', 'no-cache')
res.setHeader('set-cookie', serialize('token', '', { res.setHeader('set-cookie', serialize('token', '', {

View File

@ -1,14 +1,14 @@
import { NextApiRequest, NextApiResponse } from 'next' import { NextApiRequest } from 'next'
import nc from 'next-connect'
import ResponseWrapper from '@utils/ResponseWrapper' import ResponseWrapper from '@utils/ResponseWrapper'
import { DiscordEnpoints } from '@utils/Constants' import { DiscordEnpoints } from '@utils/Constants'
import { get, ratelimit } from '@utils/Query' import { get, ratelimit } from '@utils/Query'
import RateLimitHandler from '@utils/RateLimitHandler' import RateLimitHandler from '@utils/RateLimitHandler'
import { ImageOptionsSchema } from '@utils/Yup' import { ImageOptionsSchema } from '@utils/Yup'
import RequestHandler from '@utils/RequestHandler'
const Avatar = nc<ApiRequest, NextApiResponse>() const Avatar = RequestHandler
.get(async(req, res) => { .get(async(req: ApiRequest, res) => {
res.setHeader('Access-Control-Allow-Origin', process.env.KOREANBOTS_URL) res.setHeader('Access-Control-Allow-Origin', process.env.KOREANBOTS_URL)
const { imageRateLimit } = await import('@utils/Query') const { imageRateLimit } = await import('@utils/Query')
const { id: param, size='256' } = req.query const { id: param, size='256' } = req.query

View File

@ -1,10 +1,8 @@
import { NextApiRequest, NextApiResponse } from 'next'
import nc from 'next-connect'
import ResponseWrapper from '@utils/ResponseWrapper' import ResponseWrapper from '@utils/ResponseWrapper'
import { getMainGuild } from '@utils/DiscordBot' import { getMainGuild } from '@utils/DiscordBot'
import RequestHandler from '@utils/RequestHandler'
const HelloWorld = nc<NextApiRequest, NextApiResponse>() const HelloWorld = RequestHandler
.get(async(_req, res) => { .get(async(_req, res) => {
getMainGuild() // Load Discord Bot getMainGuild() // Load Discord Bot
return ResponseWrapper(res, { code: 200, message: '>_<' }) return ResponseWrapper(res, { code: 200, message: '>_<' })

View File

@ -1,12 +1,13 @@
import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next'
import ResponseWrapper from '@utils/ResponseWrapper' import ResponseWrapper from '@utils/ResponseWrapper'
import RequestHandler from '@utils/RequestHandler'
const Deprecated: NextApiHandler = (_req: NextApiRequest, res: NextApiResponse) => { const Deprecated = RequestHandler
return ResponseWrapper(res, { .get(async (_req, res) => {
code: 406, return ResponseWrapper(res, {
message: '해당 API 버전은 지원 종료되었습니다.', code: 406,
version: 1, message: '해당 API 버전은 지원 종료되었습니다.',
version: 1,
})
}) })
}
export default Deprecated export default Deprecated

View File

@ -1,18 +1,18 @@
import { NextApiRequest, NextApiResponse } from 'next' import { NextApiRequest } from 'next'
import nc from 'next-connect'
import { get, put } from '@utils/Query' import { get, put } from '@utils/Query'
import ResponseWrapper from '@utils/ResponseWrapper' import ResponseWrapper from '@utils/ResponseWrapper'
import { checkToken } from '@utils/Csrf' import { checkToken } from '@utils/Csrf'
import { AddBotSubmit, AddBotSubmitSchema } from '@utils/Yup' import { AddBotSubmit, AddBotSubmitSchema } from '@utils/Yup'
import RequestHandler from '@utils/RequestHandler'
const Bots = nc<ApiRequest, NextApiResponse>() const Bots = RequestHandler
.get(async(req, res) => { .get(async(req: GetApiRequest, res) => {
const bot = await get.bot.load(req.query.id) const bot = await get.bot.load(req.query.id)
if(!bot) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 봇입니다.' }) if(!bot) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 봇입니다.' })
else return ResponseWrapper(res, { code: 200, data: bot }) else return ResponseWrapper(res, { code: 200, data: bot })
}) })
.post(async (req, res) => { .post(async (req: PostApiRequest, res) => {
const user = await get.Authorization(req.cookies.token) const user = await get.Authorization(req.cookies.token)
if(!user) return ResponseWrapper(res, { code: 401 }) if(!user) return ResponseWrapper(res, { code: 401 })
const csrfValidated = checkToken(req, res, req.body._csrf) const csrfValidated = checkToken(req, res, req.body._csrf)
@ -36,7 +36,13 @@ const Bots = nc<ApiRequest, NextApiResponse>()
return res.send('Reserved') return res.send('Reserved')
}) })
interface ApiRequest extends NextApiRequest { interface GetApiRequest extends NextApiRequest {
query: {
id: string
}
}
interface PostApiRequest extends GetApiRequest {
body: AddBotSubmit | null body: AddBotSubmit | null
query: { query: {
id: string id: string

View File

@ -1,24 +1,28 @@
import { BotList } from '@types' import { NextApiRequest, NextApiResponse } from 'next'
import { get } from '@utils/Query' import { get } from '@utils/Query'
import RequestHandler from '@utils/RequestHandler'
import ResponseWrapper from '@utils/ResponseWrapper' import ResponseWrapper from '@utils/ResponseWrapper'
import { SearchQuerySchema } from '@utils/Yup' import { SearchQuerySchema } from '@utils/Yup'
import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next'
const SearchBots: NextApiHandler = async (req: ApiRequest, res: NextApiResponse) => { import { BotList } from '@types'
const validated = await SearchQuerySchema.validate({ q: req.query.q, page: req.query.page }).then(el => el).catch(e => {
ResponseWrapper(res, { code: 400, errors: e.errors }) const SearchBots = RequestHandler
.get(async (req: ApiRequest, res: NextApiResponse) => {
const validated = await SearchQuerySchema.validate({ q: req.query.q, page: req.query.page }).then(el => el).catch(e => {
ResponseWrapper(res, { code: 400, errors: e.errors })
})
if(!validated) return
let result: BotList
try {
result = await get.list.search.load(JSON.stringify({ page: validated.page, query: validated.q }))
} catch {
return ResponseWrapper(res, { code: 400, message: '검색 문법이 잘못되었습니다.' })
}
if(result.totalPage < validated.page || result.currentPage !== validated.page) return ResponseWrapper(res, { code: 404, message: '검색 결과가 없습니다.' })
else ResponseWrapper<BotList>(res, { code: 200, data: result })
}) })
if(!validated) return
let result: BotList
try {
result = await get.list.search.load(JSON.stringify({ page: validated.page, query: validated.q }))
} catch {
return ResponseWrapper(res, { code: 400, message: '검색 문법이 잘못되었습니다.' })
}
if(result.totalPage < validated.page || result.currentPage !== validated.page) return ResponseWrapper(res, { code: 404, message: '검색 결과가 없습니다.' })
else ResponseWrapper<BotList>(res, { code: 200, data: result })
}
interface ApiRequest extends NextApiRequest { interface ApiRequest extends NextApiRequest {
query: { query: {

View File

@ -1,11 +1,11 @@
import { NextApiRequest } from 'next'
import { get } from '@utils/Query' import { get } from '@utils/Query'
import { NextApiRequest, NextApiResponse } from 'next'
import nc from 'next-connect'
import ResponseWrapper from '@utils/ResponseWrapper' import ResponseWrapper from '@utils/ResponseWrapper'
import RequestHandler from '@utils/RequestHandler'
const Users = nc<ApiRequest, NextApiResponse>() const Users = RequestHandler
.get(async(req, res) => { .get(async(req: ApiRequest, res) => {
console.log(req.query) console.log(req.query)
const user = await get.user.load(req.query?.id) const user = await get.user.load(req.query?.id)
if(!user) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 유저 입니다.' }) if(!user) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 유저 입니다.' })

View File

@ -1,4 +1,4 @@
import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' import { NextApiRequest, NextApiResponse } from 'next'
import ResponseWrapper from '@utils/ResponseWrapper' import ResponseWrapper from '@utils/ResponseWrapper'
import { WidgetOptionsSchema } from '@utils/Yup' import { WidgetOptionsSchema } from '@utils/Yup'
@ -6,41 +6,43 @@ import { WidgetOptionsSchema } from '@utils/Yup'
import { badgen } from 'badgen' import { badgen } from 'badgen'
import { get } from '@utils/Query' import { get } from '@utils/Query'
import { BotBadgeType, DiscordEnpoints } from '@utils/Constants' import { BotBadgeType, DiscordEnpoints } from '@utils/Constants'
import RequestHandler from '@utils/RequestHandler'
const Widget: NextApiHandler = async(req: ApiRequest, res: NextApiResponse) => { const Widget= RequestHandler
const { id: param, type, style='flat', scale=1, icon=true } = req.query .get(async(req: ApiRequest, res: NextApiResponse) => {
const splitted = param.split('.') const { id: param, type, style='flat', scale=1, icon=true } = req.query
const splitted = param.split('.')
const validated = await WidgetOptionsSchema.validate({ const validated = await WidgetOptionsSchema.validate({
id: splitted.slice(0, splitted.length - 1).join('.'), id: splitted.slice(0, splitted.length - 1).join('.'),
ext: splitted[splitted.length - 1], ext: splitted[splitted.length - 1],
style, style,
type, type,
scale, scale,
icon icon
}).then(el=> el).catch(e=> { }).then(el=> el).catch(e=> {
ResponseWrapper(res, { code: 400, errors: e.errors }) ResponseWrapper(res, { code: 400, errors: e.errors })
return null return null
}) })
if(!validated) return if(!validated) return
const data = await get.bot.load(validated.id) const data = await get.bot.load(validated.id)
if(!data) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 봇입니다.' }) if(!data) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 봇입니다.' })
const userImage = !data.avatar ? null : await get.images.user.load(DiscordEnpoints.CDN.user(data.id, data.avatar, { format: 'png', size: 128 })) const userImage = !data.avatar ? null : await get.images.user.load(DiscordEnpoints.CDN.user(data.id, data.avatar, { format: 'png', size: 128 }))
const img = userImage || await get.images.user.load(DiscordEnpoints.CDN.default(data.tag, { format: 'png', size: 128 })) const img = userImage || await get.images.user.load(DiscordEnpoints.CDN.default(data.tag, { format: 'png', size: 128 }))
res.setHeader('content-type', 'image/svg+xml; charset=utf-8') res.setHeader('content-type', 'image/svg+xml; charset=utf-8')
const badgeData = { const badgeData = {
...BotBadgeType(data)[type], ...BotBadgeType(data)[type],
style: validated.style, style: validated.style,
scale: validated.scale, scale: validated.scale,
icon: validated.icon ? `data:image/png;base64,${img.toString('base64')}` : null icon: validated.icon ? `data:image/png;base64,${img.toString('base64')}` : null
} }
res.send(badgen(badgeData)) res.send(badgen(badgeData))
} })
interface ApiRequest extends NextApiRequest { interface ApiRequest extends NextApiRequest {
query: { query: {

15
utils/RequestHandler.ts Normal file
View File

@ -0,0 +1,15 @@
import { NextApiRequest, NextApiResponse } from 'next'
import nc from 'next-connect'
import ResponseWrapper from '@utils/ResponseWrapper'
const RequestHandler = nc<NextApiRequest, NextApiResponse>({
onNoMatch(_req, res) {
return ResponseWrapper(res, { code: 405 })
},
onError(err, _req, res) {
console.error(err)
return ResponseWrapper(res, { code: 500 })
}
})
export default RequestHandler