// index.js
const express = require('express')
const rateLimit = require('express-rate-limit')
require('dotenv').config()
const PORT = process.env.PORT || 5000
const app = express()
// // Rate limiting
const limiter = rateLimit({
windowMs: 10 * 60 * 1000, // 10 Mins
max: 100,
})
app.use(limiter)
app.set('trust proxy', 1)
// // Routes
app.use('/api', require('./routes'))
app.listen(PORT, () => console.log(`Server running on port ${PORT}`))
// ./router/index.js
const url = require('url')
const express = require('express')
const router = express.Router()
const needle = require('needle')
const apicache = require('apicache')
const API_BASE_URL = process.env.API_BASE_URL
const API_KEY_NAME = process.env.API_KEY_NAME
const API_KEY_VALUE = process.env.API_KEY_VALUE
let cache = apicache.middleware
router.get('/', cache('1 minutes'), async(req, res) => {
try{
const params = new URLSearchParams({
[API_KEY_NAME]:API_KEY_VALUE,
...url.parse(req.url, true).query
})
const apiRes = await needle('get', `${API_BASE_URL}?${params}`)
const data = apiRes.body
if(process.env.NODE_ENV !== 'production') {
console.log(`요청: ${API_BASE_URL}?${params}`)
}
res.status(200).json(data);
} catch(err) {
res.status(500).json({err})
}
})
module.exports = router
apicahe라이브러리 사용
apicache 미들웨어로 1분 설정 시, 같은 요청에 대해 클라이언트는 max-age가 지나기 전까지는 캐시 사용
[tips] 동적으로 params를 조정해야 한다면, URLSearchParams를 사용해 보자.
(1) Redis 기초(참고)
[기초]
SET 'key' 'value'
GET 'key'
DEL 'key'
keys * ~ 모든 키 조회
flushall ~ 모든 키 삭제
setex 'key' 10 'value' - 10초 후 해당 키 삭제됨
ttl 'key' - expire 남은 시간 조회
[리스트]
lplush 'key' 'value' (좌측 삽입)
rplush 'key' 'value' (우측 삽입)
lrange 'key' 0 -1 (배열 조회)
lpop 'key' (좌측 삭제)
rpop 'key' (우측 삭제)
[Set]
SADD 'key' 'value' (set 삽입)
SREM 'key' 'value' (set 삭제)
SMEMBERS 'key' (set 조회)
[Hash]
HSET person name 'value' (삽입)
HSET person age 'value' (삽입)
HGETALL person (조회)
HDEL person age (age 삭제)
(2) Redis 캐싱 적용
const express = require('express')
const axios = require('axios')
const Redis = require('redis')
const redisClient = Redis.createClient()
const DEFAULT_EXPIRATION = 5
const PORT = process.env.PORT || 5000
const app = express()
app.use(express.urlencoded({extended: true}))
app.get('/photos', async (req, res) => {
const albumId = req.query.albumId
const photos = await getOrSetCache(`photos?albumId=${albumId}`, async () => {
const {data} = await axios.get(
'https://jsonplaceholder.typicode.com/photos',
{params: {albumId}}
)
return data;
})
res.json(photos);
// redisClient.get(`photos?albumId=${albumId}`, async (err, photos) => {
// if(err) console.log(err)
// if(photos !== null) {
// return res.json(JSON.parse(photos))
// } else {
// const {data} = await axios.get(
// 'https://jsonplaceholder.typicode.com/photos',
// {params: {albumId}}
// )
// redisClient.setex(`photos?albumId=${albumId}`, DEFAULT_EXPIRATION, JSON.stringify(data))
// res.json(data)
// }
// })
})
function getOrSetCache(key, cb) {
return new Promise((resolve, reject) => {
redisClient.get(key, async (err, data) => {
if(err) return reject(err)
if(data !== null) return resolve(JSON.parse(data))
const freshData = await cb()
redisClient.setex(key, DEFAULT_EXPIRATION, JSON.stringify(freshData))
resolve(freshData)
})
})
}
app.listen(PORT, () => console.log(`Server running on port ${PORT}`))
참고 - Build an API Proxy Server - Hide Your API Keys, Rate Limiting & Caching