Categories
Express JavaScript Nodejs

Parse Cookies in Requests in Express Apps with Cookie-Parser

By default, Express 4.x or later doesn’t come with any middleware to parse cookies.

To do this, we can add the cookie-parser middleware.

In this article, we’ll look at how to use it to parse cookies sent with requests.

Adding the Package

We can install the package by running:

npm install cookie-parser

Then we can write:

const express = require('express')  
const cookieParser = require('cookie-parser')  
  
const app = express()  
app.use(cookieParser())

to add the middleware to our app.

Methods

cookieParser(secret, options)

The cookie-parser middleware’s cookieParser function takes a secret string or array of strings as the first argument and an options object as the second argument.

The secret is optional. If it’s not specified it won’t parse signed cookies. If a string is provided, it’ll be used as the secret. If an array of strings is provided, then each secret will be tried for decoding the signed cookie

options is an object that is passed into the cookie.parse as the second option.

cookieParser.JSONCookie(str)

The JSONCookie parses a JSON cookie. This returns the pared JSON value if it’s a JSON cookie. It’ll return the passed value otherwise.

cookieParser.JSONCookies(cookies)

The method will iterate over the keys and call JSONCookie on each value and replace the original value with the parsed value. This returns the same object that’s passed in.

cookieParser.signedCookie(str, secret)

signedCookie parses a cookie as a signed cookie. It’ll return the parsed unsigned value if it was a signed cookie and the signature is valid. If the value wasn’t signed, then the original value is returned. If the value is signed but the cookie can’t be validated with the secret, then false is returned.

cookieParser.signedCookies(cookies, secret)

This method will iterate over the keys and check if any value is a signed cookie. If it’s signed and the signature is valid, then the key will be deleted from the object and added to the new object that’s returned.

The secret can be an array or string. If it’s a string, then it’ll check against the string secret. Otherwise, each cookie will be checked with each string in the array.

The JSONCookie, JSONCookies, signedCookie and signedCookies methods will be automatically invoked depending on the type of cookie sent from the client. Parsing Unsigned Cookies

A simple example is parsing unsigned cookies as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const cookieParser = require('cookie-parser');  
const app = express();
app.use(bodyParser.json());  
app.use(cookieParser());
app.get('/', (req, res) => {  
  res.send(req.cookies);  
});
app.listen(3000);

Then when we send a GET request with the Cookie header’s value set to foo=bar , then we get:

{  
    "foo": "bar"  
}

as the response since req.cookies has the parsed cookie.

Parsing Signed Cookies

We can send a signed cookie and parse it as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const cookieParser = require('cookie-parser');  
const app = express();  
const secret = 'secret';
app.use(bodyParser.json());  
app.use(cookieParser(secret));
app.get('/cookie', (req, res) => {  
  res  
    .cookie('foo', 'bar', { signed: true })  
    .send();  
});
app.get('/', (req, res) => {    
  res.send(req.signedCookies);  
});
app.listen(3000);

The code has the /cookie endpoint to send the signed cookie to the client.

{ signed: true }

will make Express sign the cookie.

Then from the client, when we make a request to / , we get the signed cookie via req.signedCookies and so we get:

{  
    "foo": "bar"  
}

as the response from / .

Conclusion

We can use the cookie-parser middleware to parse the cookies.

It can parse both signed and unsigned cookies. To parse a signed cookie, we just have to sign our cookie with a secret and then cookie-parser can decode the cookie if we pass in the secret to the cookieParser middleware function.

The JSONCookie, JSONCookies, signedCookie and signedCookies methods will be automatically invoked depending on the type of cookie sent from the client.

Categories
JavaScript Rxjs

Some Useful Rxjs Transformation Operators

RxJS is a library for reactive programming. Creating operators are useful for generating data from various data sources to be subscribed to by Observers.

In this article, we’ll look at some RxJS transformation operators like bufferTime, bufferToggle, bufferWhen, and concatMap operators.

bufferTime

The bufferTime operator buffers the emitted data of the originating Observable for a specific time period.

It takes one argument, the bufferTimeSpan, which is the amount of time to fill each buffer array. The unit for the time span is milliseconds.

The buffer data is emitted and the buffer is reset once the amount of time specified is up.

It also takes a bufferCreationInterval argument which specifies the time span for which the buffer data builds up. The operator opens the buffer every bufferCreationInterval milliseconds and emits and resets every bufferTimeSpan milliseconds.

Another optional argument for this operator is the maxBufferSize, which is a number that specifies the maximum size of items buffered.

For example, we can use it as follows:

import { interval } from "rxjs";  
import { bufferTime } from "rxjs/operators";

const clicks = interval(2000);  
const buffered = clicks.pipe(bufferTime(1000));  
buffered.subscribe(x => console.log(x));

We should see a new number emitted every 2 seconds in the arrays that are emitted, while the rest of the emitted arrays are empty.

The bufferCreationInterval argument can be used as follows:

import { interval } from "rxjs";  
import { bufferTime } from "rxjs/operators";

const clicks = interval(2000);  
const buffered = clicks.pipe(bufferTime(1000, 1000));  
buffered.subscribe(x => console.log(x));

In the code above, the buffered data is emitted every second, and the buffer is created every second.

bufferToggle

bufferToggle buffers the source Observable values starting from the emission of openings and ending when the output of the closingSelector emits.

Values emitted by the originating Observable is buffered until the closingSelector tells us to stop emitting values from the originating Observable.

For example, if we have a button as follows:

<button>Click Me</button>

We can buffer the mouse click events on a button and the emit the MouseEvent objects that were buffered according to the closingSelector function’s specification as follows:

import { fromEvent, interval, EMPTY } from "rxjs";  
import { bufferToggle } from "rxjs/operators";

const clicks = fromEvent(document.querySelector("button"), "click");  
const openings = interval(1000);  
const buffered = clicks.pipe(  
  bufferToggle(openings, i => (i % 2 ? interval(1500) : EMPTY))  
);  
buffered.subscribe(x => console.log(x));

The closingSelector in the example above is:

(i % 2 ? interval(1500) : EMPTY)

The code will emit data from the openings Observable when it starts emitting, which is when we click on our button, ever 1.5 seconds. The emitted data is buffered into an array and then the buffering ends when i % 2 is false, and the interval(1500) Observable is returned signaling closure. It’ll continue buffer when EMPTY is emitted.

bufferWhen

The bufferWhen operator buffers data from the source Observable until the closingSelector function closes the buffer.

It takes one argument, which is the closingSelector function to specify when the buffer will be closed.

For example, we can use it as we do in the following code:

import { fromEvent, interval } from "rxjs";  
import { bufferWhen } from "rxjs/operators";

const clicks = fromEvent(document.querySelector("button"), "click");  
const buffered = clicks.pipe(  
  bufferWhen(() => interval(1000 + Math.random() * 4000))  
);  
buffered.subscribe(x => console.log(x));

What we did is get the button clicks and then emit the MouseEvent object array of the MouseEvent s from the clicks that are buffered.

Once we did, then the closingSelector specifies that we emit the buffered values every 1000 + Math.random() * 4000 milliseconds and empty the buffer and buffer the click events again.

concatMap

The concatMap operator takes each source value of the originating Observable and wait for one value of the originating Observable to emit before the next emitted value from it emits.

It takes 2 arguments. The first is a project function, which is a function that returns a new Observable with operations that we want to be applied to the values emitted from the originating Observable. The second argument is the resultSelector . It’s an optional argument, which is a function to pick the emitted values that we want to emit in the returned Observable.

For example, we can use it as follows:

import { fromEvent, interval, of } from "rxjs";  
import { concatMap, take } from "rxjs/operators";

const clicks = fromEvent(document, "click");  
const result = clicks.pipe(concatMap(ev => interval(1000).pipe(take(5))));  
result.subscribe(x => console.log(x));

The code above will receive the click events, then after 1 second emit 0, then after another second emit 1, up until it reaches 4.

It’ll do the same thing each time we click.

The bufferTime operator buffers the emitted data of the originating Observable for a specific time period, then the buffered data will be emitted as an array.

bufferToggle buffers the source Observable values starting from the emission of openings and ending when the output of the closingSelector function emits.

The bufferWhen operator buffers data from the source Observable until the closingSelector function emits its data.

Finally the concatMap operator takes each source value of the originating Observable and waits for one value of the originating Observable to emit before the next emitted value from it emits.

Categories
JavaScript TypeScript

TypeScript Advanced Types — this Type and Dynamic Types

TypeScript has many advanced type capabilities, which makes writing dynamically typed code easy. It also facilitates the adoption of existing JavaScript code since it lets us keep the dynamic capabilities of JavaScript while using the type-checking capability of TypeScript. There are many kinds of advanced types in TypeScript, like intersection types, union types, type guards, nullable types, and type aliases, and more. In this article, we’ll look at the this type and creating dynamic types with index signatures and mapped types.

This Type

In TypeScript, we can use this as a type. It represents the subtype of the containing class or interface. We can use it to create fluent interfaces easily since we know that each method in the class will be returning the instance of a class.

For example, we can use it to define a class with chainable methods like in the following code:

class StringAdder {  
  value: string = '';  
  getValue(): string {  
    return this.value;  
  } 

  addFoo(): this {  
    this.value += 'foo';  
    return this;  
  } 

  addBar(): this {  
    this.value += 'bar';  
    return this;  
  } 

  addGreeting(name: string): this {  
    this.value += `Hi ${name}`;  
    return this;  
  }  
}
const stringAdder: StringAdder = new StringAdder();  
const str = stringAdder  
  .addFoo()  
  .addBar()  
  .addGreeting('Jane')  
  .getValue();  
console.log(str);

In the code above, the addFoo, addBar, and addGreeting methods all return the instance of the StringAdder class, which lets us chain more method calls of the instance to it once it’s instantiated. The chaining is made possible by the this return type that we have in each method.

Index Types

To make the TypeScript compiler check code with dynamic property names, we can use index types. We can use the extends keyof keyword combination to denote that the type has the property names of another type. For example, we can write:

function choose<U, K extends keyof U>(o: U, propNames: K[]): U[K][] {  
  return propNames.map(n => o[n]);  
}

Then we can use the choose function as in the following code:

function choose<U, K extends keyof U>(o: U, propNames: K[]): U[K][] {  
  return propNames.map(n => o[n]);  
}

const obj = {  
  a: 1,  
  b: 2,  
  c: 3  
}  
choose(obj, ['a', 'b'])

Then we get the values:

[1, 2]

if we log the results of the choose function. If we pass in a property name that doesn’t exist in the obj object into the array in the second of the choose function, then we get an error from the TypeScript compiler. So if we write something like the following code:

function choose<U, K extends keyof U>(o: U, propNames: K[]): U[K][] {  
  return propNames.map(n => o[n]);  
}const obj = {  
  a: 1,  
  b: 2,  
  c: 3  
}  
const arr = choose(obj, ['d']);

Then we get the error:

Type 'string' is not assignable to type '"a" | "b" | "c"'.(2322)

In the examples above, keyof U is the same as the string literal type “a” | “b” | “c” since we passed in the type of the generic U type marker where the actual type is inferred from the object that we pass in into the first argument. The K extends keyof U part means that the second argument must have an array of some or all the key names of whatever is passed into the first argument, which we denoted by the generic U type. Then we defined the return type as an array of values that we get by looping through the object we pass into the first argument, hence we have the U[K][] type. U[K][] is also called the index access operator.

Index types and Index Signatures

An index signature is a parameter that must be of type string or number in a TypeScript interface. We can use it to denote the properties of a dynamic object. For example, we can use it like we do in the following code:

interface DynamicObject<T> {  
  [key: string]: T;  
}  
let obj: DynamicObject<number> = {  
  foo: 1,  
  bar: 2  
};  
let key: keyof DynamicObject<number> = 'foo';  
let value: DynamicObject<number>['foo'] = obj[key];

In the code above, we defined a DynamicObject<T> interface which takes a dynamic type for its members. We have an index signature called the key which is a string. It can also be a number. The type of the dynamic members is denoted by T, which is a generic type marker. This means that we can pass in any data type into it.

Then we defined the obj object, which is of type DyanmicObject<number>. This makes use of the DynamicObject interface we created earlier. Then we defined the key variable, which has the type keyof DynamicObject<number>, which means that it has to be a string or a number. This means that the key variable must have one of the property names as the value. Then we defined the value variable, which must have the value of an object of type DynamicObject .

This means that we can’t assign anything other than a string or number to the key variable. So if write something like:

let key: keyof DynamicObject<number> = false;

Then we get the following error message from the TypeScript compiler:

Type 'false' is not assignable to type 'string | number'.(2322)

Mapped Types

We can create a new type by mapping the members of an existing type into the new type. This is called a mapped type.

We can create mapped types like we do in the following code:

interface Person {  
  name: string;  
  age: number;  
}

type ReadOnly<T> = {  
  readonly [P in keyof T]: T[P];  
}

type PartialType<T> = {  
  [P in keyof T]?: T[P];  
}

type ReadOnlyPerson = ReadOnly<Person>;  
type PartialPerson = PartialType<Person>;let readOnlyPerson: ReadOnlyPerson = {  
  name: 'Jane',  
  age: 20  
}
readOnlyPerson.name = 'Joe';  
readOnlyPerson.age = 20;

In the code above, we created the ReadOnly type alias to let us map the members of an existing type into a new type by setting each member of the type as readonly. This isn’t a new type on its own since we need to pass in a type to the generic type marker T . Then we create an alias for the types that we defined by passing in the Person type into the ReadOnly alias and Partial alias respectively.

Next we defined a ReadOnlyPerson object with the name and age properties set. Then when we try to set the values again, then we get the following errors:

Cannot assign to 'name' because it is a read-only property.(2540)Cannot assign to 'age' because it is a read-only property.(2540)

Which means that the readonly property from the ReadOnly type alias is being enforced. Likewise, we can do the same with the PartialType type alias. We have defined the PartialPerson type by mapping the members of the Person type to the PartialPerson type with the PartialPerson type. Then we can define a PartialPerson object like in the following code:

let partialPerson: PartialPerson = {};

As we can see, we can omit properties from the partialPerson object we as want.

We can add new members to the mapped type alias by creating an intersection type from it. Since we used the type keyword to define the mapped types, they’re actually actually types. They are actually type aliases. This means that we can’t put members straight inside, even though they look like interfaces.

To add members, we can write something like the following:

interface Person {  
  name: string;  
  age: number;  
}

type ReadOnly<T> = {  
  readonly [P in keyof T]: T[P];  
}

type ReadOnlyEmployee = ReadOnly<Person> & {  
  employeeCode: string;  
};

let readOnlyPerson: ReadOnlyEmployee = {  
  name: 'Jane',  
  age: 20,  
  employeeCode: '123'  
}

Readonly<T> and Partial<T> are included in the TypeScript standard library. Readonly maps the members of the type that we pass into the generic type placeholder into read-only members. The Partial keyword lets us map members of a type, into nullable members.

Conclusion

In TypeScript, we can use this as a type. It represents the subtype of the containing class or interface. We can use it to create fluent interfaces easily since we know that each method in the class will be returning the instance of a class. An index signature is a parameter that must be of type string or number in a TypeScript interface.

We can use it to denote the properties of a dynamic object. To convert members of a type to add some attributes to them, we can map the members of an existing type into the new type to add the attributes to the interface with mapped types.

Categories
JavaScript Nodejs

Node.js FS Module — Symbolic Links and Timestamps

Manipulating files and directories are basic operations for any program. Since Node.js is a server-side platform and can interact with the computer that it’s running on directly, being able to manipulate files is a basic feature.

Fortunately, Node.js has a fs module built into its library. It has many functions that can help with manipulating files and folders. File and directory operations that are supported include basic ones like manipulating and opening files in directories. Likewise, it can do the same for files.

It can do this both synchronously and asynchronously. It has an asynchronous API that has functions that support promises.

Also, it can show statistics for a file. Almost all the file operations that we can think of can be done with the built-in fs module.

In this article, we will create symbolic links with the symlink family of functions and set timestamps with the utimes family of functions.

Creating Symbolic Links

Symbolic links are files that reference other files in the form of relative or absolute paths of the file. We can create symbolic links in Node.js programs with the symlink function.

The function takes 4 arguments.

The first argument is the target path for our symbolic link which is the file path that we want to reference in our symbolic link. It can be in the form of a string, a buffer object, or an URL object.

The second argument is the path of the symbolic link, it can also be in the form of a string, a buffer object, or an URL object.

The third argument is the type, which is a string. It’s only available on Windows and ignored on other platforms. The possible values are 'dir' , 'file' , or 'junction' .

If the type argument isn’t set, it will automatically detect the type of the target and use 'file' or 'dir' . If the target doesn’t exist, then 'file' would be used. Windows requires that the symbolic link path to be absolute. When using 'junction' , the target argument will be converted to the absolute path.

The last argument is a callback function that’s called when the symbolic link creation operation ends. It has an err parameter which is null when the operation succeeds and has an object with the error information when it failed.

We can create a symbolic link with the symlink function as follows:

const fs = require("fs");  
const target = "./files/file.txt";  
const path = "./files/symlink";

fs.symlink(target, path, "file", err => {  
  if (err) {  
    throw err;  
  }  
  console.log("Symbolic link creation complete!");  
});

After running the code above, when we run stat ./files/symlink on POSIX systems, we should get output that looks something like the following:

File: './files/symlink' -> './files/file.txt'  
  Size: 16              Blocks: 0          IO Block: 512    symbolic link  
Device: eh/14d  Inode: 62487444831945583  Links: 1  
Access: (0777/lrwxrwxrwx)  Uid: ( 1000/hauyeung)   Gid: ( 1000/hauyeung)  
Access: 2019-11-03 11:22:19.787359800 -0800  
Modify: 2019-11-03 11:22:19.787359800 -0800  
Change: 2019-11-03 11:22:19.787359800 -0800  
 Birth: -

This means that are symbolic link has been successfully created.

There’s also a synchronous version of the symlink function that’s called the symlinkSync function. It takes 3 arguments.

The first argument is the target path for our symbolic link which is the file path that we want to reference in our symbolic link. It can be in the form of a string, a buffer object, or an URL object.

The second argument is the path of the symbolic link, it can also be in the form of a string, a buffer object, or an URL object. The third argument is the type, which is a string. It’s only available on Windows and ignored on other platforms.

The possible values are 'dir' , 'file' , or 'junction' . If the type argument isn’t set, it will automatically detect the type of the target and use 'file' or 'dir' . If the target doesn’t exist, then 'file' would be used. Windows requires that the symbolic link path to be absolute.

When using 'junction' , the target argument will be converted to the absolute path. It returns undefined .

We can use it to create symbolic links like in the following code:

const fs = require("fs");  
const target = "./files/file.txt";  
const path = "./files/symlink";

try {  
  fs.symlinkSync(target, path, "file");  
  console.log("Symbolic link creation complete!");  
} catch (error) {  
  console.error(error);  
}

After running the code above, when we run stat ./files/symlink on POSIX systems, we should get output that looks the same as the ones above.

There’s also a promise version of the symlink function. It takes 3 arguments.

The first argument is the target path for our symbolic link which is the file path that we want to reference in our symbolic link. It can be in the form of a string, a buffer object, or an URL object.

The second argument is the path of the symbolic link, it can also be in the form of a string, a buffer object, or an URL object.

The third argument is the type, which is a string. It’s only available on Windows and ignored on other platforms.

The possible values are 'dir' , 'file' , or 'junction' . If the type argument isn’t set, it will automatically detect type of the target and use 'file' or 'dir' . If the target doesn’t exist, then 'file' would be used.

Windows requires that the symbolic link path be absolute. When using 'junction' , the target argument will be converted to the absolute path. It returns a promise that resolves with no arguments when it’s successful.

We can use it to create symbolic links like in the following code:

const fsPromises = require("fs").promises;  
const target = "./files/file.txt";  
const path = "./files/symlink";

(async () => {  
  try {  
    await fsPromises.symlink(target, path, "file");  
    console.log("Symbolic link creation complete!");  
  } catch (error) {  
    console.error(error);  
  }  
})();

After running the code above, when we run stat ./files/symlink on POSIX systems, we should get output that looks the same as the ones above.

The promise version of the symlink function is a much better choice than the symlinkSync function when you want to do multiple things sequentially that includes a call to the symlink function since it doesn’t tie up the whole program waiting for the symbolic link creation operation to complete before continuing to program other parts of the program.

Changing Timestamps of Items Stored on Disk

We can change the timestamp of the last accessed time and the last time a file was modified with the utimes function.

The function takes 4 arguments.

The first is the path of the object stored on disk. It can be a string, a Buffer object, and an URL object.

The second argument is the atime which is the time that the object was last accessed. It can be a number, a string or a Date object.

If it’s a number, then it should be the UNIX timestamp.

If it’s a string, then it should be a string form of the UNIX timestamp.

If the value can’t be converted to a number or is NaN, Infinity or -Infinity then an error will be thrown.

The third argument is the mtime , which is the time that the object was last modified. It can be a number, a string or a Date object. It should be in the same format as the atime argument.

The fourth argument is a callback function which takes an err parameter. It’s null when the operation succeeds and has an object that has the error information if it fails.

We can use the utimes function like in the following code:

const fs = require("fs");  
const path = "./files/file.txt";

fs.utimes(  
  path,  
  new Date(2019, 0, 1, 0, 0, 0, 0),  
  new Date(2019, 0, 1, 0, 0, 0, 0),  
  err => {  
    if (err) {  
      throw err;  
    }  
    console.log("Timestamps changed");  
  }  
);

If we run the code above then run stat ./files/file.txt, we should get something like the following output:

File: './files/file.txt'  
  Size: 16              Blocks: 0          IO Block: 512    regular file  
Device: eh/14d  Inode: 22799473115106242  Links: 1  
Access: (0777/-rwxrwxrwx)  Uid: ( 1000/hauyeung)   Gid: ( 1000/hauyeung)  
Access: 2019-01-01 00:00:00.000000000 -0800  
Modify: 2019-01-01 00:00:00.000000000 -0800  
Change: 2019-11-03 11:41:16.155815100 -0800  
 Birth: -

As we can see, the Access and Modify times changed to 2019–01–01 00:00:00.000000000 , so we know that the utimes function has changed the timestamps successfully.

There’s a synchronous version of the utimes function called the utimesSync function.

The function takes 3 arguments.

The first is the path of the object stored on disk. It can be a string, a Buffer object and an URL object. The second argument is the atime which is the time that the object was last accessed.

It can be a number, a string or a Date object. If it’s a number, then it should be the UNIX timestamp. If it’s a string, then it should be a string form of the UNIX timestamp. If the value can’t be converted to a number or is NaN, Infinity or -Infinity then an error will be thrown.

The third argument is the mtime , which is the time that the object was last modified. It can be a number, a string or a Date object. It should be in the same format as the atime argument.

We can use it as in the following code:

const fs = require("fs");  
const path = "./files/file.txt";

try {  
  fs.utimesSync(  
    path,  
    new Date(2019, 0, 1, 0, 0, 0, 0),  
    new Date(2019, 0, 1, 0, 0, 0, 0)  
  );  
  console.log("Timestamps changed");  
} catch (error) {  
  console.error(error);  
}

If we run the code above then run stat ./files/file.txt, we should get the same output as we did above.

There’s also a promise version of the utimes function, which let us run utimes asynchronously while running it in sequence like we do with the utimesSync function.

The function takes 3 arguments. The first is the path of the object stored on disk. It can be a string, a Buffer object, and an URL object.

The second argument is the atime which is the time that the object was last accessed. It can be a number, a string or a Date object. If it’s a number, then it should be the UNIX timestamp.

If it’s a string, then it should be a string form of the UNIX timestamp. If the value can’t be converted to a number or is NaN, Infinity or -Infinity then an error will be thrown.

The third argument is the mtime , which is the time that the object was last modified. It can be a number, a string or a Date object. It should be in the same format as the atime argument.

We can use it as in the following code:

const fsPromises = require("fs").promises;  
const path = "./files/file.txt";

(async () => {  
  try {  
    await fsPromises.utimes(  
      path,  
      new Date(2019, 0, 1, 0, 0, 0, 0),  
      new Date(2019, 0, 1, 0, 0, 0, 0)  
    );  
    console.log("Timestamps changed");  
  } catch (error) {  
    console.error(error);  
  }  
})();

If we run the code above then run stat ./files/file.txt, we should also get the same output as the regular utimes example.

We can create symbolic links with the symlink family of functions.

It takes 3 arguments. The first is the path of the object stored on disk. It can be a string, a Buffer object, and an URL object.

The second argument is the atime which is the time that the object was last accessed. It can be a number, a string or a Date object. If it’s a number, then it should be the UNIX timestamp, and if it’s a string, then it should be a string form of the UNIX timestamp.

The regular asynchronous version also takes a callback function which runs when it ends. The utimes function changes the timestamp of the access and modified time of an object stored on disk. It takes the path of the entity to apply the change and timestamps for access and modified times.

The regular asynchronous version also takes a callback function which runs when it ends. They are handy for times when we need to do these operations in our Node.js programs.

Categories
Express JavaScript

Guide to the Express Request Object — Methods

The request object lets us get the information about requests made from the client in middlewares and route handlers.

In this article, we’ll look at the properties of Express’s request object methods in detail, including getting headers and query strings.

Methods

The request object has various methods.

req.accepts(types)

The accepts method checks the Accept request header for the value that’s sent with the header. It takes a string with the value of the data type that we want to check if it’s sent with the Accept request header.

It returns the best match, or if nothing matches, false is returned.

If false is returned, then the 406 response code should be returned since the data type isn’t accepted by our route.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const app = express();
app.get('/', (req, res) => {  
  res.send(req.accepts('html'));  
})
app.listen(3000);

Then when we send the Accept header with a value that has html in it, then it’ll return html.

Otherwise, false will be returned.

Other examples include:

req.accepts('text/html')  
req.accepts(['json', 'text'])  
req.accepts('application/json')  
req.accepts('image/png')  
req.accepts('png')  
req.accepts(['html', 'json'])

req.acceptsCharsets(charset [, …]), req.acceptsEncodings(encoding [, …]), req.acceptsLanguages(lang [, …])

The method returns the first accepted charset of the specified character set. The charset is from the request’s Accept-Charset HTTP header field.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const app = express();
app.get('/', (req, res) => {  
  res.send(req.acceptsCharsets('utf8'));  
})
app.listen(3000);

Then we get back the character set in the Accept-Charset HTTP header if it’s set.

acceptsEncodings returns the encoding based on the Accepts-Encoding HTTP header; and acceptsLanguages returns the encoding based on the Accepts-Language HTTP header.

req.get(field)

We can get the header field value with the get method. It takes the key of the header and it’s case-insensitive.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const app = express();
app.get('/', (req, res) => {  
  res.send(req.get('content-type'));  
})
app.listen(3000);

Then when we make a request to the / route with the Content-Type header’s value set to text/cmd, then we get back text/cmd.

req.is(type)

The is method returns the Content-Type header’s value if it matches the type passed in. If the request has no body, the null is returned. Otherwise, false is returned.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const app = express();
app.get('/', (req, res) => {  
  res.send(req.is('html'));  
})
app.listen(3000);

Then we get null since it’s a GET request, which has no request body.

On the other hand, if we have:

const express = require('express');  
const bodyParser = require('body-parser');  
const app = express();
app.post('/', (req, res) => {  
  res.send(req.is('html'));  
})
app.listen(3000);

When we make a POST request to the/ route with the Content-Type header set to text/html, then we get back html .

If the Content-Type header is set to something without html, then we get back false .

req.param(name [, defaultValue])

req.param gets the value from the query string’s search parameter with the given key.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const app = express();
app.post('/', (req, res) => {  
  res.send(req.param('name', 'Joe'));  
})
app.listen(3000);

The code above get the search parameter value with the name key. The default value is set to 'Joe'.

Then when we make a request to /?name=jane, then we get jane. Otherwise, if the name search parameter isn’t specified, then we get Joe.

req.param is deprecated, so we should use req.params, req.body or req.query, as applicable instead.

Lookup is of query string, URL parameter and body values are performed in the following order:

  • req.params
  • req.body
  • req.query

req.range(size[, options])

The range method parses the Range header. The size parameter has the maximum size of the resource. The options parameter is an object which can have the following property:

  • combine — a boolean that specifies if overlapping and adjacent ranges should be combined.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const app = express();app.get('/', (req, res) => {  
  const range = req.range(20000);  
  if (range && range.type === 'bytes') {  
    res.json(range);  
  }  
  else {  
    res.send();  
  }  
})app.listen(3000);

Then when we make a GET request to / with the Range header set to bytes=200–1000, 2000–6576, 19000- , we get:

[  
    {  
        "start": 200,  
        "end": 1000  
    },  
    {  
        "start": 2000,  
        "end": 6576  
    },  
    {  
        "start": 19000,  
        "end": 19999  
    }  
]

since we specified the size parameter to be 20000, so the last end value is 19999.

If we didn’t specify bytes in the value, we get nothing.

Conclusion

The request object has methods to parse query strings and get various headers like the Range, Accepts and Content-Type headers.

We can get the Range header with range, Accepts with accepts and Content-Type with is.

The get method can get any request header field’s value.