Issue
I am struggling with some Express routs that behave differently even though the code to execute is the same.
I want a client application to call the API as follows:
async search(){
const query = this.$refs.searchInput.value;
console.log(query);
const addressToFetch = "/api/budget/search?q=" + query;
await fetch(addressToFetch)
.then((response) => response.json())
.then((response) => {
console.log(response);
});
}
Where the value of query
is taken from the following input HTML tag:
<div class="input-group row text-right">
<!--flex-nowrap-->
<div class="col">
<input
type="text"
id="searchInput"
name="search"
placeholder="Search"
ref="searchInput"
/>
<button
type="button"
class="btn btn-primary btn-search btn-filter"
@click="search"
>
<i class="fa fa-search" aria-hidden="true"></i>
</button>
<button
type="button"
class="btn btn-danger"
v-if="filteredResults"
@click="getExpenses"
>
Undo
</button>
</div>
</div>
The server-side application handles the request as follows:
app.get("/api/budget/search", verify, async (req, res) => {
console.log(req.query.q);
const users = await db
.collection("users")
.find({ username: { $regex: req.query.q } })
.toArray();
users.forEach((user) => {
delete user.password;
});
res.json(users);
});
After authentication, this function returns []
and not even server-side logs are printed. Checking with Postman, I can see that the response is 200 OK anyway. I created a different route for testing purposes with the same code inside. It turns out that the new route gives different (good) results:
app.get("/api/users/search", verify, async (req, res) => {
console.log(req.query.q);
const users = await db
.collection("users")
.find({ username: { $regex: req.query.q } })
.toArray();
users.forEach((user) => {
delete user.password;
});
res.json(users);
});
I leave you all the routes to see if there are any problems with it:
const express = require("express");
const fs = require("fs/promises");
const session = require("express-session");
const { MongoClient } = require("mongodb");
const exp = require("constants");
const uri = "mongodb://mongohost";
const app = express();
const client = new MongoClient(uri);
let db = null;
app.use(express.static(`${__dirname}/public`));
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(
session({
secret: "segreto",
resave: false,
})
);
function verify(req, res, next) {
if (req.session.user) {
next();
} else {
res.status(403);
}
}
app.post("/api/auth/signup", async (req, res) => {});
app.post("/api/auth/signin", async (req, res) => {...});
app.get("/api/budget/whoami", verify, (req, res) => {...});
app.get("/api/budget", verify, async (req, res) => {...});
app.get("/api/budget/:year", verify, async (req, res) => {...});
app.get("/api/budget/:year/:month", verify, async (req, res) => {...});
app.get("/api/budget/:year/:month/:id", verify, async (req, res) => {...});
app.post("/api/budget/:year/:month", verify, async (req, res) => {...});
app.put("/api/budget/:year/:month/:id", verify, async (req, res) => {...});
app.delete("/api/budget/:year/:month/:id", verify, async (req, res) => {...});
app.get("/api/balance", verify, async (req, res) => {...});
app.get("/api/balance/:id", verify, async (req, res) => {...});
app.get("/api/budget/search", verify, async (req, res) => {...});
app.get("/api/users/search", verify, async (req, res) => {...});
app.listen(3000, async () => {
await client.connect();
db = client.db("balanceApp");
});
I don't get the problem with the first route, is there anything I can do to fix the problem? Thank you very much for your patience.
Solution
Express uses the path-to-regexp package to match your route paths.
When you make GET
request to
/api/budget/search
the path-to-regexp package gets the path as /api/budget/search
and as express goes through your routes top-to-bottom looking for a match it hits:
app.get("/api/budget/:year", verify, async (req, res) => {...});
Now path-to-regexp has a keys
array with objects each containing a name
property that holds your request parameters. It must have parsed your word search
and interpreted that as the request parameter :year
so as far as express is concerned /api/budget/search
matches /api/budget/:year
so it routes the request to here.
All you have to do is move this route:
app.get("/api/budget/search", verify, async (req, res) => {...});
above this route:
app.get("/api/budget/:year", verify, async (req, res) => {...});
so that express has a chance to make an exact pattern match.
Answered By - jQueeny
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.