From 768e26b7ee2769652c28dff09355cfa4468431ab Mon Sep 17 00:00:00 2001 From: Edy Segura Date: Fri, 14 Apr 2023 11:06:54 -0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix:=20error=20thrown=20when=20u?= =?UTF-8?q?sing=20exposed=20server=20function=20with=20HTTP=20POST?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/exposeServerFunctions.js | 3 +- tests/server.js | 2 ++ tests/src/ExposedServerFunctions.jsx | 35 ++++++++++++++++-------- tests/src/ExposedServerFunctions.test.js | 32 +++++++++++++++++++--- 4 files changed, 56 insertions(+), 16 deletions(-) diff --git a/server/exposeServerFunctions.js b/server/exposeServerFunctions.js index c2f55047..45e55af0 100644 --- a/server/exposeServerFunctions.js +++ b/server/exposeServerFunctions.js @@ -23,7 +23,8 @@ export default function exposeServerFunctions(server) { params[key] = extractParamValue(request.query[key]) } if (request.method !== 'GET') { - Object.assign(params, deserialize(request.body)) + const payload = typeof request.body === 'object' ? JSON.stringify(request.body) : request.body + Object.assign(params, deserialize(payload)) } try { const subcontext = generateContext({ request, response, ...params }) diff --git a/tests/server.js b/tests/server.js index 09d0df4b..345659d1 100644 --- a/tests/server.js +++ b/tests/server.js @@ -1,6 +1,7 @@ import Nullstack from 'nullstack' import cors from 'cors' +import express from 'express' import Application from './src/Application' import CatchError from './src/CatchError' @@ -25,6 +26,7 @@ context.server.use( optionsSuccessStatus: 200, }), ) +context.server.use(express.json()) context.worker.staleWhileRevalidate = [/[0-9]/] context.worker.cacheFirst = [/[0-9]/] diff --git a/tests/src/ExposedServerFunctions.jsx b/tests/src/ExposedServerFunctions.jsx index 40951a87..16950726 100644 --- a/tests/src/ExposedServerFunctions.jsx +++ b/tests/src/ExposedServerFunctions.jsx @@ -1,14 +1,19 @@ import Nullstack from 'nullstack' -async function api(method) { - const body = { +async function api(method, contentType = 'text/plain') { + const payload = { number: 69, date: new Date(), string: 'nullstack', } const response = await fetch(`/data/${method}/param?query=query&truthy=true&falsy=false`, { method: method.toUpperCase(), - body: method === 'get' ? undefined : JSON.stringify(body), + ...(method !== 'get' && { + headers: { + 'Content-Type': contentType, + }, + body: JSON.stringify(payload), + }), }) const data = await response.json() return data.status @@ -40,20 +45,28 @@ class ExposedServerFunctions extends Nullstack { this.chainableRegularFunction = await chainable('regular') this.all = await api('get') this.get = await api('get') - this.post = await api('post') - this.put = await api('put') - this.patch = await api('patch') - this.delete = await api('delete') + this.postTextPayload = await api('post') + this.postJsonPayload = await api('post', 'application/json') + this.putTextPayload = await api('put') + this.putJsonPayload = await api('put', 'application/json') + this.patchTextPayload = await api('patch') + this.patchJsonPayload = await api('patch', 'application/json') + this.deleteTextPayload = await api('delete') + this.deleteJsonPayload = await api('delete', 'application/json') } render() { return (
{ expect(element).toBeTruthy() }) - test('server functions can be exposed to POST and serialize params and query and body', async () => { + test('server functions can be exposed to POST and serialize params and query and body as text', async () => { await page.waitForSelector('[data-post]') const element = await page.$('[data-post]') expect(element).toBeTruthy() }) - test('server functions can be exposed to PUT and serialize params and query and body', async () => { + test('server functions can be exposed to POST and serialize params and query and body as json', async () => { + await page.waitForSelector('[data-post-json]') + const element = await page.$('[data-post-json]') + expect(element).toBeTruthy() + }) + + test('server functions can be exposed to PUT and serialize params and query and body as text', async () => { await page.waitForSelector('[data-put]') const element = await page.$('[data-put]') expect(element).toBeTruthy() }) - test('server functions can be exposed to PATCH and serialize params and query and body', async () => { + test('server functions can be exposed to PUT and serialize params and query and body as json', async () => { + await page.waitForSelector('[data-put-json]') + const element = await page.$('[data-put-json]') + expect(element).toBeTruthy() + }) + + test('server functions can be exposed to PATCH and serialize params and query and body as text', async () => { await page.waitForSelector('[data-patch]') const element = await page.$('[data-patch]') expect(element).toBeTruthy() }) - test('server functions can be exposed to DELETE and serialize params and query and body', async () => { + test('server functions can be exposed to PATCH and serialize params and query and body as json', async () => { + await page.waitForSelector('[data-patch-json]') + const element = await page.$('[data-patch-json]') + expect(element).toBeTruthy() + }) + + test('server functions can be exposed to DELETE and serialize params and query and body as text', async () => { await page.waitForSelector('[data-delete]') const element = await page.$('[data-delete]') expect(element).toBeTruthy() }) + test('server functions can be exposed to DELETE and serialize params and query and body as json', async () => { + await page.waitForSelector('[data-delete-json]') + const element = await page.$('[data-delete-json]') + expect(element).toBeTruthy() + }) + test('server functions can be exposed to ALL and serialize params and query and body', async () => { await page.waitForSelector('[data-all]') const element = await page.$('[data-all]')