diff --git a/README.md b/README.md index be2980a..d2a5456 100644 --- a/README.md +++ b/README.md @@ -172,6 +172,18 @@ export default [ } }, }, + { + url: '/api/get', + method: 'get', + response: async ({ query }) => { + return { + code: 0, + data: { + name: 'vben', + }, + } + }, + }, { url: '/api/post', method: 'post', @@ -183,6 +195,36 @@ export default [ }, }, }, + // Custom status code and response + { + url: '/api/query', + method: 'get', + response: ({ query, res }) => { + // res.setHeader('X-Hello', 'World') + if (query.name === 'vite') { + res.statusCode = 200 + return { message: 'OK' } + } else { + res.statusCode = 404 + return { message: 'Not Found' } + } + }, + }, + { + url: '/api/plaintext', + method: 'get', + response: () => { + return '200 OK' + }, + }, + // 204 No Content + { + url: '/api/204', + method: 'get', + response: () => { + return + }, + }, { url: '/api/text', method: 'post', diff --git a/packages/vite-plugin-mock/src/createMockServer.ts b/packages/vite-plugin-mock/src/createMockServer.ts index c092734..d9c1fce 100644 --- a/packages/vite-plugin-mock/src/createMockServer.ts +++ b/packages/vite-plugin-mock/src/createMockServer.ts @@ -62,7 +62,7 @@ export async function requestMiddleware(opt: ViteMockOptions) { if (matchRequest) { const isGet = req.method && req.method.toUpperCase() === 'GET' - const { response, rawResponse, timeout, statusCode, url } = matchRequest + const { response: handler, rawResponse, timeout, statusCode, url } = matchRequest if (timeout) { await sleep(timeout) @@ -87,16 +87,40 @@ export async function requestMiddleware(opt: ViteMockOptions) { await rawResponse.bind(self)(req, res) } else { const body = await parseJson(req) - res.setHeader('Content-Type', 'application/json') if (opt) { res.setHeader('Access-Control-Allow-Credentials', true) res.setHeader('Access-Control-Allow-Origin', req.headers.origin || '*') } res.statusCode = statusCode || 200 - const mockResponse = isFunction(response) - ? response.bind(self)({ url: req.url as any, body, query, headers: req.headers }) - : response - res.end(JSON.stringify(Mock.mock(mockResponse))) + let response = isFunction(handler) + ? handler.bind(self)({ + url: req.url as any, + body, + query, + headers: req.headers, + req, + res, + }) + : handler + if (response.then) { + response = await response + } + response = Mock.mock(response) + if (typeof response === 'undefined') { + res.statusCode = 204 + res.end() + return + } + if (!res.statusCode) { + res.statusCode = statusCode || 200 + } + if (!res.getHeader('Content-Type')) { + res.setHeader('Content-Type', guessContentType(response)) + } + if (res.getHeader('Content-Type') === 'application/json' && typeof response !== 'string') { + response = JSON.stringify(response) + } + res.end(response) } logger && loggerOutput('request invoke', req.url!) @@ -107,6 +131,19 @@ export async function requestMiddleware(opt: ViteMockOptions) { return middleware } +function guessContentType(body: any) { + if (body instanceof Buffer || body instanceof Uint8Array) { + return 'application/octet-stream' + } + switch (typeof body) { + case 'string': + return 'text/plain' + case 'undefined': + default: + return 'application/json' + } +} + // create watch mock function createWatch(opt: ViteMockOptions, config: ResolvedConfig) { const { configPath, logger, watchFiles } = opt diff --git a/packages/vite-plugin-mock/src/types.ts b/packages/vite-plugin-mock/src/types.ts index 7378772..73c0046 100644 --- a/packages/vite-plugin-mock/src/types.ts +++ b/packages/vite-plugin-mock/src/types.ts @@ -28,7 +28,7 @@ export declare interface MockMethod { response?: | (( this: RespThisType, - opt: { url: Recordable; body: Recordable; query: Recordable; headers: Recordable }, + opt: { url: Recordable; body: Recordable; query: Recordable; headers: Recordable, req: IncomingMessage, res: ServerResponse }, ) => any) | any rawResponse?: (this: RespThisType, req: IncomingMessage, res: ServerResponse) => void