So I am currently doing the following.
http://example.com/podcast?url=https://storage.googleapis.com/radiomediapodcast/QWA/S01/QWAS1E1.mp3
However, I want to do the following.
http://example.com/podcast/https://storage.googleapis.com/XXX/XXX/S01/QWAS1E1.mp3
I understand that router.get('/:url', (req, res) => {
should allow me to send http://example.com/podcast/http
I also understand that
router.get('/:url*', (req, res) => {
should also allow http://example.com/podcast/https://storage.googleapis.com/XXX/XXX/S01/QWAS1E1.mp3`
The * enables the route to be called for your url and the req.params would let you read the the inner url passed along with.
Try the following route with http://example.com/podcast/https://storage.googleapis.com/XXX/XXX/S01/QWAS1E1.mp3
router.get('/prodcast/*', async (req, res, next) => {
console.log(req.query.params); //https://storage.googleapis.com/XXX/XXX/S01/QWAS1E1.mp3
res.status(200).send('ok');
});
Define you router like
app.get('/podcast/:url(*)', (req, res) =>
:url(*) instead of :url*
Now you can get your url via req.params.url.
You can use your way (:url*), but you need some trick to get your url data, in this case, req.params will be like
{
0: "//example.com/podcast/https://storage.googleapis.com/XXX/XXX/S01/QWAS1E1.mp3",
url: "http:"
}
Then, the url data will be: const url = req.params.url + req.params[0];
Related
I have a route where I built two GET APIs. I would like one to redirect from /download to /zip all while passing a parameter. The problem is I am getting a 404 for some reason the routes url is not being included in the redirect()
Here are the APIs.
// respond with xml from from static folder
router.get('/zip/:id', function (req, res) {
fileName = req.params.id
});
router.get('/download', function (req, res, next) {
var id = req.query.id
res.redirect('/zip?id='+ id);
});
module.exports = router;
I get a 404 when testing the URL:
localhost:8000/rest/pluto/v1/plugin/download?id=networktool
I am thinking it might be how I have the middleware setup but not real sure. I'm still new to node/express.
You are redirecting to a route that isn't actually defined. With your /zip/:id route definition:
router.get('/zip/:id', function (req, res) {
var fileName = req.params.id
});
The way that is defined, you have to have id information in the URL itself, so while the following routes would work:
/zip/networktool
/zip/1234
these routes would not:
/zip
/zip?id=networktool
/zip?id=1234
because Express is looking for the id to be built into the route itself. So you can do one of two things. You can either change your redirect to:
router.get('/download', function (req, res, next) {
res.redirect('/zip/'+ req.query.id);
});
or, you can modify your /zip route to make the id parameter optional with ?:
router.get('/zip/:id?', function (req, res) {
var fileName = (req.params.id) ? req.params.id : req.query.id;
});
I would recommend the first option, as the latter optional parameter only makes your zip route more complicated and require extra handling of whether id is actually passed to your route.
The path /zip/:id is expecting a path parameter not a query parameter.
You should redirect like this
res.redirect('/zip/'+ id);
I want to route 2 different requests.
/api/heroes/:id
/api/heroes/?name=
So using nodejs and express I write the server to handle this request.
To handle the first request I write below code:
app.get('/api/heroes/:id', jsonParser, function (req, res) {
To handle the second request I write as below:
app.get('/api/heroes/name', jsonParser, function (req, res) {
But only the first handle working as expected. The 2nd request is handled by:
app.get('/api/heroes', jsonParser, function (req, res) {
How do I change the code so the second handle can work?
If I correctly got your question, then probably you asking why req for /api/heroes/?name= is handled by /api/heroes.
You are trying to send query string parameter in 2nd req which will be handled by route /api/heroes. You will get query string parameter in req.query object.
So, your first request handler will work for urls - /api/heroes/:id (eg - /api/heroes/123) as follow:
app.get('/api/heroes/:id', function (req, res) {
var id = req.param.id
}
and for 2nd req: /api/heroes?name= (eg - /api/heroes?name=abc)
app.get('/api/heroes', function (req, res) {
var name = req.query.name
}
Refer here req.query
This is what is expected:
For query parameters /api/heroes/?name= is handled by
app.get('/api/heroes', jsonParser, function (req, res) {
What you can do is to check if req.query.name is undefined then act as normal or act with the query. Using if...else condition.
/api/heroes/name is the endpoint with name.
You can differentiate if you want as below:
app.get('/api/heroes/name/:text', jsonParser, function (req, res) {
I've a route A that uses controller 1.
#A
router.get("/:id", require("./user_get"));
I want to use same logic for route B but only serve different html.
#B
router.get("/:id", ????);
I could copy paste code from user_get to new file. But I was wondering is there a way to extend it. Can I change res.render value somehow if I simply include user_get in new file.
What you want to do is separate out whatever action you're doing in userGet into a middleware.
const userGet = (req, res, next) => {
// whatever you use to get the user
// if your user getting is async the following lines would of course need to be in your `.then`
res.locals.user = user
next()
)}
Notice the middleware signature -- a function with req, res, and next, the use of res.locals, and the call to next at the end.
Then you'd write your route handlers:
const routeOneHandler = (req, res) => {
res.render('templateForRouteOne', { user: res.locals.user })
}
const routeTwoHandler = (req, res) => {
res.render('templateForRouteTwo', { user: res.locals.user })
}
and update your routes like so:
// route one
router.get('/:id', userGet, routeOneHandler)
// route two
router.get('/:id', userGet, routeTwoHandler)
If the concept of middleware and next is new to you, I recommend checking out the Express documentation, or see the info in this answer.
I want to redirect from one URL request to another 'POST' request, like this:
var app = require('express')();
app.get('/', function(req, res) {
res.redirect('/test');
});
app.post('/test', function(req, res) {
res.send('/test page');
});
app.listen(3000, function() {
console.log('listenning on port:3000');
});
However, I can't redirect to '/test' page because it is a POST request. So what should I do to make the redirection work, keeping the '/test' request POST?
You can do this:
app.post('/', function(req, res) {
res.redirect(307, '/test');
});
Which will preserve the send method.
For reference, the 307 http code spec is:
307 Temporary Redirect (since HTTP/1.1) In this occasion, the request
should be repeated with another URI, but future requests can still use
the original URI.2 In contrast to 303, the request method should not
be changed when reissuing the original request. For instance, a POST
request must be repeated using another POST request.
For more info, see: http://www.alanflavell.org.uk/www/post-redirect.html
Keep in mind the middleware architecture: Each handler may manipulate the context, and either respond - or - call next().
By this premise, the express router is basically a middleware function you may use after "correcting" the url.
(BTW, the request app is also a function, although I'm not sure if I recommend going back so early in the chain)
Here's a kind'a example:
const router = new require('express').Router()
const user = require('../model/user')
//assume user implements:
// user.byId(id) -> Promise<user>
// user.byMail(email) -> Promise<user>
const reqUser = userPromise => (req, res, next) =>
req.user
? next()
: userPromise(req)
.then(user => { req.user = user })
.then(next, next)
//assume the sever that uses this router has a
//standard (err, req, res, next) handler in the end of the chain...
const byId = reqUser( req => user.byId(req.params.id) )
const byMail = reqUser( req => user.byMail(req.params.mail) )
router.post('/by-id/:id/friends',
byId,
(req, res) => res.render('user-friends', req.user)
)
router.post('/by-email/:email/friends',
byMail,
(req, res, next) => {
req.url = `/by-id/${req.user.id}/friends`
next()
},
router
)
The only difference between 307 and 302 is that 307 guarantees that the method and the body will not be changed when the redirected request is made.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/307
I believe the question is that the node server is receiving a POST request but needs to redirect it to a different server as GET request. I recently had to deal with something similar. Here is how I solved it:
var proxy = require('express-http-proxy');
app.use('incomin/url', proxy('forwarding:server', {
//The proxyRqDecorator allows us to change a few things including the request type.
proxyReqOptDecorator: (proxyReqOpts, srcReq) => {
proxyReqOpts.method = 'GET';
return proxyReqOpts;
},
//The proxyReqPathResolver takes the Given URL and updates it to the forward path
proxyReqPathResolver: function (req) {
return new Promise( (resolve, reject) => {
setTimeout( () =>{
var value = req.body.key;
var resolvedPathValue = 'forwarding/url' + value;
console.log(`Inside forward path. The resolved path is ${resolvedPathValue}`);
resolve(resolvedPathValue);
}, 200);
});
}
}));
Keep in mind that the above proxyReqPathResolver is setup async. The synchronous vesrion and more info on express-http-proxy are described here:
https://www.npmjs.com/package/express-http-proxy
I have a server in express and it uses an external api. I would like for each request to that api ('/api/*'), that it appends a query param in the url without to write it for each requests.
app.use(function(req, res) {
req.query.key = process.env.APIKEY;
});
I tried something like that but it doesn't work.
I thought of doing something like :
app.get('/api/stuff', addApiKey, api.stuff);
Is there a better way?
You need to supply your middleware function with a next callback:
function addApiKey(req, res, next) {
req.query.key = process.env.APIKEY;
next();
});
app.get('/api/:endpoint', addApiKey, function(req, res) {
// do your stuff here
});