dimdenGD / ultimate-express

The Ultimate Express. Fastest http server with full Express compatibility, based on µWebSockets.
Apache License 2.0
519 stars 15 forks source link

Unexpected non-whitespace character after JSON #42

Closed cesco69 closed 2 weeks ago

cesco69 commented 2 weeks ago

Hi @dimdenGD I'm investigating on this error on my end

SyntaxError: Unexpected non-whitespace character after JSON at position 3 (line 1 column 4)
at JSON.parse (<anonymous>) 
at /.pnpm/ultimate-express@1.3.5/node_modules/ultimate-express/src/middlewares.js:281:25
at onEnd (/.pnpm/ultimate-express@1.3.5/node_modules/ultimate-express/src/middlewares.js:253:17)    
at /.pnpm/ultimate-express@1.3.5/node_modules/ultimate-express/src/middlewares.js:263:25 
at callbackTrampoline (node:internal/async_hooks:130:17)

after a lot of debug seems there is something of wrong with https://github.com/dimdenGD/ultimate-express/blob/main/src/middlewares.js#L281 the buffer with huge JSON is incomplete (there is always an initial part missing)

Try to post a 100kb of json

On Windows 11 it works as expected, but on Linux (Debian) with Nodejs 22 the error appears.

Maybe it's an issue for uWebSockets.js ?

Side node: works on vanilla express.js

dimdenGD commented 2 weeks ago

reproduction code?

cesco69 commented 2 weeks ago

If you works on linux/nodejs22 you can just try index.js, otherwise this is full reproduction code on Docker

docker-compose.yml

version: '3'
services:
    service:
        build:
            context: .
            dockerfile: Dockerfile
        expose:
            - 3000
        ports:
            - 3000:3000
        restart: always
        environment:
            PORT: 3000

Dockerfile

FROM node:22-slim

ENV NODE_ENV production
ENV PORT=${PORT:-3000}
ENV TZ Europe/Rome

ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get -y install git && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*

ENV PATH $PATH:/usr/bin/git

RUN mkdir -p /opt/backend
WORKDIR /opt/backend

COPY package.json package-lock.json /opt/backend/

RUN git config --global url."https://".insteadOf git://
RUN git config --global url."https://".insteadOf git+ssh://git@

RUN npm i

COPY --chown=node:node ./index.js /opt/backend/index.js

EXPOSE ${PORT}
USER node
CMD [ "node", "index.js" ]

package.json

{
    "name": "issue",
    "main": "index.js",
    "scripts": {
        "start": "node index.js",
        "docker": "docker compose build && docker compose up"
    },
    "dependencies": {
        "ultimate-express": "^1.3.5"
    },
    "sideEffects": false,
    "engines": {
        "node": ">=18"
    }
}

index.js

const express = require("ultimate-express");

const app = express();

app.disable('etag');
app.set('etag fn', null);
app.set('catch async errors', true);
app.set('case sensitive routing', true);
app.disable('x-powered-by');

app.post('*', express.json({ limit: '1mb', strict: false }));

app.post('/test', (req, res) => {
    res.send({ result: req.body?.items?.length })
});

app.use((err, req, res, next) => {
    console.error(err)
    next();
});

const port = process.env.PORT ?? '3000';
app.listen(port, () => {
    console.log(`http://127.0.0.1:${port}`);

    fetch(`http://127.0.0.1:${port}/test`, {
        method: 'POST',
        headers: {
            "Content-Type": "application/json",
        },
        body: JSON.stringify({ items: Array(100_000).fill().map((_, i) => i + 1) })
    }).then(resp => resp.json()).then(console.log).catch(console.error)
});

run command:

npm run docker

output

npm run docker

> docker
> docker compose build && docker compose up

[+] Building 0.8s (15/15) FINISHED                                                                                                                                                                                                                                                     
 => [internal] load build definition from Dockerfile                                                                                                                                                                                                                              0.0s
 => => transferring dockerfile: 32B                                                                                                                                                                                                                                               0.0s 
 => [internal] load .dockerignore                                                                                                                                                                                                                                                 0.0s
 => => transferring context: 2B                                                                                                                                                                                                                                                   0.0s 
 => [internal] load metadata for docker.io/library/node:22-slim                                                                                                                                                                                                                   0.6s 
 => [ 1/10] FROM docker.io/library/node:22-slim@sha256:f73e9c70d4279d5e7b7cc1fe307c5de18b61089ffa2235230408dfb14e2f09a0                                                                                                                                                           0.0s
 => [internal] load build context                                                                                                                                                                                                                                                 0.0s 
 => => transferring context: 1.01kB                                                                                                                                                                                                                                               0.0s 
 => CACHED [ 2/10] RUN apt-get update && apt-get -y install git && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*                                                                                                                                                          0.0s 
 => CACHED [ 3/10] RUN mkdir -p /opt/backend                                                                                                                                                                                                                                      0.0s 
 => CACHED [ 4/10] WORKDIR /opt/backend                                                                                                                                                                                                                                           0.0s 
 => CACHED [ 5/10] COPY package.json package-lock.json /opt/backend/                                                                                                                                                                                                                                                                                                                                                                                                                                0.0s 
 => CACHED [ 7/10] RUN git config --global url."https://".insteadOf git://                                                                                                                                                                                                        0.0s 
 => CACHED [ 8/10] RUN git config --global url."https://".insteadOf git+ssh://git@                                                                                                                                                                                                0.0s 
 => CACHED [ 9/10] RUN npm i                                                                                                                                                                                                                                                      0.0s 
linux-express-service-1  | SyntaxError: Unexpected non-whitespace character after JSON at position 1 (line 1 column 2)
linux-express-service-1  |     at JSON.parse (<anonymous>)
linux-express-service-1  |     at /opt/backend/node_modules/ultimate-express/src/middlewares.js:281:25
linux-express-service-1  |     at onEnd (/opt/backend/node_modules/ultimate-express/src/middlewares.js:253:17)
linux-express-service-1  |     at /opt/backend/node_modules/ultimate-express/src/middlewares.js:263:25
linux-express-service-1  | SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
linux-express-service-1  |     at JSON.parse (<anonymous>)
linux-express-service-1  |     at parseJSONFromBytes (node:internal/deps/undici/undici:5682:19)
linux-express-service-1  |     at successSteps (node:internal/deps/undici/undici:5663:27)
linux-express-service-1  |     at fullyReadBody (node:internal/deps/undici/undici:4561:9)
linux-express-service-1  |     at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
linux-express-service-1  |     at async consumeBody (node:internal/deps/undici/undici:5672:7)

error

SyntaxError: Unexpected non-whitespace character after JSON at position 1 (line 1 column 2)
at JSON.parse (<anonymous>)
at /opt/backend/node_modules/ultimate-express/src/middlewares.js:281:25
at onEnd (/opt/backend/node_modules/ultimate-express/src/middlewares.js:253:17)
at /opt/backend/node_modules/ultimate-express/src/middlewares.js:263:25