You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

78 lines
1.9 KiB

const redis = require('redis');
const validUrl = require('valid-url');
const express = require('express');
const app = express();
app.use(express.json());
const port = 3000;
//redis client
const redisCli = redis.createClient({
host: 'redis',
port: 6379
})
redisCli.on("error", console.error);
//validation
const outpath = ['sym', '', 'manifest.json', 'admin', 'stats', 'api', 'swagger'];
const validateKey = key => !outpath.find(path=>path===key);
//random key
const getKey = length => {
let forbidden = false;
let key = '';
let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
do{
for (let i = 0; i < length; i++ )
key += characters.charAt(Math.floor(Math.random() * characters.length));
forbidden = !validateKey(key);
redisCli.hget('surl;'+key, 'url', (err, obj) => {
if(err) console.error(err);
if(obj) forbidden = true;
});
} while (forbidden);
return key;
}
const keyLength = 4;
//validate url
const validateUrl = url => validUrl.isUri(url);
//express server
app.put('/api/v1/key', async (req, res) => {
if (req.body.url === undefined){
res.status(400);
res.send({status: 400, message: 'url is undefined'});
return
}
if (!validateUrl(req.body.url)){
res.status(400);
res.send({status: 400, message: 'url is invalid'});
return
}
try{
let key = getKey(keyLength);
await redisCli.HMSET('surl;'+key, 'url', req.body.url, 'time', Date.now());
res.status(201);
res.send({status: 201, url: req.body.url, key});
}catch (e){
console.error(e);
res.status(500);
res.send({status: 500, message: 'server error'});
}
});
app.get('/:key', (req, res) => {
redisCli.HGET('surl;'+req.params.key, 'url', (err, obj) => {
if(obj){
res.redirect(302, obj);
}else{
res.status(404);
res.send({status: 404, message: 'this short url does not exist'});
}
});
});
app.listen(port);