Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
fever-ch
GitHub Repository: fever-ch/go-google-sites-proxy
Path: blob/master/proxy/smartproxy.go
508 views
1
package proxy
2
3
import (
4
"github.com/fever-ch/go-google-sites-proxy/common/config"
5
"net/http"
6
"strconv"
7
"sync/atomic"
8
"unsafe"
9
)
10
11
type context struct {
12
configuration config.Configuration
13
sites map[string]*func(responseWriter http.ResponseWriter, request *http.Request)
14
}
15
16
// NewSmartProxy returns a smartProxy listening to a given TCP port
17
func NewSmartProxy(port uint16) *smartProxy {
18
19
buildContext := func(configuration config.Configuration) *context {
20
21
ctx := context{
22
configuration,
23
make(map[string]*func(responseWriter http.ResponseWriter, request *http.Request))}
24
25
for _, e := range configuration.Sites() {
26
27
addRedirect := func(redirectedHost string, destHost string) *func(responseWriter http.ResponseWriter, request *http.Request) {
28
redirectHandler := func(response http.ResponseWriter, req *http.Request) {
29
30
response.WriteHeader(http.StatusMovedPermanently)
31
response.Header().Add("Location", req.Proto+"://"+destHost+"/"+req.URL.Path)
32
33
response.Write([]byte(strconv.Itoa(http.StatusMovedPermanently) + " Moved permanently"))
34
}
35
return &redirectHandler
36
}
37
38
ctx.sites[e.Host()] = GetSiteHandler(e)
39
for _, f := range e.Redirects() {
40
ctx.sites[f] = addRedirect(f, e.Host())
41
}
42
}
43
return &ctx
44
}
45
46
var ctx unsafe.Pointer
47
48
handler := func(responseWriter http.ResponseWriter, request *http.Request) {
49
ctx := (*context)(atomic.LoadPointer(&ctx))
50
siteHandler := ctx.sites[request.Host]
51
if siteHandler != nil {
52
(*siteHandler)(responseWriter, request)
53
} else if ctx.configuration.Index() {
54
(*getIndex(ctx.configuration))(responseWriter, request)
55
}
56
}
57
58
return &smartProxy{
59
SetConfiguration: func(configuration config.Configuration) {
60
atomic.StorePointer(&ctx, unsafe.Pointer(buildContext(configuration)))
61
},
62
Port: func() uint16 { return port },
63
Start: func() error {
64
http.HandleFunc("/", handler)
65
return http.ListenAndServe(":"+strconv.Itoa(int(port)), nil)
66
},
67
}
68
}
69
70
type smartProxy struct {
71
Start func() error
72
SetConfiguration func(config.Configuration)
73
Port func() uint16
74
}
75
76