Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes 01-02 – Express middlewares and request handlers #2

Open
wants to merge 14 commits into
base: 01-setup
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/02-express-middlewares-and-request-handlers.md
@@ -0,0 +1,6 @@
## 2 – Express Middlewares and Request Handlers

Now the server application gets its first REST API endpoint implemented. So start the server using `npm start` and visit:

1. `http://localhost:8000/api/cat/1` – It responds with a 404
2. `http://localhost:8000/api/cat/123` – It responds with a 200 and very little information about a cat
66 changes: 66 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion package.json
Expand Up @@ -13,10 +13,15 @@
"prettier:write": "prettier --write service/**/*.{ts,tsx,js,jsx}"
},
"dependencies": {
"express": "^4.16.2"
"express": "^4.16.2",
"compression": "1.7.2",
"cookie-parser": "1.4.3",
"http-status-codes": "1.3.0"
},
"devDependencies": {
"@types/express": "4.11.1",
"@types/compression": "0.0.35",
"@types/cookie-parser": "1.4.1",
"typescript": "3.1.1",
"ts-node": "6.1.1",
"prettier": "^1.9.2"
Expand Down
3 changes: 2 additions & 1 deletion service/Application.ts
@@ -1,12 +1,13 @@
import { ExpressServer } from './ExpressServer'
import { CatEndpoints } from './cats/CatEndpoints'

/**
* Wrapper around the Node process, ExpressServer abstraction and complex dependencies such as services that ExpressServer needs.
* When not using Dependency Injection, can be used as place for wiring together services which are dependencies of ExpressServer.
*/
export class Application {
public static async createApplication() {
const expressServer = new ExpressServer()
const expressServer = new ExpressServer(new CatEndpoints())
await expressServer.setup(8000)
Application.handleExit(expressServer)

Expand Down
22 changes: 22 additions & 0 deletions service/ExpressServer.ts
@@ -1,6 +1,12 @@
import * as express from 'express'
import { Express } from 'express'
import { Server } from 'http'
import * as compress from 'compression'
import * as bodyParser from 'body-parser'
import * as cookieParser from 'cookie-parser'

import { noCache } from './NoCacheMiddleware'
import { CatEndpoints } from './cats/CatEndpoints'

/**
* Abstraction around the raw Express.js server and Nodes' HTTP server.
Expand All @@ -11,8 +17,14 @@ export class ExpressServer {
private server?: Express
private httpServer?: Server

constructor(private catEndpoints: CatEndpoints) {
}

public async setup(port: number) {
const server = express()
this.setupStandardMiddlewares(server)
this.configureApiEndpoints(server)

this.httpServer = this.listen(server, port)
this.server = server
return this.server
Expand All @@ -25,4 +37,14 @@ export class ExpressServer {
public kill() {
if (this.httpServer) this.httpServer.close()
}

private setupStandardMiddlewares(server: Express) {
server.use(bodyParser.json())
server.use(cookieParser())
server.use(compress())
}

private configureApiEndpoints(server: Express) {
server.get('/api/cat/:catId', noCache, this.catEndpoints.getCatDetails)
}
}
8 changes: 8 additions & 0 deletions service/NoCacheMiddleware.ts
@@ -0,0 +1,8 @@
import { Request, Response, NextFunction } from 'express'

export function noCache(_: Request, res: Response, next: NextFunction) {
res.setHeader('Expires', '0')
res.setHeader('Pragma', 'no-cache')
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate')
next()
}
21 changes: 21 additions & 0 deletions service/cats/CatEndpoints.ts
@@ -0,0 +1,21 @@
import { NextFunction, Request, Response } from 'express'
import * as HttpStatus from 'http-status-codes'

export class CatEndpoints {
public getCatDetails = async (req: Request, res: Response, next: NextFunction) => {
try {
// usually we will contact some service here and do some logic
const catId = req.params.catId

if (catId >= 90) {
res.json({ catId, name: 'Some lovely Kitty' })
} else {
res.sendStatus(HttpStatus.NOT_FOUND)
}
} catch (err) {
// something could fail unexpectedly...
// at some point the middleware chain should handle errors
next(err)
}
}
}