-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
132 lines (112 loc) · 3.66 KB
/
main.go
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
package main
import (
"database/sql"
"encoding/json"
"fmt"
"math/rand"
"net/http"
"os"
"regexp"
"strconv"
"strings"
"time"
_ "github.com/go-sql-driver/mysql"
"github.com/julienschmidt/httprouter"
)
var db *sql.DB
var err error
type UrlResponse struct {
OriginalURL interface{} `json:"original_url"`
ShortURL interface{} `json:"short_url"`
}
type ErrorResponse struct {
Error interface{} `json:"error"`
}
type Config struct {
Database struct {
User string `json:"user"`
Password string `json:"password"`
} `json:"database"`
Host string `json:"host"`
Port string `json:"port"`
Name string `json:"name"`
}
func main() {
databaseURI := os.Getenv("MYSQL_URL") //This is the config variable for Heroku
db, err = sql.Open("mysql", databaseURI)
check(err)
defer db.Close()
err = db.Ping()
check(err)
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
router := httprouter.New()
router.GET("/new/*url", createURL)
router.GET("/get/:id", getURL)
router.GET("/", index)
http.ListenAndServe(":"+port, router)
}
func loadConfig(file string) Config {
var config Config
configFile, err := os.Open(file)
if err != nil {
fmt.Println(err.Error())
}
jsonParser := json.NewDecoder(configFile)
jsonParser.Decode(&config)
configFile.Close()
return config
}
func index(res http.ResponseWriter, req *http.Request, _ httprouter.Params) {
http.ServeFile(res, req, "./static/index.html")
}
func createURL(res http.ResponseWriter, req *http.Request, ps httprouter.Params) {
response := UrlResponse{}
var shortUrl string
var originalUrl string = ps.ByName("url")
var newUrl string = strings.Replace(originalUrl, "/", "", 1) //This removes the first forward slash: '/'
reg, _ := regexp.Compile(`^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?:!(?:10|127)(?:\.\d{1,3}){3})(?:!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?:!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]-*)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]-*)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$`)
if reg.MatchString(newUrl) {
err = db.QueryRow("SELECT original_url, short_url FROM urls WHERE original_url = ?", newUrl).Scan(&newUrl, &shortUrl)
if err != nil {
idNum := random(0, 9999)
idStr := strconv.Itoa(idNum)
check(err)
shortUrl = "https://morning-retreat-24523.herokuapp.com/get/" + idStr
_, err := db.Exec("INSERT INTO urls(id, original_url, short_url) VALUES(?, ?, ?)", idNum, newUrl, shortUrl)
check(err)
response = UrlResponse{OriginalURL: newUrl, ShortURL: shortUrl}
} else {
response = UrlResponse{OriginalURL: newUrl, ShortURL: shortUrl}
}
js, err := json.Marshal(response)
check(err)
res.Header().Set("Content-Type", "application/json")
res.Write(js)
} else {
errorResponse := ErrorResponse{Error: "Sorry, wrong url format. Please make sure you have a valid protocol and real site."}
js, err := json.Marshal(errorResponse)
check(err)
res.Header().Set("Content-Type", "application/json")
res.Write(js)
}
}
func getURL(res http.ResponseWriter, req *http.Request, ps httprouter.Params) {
var idStr string = ps.ByName("id")
var idNum, err = strconv.Atoi(idStr)
var originalUrl string
err = db.QueryRow("SELECT original_url FROM urls WHERE id = ?", idNum).Scan(&originalUrl)
check(err)
http.Redirect(res, req, originalUrl, 301) //This needs to have a protocol, i.e. http or https
}
func random(min, max int) int {
rand.Seed(time.Now().Unix())
return rand.Intn(max-min) + min
}
func check(err error) {
if err != nil {
fmt.Println(err)
}
}