How can I extract a URL's extension with nodejs? - node.js

I would like to extract the file extension from a url. For example, http://www.url.com/index.html. I would something like a function extension, where extension(http://www.url.com/index.html) return http. The task is trivial in the case of the URL I have given, but what if I have query parameters, i.e. http://www.url.com/index.html?q=bar?
UPDATE:
This is what I've gotten so far:
function extension(url) {
var components = url.split('/');
var lastComponent = components[components.length-1];
return lastComponent.split('?')[0].split('.')[1];
}
I have't tested it extensively yet. Is there better?

This can be done without introducing vars, as:
var fileExtension = function( url ) {
return url.split('.').pop().split(/\#|\?/)[0];
}

Related

express js: is there a way to map all the rest of url as one parameter?

The code segment is:
app.get('/api/photo/:S3ObjectKey', photo.get);
And photo.get():
const S3ObjectKey = req.params.S3ObjectKey;
if (!S3ObjectKey) {
console.log("No S3ObjectKey specified");
}
console.log("S3ObjectKey: ", S3ObjectKey);
const canShow = true;
if (canShow) {
const bucket_name = process.env.AWS_S3_BUCKET_NAME;
const data = await S3.getFile(bucket_name, S3ObjectKey);
data.Body.pipe(res);
}
Is there a way to map all the rest of url as one parameter, such that:
a GET request to https://mylovelydomain/api/photo/bucketMyPhoto/2020/07/12/home/table.jpeg would hit the api endpoint and S3ObjectKey has the value bucketMyPhoto/2020/07/12/home/table.jpeg?
Express uses path-to-regex:
Custom Matching Parameters
Parameters can have a custom regexp, which overrides the default match ([^/]+).
On your routing path you can use * to get everything overwriting that default match (note that this code also reatcs to empty requests):
app.get("/api/photos/:S3ObjectKey(*)", /*...*/)
As per express documentation, route path supports regular expression, so should be able to do it. Quoting the example from the documentation.

Can't make #Get('id') to work in NestJS tutorial

So I am following this tutorial, and following it, word by word:
https://medium.com/#kaushiksamanta23/nest-js-tutorial-series-part-1-introduction-setup-c87ba810ea9e
So I have this in my service file:
getCourse(courseId): Promise<any> {
let id = Number(courseId);
return new Promise(resolve => {
const course = this.courses.find(course => course.id === id);
if (!course) {
throw new HttpException('Course does not exist', 404)
}
resolve(course);
});
}
and this in my controller, exactly like in the tutorial ,except the log:
#Get(':courseId')
async getCourse(#Param('courseId') courseId) {
console.log(courseId)
const course = await this.coursesService.getCourse(courseId);
return course;
}
In the POSTMAN, when calling http://localhost:3000/courses/courseId=3, I am getting "message": "Course does not exist"
The log clearly shows the problem:
{ courseId: 'courseId=3' }
So when I try http://localhost:3000/courses/3 instead it works, but it's not the right way.
I am lost here, my code is identical to the one in tutorial, and I thought the whole purpose of #Param('courseId') is to recognize the string 'courseId' as key and get whatever value after the '=' in the url. If so, why am I receiving 'courseId=3'? Surely I am not supposed to parse the string manually.
You're confusing URL Parameters with Query Parameters. In a URL, you can have parameters that are parsed differently depending on the route handler. In this case, your URL says that you have a base of courses and then a url parameter by the name courseId. When you make the request, the URL looks likehttp://localhost/courses/3 (the 3 is the courseId) and then you would get the id like req.param['courseId]. If you are wanting to use a URL more like http://localhost/courses/?courseId=3 then you need to use #Query() instead to get the query parameter (this would map to req.query instead of req.param)

How to send integers in query parameters in nodejs Express service

I have a nodejs express web server running on my box. I want to send a get request along with query parameters. Is there any way to find type of each query parameter like int,bool,string. The query parameters key value is not know to me. I interpret as a json object of key value pairs at server side.
You can't, as HTTP has no notion of types: everything is a string, including querystring parameters.
What you'll need to do is to use the req.query object and manually transform the strings into integers using parseInt():
req.query.someProperty = parseInt(req.query.someProperty);
You can also try
var someProperty = (+req.query.someProperty);
This worked for me!
As mentioned by Paul Mougel, http query and path variables are strings. However, these can be intercepted and modified before being handled. I do it like this:
var convertMembershipTypeToInt = function (req, res, next) {
req.params.membershipType = parseInt(req.params.membershipType);
next();
};
before:
router.get('/api/:membershipType(\\d+)/', api.membershipType);
after:
router.get('/api/:membershipType(\\d+)/', convertMembershipTypeToInt, api.membershipType);
In this case, req.params.membershipType is converted from a string to an integer. Note the regex to ensure that only integers are passed to the converter.
This have been answered a long ago but there's a workaround for parsing query params as strings to their proper types using 3rd party library express-query-parser
// without this parser
req.query = {a: 'null', b: 'true', c: {d: 'false', e: '3.14'}}
// with this parser
req.query = {a: null, b: true, c: {d: false, e: 3.14}}
let originalType = JSON.parse(req.query.someproperty);
In HTTP, querystring parameters are treated as string whether you have originally sent say [0,1] or 5 or "hello".
So we have to parse it using json parsing.
//You can use like that
let { page_number } : any = req.query;
page_number = +page_number;
Maybe this will be of any help to those who read this, but I like to use arrow functions to keep my code clean. Since all I do is change one variable it should only take one line of code:
module.exports = function(repo){
router.route('/:id',
(req, res, next) => { req.params.id = parseInt(req.params.id); next(); })
.get(repo.getById)
.delete(repo.deleteById)
.put(repo.updateById);
}

Modify Node.js req object parameters

So as usual, I tried to find this question on SO but still no luck.
I am aware that the answer is "Yes, you CAN modify the req object" but nothing is said about the req object parameters.
For example the following code will throw an error:
app.get('/search', function(req, res) {
req.param('q') = "something";
});
Error:
ReferenceError: Invalid left-hand side in assignment
I imagine this has something to do with the property not having a 'SET' method or something along those lines.
There are a few scenarios where this could come in handy.
A service that turns quick-links into full blown requests and proxies those out.
Simply modifying the parameters before sending it off to another function that you have no desire to modify.
Onto the question, Is there a way to modify the req object parameters?
Rather than:
req.param('q') = "something";
You'll need to use:
req.params.q = "something";
The first one is trying to set a value on the return value of the param function, not the parameter itself.
It's worth noting the req.param() method retrieves values from req.body, req.params and req.query all at once and in that order, but to set a value you need to specify which of those three it goes in:
req.body.q = "something";
// now: req.param('q') === "something"
req.query.r = "something else";
// now: req.param('r') === "something else"
That said unless you're permanently modifying something submitted from the client it might be better to put it somewhere else so it doesn't get mistaken for input from the client by any third party modules you're using.
Alternative approaches to set params in request (use any):
req.params.model = 'Model';
Or
req.params['model'] = 'Model';
Or
req.body.name = 'Name';
Or
req.body['name'] = 'Name';
Or
req.query.ids = ['id'];
Or
req.query['ids'] = ['id'];
Now get params as following:
var model = req.param('model');
var name = req.param('name');
var ids = req.param('ids');
One can also imagine that the left-hand side is not a variable or property, so it makes no sense to try to assign a value to it. If you want to change a query param you have to modify the property in the req.query object.
req.query.q = 'something';
The same goes for req.body and req.params.

Chrome Omnibox extension to post form data to a website?

How can an Omnibox extension create and post form data to a website and then display the result?
Here's an example of what I want to do. When you type lookup bieber into the Omnibox, I want my extension to post form data looking like
searchtype: all
searchterm: bieber
searchcount: 20
to the URL http://lookup.com/search
So that the browser will end up loading http://lookup.com/search with the results of the search.
This would be trivial if I could send the data in a GET, but lookup.com expects an HTTP POST. The only way I can think of is to inject a form into the current page and then submit it, but (a) that only works if there is a current page, and (b) it doesn't seem to work anyway (maybe permissions need to be set).
Before going off down that route, I figured that somebody else must at least have tried to do this before. Have you?
You could do this by using the omnibox api:
chrome.omnibox.onInputChanged.addListener(
function(text, suggest) {
doYourLogic...
});
Once you have you extension 'activated' due to a certain keyword you typed you can call something like this:
var q = the params you wish to pass
var url = "http://yourSite.com";
var req = new XMLHttpRequest();
req.open("POST", url, true);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.onreadystatechange = function() {
if (req.readyState == 4) {
callback(req.responseXML);
}
}
req.send(q);

Resources