We've successfully created our own Request class, now let's add some methods to allow us getting data from the request.
Request Input
Our first method we'll use here is input
which will grab us a value from the request body, query string, or URL parameters.
// src/core/http/request.ts
/**
* Get the value of the given key from the request body, query or params
*/
public input(key: string, defaultValue?: any) {
return (
this.request.params[key] ||
this.request.body[key]?.value ||
this.request.query[key] ||
defaultValue
);
}
In this method, we checked for the key in the params list, body, and query string. If the key is not found, we return the default value.
Now we can use this method in our controller to get the value of the name
key from the request body.
// src/app/users/controllers/create-user.ts
/**
* Create a new user
*/
export default function async createUser(request: Request) {
const name = request.input('name');
return {
name
};
}
Request All
The all
method will return all the data from the request body, query string, and URL parameters.
// src/core/http/request.ts
/**
* Get all the data from the request body, query or params
*/
/**
* Get all inputs from the request body, query or params
*/
public all() {
const body: any = {};
for (const key in this.request.body) {
body[key] = this.request.body[key].value;
}
return {
...this.request.params,
...body,
...this.request.query,
};
}
We can also expose the params
, body
, and query
properties to get the data from each of them.
// src/core/http/request.ts
/**
* Get the request params
*/
public get params() {
return this.request.params;
}
/**
* Get the request body
*/
public get body() {
const body: any = {};
for (const key in this.request.body) {
body[key] = this.request.body[key].value;
}
return body;
}
/**
* Get the request query
*/
public get query() {
return this.request.query;
}
Now we can update or all
and input
methods again to use the body
property.
/**
* Get all inputs from the request body, query or params
*/
public all() {
return {
...this.request.params,
...this.body,
...this.request.query,
};
}
/**
* Get the value of the given key from the request body, query or params
*/
public input(key: string, defaultValue?: any) {
return (
this.request.params[key] ||
this.body[key] ||
this.request.query[key] ||
defaultValue
);
}
Request Boolean Input
Let's add a new method that we can call bool
to make sure that we can receive a boolean value from the request.
For example if the url is something like this: google.com?is_admin=true
we want to make sure that the value of is_admin
is a boolean.
/**
* Get the boolean value of the given key from the request body, query or params
*/
public bool(key: string, defaultValue?: boolean = false) {
const value = this.input(key, defaultValue);
if (value === 'true') {
return true;
}
if (value === 'false') {
return false;
}
return Boolean(value);
}
Request Integer Input
We can also add a method to get an integer value from the request.
/**
* Get the integer value of the given key from the request body, query or params
*/
public int(key: string, defaultValue = 0) {
const value = this.input(key, defaultValue);
return parseInt(value);
}
Request Float Input
We can also add a method to get a float value from the request.
/**
* Get the float value of the given key from the request body, query or params
*/
public float(key: string, defaultValue = 0) {
const value = this.input(key, defaultValue);
return parseFloat(value);
}
Request Number Input
We can also add a method to get a number value from the request.
/**
* Get the number value of the given key from the request body, query or params
*/
public number(key: string, defaultValue = 0) {
const value = this.input(key, defaultValue);
return Number(value);
}
Request File Input
Now let's head to the big boss input, the file
input, this one will have a special treatment as we'll create a new class handler for that file, we'll call it UploadedFile
but let's first create the file
method
/**
* Get the file value of the given key from the request body, query or params
*/
public file(key: string) {
return this.request.body[key];
}
Here we'll have a little problem, the file itself is stored in another key than the value
that we used in the body
which is called file
, so we need to make a small modification about that first in our body
property.
/**
* Get the request body
*/
public get body() {
const body: any = {};
for (const key in this.request.body) {
const data = this.request.body[key];
if (data.file) {
body[key] = {
file: data.file,
filename: data.filename,
mimetype: data.mimetype,
};
} else {
body[key] = data.value;
}
}
return body;
}
As we can see the multipart plugin provides us with some extra data about the file like the file name and its mimetype so we can catch these too.
Watchout for the array of inputs
Let's hold the files for a moment, imagine with me that you're receiving an array of values of the same key, for example tags
which is an array of strings, so the request will look like this:
tags[]: tag1
tags[]: tag2
tags[]: tag3
Please keep in mind that we're still managing the multipart form data, there will be also a json handling next.
Now these values will be sent in one key called tags[]
and it will sent as an array instead.
Now we have to check if the data from the body is an array or not, if so then handle it as an array, otherwise handle it as a single value.
/**
* Get the request body
*/
public get body() {
const body: any = {};
for (const key in this.request.body) {
const data = this.request.body[key];
if (Array.isArray(data)) {
body[key] = data.map(this.parseBodyValue.bind(this));
} else {
body[key] = this.parseBodyValue(data);
}
return body;
}
Wait! parseBodyValue
, what? this method will just use now to handle the given data properly, so we don't have to repeat our code again, as we can see we'll use it in the map to convert the request body data into proper data, and it is not an array then we'll call it directly.
/**
* Parse the body value
*/
private parseBodyValue(data: any) {
if (data.file) {
return {
file: data.file,
filename: data.filename,
mimetype: data.mimetype,
};
}
return data.value;
}
If the request body content is json
, then the data will be returned directly, so we can just return it as it is.
/**
* Parse the body value
*/
private parseBodyValue(data: any) {
if (data.file) {
return {
file: data.file,
filename: data.filename,
mimetype: data.mimetype,
};
}
return data.value || data;
}
Uploaded File
This is where we'll stop for this article, we'll continue in the next article to handle the UploadedFile
class.
🎨 Project Repository
You can find the latest updates of this project on Github
😍 Join our community
Join our community on Discord to get help and support (Node Js 2023 Channel).
🎞️ Video Course (Arabic Voice)
If you want to learn this course in video format, you can find it on Youtube, the course is in Arabic language.
💰 Bonus Content 💰
You may have a look at these articles, it will definitely boost your knowledge and productivity.
General Topics
- Event Driven Architecture: A Practical Guide in Javascript
- Best Practices For Case Styles: Camel, Pascal, Snake, and Kebab Case In Node And Javascript
- After 6 years of practicing MongoDB, Here are my thoughts on MongoDB vs MySQL
Packages & Libraries
- Collections: Your ultimate Javascript Arrays Manager
- Supportive Is: an elegant utility to check types of values in JavaScript
- Localization: An agnostic i18n package to manage localization in your project
React Js Packages
Courses (Articles)
Top comments (0)