hoangvvo / next-connect

The TypeScript-ready, minimal router and middleware layer for Next.js, Micro, Vercel, or Node.js http/http2
https://www.npmjs.com/package/next-connect
MIT License
1.63k stars 65 forks source link

Pattern match not working #110

Closed petermarks12 closed 3 years ago

petermarks12 commented 3 years ago

I have created index.js file in api folder and using following code. I am getting 404 on both routes.

It works fine if I use dynamic routing by Next.js. Does this optional pattern really works? Because I want to have single file to handle routes like we do in Express.js instead of creating bunch of nested files.

Getting 404 on these routes

http://localhost:3000/api/user
http://localhost:3000/api/user/555
import nc from 'next-connect';
const handler = nc();

handler.get('/user', (req, res, next) => {
    res.send('User Route');
});

handler.get('/user/:id', (req, res, next) => {
    res.send(`User ${req.query.id} updated`);
});

export default handler;
hoangvvo commented 3 years ago

Create this file instead api/[[...slug]].js

doc: https://nextjs.org/docs/api-routes/dynamic-api-routes#optional-catch-all-api-routes

Turanchoks commented 3 years ago

Create this file instead api/[[...slug]].js

req.query will receive a Next.js query which is { slug: [] } in this case since params from trouter.find are never passed to req.

I've copied the source code locally and assigned assigned params to req.params here https://github.com/hoangvvo/next-connect/blob/master/lib/index.js#L60

@hoangvvo If this is fine I can send a PR. I'm not sure I want to mutate req.query which is assigned by Next.js but it's your call.

hoangvvo commented 3 years ago

Create this file instead api/[[...slug]].js

req.query will receive a Next.js query which is { slug: [] } in this case since params from trouter.find are never passed to req.

I've copied the source code locally and assigned assigned params to req.params here https://github.com/hoangvvo/next-connect/blob/master/lib/index.js#L60

@hoangvvo If this is fine I can send a PR. I'm not sure I want to mutate req.query which is assigned by Next.js but it's your call.

I do not want next-connect to do any url parsing tbh. However, perhaps it can live in the doc as a "recipe" as a middleware.

Turanchoks commented 3 years ago

url parsing is done internally by trouter anyways. Trouter.find returns both handlers and params but the params are ignored. I can't see a a way of doing it properly since the matched pattern is not passed to the handlers either so you can't create a middleware.

smeijer commented 3 years ago

I ran against this today. The docs seem to be incorrect in this area. The following example from the docs, does not work.

handler.put('/user/:id', (req, res, next) => {
  // https://nextjs.org/docs/routing/dynamic-routes
  res.end(`User ${req.query.id} updated`);
});

As mentioned above, the id will be available as item in the array req.query.slug.

A middleware example for how to fix that, would be welcome. But it would also require an update of the docs.

smeijer commented 3 years ago

For now, I'm using patch-package to add the functionality that I need. It merges the path params, together with next's query object.

For those interested, use patch-package, and add the following diff to /patches/next-connect+0.9.1.patch.

diff --git a/node_modules/next-connect/lib/index.js b/node_modules/next-connect/lib/index.js
index 9c5aac6..a4beb92 100755
--- a/node_modules/next-connect/lib/index.js
+++ b/node_modules/next-connect/lib/index.js
@@ -57,10 +57,11 @@ module.exports = ({
   nc.handle = function handle(req, res, done) {
     const idx = req.url.indexOf("?");
     const pathname = idx !== -1 ? req.url.substring(0, idx) : req.url;
-    const { handlers } = this.find(
+    const { handlers, params } = this.find(
       req.method,
       this.baseUrl ? pathname.substring(this.baseUrl.length) : pathname
     );
+    req.query = Object.assign({}, req.query, params);
     let i = 0;
     const len = handlers.length;
     const next = (err) => {
kotsh23 commented 3 years ago

i created file [[...slug]] in api folder

and i try to post from postman by this url : localhost:3000/api/users its give error's

if i remove base ("/users", its give me not found as result at postman

const app = require("next-connect")();
const helmet = require("helmet");
const cors = require("cors");

app.use(helmet());
app.use(cors());

app.post("/users", (req, res, next) => {
  res.end("User created");
});

export default app;

Please tell me if it can be fixed soon i wont move to express as spare backend

kotsh23 commented 3 years ago

maybe its will help someone if it helped you please give me Like to know thats help you 👍

create dynamic file in api folder [[...slug]] for example and add /api to the pattern
will be for example /api/users maybe the owner can skip it in the Code 🍡

function onError(err, req, res, next) {
  res.status(500).end(err.toString());
}

function onNoMatch(req, res) {
  res.status(404).end("Page Not Found");
}

import lol from "next-connect";
const helmet = require("helmet");
const cors = require("cors");

const app = lol({ onError, onNoMatch });

app.use(helmet());
app.use(cors());

app.use("/api/users", (req, res, next) => {
  console.log(req.url);
  res.end("User created");
});

export default app;
kotsh23 commented 3 years ago

I ran against this today. The docs seem to be incorrect in this area. The following example from the docs, does not work.

handler.put('/user/:id', (req, res, next) => {
  // https://nextjs.org/docs/routing/dynamic-routes
  res.end(`User ${req.query.id} updated`);
});

As mentioned above, the id will be available as item in the array req.query.slug.

A middleware example for how to fix that, would be welcome. But it would also require an update of the docs.

[[...slug]].js app.use("/api/users/:id", (req, res) => { res.end(user ${req.query.slug[1]} created :D); });

hoangvvo commented 3 years ago

It is now possible to use req.params by setting attachParams to true.

I also add a recipe for quickly migrating from Express that uses the mentioned optional catch-all route feature here

Igor2122 commented 2 years ago

setting attachParams to true

this does not work for me

hoangvvo commented 2 years ago

setting attachParams to true

this does not work for me

Please create a new issue on this. Thanks!

heinwaiyanhtet commented 11 months ago
import nc from "next-connect";
import onError from "../../../middlewares/errors";
import { getStreaming, postStreaming } from "../../../controller/StreamingController";

// Initiate next-connect with error middleware
const handler  = nc ({ onError });

// Define routes using the handler's methods
handler.get(getStreaming);

handler.post(postStreaming);

export default handler; 

this code got error - - error pages/api/Streaming/streaming.tsx (6:21) @ eval