-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhandlers.go
130 lines (101 loc) · 2.95 KB
/
handlers.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
package main
import (
"encoding/json"
"fmt"
"html/template"
"net/http"
"path"
"strconv"
"io"
"os"
"github.com/pkg/errors"
"gopkg.in/mgo.v2"
)
// Error Response defines the structure of an api error
type ErrorResponse struct {
Error string `json:"error"`
}
// Handlers is responsible for processing requests to the api
type Handlers struct {
masterDB *mgo.Session
api *CustomSearchAPI
}
var (
ErrInvalidOffsetArgument = errors.New("Invalid offset argument, must be an integer >= 1")
ErrUnableToQueryAPI = errors.New("Unable to query search API")
ErrUnableToSaveQuery = errors.New("Unable to save document to database")
ErrUnableToLocatePreviousSearches = errors.New("Unable to locate previous searches")
)
func (h *Handlers) Index(w http.ResponseWriter, r *http.Request, params map[string]string) {
file := path.Join("index.html")
tempVars := struct {
Host string
}{
Host: os.Getenv("APP_HOST"),
}
temp, _ := template.ParseFiles(file)
temp.Execute(w, &tempVars)
}
// ImageSearch is the handler for querying google's api
func (h *Handlers) ImageSearch(w http.ResponseWriter, r *http.Request, params map[string]string) {
offset := 1
var err error
if r.URL.Query().Get("offset") != "" {
offset, err = strconv.Atoi(r.URL.Query().Get("offset"))
if err != nil || offset < 1 {
h.RespondError(w, ErrInvalidOffsetArgument, http.StatusBadRequest)
return
}
}
resp, err := h.api.New().Offset(offset).Search(params["query"]).Get()
if err != nil {
h.RespondError(w, ErrUnableToQueryAPI, http.StatusInternalServerError)
return
}
response := make(SearchResultResponse, len(resp.Items))
for k, v := range resp.Items {
response[k] = SearchResult{
URL: v.Link,
Snippet: v.Snippet,
Context: v.Image.ContextLink,
Thumbnail: v.Image.ThumbnailLink,
}
}
sess := h.masterDB.Copy()
defer sess.Close()
if err := ArchiveSearch(sess, params["query"]); err != nil {
h.RespondError(w, ErrUnableToSaveQuery, 500)
}
h.Respond(w, response, 200)
return
}
// Latest fetches the most recent searches from the database
func (h *Handlers) Latest(w http.ResponseWriter, r *http.Request, params map[string]string) {
db := h.masterDB.Copy()
defer db.Close()
results, err := RetrieveSearches(db)
if err != nil {
h.RespondError(w, ErrUnableToLocatePreviousSearches, 404)
return
}
h.Respond(w, results, http.StatusOK)
return
}
// RespondError handle all error responses to the client
func (h *Handlers) RespondError(w http.ResponseWriter, apiError error, statusCode int) {
e := ErrorResponse{
Error: apiError.Error(),
}
h.Respond(w, e, statusCode)
}
// Respond handles all responses to the client
func (h *Handlers) Respond(w http.ResponseWriter, value interface{}, statusCode int) {
js, err := json.Marshal(value)
if err != nil {
fmt.Println("error", err)
js = []byte("{}")
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(statusCode)
io.WriteString(w, string(js))
}