Skip to content

Commit aef373e

Browse files
authored
Merge pull request #64 from PokeAPI/validation
Validate user input
2 parents ed36c77 + 2874070 commit aef373e

File tree

3 files changed

+51
-33
lines changed

3 files changed

+51
-33
lines changed

.vscode/launch.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
"type": "node",
66
"request": "attach",
77
"name": "deploy function debugger",
8-
"port": 9229
8+
"port": 9229,
9+
"skipFiles": ["<node_internals>/**"]
910
}
1011
]
1112
}

functions_v1/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "functions",
33
"scripts": {
4-
"emulator": "firebase emulators:start --project pokeapi-215911",
4+
"emulator": "firebase emulators:start --project pokeapi-215911 --inspect-functions",
55
"serve": "firebase serve",
66
"shell": "firebase functions:shell",
77
"start": "npm run shell",

functions_v1/src/index.js

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ const express = require("express")
55
const functions = require("firebase-functions/v1")
66

77
const config = functions.config()
8+
const endpoints = ["ability","berry","berry-firmness","berry-flavor","characteristic","contest-effect","contest-type","egg-group","encounter-condition","encounter-condition-value","encounter-method","evolution-chain","evolution-trigger","gender","generation","growth-rate","item","item-attribute","item-category","item-fling-effect","item-pocket","language","location","location-area","machine","move","move-ailment","move-battle-style","move-category","move-damage-class","move-learn-method","move-target","nature","pal-park-area","pokeathlon-stat","pokedex","pokemon","pokemon-color","pokemon-form","pokemon-habitat","pokemon-shape","pokemon-species","region","stat","super-contest-effect","type","version","version-group"]
9+
const resources_r=/^[\w\d-_]+$/
810
let BASE_URL = "https://pokeapi.co"
911

1012
if (process.env.FIREBASE_DEBUG_MODE) {
@@ -90,15 +92,32 @@ function handleErrors(reason, req, res) {
9092
}
9193
}
9294

95+
function fetchAndReply(req, res, paginated=false) {
96+
const params = paramsOrDefault(req.query)
97+
got(targetUrlForPath(req.path), gotConfig)
98+
.json()
99+
.then(json => {
100+
res.set('Cache-Control', `public, max-age=${successTtl}, s-maxage=${successTtl}`)
101+
if (! paginated) {
102+
res.send(json)
103+
} else {
104+
res.send(
105+
Object.assign(json, {
106+
next: getPageUrl(req.path, getNextPage(params, json.count)),
107+
previous: getPageUrl(req.path, getPreviousPage(params)),
108+
results: json.results.slice(params.offset, params.offset + params.limit)
109+
})
110+
)
111+
}
112+
})
113+
.catch(reason => {
114+
handleErrors(reason, req, res)
115+
})
116+
}
93117

94118
const api = express()
95-
96-
api.use(compression())
97-
api.use(cors())
98-
99119
const successTtl = 86400 // 1 day
100120
const failTtl = 432000 // 5 days
101-
102121
const gotConfig = {
103122
timeout: 8000,
104123
retry: {
@@ -114,39 +133,37 @@ const gotConfig = {
114133
}
115134
}
116135

136+
api.use(compression())
137+
api.use(cors())
138+
139+
api.get([
140+
"/api/v2/"
141+
], (req, res) => {
142+
fetchAndReply(req, res)
143+
})
144+
117145
api.get([
118-
"/api/v2/",
119146
"/api/v2/:endpoint/:id/",
120147
"/api/v2/:endpoint/:id/:extra/"
121148
], (req, res) => {
122-
got(targetUrlForPath(req.path), gotConfig)
123-
.json()
124-
.then(json => {
125-
res.set('Cache-Control', `public, max-age=${successTtl}, s-maxage=${successTtl}`)
126-
res.send(json)
127-
})
128-
.catch(reason => {
129-
handleErrors(reason, req, res)
130-
})
149+
if (req.params.extra === undefined || req.params.extra === 'encounters') {
150+
if (endpoints.includes(req.params.endpoint) && req.params.id.match(resources_r)) {
151+
fetchAndReply(req, res)
152+
} else {
153+
res.sendStatus(400)
154+
}
155+
} else {
156+
res.sendStatus(400)
157+
}
131158
})
132159

133160
api.get("/api/v2/:endpoint/", (req, res) => {
134-
got(targetUrlForPath(req.path), gotConfig)
135-
.json()
136-
.then(json => {
137-
const params = paramsOrDefault(req.query)
138-
res.set('Cache-Control', `public, max-age=${successTtl}, s-maxage=${successTtl}`)
139-
res.send(
140-
Object.assign(json, {
141-
next: getPageUrl(req.path, getNextPage(params, json.count)),
142-
previous: getPageUrl(req.path, getPreviousPage(params)),
143-
results: json.results.slice(params.offset, params.offset + params.limit)
144-
})
145-
)
146-
})
147-
.catch(reason => {
148-
handleErrors(reason, req, res)
149-
})
161+
if (endpoints.includes(req.params.endpoint)) {
162+
fetchAndReply(req, res, true)
163+
} else {
164+
res.sendStatus(400)
165+
}
166+
150167
})
151168

152169
exports.api_v1functions = functions.runWith({

0 commit comments

Comments
 (0)