-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
103 lines (85 loc) 路 2.17 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
package main
import (
"encoding/json"
"flag"
"fmt"
"github.com/gorilla/mux"
"go.roman.zone/crawl/index"
"log"
"net/http"
"sort"
"strings"
)
var (
listenHost = flag.String("host", "127.0.0.1", "Host to listen on")
listenPort = flag.Int("port", 8080, "Port to listen on")
)
func main() {
listenAddr := fmt.Sprintf("%s:%d", *listenHost, *listenPort)
log.Printf("Starting server on %s...\n", listenAddr)
check(http.ListenAndServe(listenAddr, makeRouter()))
}
func makeRouter() *mux.Router {
r := mux.NewRouter().StrictSlash(true)
// Attach new handlers here:
r.HandleFunc("/", queryHandler)
return r
}
func queryHandler(w http.ResponseWriter, r *http.Request) {
keywords := strings.Split(r.URL.Query().Get("q"), ",")
if len(keywords) < 1 {
http.Error(w, "No query", http.StatusBadRequest)
return
}
items := make([]index.IndexItem, 0)
for _, keyword := range keywords {
// Retrieving items for every keyword
items = append(items, index.Index.GetItems(strings.ToLower(keyword))...)
}
// Raking items by how often they appear
itemsRanked := make(map[index.IndexItem]int)
for _, item := range items {
itemsRanked[item]++
}
results := make(SearchResults, len(itemsRanked))
i := 0
for k, v := range itemsRanked {
results[i] = SearchResult{k, v}
i++
}
sort.Sort(sort.Reverse(results))
resultsOut := make([]SearchResultOutput, len(results))
i = 0
for _, item := range results {
resultsOut[i] = SearchResultOutput{
URL: item.Item.URL.String(),
Rank: item.Rank,
}
i++
}
b, err := json.MarshalIndent(resultsOut, "", " ")
if err != nil {
http.Error(w, "Internal error.", http.StatusInternalServerError)
log.Println(err)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write(b)
}
type SearchResultOutput struct {
URL string `json:"url"`
Rank int `json:"rank"`
}
type SearchResult struct {
Item index.IndexItem
Rank int
}
type SearchResults []SearchResult
func (p SearchResults) Len() int { return len(p) }
func (p SearchResults) Less(i, j int) bool { return p[i].Rank < p[j].Rank }
func (p SearchResults) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func check(err error) {
if err != nil {
log.Fatal(err)
}
}