Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
fever-ch
GitHub Repository: fever-ch/go-google-sites-proxy
Path: blob/master/proxy/sitehandler.go
508 views
1
package proxy
2
3
import (
4
"strconv"
5
"time"
6
7
"io/ioutil"
8
9
"github.com/fever-ch/go-google-sites-proxy/blob"
10
"net/http"
11
"strings"
12
13
"fmt"
14
"github.com/fever-ch/go-google-sites-proxy/common/config"
15
log "github.com/sirupsen/logrus"
16
)
17
18
type siteContext struct {
19
Site *config.SiteYaml
20
Favicon *Page
21
}
22
23
func retrieveF(site config.Site) func(string) (*http.Response, error) {
24
googleSitePathRoot := "https://sites.google.com/" + site.GRef()
25
26
return func(url string) (*http.Response, error) {
27
var netClient = &http.Client{
28
Timeout: time.Second * 10,
29
}
30
31
req, _ := http.NewRequest("GET", googleSitePathRoot+url, nil)
32
if site.Language() != "" {
33
req.Header.Set("Accept-Language", site.Language())
34
}
35
36
req.Header.Set("Accept-Encoding", "gzip")
37
gsitesResponse, err := netClient.Do(req)
38
if err != nil {
39
log.WithError(err).Error("Unable to retrieve page on Google Sites")
40
}
41
return gsitesResponse, err
42
}
43
}
44
45
func respToPageF(site config.Site, siteContext *siteContext) func(*http.Response) *Page {
46
patcher := newPatcher(site, siteContext)
47
48
return func(resp *http.Response) *Page {
49
headers := make(map[string](string))
50
51
selectedHeaders := []string{"Content-Type", "Date", "Expires"}
52
for _, key := range selectedHeaders {
53
value := resp.Header.Get(key)
54
if value != "" {
55
headers[key] = value
56
}
57
}
58
headers["Server"] = resp.Header.Get("Server") + " + GGSP"
59
60
gzipped := resp.Header.Get("Content-Encoding") == "gzip"
61
62
var body blob.HybridRawGzipBlob
63
b, _ := ioutil.ReadAll(ioutil.NopCloser(resp.Body))
64
if gzipped {
65
body = blob.NewGzippedBlob(b)
66
} else {
67
body = blob.NewRawBlob(b)
68
}
69
70
return patcher(&Page{resp.StatusCode, headers, body, gzipped})
71
}
72
}
73
74
func renderPageF() func(*Page, http.ResponseWriter, bool) {
75
return func(page *Page, responseWriter http.ResponseWriter, gzipSupport bool) {
76
var buff []byte
77
if page.OriginallyGziped && gzipSupport {
78
responseWriter.Header().Set("Content-Encoding", "gzip")
79
buff = page.Blob.Gzipped()
80
} else {
81
buff = page.Blob.Raw()
82
}
83
84
for key, value := range page.Headers {
85
if value != "" {
86
responseWriter.Header().Set(key, value)
87
}
88
}
89
90
responseWriter.WriteHeader(page.Code)
91
responseWriter.Header().Set("Content-Length", strconv.Itoa(len(buff)))
92
_, e := responseWriter.Write(buff)
93
if e != nil {
94
log.WithError(e).Warn("Unable to write response to client")
95
}
96
97
}
98
}
99
100
// GetSiteHandler returns a function that will handle calls to this site
101
func GetSiteHandler(site config.Site) *func(responseWriter http.ResponseWriter, request *http.Request) {
102
siteContext := &siteContext{}
103
104
if site.FaviconPath() != "" {
105
buf, err := ioutil.ReadFile(site.FaviconPath())
106
if err == nil {
107
h := make(map[string](string))
108
h["Content-Type"] = "image/x-icon"
109
siteContext.Favicon = &Page{200, h, blob.NewRawBlob(buf), true}
110
} else {
111
log.WithError(err).Warning(fmt.Sprintf("Failed to load favicon for site %v", site.Host()))
112
}
113
}
114
115
retrieve := retrieveF(site)
116
117
respToPage := respToPageF(site, siteContext)
118
119
renderPage := renderPageF()
120
121
// The actual handler that will get the request for this site
122
handleRequest := func(responseWriter http.ResponseWriter, request *http.Request) {
123
124
if strings.HasPrefix(request.URL.Path, "/_/") {
125
responseWriter.WriteHeader(200)
126
} else {
127
var code int
128
switch request.Method {
129
case "GET":
130
var page *Page
131
if request.URL.Path == "/favicon.ico" && siteContext.Favicon != nil {
132
page = siteContext.Favicon
133
} else {
134
gsitesResponse, err := retrieve(request.URL.Path)
135
if err != nil {
136
errorPage(http.StatusInternalServerError, "Bad gateway", "Unable to retrieve page on remote server")(responseWriter, request)
137
break
138
}
139
page = respToPage(gsitesResponse)
140
}
141
142
renderPage(page, responseWriter, strings.Contains(request.Header.Get("Content-Encoding"), "gzip"))
143
code = page.Code
144
145
default:
146
}
147
var ip string
148
if site.IPHeader() == "" {
149
ip = request.RemoteAddr
150
} else {
151
ip = request.Header.Get(site.IPHeader())
152
}
153
154
log.Info(fmt.Sprintf("%s \"%s %s %s\" %s %s %d", request.Host, request.Method, request.URL, request.Proto, ip, request.UserAgent(), code))
155
}
156
}
157
return &handleRequest
158
}
159
160