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
|
package main
import (
"encoding/json"
"fmt"
"log"
"math/rand/v2"
"net/http"
"unicode/utf8"
)
const charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
const version = "0.0.1"
var Table map[string]string = make(map[string]string)
type Request struct {
URL string
}
type Response struct {
Version string
Status string
Original string
New string
}
func NewRequest(r *http.Request) (Request, error) {
var request Request
err := json.NewDecoder(r.Body).Decode(&request)
return request, err
}
func log_header(r *http.Request) {
log.Println("Header {")
for k, v := range r.Header {
log.Printf("\t\"%s\": \"%s\"\n", k, v)
}
log.Println("}")
}
func redirect(w http.ResponseWriter, r *http.Request) {
log.Println("Request for:", r.URL.String())
log_header(r)
_, i := utf8.DecodeRuneInString(r.URL.String())
url := r.URL.String()[i:]
original, ok := Table[url]
if ok {
w.Header().Set("location", original)
http.Error(w, http.StatusText(301), 301)
} else {
http.Error(w, http.StatusText(404), 404)
}
}
func shorten(w http.ResponseWriter, r *http.Request) {
log.Println("Request to Shorten")
log_header(r)
request, err := NewRequest(r)
if err != nil {
http.Error(w, http.StatusText(500), 500)
}
url := GenerateString(4)
_, ok := Table[url]
for ok {
url = GenerateString(4)
_, ok = Table[url]
}
Table[url] = request.URL
response := Response{version, "ok", request.URL, url}
data, err := json.Marshal(response)
if err != nil {
http.Error(w, http.StatusText(500), 500)
}
fmt.Fprintf(w, "%s", string(data))
}
func GenerateString(size uint) string {
buffer := make([]rune, size)
for i := uint(0); i < size; i++ {
index := rand.Uint() % uint(len(charSet))
buffer[i] = []rune(charSet)[index]
}
return string(buffer)
}
func main() {
http.HandleFunc("/shorten", shorten)
http.HandleFunc("/", redirect)
log.Fatal(http.ListenAndServe(":8000", nil))
}
|