Repository: vercel/next.js
Pull request: fix: ensure req.query is writable

### What?
- Upgrade development dependency **Express** to the latest version (5.1.0).
- Replace direct assignment of `apiReq.query` with `Object.defineProperty` to ensure the property is writable, enumerable, and configurable.

### Why?
- To use the most up-to-date and supported version of Express instead of a legacy one.
- To fix [expressjs/express#6633](https://github.com/expressjs/express/issues/6633), where Express 5.x defines `req.query` as a read-only getter, preventing Next.js from overriding it directly.

### How?
- Update the Express version in `package.json` and run `pnpm install` to apply the change.
- Replace:

```js
apiReq.query = query;
```
With 
```js
Object.defineProperty(apiReq, 'query', {
  value: { ...query },
  writable: true,
  enumerable: true,
  configurable: true,
});
```

Changed files:
filename: packages/next/src/server/api-utils/node/api-resolver.ts
patch: @@ -355,8 +355,14 @@ export async function apiResolver(
 
     // Parsing of cookies
     setLazyProp({ req: apiReq }, 'cookies', getCookieParser(req.headers))
-    // Parsing query string
-    apiReq.query = query
+    // Ensure req.query is a writable, enumerable property by using Object.defineProperty.
+    // This addresses Express 5.x, which defines query as a getter only (read-only).
+    Object.defineProperty(apiReq, 'query', {
+      value: { ...query },
+      writable: true,
+      enumerable: true,
+      configurable: true,
+    })
     // Parsing preview data
     setLazyProp({ req: apiReq }, 'previewData', () =>
       tryGetPreviewData(req, res, apiContext, !!apiContext.multiZoneDraftMode)

filename: test/e2e/api-resolver-query-writeable/api-resolver-query-writeable.test.ts
patch: @@ -0,0 +1,31 @@
+import { nextTestSetup } from 'e2e-utils'
+
+describe('api-resolver-query-writeable', () => {
+  const { next, skipped } = nextTestSetup({
+    files: __dirname,
+    skipDeployment: true,
+    startCommand: 'node server.js',
+    serverReadyPattern: /Next mode: (production|development)/,
+    dependencies: {
+      'get-port': '5.1.1',
+      express: '5.1.0',
+    },
+  })
+
+  if (skipped) {
+    return
+  }
+
+  it('should allow req.query to be writable and reflect changes made in the API handler', async () => {
+    const res = await next.fetch('/api?hello=yes', {
+      headers: {
+        'Content-Type': 'application/json; charset=utf-8',
+      },
+    })
+    if (!res.ok) {
+      throw new Error('Fetch failed')
+    }
+    const data = await res.json()
+    expect(data).toEqual({ query: { hello: 'yes', changed: 'yes' } })
+  })
+})

filename: test/e2e/api-resolver-query-writeable/pages/api/index.js
patch: @@ -0,0 +1,4 @@
+export default (req, res) => {
+  req.query = { ...req.query, changed: 'yes' }
+  res.status(200).json({ query: req.query })
+}

filename: test/e2e/api-resolver-query-writeable/server.js
patch: @@ -0,0 +1,35 @@
+const next = require('next')
+const express = require('express')
+
+const getPort = require('get-port')
+
+async function main() {
+  const dev = process.env.NEXT_TEST_MODE === 'dev'
+  process.env.NODE_ENV = dev ? 'development' : 'production'
+
+  const port = await getPort()
+  const app = next({ dev })
+  const handleNextRequest = app.getRequestHandler()
+
+  await app.prepare()
+
+  const server = express()
+
+  server.all('/:path', (req, res) => {
+    handleNextRequest(req, res)
+  })
+
+  server.listen(port, (err) => {
+    if (err) {
+      throw err
+    }
+
+    console.log(`- Local: http://localhost:${port}`)
+    console.log(`- Next mode: ${dev ? 'development' : process.env.NODE_ENV}`)
+  })
+}
+
+main().catch((err) => {
+  console.error(err)
+  process.exit(1)
+})