in

Express.js Route Parameters

URL Variables

Because explicitly listing all of your route URL’s is not dry code, we need to know how to structure routes using parameters.

If we take reddit as an example, to create a route parameter you add a colon : in front of a variable.

app.get("/r/:subredditName")

We can add a colon to any item in a URL that is going to be a variable.

app.get("/r/:subredditName/comments/:id/:title")

So how do we set the rules regarding these route parameters. In the previous post Express.js Basics we talked about request and response as parameters of the route function. Here is a quick refresher:

app.get("/", function(req, res){
    res.send("Welcome to the Home Page");
});

but we only had examples of a response before. Now we will get into the request portion, which is where the route parameters for the incoming request are defined.

Request Data

When your server receives a request, it gets a whole load of information. To view a full output of that information you can simply console.log(req) in your route like this:

// route parameter :sample 
app.get("/r/:subreddit", function(req, res){
    res.send("Welcome to a subreddit");
    console.log(req);
});

and the next time you visit that url you will get the following in the console

IncomingMessage {
  _readableState:
   ReadableState {
     objectMode: false,
     highWaterMark: 16384,
     buffer: BufferList { head: null, tail: null, length: 0 },
     length: 0,
     pipes: null,
     pipesCount: 0,
     flowing: null,
     ended: false,
     endEmitted: false,
     reading: false,
     sync: true,
     needReadable: false,
     emittedReadable: false,
     readableListening: false,
     resumeScheduled: false,
     paused: true,
     emitClose: true,
     autoDestroy: false,
     destroyed: false,
     defaultEncoding: 'utf8',
     awaitDrain: 0,
     readingMore: true,
     decoder: null,
     encoding: null },
  readable: true,
  _events:
   [Object: null prototype] { end: [Function: resetHeadersTimeoutOnReqEnd] },
  _eventsCount: 1,
  _maxListeners: undefined,
  socket:
   Socket {
     connecting: false,
     _hadError: false,
     _handle:
      TCP {
        reading: true,
        onread: [Function: onStreamRead],
        onconnection: null,
        _consumed: true,
        [Symbol(owner)]: [Circular] },
     _parent: null,
     _host: null,
     _readableState:
      ReadableState {
        objectMode: false,
        highWaterMark: 16384,
        buffer: BufferList { head: null, tail: null, length: 0 },
        length: 0,
        pipes: null,
        pipesCount: 0,
        flowing: true,
        ended: false,
        endEmitted: false,
        reading: true,
        sync: false,
        needReadable: true,
        emittedReadable: false,
        readableListening: false,
        resumeScheduled: false,
        paused: false,
        emitClose: false,
        autoDestroy: false,
        destroyed: false,
        defaultEncoding: 'utf8',
        awaitDrain: 0,
        readingMore: false,
        decoder: null,
        encoding: null },
     readable: true,
     _events:
      [Object: null prototype] {
        end: [Array],
        drain: [Array],
        timeout: [Function: socketOnTimeout],
        data: [Function: bound socketOnData],
        error: [Function: socketOnError],
        close: [Array],
        resume: [Function: onSocketResume],
        pause: [Function: onSocketPause] },
     _eventsCount: 8,
     _maxListeners: undefined,
     _writableState:
      WritableState {
        objectMode: false,
        highWaterMark: 16384,
        finalCalled: false,
        needDrain: false,
        ending: false,
        ended: false,
        finished: false,
        destroyed: false,
        decodeStrings: false,
        defaultEncoding: 'utf8',
        length: 0,
        writing: false,
        corked: 0,
        sync: false,
        bufferProcessing: false,
        onwrite: [Function: bound onwrite],
        writecb: null,
        writelen: 0,
        bufferedRequest: null,
        lastBufferedRequest: null,
        pendingcb: 1,
        prefinished: false,
        errorEmitted: false,
        emitClose: false,
        autoDestroy: false,
        bufferedRequestCount: 0,
        corkedRequestsFree: [Object] },
     writable: true,
     allowHalfOpen: true,
     _sockname: null,
     _pendingData: null,
     _pendingEncoding: '',
     server:
      Server {
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        _connections: 1,
        _handle: [TCP],
        _usingWorkers: false,
        _workers: [],
        _unref: false,
        allowHalfOpen: true,
        pauseOnConnect: false,
        httpAllowHalfOpen: false,
        timeout: 120000,
        keepAliveTimeout: 5000,
        maxHeadersCount: null,
        headersTimeout: 40000,
        _connectionKey: '4:127.0.0.1:8080',
        [Symbol(IncomingMessage)]: [Function],
        [Symbol(ServerResponse)]: [Function],
        [Symbol(asyncId)]: 8 },
     _server:
      Server {
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        _connections: 1,
        _handle: [TCP],
        _usingWorkers: false,
        _workers: [],
        _unref: false,
        allowHalfOpen: true,
        pauseOnConnect: false,
        httpAllowHalfOpen: false,
        timeout: 120000,
        keepAliveTimeout: 5000,
        maxHeadersCount: null,
        headersTimeout: 40000,
        _connectionKey: '4:127.0.0.1:8080',
        [Symbol(IncomingMessage)]: [Function],
        [Symbol(ServerResponse)]: [Function],
        [Symbol(asyncId)]: 8 },
     timeout: 120000,
     parser:
      HTTPParser {
        '0': [Function: parserOnHeaders],
        '1': [Function: parserOnHeadersComplete],
        '2': [Function: parserOnBody],
        '3': [Function: parserOnMessageComplete],
        '4': [Function: bound onParserExecute],
        _headers: [],
        _url: '',
        socket: [Circular],
        incoming: [Circular],
        outgoing: null,
        maxHeaderPairs: 2000,
        _consumed: true,
        onIncoming: [Function: bound parserOnIncoming],
        parsingHeadersStart: 0,
        [Symbol(isReused)]: false },
     on: [Function: socketOnWrap],
     _paused: false,
     _httpMessage:
      ServerResponse {
        _events: [Object],
        _eventsCount: 1,
        _maxListeners: undefined,
        output: [],
        outputEncodings: [],
        outputCallbacks: [],
        outputSize: 0,
        writable: true,
        _last: true,
        chunkedEncoding: false,
        shouldKeepAlive: false,
        useChunkedEncodingByDefault: true,
        sendDate: true,
        _removedConnection: false,
        _removedContLen: true,
        _removedTE: true,
        _contentLength: 0,
        _hasBody: false,
        _trailer: '',
        finished: true,
        _headerSent: true,
        socket: [Circular],
        connection: [Circular],
        _header:
         'HTTP/1.1 304 Not Modified\r\nX-Powered-By: Express\r\nETag: W/"16-uWKsSQfMsYIHFEu43T+yvLZhxuA"\r\nDate: Fri, 01 Nov 2019 12:38:40 GMT\r\nConnection: close\r\n\r\n',
        _onPendingData: [Function: bound updateOutgoingData],
        _sent100: false,
        _expect_continue: false,
        req: [Circular],
        locals: [Object: null prototype] {},
        statusCode: 304,
        statusMessage: 'Not Modified',
        [Symbol(isCorked)]: false,
        [Symbol(outHeadersKey)]: [Object] },
     [Symbol(asyncId)]: 11,
     [Symbol(lastWriteQueueSize)]: 0,
     [Symbol(timeout)]:
      Timeout {
        _called: false,
        _idleTimeout: 120000,
        _idlePrev: [TimersList],
        _idleNext: [TimersList],
        _idleStart: 3778,
        _onTimeout: [Function: bound ],
        _timerArgs: undefined,
        _repeat: null,
        _destroyed: false,
        [Symbol(unrefed)]: true,
        [Symbol(asyncId)]: 12,
        [Symbol(triggerId)]: 11 },
     [Symbol(kBytesRead)]: 0,
     [Symbol(kBytesWritten)]: 0 },
  connection:
   Socket {
     connecting: false,
     _hadError: false,
     _handle:
      TCP {
        reading: true,
        onread: [Function: onStreamRead],
        onconnection: null,
        _consumed: true,
        [Symbol(owner)]: [Circular] },
     _parent: null,
     _host: null,
     _readableState:
      ReadableState {
        objectMode: false,
        highWaterMark: 16384,
        buffer: BufferList { head: null, tail: null, length: 0 },
        length: 0,
        pipes: null,
        pipesCount: 0,
        flowing: true,
        ended: false,
        endEmitted: false,
        reading: true,
        sync: false,
        needReadable: true,
        emittedReadable: false,
        readableListening: false,
        resumeScheduled: false,
        paused: false,
        emitClose: false,
        autoDestroy: false,
        destroyed: false,
        defaultEncoding: 'utf8',
        awaitDrain: 0,
        readingMore: false,
        decoder: null,
        encoding: null },
     readable: true,
     _events:
      [Object: null prototype] {
        end: [Array],
        drain: [Array],
        timeout: [Function: socketOnTimeout],
        data: [Function: bound socketOnData],
        error: [Function: socketOnError],
        close: [Array],
        resume: [Function: onSocketResume],
        pause: [Function: onSocketPause] },
     _eventsCount: 8,
     _maxListeners: undefined,
     _writableState:
      WritableState {
        objectMode: false,
        highWaterMark: 16384,
        finalCalled: false,
        needDrain: false,
        ending: false,
        ended: false,
        finished: false,
        destroyed: false,
        decodeStrings: false,
        defaultEncoding: 'utf8',
        length: 0,
        writing: false,
        corked: 0,
        sync: false,
        bufferProcessing: false,
        onwrite: [Function: bound onwrite],
        writecb: null,
        writelen: 0,
        bufferedRequest: null,
        lastBufferedRequest: null,
        pendingcb: 1,
        prefinished: false,
        errorEmitted: false,
        emitClose: false,
        autoDestroy: false,
        bufferedRequestCount: 0,
        corkedRequestsFree: [Object] },
     writable: true,
     allowHalfOpen: true,
     _sockname: null,
     _pendingData: null,
     _pendingEncoding: '',
     server:
      Server {
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        _connections: 1,
        _handle: [TCP],
        _usingWorkers: false,
        _workers: [],
        _unref: false,
        allowHalfOpen: true,
        pauseOnConnect: false,
        httpAllowHalfOpen: false,
        timeout: 120000,
        keepAliveTimeout: 5000,
        maxHeadersCount: null,
        headersTimeout: 40000,
        _connectionKey: '4:127.0.0.1:8080',
        [Symbol(IncomingMessage)]: [Function],
        [Symbol(ServerResponse)]: [Function],
        [Symbol(asyncId)]: 8 },
     _server:
      Server {
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        _connections: 1,
        _handle: [TCP],
        _usingWorkers: false,
        _workers: [],
        _unref: false,
        allowHalfOpen: true,
        pauseOnConnect: false,
        httpAllowHalfOpen: false,
        timeout: 120000,
        keepAliveTimeout: 5000,
        maxHeadersCount: null,
        headersTimeout: 40000,
        _connectionKey: '4:127.0.0.1:8080',
        [Symbol(IncomingMessage)]: [Function],
        [Symbol(ServerResponse)]: [Function],
        [Symbol(asyncId)]: 8 },
     timeout: 120000,
     parser:
      HTTPParser {
        '0': [Function: parserOnHeaders],
        '1': [Function: parserOnHeadersComplete],
        '2': [Function: parserOnBody],
        '3': [Function: parserOnMessageComplete],
        '4': [Function: bound onParserExecute],
        _headers: [],
        _url: '',
        socket: [Circular],
        incoming: [Circular],
        outgoing: null,
        maxHeaderPairs: 2000,
        _consumed: true,
        onIncoming: [Function: bound parserOnIncoming],
        parsingHeadersStart: 0,
        [Symbol(isReused)]: false },
     on: [Function: socketOnWrap],
     _paused: false,
     _httpMessage:
      ServerResponse {
        _events: [Object],
        _eventsCount: 1,
        _maxListeners: undefined,
        output: [],
        outputEncodings: [],
        outputCallbacks: [],
        outputSize: 0,
        writable: true,
        _last: true,
        chunkedEncoding: false,
        shouldKeepAlive: false,
        useChunkedEncodingByDefault: true,
        sendDate: true,
        _removedConnection: false,
        _removedContLen: true,
        _removedTE: true,
        _contentLength: 0,
        _hasBody: false,
        _trailer: '',
        finished: true,
        _headerSent: true,
        socket: [Circular],
        connection: [Circular],
        _header:
         'HTTP/1.1 304 Not Modified\r\nX-Powered-By: Express\r\nETag: W/"16-uWKsSQfMsYIHFEu43T+yvLZhxuA"\r\nDate: Fri, 01 Nov 2019 12:38:40 GMT\r\nConnection: close\r\n\r\n',
        _onPendingData: [Function: bound updateOutgoingData],
        _sent100: false,
        _expect_continue: false,
        req: [Circular],
        locals: [Object: null prototype] {},
        statusCode: 304,
        statusMessage: 'Not Modified',
        [Symbol(isCorked)]: false,
        [Symbol(outHeadersKey)]: [Object] },
     [Symbol(asyncId)]: 11,
     [Symbol(lastWriteQueueSize)]: 0,
     [Symbol(timeout)]:
      Timeout {
        _called: false,
        _idleTimeout: 120000,
        _idlePrev: [TimersList],
        _idleNext: [TimersList],
        _idleStart: 3778,
        _onTimeout: [Function: bound ],
        _timerArgs: undefined,
        _repeat: null,
        _destroyed: false,
        [Symbol(unrefed)]: true,
        [Symbol(asyncId)]: 12,
        [Symbol(triggerId)]: 11 },
     [Symbol(kBytesRead)]: 0,
     [Symbol(kBytesWritten)]: 0 },
  httpVersionMajor: 1,
  httpVersionMinor: 1,
  httpVersion: '1.1',
  complete: false,
  headers:
   { cookie:
      'AWSALB=6iRpICGdNsXshkOmkGMJwIwzswh/t4Rez45EHvhccH5Zm2zsNNR+6JJ/Lw4XeQq5eJiy5UZXKhomTIIjFCASpIj/8eUxzhE2iLQNfHPs1ESxEzNQL1O7Mjzdi8AO; previewc9vfs_9c5EpavoWDp1z7ZZ=9cFMIIPWuDBS6EdSOqCdUFRIbKJEclWB',
     'cache-control': 'max-age=0',
     'if-none-match': 'W/"16-uWKsSQfMsYIHFEu43T+yvLZhxuA"',
     'upgrade-insecure-requests': '1',
     'accept-encoding': 'gzip, deflate, br',
     'accept-language': 'en-US,en;q=0.5',
     accept:
      'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
     'user-agent':
      'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0',
     'x-amzn-trace-id': 'Root=1-5dbc2750-22d125405ae98e1037c23b3c',
     host:
      '80c86b66f56a44e5bf48d418c81eaeb6.vfs.cloud9.us-east-2.amazonaws.com',
     'x-forwarded-port': '443',
     'x-forwarded-proto': 'https',
     'x-forwarded-for': '189.6.27.151',
     connection: 'close' },
  rawHeaders:
   [ 'cookie',
     'AWSALB=6iRpICGdNsXshkOmkGMJwIwzswh/t4Rez45EHvhccH5Zm2zsNNR+6JJ/Lw4XeQq5eJiy5UZXKhomTIIjFCASpIj/8eUxzhE2iLQNfHPs1ESxEzNQL1O7Mjzdi8AO; previewc9vfs_9c5EpavoWDp1z7ZZ=9cFMIIPWuDBS6EdSOqCdUFRIbKJEclWB',
     'cache-control',
     'max-age=0',
     'if-none-match',
     'W/"16-uWKsSQfMsYIHFEu43T+yvLZhxuA"',
     'upgrade-insecure-requests',
     '1',
     'accept-encoding',
     'gzip, deflate, br',
     'accept-language',
     'en-US,en;q=0.5',
     'accept',
     'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
     'user-agent',
     'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0',
     'x-amzn-trace-id',
     'Root=1-5dbc2750-22d125405ae98e1037c23b3c',
     'host',
     '80c86b66f56a44e5bf48d418c81eaeb6.vfs.cloud9.us-east-2.amazonaws.com',
     'x-forwarded-port',
     '443',
     'x-forwarded-proto',
     'https',
     'x-forwarded-for',
     '189.6.27.151',
     'connection',
     'close' ],
  trailers: {},
  rawTrailers: [],
  aborted: false,
  upgrade: false,
  url: '/r/anything',
  method: 'GET',
  statusCode: null,
  statusMessage: null,
  client:
   Socket {
     connecting: false,
     _hadError: false,
     _handle:
      TCP {
        reading: true,
        onread: [Function: onStreamRead],
        onconnection: null,
        _consumed: true,
        [Symbol(owner)]: [Circular] },
     _parent: null,
     _host: null,
     _readableState:
      ReadableState {
        objectMode: false,
        highWaterMark: 16384,
        buffer: BufferList { head: null, tail: null, length: 0 },
        length: 0,
        pipes: null,
        pipesCount: 0,
        flowing: true,
        ended: false,
        endEmitted: false,
        reading: true,
        sync: false,
        needReadable: true,
        emittedReadable: false,
        readableListening: false,
        resumeScheduled: false,
        paused: false,
        emitClose: false,
        autoDestroy: false,
        destroyed: false,
        defaultEncoding: 'utf8',
        awaitDrain: 0,
        readingMore: false,
        decoder: null,
        encoding: null },
     readable: true,
     _events:
      [Object: null prototype] {
        end: [Array],
        drain: [Array],
        timeout: [Function: socketOnTimeout],
        data: [Function: bound socketOnData],
        error: [Function: socketOnError],
        close: [Array],
        resume: [Function: onSocketResume],
        pause: [Function: onSocketPause] },
     _eventsCount: 8,
     _maxListeners: undefined,
     _writableState:
      WritableState {
        objectMode: false,
        highWaterMark: 16384,
        finalCalled: false,
        needDrain: false,
        ending: false,
        ended: false,
        finished: false,
        destroyed: false,
        decodeStrings: false,
        defaultEncoding: 'utf8',
        length: 0,
        writing: false,
        corked: 0,
        sync: false,
        bufferProcessing: false,
        onwrite: [Function: bound onwrite],
        writecb: null,
        writelen: 0,
        bufferedRequest: null,
        lastBufferedRequest: null,
        pendingcb: 1,
        prefinished: false,
        errorEmitted: false,
        emitClose: false,
        autoDestroy: false,
        bufferedRequestCount: 0,
        corkedRequestsFree: [Object] },
     writable: true,
     allowHalfOpen: true,
     _sockname: null,
     _pendingData: null,
     _pendingEncoding: '',
     server:
      Server {
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        _connections: 1,
        _handle: [TCP],
        _usingWorkers: false,
        _workers: [],
        _unref: false,
        allowHalfOpen: true,
        pauseOnConnect: false,
        httpAllowHalfOpen: false,
        timeout: 120000,
        keepAliveTimeout: 5000,
        maxHeadersCount: null,
        headersTimeout: 40000,
        _connectionKey: '4:127.0.0.1:8080',
        [Symbol(IncomingMessage)]: [Function],
        [Symbol(ServerResponse)]: [Function],
        [Symbol(asyncId)]: 8 },
     _server:
      Server {
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        _connections: 1,
        _handle: [TCP],
        _usingWorkers: false,
        _workers: [],
        _unref: false,
        allowHalfOpen: true,
        pauseOnConnect: false,
        httpAllowHalfOpen: false,
        timeout: 120000,
        keepAliveTimeout: 5000,
        maxHeadersCount: null,
        headersTimeout: 40000,
        _connectionKey: '4:127.0.0.1:8080',
        [Symbol(IncomingMessage)]: [Function],
        [Symbol(ServerResponse)]: [Function],
        [Symbol(asyncId)]: 8 },
     timeout: 120000,
     parser:
      HTTPParser {
        '0': [Function: parserOnHeaders],
        '1': [Function: parserOnHeadersComplete],
        '2': [Function: parserOnBody],
        '3': [Function: parserOnMessageComplete],
        '4': [Function: bound onParserExecute],
        _headers: [],
        _url: '',
        socket: [Circular],
        incoming: [Circular],
        outgoing: null,
        maxHeaderPairs: 2000,
        _consumed: true,
        onIncoming: [Function: bound parserOnIncoming],
        parsingHeadersStart: 0,
        [Symbol(isReused)]: false },
     on: [Function: socketOnWrap],
     _paused: false,
     _httpMessage:
      ServerResponse {
        _events: [Object],
        _eventsCount: 1,
        _maxListeners: undefined,
        output: [],
        outputEncodings: [],
        outputCallbacks: [],
        outputSize: 0,
        writable: true,
        _last: true,
        chunkedEncoding: false,
        shouldKeepAlive: false,
        useChunkedEncodingByDefault: true,
        sendDate: true,
        _removedConnection: false,
        _removedContLen: true,
        _removedTE: true,
        _contentLength: 0,
        _hasBody: false,
        _trailer: '',
        finished: true,
        _headerSent: true,
        socket: [Circular],
        connection: [Circular],
        _header:
         'HTTP/1.1 304 Not Modified\r\nX-Powered-By: Express\r\nETag: W/"16-uWKsSQfMsYIHFEu43T+yvLZhxuA"\r\nDate: Fri, 01 Nov 2019 12:38:40 GMT\r\nConnection: close\r\n\r\n',
        _onPendingData: [Function: bound updateOutgoingData],
        _sent100: false,
        _expect_continue: false,
        req: [Circular],
        locals: [Object: null prototype] {},
        statusCode: 304,
        statusMessage: 'Not Modified',
        [Symbol(isCorked)]: false,
        [Symbol(outHeadersKey)]: [Object] },
     [Symbol(asyncId)]: 11,
     [Symbol(lastWriteQueueSize)]: 0,
     [Symbol(timeout)]:
      Timeout {
        _called: false,
        _idleTimeout: 120000,
        _idlePrev: [TimersList],
        _idleNext: [TimersList],
        _idleStart: 3778,
        _onTimeout: [Function: bound ],
        _timerArgs: undefined,
        _repeat: null,
        _destroyed: false,
        [Symbol(unrefed)]: true,
        [Symbol(asyncId)]: 12,
        [Symbol(triggerId)]: 11 },
     [Symbol(kBytesRead)]: 0,
     [Symbol(kBytesWritten)]: 0 },
  _consuming: false,
  _dumped: false,
  next: [Function: next],
  baseUrl: '',
  originalUrl: '/r/anything',
  _parsedUrl:
   Url {
     protocol: null,
     slashes: null,
     auth: null,
     host: null,
     port: null,
     hostname: null,
     hash: null,
     search: null,
     query: null,
     pathname: '/r/anything',
     path: '/r/anything',
     href: '/r/anything',
     _raw: '/r/anything' },
  params: { subreddit: 'anything' },
  query: {},
  res:
   ServerResponse {
     _events:
      [Object: null prototype] { finish: [Function: bound resOnFinish] },
     _eventsCount: 1,
     _maxListeners: undefined,
     output: [],
     outputEncodings: [],
     outputCallbacks: [],
     outputSize: 0,
     writable: true,
     _last: true,
     chunkedEncoding: false,
     shouldKeepAlive: false,
     useChunkedEncodingByDefault: true,
     sendDate: true,
     _removedConnection: false,
     _removedContLen: true,
     _removedTE: true,
     _contentLength: 0,
     _hasBody: false,
     _trailer: '',
     finished: true,
     _headerSent: true,
     socket:
      Socket {
        connecting: false,
        _hadError: false,
        _handle: [TCP],
        _parent: null,
        _host: null,
        _readableState: [ReadableState],
        readable: true,
        _events: [Object],
        _eventsCount: 8,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: true,
        allowHalfOpen: true,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: [Server],
        _server: [Server],
        timeout: 120000,
        parser: [HTTPParser],
        on: [Function: socketOnWrap],
        _paused: false,
        _httpMessage: [Circular],
        [Symbol(asyncId)]: 11,
        [Symbol(lastWriteQueueSize)]: 0,
        [Symbol(timeout)]:
         Timeout {
           _called: false,
           _idleTimeout: 120000,
           _idlePrev: [TimersList],
           _idleNext: [TimersList],
           _idleStart: 3778,
           _onTimeout: [Function: bound ],
           _timerArgs: undefined,
           _repeat: null,
           _destroyed: false,
           [Symbol(unrefed)]: true,
           [Symbol(asyncId)]: 12,
           [Symbol(triggerId)]: 11 },
        [Symbol(kBytesRead)]: 0,
        [Symbol(kBytesWritten)]: 0 },
     connection:
      Socket {
        connecting: false,
        _hadError: false,
        _handle: [TCP],
        _parent: null,
        _host: null,
        _readableState: [ReadableState],
        readable: true,
        _events: [Object],
        _eventsCount: 8,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: true,
        allowHalfOpen: true,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: [Server],
        _server: [Server],
        timeout: 120000,
        parser: [HTTPParser],
        on: [Function: socketOnWrap],
        _paused: false,
        _httpMessage: [Circular],
        [Symbol(asyncId)]: 11,
        [Symbol(lastWriteQueueSize)]: 0,
        [Symbol(timeout)]:
         Timeout {
           _called: false,
           _idleTimeout: 120000,
           _idlePrev: [TimersList],
           _idleNext: [TimersList],
           _idleStart: 3778,
           _onTimeout: [Function: bound ],
           _timerArgs: undefined,
           _repeat: null,
           _destroyed: false,
           [Symbol(unrefed)]: true,
           [Symbol(asyncId)]: 12,
           [Symbol(triggerId)]: 11 },
        [Symbol(kBytesRead)]: 0,
        [Symbol(kBytesWritten)]: 0 },
     _header:
      'HTTP/1.1 304 Not Modified\r\nX-Powered-By: Express\r\nETag: W/"16-uWKsSQfMsYIHFEu43T+yvLZhxuA"\r\nDate: Fri, 01 Nov 2019 12:38:40 GMT\r\nConnection: close\r\n\r\n',
     _onPendingData: [Function: bound updateOutgoingData],
     _sent100: false,
     _expect_continue: false,
     req: [Circular],
     locals: [Object: null prototype] {},
     statusCode: 304,
     statusMessage: 'Not Modified',
     [Symbol(isCorked)]: false,
     [Symbol(outHeadersKey)]:
      [Object: null prototype] { 'x-powered-by': [Array], etag: [Array] } },
  route:
   Route {
     path: '/r/:subreddit',
     stack: [ [Layer] ],
     methods: { get: true } } }

That’s a lot of incoming information that you receive every time someone sends a request to your server. The key piece that we are looking for here is:

params: { subreddit: 'anything' },

Where ‘anything’ is the name of the subreddit we requested in the browsers. If we just wanted to return the name of the requested subreddit in the console, we can further refine the request like so

Returning req.params

// log req.params
app.get("/r/:subreddit", function(req, res){
    res.send("Welcome to a subreddit");
    console.log(req.params);
});

If I then go to the browser and request the following three subreddits in a row /r/dogs, /r/cats, /r/capybaras I get the following in my console:

Likewise if add those console.log to my longer Comments section parameter string:

// route parameter :sample 
app.get("/r/:subredditName/comments/:id/:title", function(req, res){
    res.send("Welcome to the comments");
    console.log(req.params);
});

and then go to the following URL: /r/capybaras/comments/12345/aCommentTitle

I get the following in my console:

Setting req.params to Variables

This is where we start showing content dynamically based on the URL.

If we take our route, and within it set our URL parameters to a variable, we can res.send information back based on that variable. For example:

// route parameter :sample 
app.get("/r/:subreddit", function(req, res){
    var subreddit = req.params.subreddit;
    res.send("Welcome to the " + subreddit + " subreddit");
    console.log(req.params);

Example App

This example app has two functions. The first is to return a sound of an animal based on the animal that is requested in the URL. The second is to print a given word X number of times, based on the word and the number input you give the URL.

// ***************************
// SETUP
// ***************************

console.log("app.js is connected");

// import express module
var express = require("express");
// set express to variable
var app = express();

// set listen port
app.listen(process.env.PORT, process.env.IP, function(){
    console.log("Listening on PORT: " + process.env.PORT + " at IP: " + process.env.IP);
});

// ***************************
// ROUTES
// ***************************
app.get("/", function(req, res){
    res.send("Welcome to Assignment 1");
});

// /speak/:animal    pig cow dog
app.get("/speak/:animal", function(req, res){
    // set animal to lowercase to sanitize input for matching to object sounds
    var animal = req.params.animal.toLowerCase();
    var sounds = {
        pig: "Oink",
        cow: "Moo",
        dog: "Woof",
    }
    
    res.send("The " + animal + " says " + sounds[animal])
});

// print :word x :times 
app.get("/repeat/:word/:times", function(req, res){
    
    // capturing word
    var word = req.params.word;
    // capturing times and converting times to number from string input
    var times = Number(req.params.times);
    // placeholder variable for final string to be sent
    var result = "";
    
    console.log("The Word is " + word);
    console.log("The Number is " + times);
    
    // building the string that will be sent
    for(var i=1;i<=times;i++){
        result += " " + word;
    }

    
    // res.send can only be used 1 time, so it cannot be put inside the loop
    res.send(result);
});

// wildcard
app.get("*", function(req, res){
    res.send("404 Page Not Found")
});

Express.js Basics

Express.js + EJS: Rendering Templates with Dynamic Content