First Restful API Version

master
kreativmonkey 8 years ago
parent 9d4d1cae6d
commit 8fcb8c3f23

@ -5,6 +5,8 @@ import (
"encoding/json"
"fmt"
"text/template"
"net/url"
shorty "github.com/kreativmonkey/shrt/short"
)
type Page struct {
@ -13,6 +15,11 @@ type Page struct {
Body string
}
type response struct {
Action string `json:"action"`
Result interface{} `json:"result"`
}
// Load the main Page with an Imput field for the URL to short.
func index(w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles("template/index.gohtml")
@ -44,35 +51,63 @@ func shorten(w http.ResponseWriter, r *http.Request){
// GET: http://example.com/api/action/shorten?key=API_KEY_HERE&url=https://google.com&custom_ending=CUSTOM_ENDING
// Response: {"action": "shorten","result": "https://example.com/5kq"}
func shortenJSON(w http.ResponseWriter, r *http.Request){
decoder := json.NewDecoder(r.Body)
var response shrt
err := decoder.Decode(&response)
if err != nil {
query := r.URL.Query()
queryu, err := url.QueryUnescape(query.Get("url"))
check(err)
var test string
err = short.Short(queryu, &test)
check(err)
respond := response{
Action: "shorten",
Result: r.Host + "/" + test,
}
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(&respond); err != nil {
panic(err)
}
defer r.Body.Close()
fmt.Println(response)
/*response := map[string]string{
"action": "shorten",
"result": "",
}*/
}
// GET: http://example.com/api/action/lookup?key=API_KEY_HERE&url_ending=5kq
// Response: {"action":"lookup","result": {"long_url": "https:\/\/google.com","created_at": {"date":"2016-02-12 15:20:34.000000","timezone_type":3,"timezone":"UTC"},"clicks":"0"}}
func lookup(w http.ResponseWriter, r *http.Request){
/*response := map[string]interface{}{
"action": "lookup",
"result": map[string]string{
"long_url": "",
"created_at": "",
"clicks": "",
func lookupJSON(w http.ResponseWriter, r *http.Request){
query := r.URL.Query()
queryu, err := url.QueryUnescape(query.Get("url_ending"))
check(err)
var result shorty.Shrt
var respond response
if ok := short.GetAPI(queryu, &result); ok {
respond := response{
Action: "shorten",
Result: result,
}
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(&respond); err != nil {
panic(err)
}
} else {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusNotFound)
if err := json.NewEncoder(w).Encode(&respond); err != nil {
panic(err)
}
}
}*/
}
func all(w http.ResponseWriter, r *http.Request){
t, _ := template.New("all").Parse("{{.}}")
t.Execute(w, short.All())
}
func check(err error) {
if err != nil {
panic(err)
}
}

@ -45,19 +45,12 @@ type shrt struct {
}
func main() {
http.HandleFunc("/", index) // render form for Input
http.HandleFunc("/{token}", redirect) // request token for redirect URL
http.HandleFunc("/shorten", shorten) // render Page for shorten URL
http.HandleFunc("/all", all) // render all in a json
http.HandleFunc("/api/action/shorten", shortenJSON) // setting router rule
http.HandleFunc("/api/action/lookup", lookup) // setting router rule
router := NewRouter()
http.Handle("/css/", http.StripPrefix("/css/", http.FileServer(http.Dir("template/css"))))
http.Handle("/img/", http.StripPrefix("/img/", http.FileServer(http.Dir("template/img"))))
err := http.ListenAndServe(":"+port, nil) // setting listening port
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
fmt.Printf("Shrt %s started on Port: %s", version, port)
fmt.Printf("Shrt %s started on Port: %s \n", version, port)
log.Fatal(http.ListenAndServe(":"+port, router))
}

@ -37,15 +37,33 @@ var routes = Routes{
index,
},
Route{
"TodoIndex",
"ShortenAPI",
"GET",
"/api/v1/action/shorten",
shortenJSON,
},
Route{
"LookupAPI",
"GET",
"/api/v1/action/lookup",
lookupJSON,
},
Route{
"GetAll",
"GET",
"/all",
all,
},
Route{
"Shorten",
"POST",
"/shorten",
shorten,
},
Route{
"TodoShow",
"Redirect",
"GET",
"/{token}",
lookup,
redirect,
},
}

@ -1,26 +1,26 @@
package shrt
import (
"fmt"
"bytes"
"crypto/sha256"
"errors"
"encoding/json"
"errors"
"fmt"
"io"
"net/url"
"os"
"io"
"bytes"
"time"
)
type Storage struct {
Token map[string]*shrt `json:"token"`
Token map[string]*Shrt `json:"token"`
Url map[string]string `json:"url"`
}
type shrt struct {
type Shrt struct {
URL string `json:"url"`
Datum string `json:"datum"`
Count int64 `json:"count"`
Date string `json:"datum"`
Clicks int64 `json:"clicks"`
}
var (
@ -30,8 +30,8 @@ var (
)
// Open up
func Open(path string) (*Storage, error){
s := Storage{Token: make(map[string]*shrt), Url: make(map[string]string)}
func Open(path string) (*Storage, error) {
s := Storage{Token: make(map[string]*Shrt), Url: make(map[string]string)}
// Open db ore create if not exist!
if db, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0644); err == nil {
json.Unmarshal(StreamToByte(db), &s)
@ -42,12 +42,12 @@ func Open(path string) (*Storage, error){
}
}
func (s *Storage) Short(URL string, value *string) (string, error) {
func (s *Storage) Short(URL string, value *string) error {
// Check if it is a valide Url found on:
// http://stackoverflow.com/questions/31480710/validate-url-with-standard-package-in-go
_, err := url.ParseRequestURI(URL)
if err != nil {
return "", ErrNoUrl
return ErrNoUrl
}
// Create a sha256 Hash from the URL
@ -55,7 +55,8 @@ func (s *Storage) Short(URL string, value *string) (string, error) {
// Test if the URL alraedy exist and return the key
if val, ok := s.Url[hash]; ok {
return val, nil
value = &val
return nil
}
// Iterate to the length of hash to get the shortest output
for hashShortestLen := 1; hashShortestLen <= 32; hashShortestLen++ {
@ -63,18 +64,18 @@ func (s *Storage) Short(URL string, value *string) (string, error) {
if _, ok := s.Token[hash[:hashShortestLen]]; !ok {
token := hash[:hashShortestLen]
t := time.Now()
s.Token[token] = &shrt{
s.Token[token] = &Shrt{
URL: URL,
Datum: t.String(),
Date: t.String(),
}
s.Url[hash] = token
*value = s.Url[hash]
s.Save()
return token, nil
return nil
}
}
return "", ErrCreateToken
return ErrCreateToken
}
func (s *Storage) Add(URL string, value *string) (string, error) {
@ -98,9 +99,9 @@ func (s *Storage) Add(URL string, value *string) (string, error) {
if _, ok := s.Token[hash[:hashShortestLen]]; !ok {
token := hash[:hashShortestLen]
t := time.Now()
s.Token[token] = &shrt{
s.Token[token] = &Shrt{
URL: URL,
Datum: t.String(),
Date: t.String(),
}
s.Url[hash] = token
*value = s.Url[hash]
@ -120,15 +121,24 @@ func (s *Storage) Remove(URL string) error {
func (s *Storage) Get(token string) (string, bool) {
if shrt, ok := s.Token[token]; ok {
fmt.Printf("Url mit dem Token %s gefunden: %s \n", token, shrt.URL)
s.Token[token].Count += 1
s.Token[token].Clicks += 1
s.Save()
return shrt.URL, true
}
return "", false
}
// Get returns the URL for the given token
func (s *Storage) GetAPI(token string, value *Shrt) bool {
if shrt, ok := s.Token[token]; ok {
*value = *shrt
return true
}
return false
}
// Get all entries
func (s *Storage) All() (string) {
func (s *Storage) All() string {
b, err := json.Marshal(&s)
if err != nil {
return ""

Loading…
Cancel
Save