koajs / koa

Expressive middleware for node.js using ES2017 async functions
https://koajs.com
MIT License
35.11k stars 3.22k forks source link

Issue with reassigning ctx.query and type preservation #1747

Closed wjonesusna2012 closed 12 months ago

wjonesusna2012 commented 1 year ago

Describe the bug

Node.js version: 16.15.1 OS version: Windows 11 Description:

Per the Koa docs, you can reassign to the ctx.query object. Whenever I do so, any typing that I have, is not preserved in future middleware or future calls to ctx.query (i.e. a value of [ 2 ] in the object just becomes '2' or the number 5 becomes the string '5'), although the actual assignment does seem to occur as indicated below by the fact that id becomes 4 after assignment, indicating something has changed.

Actual behavior

INITIAL QUERY OBJECT [Object: null prototype] { id: '2', arr: '5' } QUERY FROM JOI VALIDATION [Object: null prototype] { id: 2, arr: [ 5 ] } number CTX.QUERY AFTER ASSIGNMENT [Object: null prototype] { id: '4', arr: '5' } QUERY IN 2ND MIDDLEWARE [Object: null prototype] { id: '4', arr: '5' } string

Expected behavior

This is what I would expect from code example below.

INITIAL QUERY OBJECT [Object: null prototype] { id: '2', arr: '5' } QUERY FROM JOI VALIDATION [Object: null prototype] { id: 2, arr: [ 5 ] } number CTX.QUERY AFTER ASSIGNMENT [Object: null prototype] { id: 4, arr: [ 5 ] } QUERY IN 2ND MIDDLEWARE [Object: null prototype] { id: 4, arr: [ 5 ] } number

Code to reproduce

I've included a stack overflow entry and code sandbox that replicates this issue in addition to my project on my Windows 11 computer.

https://stackoverflow.com/questions/75368044/unable-to-reassign-ctx-query-in-a-koa-middleware

const Koa = require("koa");
const app = new Koa();
const Joi = require("joi");
const PORT = 3000;
const validSchema = Joi.object({
  name: Joi.string().optional(),
  id: Joi.number().required().min(0),
  arr: Joi.array().items(Joi.number()).optional().single(),
});
// #1
app.use(async (ctx, next) => {
  console.log("INITIAL QUERY OBJECT", ctx.query);
  const { error, value } = validSchema.validate(ctx.query);
  if (!!error) ctx.throw(400, error);
  console.log("QUERY FROM JOI VALIDATION", value);
  value.id += 2;
  console.log(typeof value.id);
  ctx.query = value;
  console.log("CTX.QUERY AFTER ASSIGNMENT", ctx.query);
  await next();
});
// #2
app.use(async (ctx, next) => {
  console.log("QUERY IN 2ND MIDDLEWARE", ctx.query);
  console.log(typeof ctx.query.id);
  await next();
});

app.use(async (ctx, next) => {
  ctx.body = `test koa`;
});

app.listen(PORT);
console.log(`http://localhost:${PORT}`);