/
controller.go
101 lines (86 loc) · 2.67 KB
/
controller.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
package controller
import (
"context"
"fmt"
"github.com/google/go-github/github"
"github.com/michal-bures/githubsearch/pages"
"github.com/michal-bures/githubsearch/refiners"
"github.com/michal-bures/githubsearch/searcher"
"github.com/pkg/errors"
"log"
"net/http"
"time"
)
type Controller struct {
searcher *searcher.GithubSearcher
}
func (c Controller) IndexPageHandler(w http.ResponseWriter, r *http.Request) {
keyword := getQueryParam(r, "search")
language := getQueryParam(r, "language")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
errorHandler := func(e error) {
handleError(w, e)
}
if keyword == "" {
pages.SearchPage(w, errorHandler, pages.SearchPageData{
ShowResults: false,
})
} else {
results, err := c.searcher.Search(ctx, keyword, language)
handleError(w, err)
pipeline := [...]refiners.SearchResultsRefiner{
refiners.MatchPattern{Pattern: keyword},
refiners.SortByRepositoryScore{MaxRequests: 20, Client: (*c.searcher).Client},
}
for _, refinement := range pipeline {
results = refinement.Apply(ctx, results)
}
pages.SearchPage(w, errorHandler, pages.SearchPageData{
ShowResults: true,
SearchLanguage: language,
SearchString: r.URL.Query()["search"][0],
Results: convertResults(results),
})
}
}
func handleError(w http.ResponseWriter, e error) {
if e != nil { //TODO to me it feels more standard to have the condition outside, even though at the first peak it might look like it clutters the code
log.Print(errors.WithStack(e))
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprint(w, "Oops, something went wrong") //TODO as this is a a Write() it can also fail here, unfortunately
}
}
func convertResults(codeResults *[]github.CodeResult) []pages.SearchResult {
searchResults := make([]pages.SearchResult, len(*codeResults))
fmt.Printf("Total results: %d\n", len(*codeResults))
for i, codeResult := range *codeResults { //TODO you can just append I guess
searchResults[i] = pages.SearchResult{
Name: codeResult.Name,
Path: codeResult.Path,
FileUrl: codeResult.HTMLURL,
Repository: codeResult.Repository.Name,
Fragments: getFragments(codeResult.TextMatches),
}
}
return searchResults
}
func getFragments(matches []github.TextMatch) []*string {
fragments := make([]*string, len(matches))
for i, match := range matches {
fragments[i] = match.Fragment
}
return fragments
}
func NewController(searcher *searcher.GithubSearcher) *Controller {
return &Controller{
searcher: searcher,
}
}
func getQueryParam(r *http.Request, name string) string {
values := r.URL.Query()[name]
if values == nil {
return ""
}
return values[0]
}