Re work
This commit is contained in:
parent
f212a85a41
commit
1209271cd4
24
.eslintrc.json
Normal file
24
.eslintrc.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"plugins": [
|
||||
"react"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"env": {
|
||||
"es6": true,
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"mocha": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:react/recommended"
|
||||
],
|
||||
"rules": {
|
||||
}
|
||||
}
|
166
.gitignore
vendored
166
.gitignore
vendored
@ -1,3 +1,147 @@
|
||||
### Archives template
|
||||
# It's better to unpack these files and commit the raw source because
|
||||
# git has its own built in compression methods.
|
||||
*.7z
|
||||
*.jar
|
||||
*.rar
|
||||
*.zip
|
||||
*.gz
|
||||
*.bzip
|
||||
*.bz2
|
||||
*.xz
|
||||
*.lzma
|
||||
*.cab
|
||||
|
||||
#packing-only formats
|
||||
*.iso
|
||||
*.tar
|
||||
|
||||
#package management formats
|
||||
*.dmg
|
||||
*.xpi
|
||||
*.gem
|
||||
*.egg
|
||||
*.deb
|
||||
*.rpm
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
### Windows template
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
### JetBrains template
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
|
||||
|
||||
*.iml
|
||||
|
||||
## Directory-based project format:
|
||||
.idea/
|
||||
# if you remove the above rule, at least ignore the following:
|
||||
|
||||
# User-specific stuff:
|
||||
# .idea/workspace.xml
|
||||
# .idea/tasks.xml
|
||||
# .idea/dictionaries
|
||||
|
||||
# Sensitive or high-churn files:
|
||||
# .idea/dataSources.ids
|
||||
# .idea/dataSources.xml
|
||||
# .idea/sqlDataSources.xml
|
||||
# .idea/dynamic.xml
|
||||
# .idea/uiDesigner.xml
|
||||
|
||||
# Gradle:
|
||||
# .idea/gradle.xml
|
||||
# .idea/libraries
|
||||
|
||||
# Mongo Explorer plugin:
|
||||
# .idea/mongoSettings.xml
|
||||
|
||||
## File-based project format:
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
## Plugin-specific files:
|
||||
|
||||
# IntelliJ
|
||||
/out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
### Xcode template
|
||||
# Xcode
|
||||
#
|
||||
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
|
||||
## Other
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
*.xcuserstate
|
||||
### OSX template
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
### Node template
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
@ -24,10 +168,24 @@ coverage
|
||||
build/Release
|
||||
|
||||
# Dependency directory
|
||||
# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
|
||||
node_modules
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
# compiled output
|
||||
/dist
|
||||
/tmp
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/bower_components
|
||||
|
||||
# misc
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage/*
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
testem.log
|
||||
/lib/newdata.json
|
||||
|
64
app.js
64
app.js
@ -1,13 +1,16 @@
|
||||
var express = require('express');
|
||||
var app = express();
|
||||
var path = require('path');
|
||||
var bodyParser = require('body-parser');
|
||||
var mongoose = require('mongoose');
|
||||
var config = require('./config');
|
||||
var base58 = require('./base58.js');
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
const path = require('path');
|
||||
const bodyParser = require('body-parser');
|
||||
const mongoose = require('mongoose');
|
||||
const config = require('./config');
|
||||
const base58 = require('./base58.js');
|
||||
const log4js = require('log4js');
|
||||
const logger = log4js.getLogger();
|
||||
logger.level = 'debug';
|
||||
|
||||
// grab the url model
|
||||
var Url = require('./models/url');
|
||||
const Url = require('./models/url');
|
||||
|
||||
mongoose.connect('mongodb://' + config.db.host + '/' + config.db.name);
|
||||
|
||||
@ -16,16 +19,30 @@ app.use(bodyParser.urlencoded({ extended: true }));
|
||||
|
||||
app.use(express.static(path.join(__dirname, 'public')));
|
||||
|
||||
app.all('/*', function(req, res, next) {
|
||||
// CORS headers
|
||||
res.header("Access-Control-Allow-Origin", "*"); // restrict it to the required domain
|
||||
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
|
||||
// Set custom headers for CORS
|
||||
res.header('Access-Control-Allow-Headers', 'Content-type,Accept,X-Access-Token,X-Key');
|
||||
if (req.method == 'OPTIONS') {
|
||||
res.status(200).end();
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.sendFile(path.join(__dirname, 'views/index.html'));
|
||||
});
|
||||
|
||||
app.post('/api/shorten', function(req, res){
|
||||
var longUrl = req.body.url;
|
||||
var shortUrl = '';
|
||||
app.post('/api/v1/shorten', function(req, res){
|
||||
const longUrl = req.body.url;
|
||||
let shortUrl = '';
|
||||
|
||||
// check if url already exists in database
|
||||
// check if url already exists in database
|
||||
Url.findOne({long_url: longUrl}, function (err, doc){
|
||||
|
||||
if (doc){
|
||||
shortUrl = config.webhost + base58.encode(doc._id);
|
||||
|
||||
@ -33,14 +50,14 @@ app.post('/api/shorten', function(req, res){
|
||||
res.send({'shortUrl': shortUrl});
|
||||
} else {
|
||||
// since it doesn't exist, let's go ahead and create it:
|
||||
var newUrl = Url({
|
||||
long_url: longUrl
|
||||
});
|
||||
const newUrl = Url({
|
||||
long_url: longUrl
|
||||
});
|
||||
|
||||
// save the new link
|
||||
// save the new link
|
||||
newUrl.save(function(err) {
|
||||
if (err){
|
||||
console.log(err);
|
||||
logger.error(err);
|
||||
}
|
||||
|
||||
shortUrl = config.webhost + base58.encode(newUrl._id);
|
||||
@ -55,13 +72,14 @@ app.post('/api/shorten', function(req, res){
|
||||
|
||||
app.get('/:encoded_id', function(req, res){
|
||||
|
||||
var base58Id = req.params.encoded_id;
|
||||
const base58Id = req.params.encoded_id;
|
||||
|
||||
var id = base58.decode(base58Id);
|
||||
const id = base58.decode(base58Id);
|
||||
|
||||
// check if url already exists in database
|
||||
Url.findOne({_id: id}, function (err, doc){
|
||||
// check if url already exists in database
|
||||
Url.findOneAndUpdate({_id: id}, {$inc:{visits:1}}, function (err, doc){
|
||||
if (doc) {
|
||||
logger.debug('doc', doc);
|
||||
res.redirect(doc.long_url);
|
||||
} else {
|
||||
res.redirect(config.webhost);
|
||||
@ -70,6 +88,6 @@ app.get('/:encoded_id', function(req, res){
|
||||
|
||||
});
|
||||
|
||||
var server = app.listen(3000, function(){
|
||||
console.log('Server listening on port 3000');
|
||||
const server = app.listen(3000, function () {
|
||||
logger.info('Server listening on port 3000');
|
||||
});
|
||||
|
24
base58.js
24
base58.js
@ -1,22 +1,24 @@
|
||||
var alphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
|
||||
var base = alphabet.length;
|
||||
// var alphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
|
||||
const alphabet = 'bMJZSrnxEyq8kN3UYQL5oXwV7BCFRtvpmDf1shAuHzKicTjeG29Pg4adW6';
|
||||
|
||||
const base = alphabet.length;
|
||||
|
||||
function encode(num){
|
||||
var encoded = '';
|
||||
while (num){
|
||||
var remainder = num % base;
|
||||
num = Math.floor(num / base);
|
||||
let encoded = '';
|
||||
while (num){
|
||||
const remainder = num % base;
|
||||
num = Math.floor(num / base);
|
||||
encoded = alphabet[remainder].toString() + encoded;
|
||||
}
|
||||
return encoded;
|
||||
}
|
||||
|
||||
function decode(str){
|
||||
var decoded = 0;
|
||||
while (str){
|
||||
var index = alphabet.indexOf(str[0]);
|
||||
var power = str.length - 1;
|
||||
decoded += index * (Math.pow(base, power));
|
||||
let decoded = 0;
|
||||
while (str){
|
||||
const index = alphabet.indexOf(str[0]);
|
||||
const power = str.length - 1;
|
||||
decoded += index * (Math.pow(base, power));
|
||||
str = str.substring(1);
|
||||
}
|
||||
return decoded;
|
||||
|
@ -1,4 +1,4 @@
|
||||
var config = {};
|
||||
const config = {};
|
||||
|
||||
config.db = {};
|
||||
config.webhost = 'http://localhost:3000/';
|
||||
|
@ -1,23 +1,24 @@
|
||||
var mongoose = require('mongoose');
|
||||
var Schema = mongoose.Schema;
|
||||
const mongoose = require('mongoose');
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
var CounterSchema = Schema({
|
||||
const CounterSchema = Schema({
|
||||
_id: {type: String, required: true},
|
||||
seq: { type: Number, default: 0 }
|
||||
seq: {type: Number, default: 1000}
|
||||
});
|
||||
|
||||
var counter = mongoose.model('counter', CounterSchema);
|
||||
const counter = mongoose.model('counter', CounterSchema);
|
||||
|
||||
// create a schema for our links
|
||||
var urlSchema = new Schema({
|
||||
_id: {type: Number, index: true},
|
||||
long_url: String,
|
||||
created_at: Date
|
||||
const urlSchema = new Schema({
|
||||
_id: {type: Number, index: true},
|
||||
long_url: String,
|
||||
created_at: Date,
|
||||
visits: {type: Number, default: 0}
|
||||
});
|
||||
|
||||
urlSchema.pre('save', function(next){
|
||||
var doc = this;
|
||||
counter.findByIdAndUpdate({_id: 'url_count'}, {$inc: {seq: 1} }, function(error, counter) {
|
||||
const doc = this;
|
||||
counter.findByIdAndUpdate({_id: 'url_count'}, {$inc: {seq: 1} }, function(error, counter) {
|
||||
if (error)
|
||||
return next(error);
|
||||
doc.created_at = new Date();
|
||||
@ -26,6 +27,6 @@ urlSchema.pre('save', function(next){
|
||||
});
|
||||
});
|
||||
|
||||
var Url = mongoose.model('Url', urlSchema);
|
||||
const Url = mongoose.model('Url', urlSchema);
|
||||
|
||||
module.exports = Url;
|
||||
|
7883
package-lock.json
generated
Normal file
7883
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
26
package.json
26
package.json
@ -12,5 +12,31 @@
|
||||
"body-parser": "^1.14.1",
|
||||
"express": "^4.13.3",
|
||||
"mongoose": "4.2.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^3.18.0",
|
||||
"eslint-config-defaults": "^9.0.0",
|
||||
"eslint-config-standard": "^7.1.0",
|
||||
"eslint-plugin-import": "^2.2.0",
|
||||
"eslint-plugin-node": "^4.2.2",
|
||||
"eslint-plugin-promise": "^3.5.0",
|
||||
"eslint-plugin-react": "^6.10.3",
|
||||
"eslint-plugin-standard": "^2.1.1",
|
||||
"eslint-watch": "^3.0.1",
|
||||
"gulp-autoprefixer": "^3.1.1",
|
||||
"gulp-babel": "^6.1.2",
|
||||
"gulp-cache": "^0.4.6",
|
||||
"gulp-concat": "^2.6.1",
|
||||
"gulp-cssnano": "^2.1.2",
|
||||
"gulp-google-webfonts": "0.0.14",
|
||||
"gulp-html-replace": "^1.6.2",
|
||||
"gulp-htmlmin": "^3.0.0",
|
||||
"gulp-jshint": "^2.0.4",
|
||||
"gulp-rename": "^1.2.2",
|
||||
"gulp-sass": "^3.1.0",
|
||||
"gulp-scss": "^1.4.0",
|
||||
"gulp-strip-debug": "^1.1.0",
|
||||
"gulp-uglify": "^2.1.2",
|
||||
"log4js": "^2.3.3"
|
||||
}
|
||||
}
|
||||
|
@ -5,13 +5,13 @@
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
background-color: #4791D2;
|
||||
background-color: #FFC107;
|
||||
}
|
||||
|
||||
body {
|
||||
color: #fff;
|
||||
color: #4A148C;
|
||||
text-align: center;
|
||||
font-family: 'Raleway', sans-serif;
|
||||
font-family: 'Roboto Condensed', sans-serif;
|
||||
}
|
||||
|
||||
.btn-shorten {
|
||||
@ -69,7 +69,7 @@ body {
|
||||
}
|
||||
|
||||
#link a{
|
||||
color: #F89406;
|
||||
color: #FF4081;
|
||||
font-size: 1.5em;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
$('.btn-shorten').on('click', function(){
|
||||
$('#btn-shorten').on('click', function(){
|
||||
console.log('Click');
|
||||
|
||||
$.ajax({
|
||||
url: '/api/shorten',
|
||||
url: '/api/v1/shorten',
|
||||
type: 'POST',
|
||||
dataType: 'JSON',
|
||||
data: {url: $('#url-field').val()},
|
||||
|
@ -5,14 +5,31 @@
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>URL Shortener - coligo.io</title>
|
||||
<link href='https://fonts.googleapis.com/css?family=Raleway' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
|
||||
<title>nURL</title>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto+Condensed" rel="stylesheet">
|
||||
<!--<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">-->
|
||||
<link rel="stylesheet" href="//cdn.muicss.com/mui-0.9.20/css/mui.min.css">
|
||||
<link href="css/styles.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="site-wrapper">
|
||||
<div class="mui-container-fluid">
|
||||
<div class="mui--text-display3">nURL</div>
|
||||
<div class="mui--text-subhead">nurl.co</div>
|
||||
<div class="mui-panel">
|
||||
<form class="mui-form--inline">
|
||||
<div class="mui-textfield">
|
||||
<input type="text" id="url-field" placeholder="Paste a link...">
|
||||
</div>
|
||||
<button class="mui-btn mui-btn--raised mui-btn--accent" id="btn-shorten" type="button">SHORTEN</button>
|
||||
</form>
|
||||
<div class="mui-row">
|
||||
<div class="mui-col-lg-12" id="link"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--<div class="site-wrapper">
|
||||
|
||||
<div class="site-wrapper-inner">
|
||||
|
||||
@ -20,8 +37,8 @@
|
||||
|
||||
<div class="inner cover">
|
||||
<span class="glyphicon glyphicon-link"></span>
|
||||
<h1>URL Shortener</h1>
|
||||
<h4>coligo.io</h4>
|
||||
<h1>nURL</h1>
|
||||
<h4>nurl.co</h4>
|
||||
|
||||
<div class="row">
|
||||
|
||||
@ -46,7 +63,7 @@
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>-->
|
||||
|
||||
<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
|
||||
|
Loading…
Reference in New Issue
Block a user