forked from thericfang/express-js-starter-app
-
Notifications
You must be signed in to change notification settings - Fork 43
/
Copy pathapp.js
193 lines (172 loc) · 6.87 KB
/
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
// import and instantiate express
const express = require('express') // CommonJS import style!
const app = express() // instantiate an Express object
const path = require('path')
// import some useful middleware
const multer = require('multer') // middleware to handle HTTP POST requests with file uploads
const axios = require('axios') // middleware for making requests to APIs
require('dotenv').config({ silent: true }) // load environmental variables from a hidden file named .env
const morgan = require('morgan') // middleware for nice logging of incoming HTTP requests
/**
* Typically, all middlewares would be included before routes
* In this file, however, most middlewares are after most routes
* This is to match the order of the accompanying slides
*/
// use the morgan middleware to log all incoming http requests
app.use(morgan('dev')) // morgan has a few logging default styles - dev is a nice concise color-coded style
// use express's builtin body-parser middleware to parse any data included in a request
app.use(express.json()) // decode JSON-formatted incoming POST data
app.use(express.urlencoded({ extended: true })) // decode url-encoded incoming POST data
// make 'public' directory publicly readable with static content
app.use('/static', express.static('public'))
// route for HTTP GET requests to the root document
app.get('/', (req, res) => {
res.send('Goodbye world!')
})
// route for HTTP GET requests to /html-example
app.get('/html-example', (req, res) => {
res.sendFile('/public/some-page.html', { root: __dirname })
})
// route for HTTP GET requests to /json-example
app.get('/json-example', (req, res) => {
// assemble an object with the data we want to send
const body = {
title: 'Hello!',
heading: 'Hello!',
message: 'Welcome to this JSON document, served up by Express',
imagePath: '/static/images/donkey.jpg',
}
// send the response as JSON to the client
res.json(body)
})
// custom middleware - first
app.use('/middleware-example', (req, res, next) => {
// make a modification to either the req or res objects
res.addedStuff = 'First middleware function run!'
// run the next middleware function, if any
next()
})
// custom middleware - second
app.use('/middleware-example', (req, res, next) => {
// make a modification to either the req or res objects
res.addedStuff += ' Second middleware function run!'
// run the next middleware function, if any
next()
})
// route for HTTP GET requests to /middleware-example
app.get('/middleware-example', (req, res) => {
// grab data passed by the middleware, if available
const message = res.addedStuff
? res.addedStuff
: 'Sorry, the middleware did not work!'
// use the data added by the middleware in some way
res.send(message)
})
// receive POST data from the client
app.post('/post-example', (req, res) => {
// now do something amazing with the data we received from the client
const data = {
status: 'amazing success!',
message: 'congratulations on sending us this data!',
your_data: {
name: req.body.your_name,
email: req.body.your_email,
agree: req.body.agree,
},
}
// ... then send a response of some kind to client
res.json(data)
})
// enable file uploads saved to disk in a directory named 'public/uploads'
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/uploads')
},
filename: function (req, file, cb) {
// take apart the uploaded file's name so we can create a new one based on it
const extension = path.extname(file.originalname)
const basenameWithoutExtension = path.basename(file.originalname, extension)
// create a new filename with a timestamp in the middle
const newName = `${basenameWithoutExtension}-${Date.now()}${Math.random()}${extension}`
// tell multer to use this new filename for the uploaded file
cb(null, newName)
},
})
const upload = multer({ storage })
// route for HTTP POST requests for /upload-example
app.post('/upload-example', upload.array('my_files', 3), (req, res, next) => {
// check whether anything was uploaded
if (!req.files || req.files.length == 0) {
// failure!
const error = new Error('Please upload some files!')
error.httpStatusCode = 400
res.json({
status: 'you fail!!!',
message: 'rejected your files... try harder',
})
// return next(error)
} else if (req.files.length > 3) {
res.json({
status: 'you fail!!!',
message: 'rejected your files... try harder',
})
} else {
// success
// send a message back to the client, for example, a simple JSON object
const data = {
status: 'all good',
message: 'files were uploaded!!!',
files: req.files,
}
res.json(data)
}
})
// proxy requests to/from an API
app.get('/proxy-example', (req, res, next) => {
// use axios to make a request to an API for animal data
axios
.get('https://my.api.mockaroo.com/animals.json?key=d9ddfc40&num=10')
.then(apiResponse => res.json(apiResponse.data)) // pass data along directly to client
.catch(err => next(err)) // pass any errors to express
})
// same route as above, but using environmental variables for secret credentials
app.get('/dotenv-example', async (req, res, next) => {
try {
// insert the environmental variable into the URL we're requesting
const response = await axios.get(
`${process.env.API_BASE_URL}?key=${process.env.API_SECRET_KEY}&num=10`
)
res.json(response.data) // pass data along directly to client
} catch (err) {
res.json({
success: false,
error: `Oops... In order to use the dotenv module, you must first make a file named .env on your server - see the .env.example file for example.`,
})
}
})
// a route with parameter ... animalId is a parameter
// the code here is similar to the dotenv-example route above... but...
// using async/await in this route to show another way of dealing with asynchronous requests to an external API or database
app.get('/parameter-example/:animalId', async (req, res) => {
// use axios to make a request to an API to fetch a single animal's data
// we use a Mock API here, but imagine we passed the animalId to a real API and received back data about that animal
try {
const apiResponse = await axios.get(
`${process.env.API_BASE_URL}?key=${process.env.API_SECRET_KEY}&num=1&id=${req.params.animalId}`
)
// express places parameters into the req.params object
const responseData = {
status: 'wonderful',
message: `Imagine we got the data from the API for animal #${req.params.animalId}`,
animalId: req.params.animalId,
animal: apiResponse.data,
}
// send the data in the response
res.json(responseData)
} catch (err) {
// send an error JSON object back to the browser
res.json(err)
}
})
// export the express app we created to make it available to other modules
module.exports = app // CommonJS export style!