diff --git a/README.md b/README.md index be2980a..db4e995 100644 --- a/README.md +++ b/README.md @@ -183,6 +183,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..04e44ce 100644 --- a/packages/vite-plugin-mock/src/createMockServer.ts +++ b/packages/vite-plugin-mock/src/createMockServer.ts @@ -87,16 +87,41 @@ 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 mockResponse = Mock.mock( + isFunction(response) + ? response.bind(self)({ + url: req.url as any, + body, + query, + headers: req.headers, + req, + res, + }) + : response, + ) + if (typeof mockResponse === 'undefined') { + res.statusCode = 204 + res.end() + return + } + if (!res.statusCode) { + res.statusCode = statusCode || 200 + } + if (!res.getHeader('Content-Type')) { + res.setHeader('Content-Type', guessContentType(mockResponse)) + } + if ( + res.getHeader('Content-Type') === 'application/json' && + typeof mockResponse !== 'string' + ) { + mockResponse = JSON.stringify(mockResponse) + } + res.end(mockResponse) } logger && loggerOutput('request invoke', req.url!) @@ -107,6 +132,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