-
Notifications
You must be signed in to change notification settings - Fork 0
/
serve.go
128 lines (108 loc) · 3.17 KB
/
serve.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
// Copyright 2022 Kirill Scherba <kirill@scherba.ru>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Teonews website server application.
// Web-server page module.
package main
import (
"embed"
"net/http"
"strings"
"text/template"
"golang.org/x/crypto/acme/autocert"
)
type Serve struct {
*Teonet
domain string
description string
templates *template.Template
}
// Page struct send to HTML template
type Page struct {
Title string
Name string
Subj string
Body string
AppName string
AppVersion string
TeonetVersion string
Address string
}
//go:embed static tmpl
var f embed.FS
// newServe create Serve object and start http server which process http
// requests and communicate with teonet to get / set page values
func newServe(domain, description, addr string, teo *Teonet) (err error) {
s := &Serve{teo, domain, description, nil}
err = s.serve(addr)
return
}
// serve define handlers and start http server
func (s *Serve) serve(addr string) (err error) {
// Parse template files
s.templates = template.Must(
template.ParseFS(f, "tmpl/*.html"),
)
// Dynamic handlers
http.HandleFunc("/", s.homeHandler)
// Static files handlers
http.HandleFunc("/favicon.ico", s.faviconHandler)
// Run web server
if len(domain) > 0 {
// Redirect HTTP to HTTPS
go func() {
if err := http.ListenAndServe(":80", http.HandlerFunc(redirectTLS)); err != nil {
s.Log().Error.Fatalf("ListenAndServe error: %v", err)
}
}()
// HTTPS server
err = http.Serve(autocert.NewListener(domain), nil)
} else {
// HTTP server
s.Log().Debug.Printf("start listening for HTTP requests on %s", addr)
err = http.ListenAndServe(addr, nil)
}
return
}
// redirectTLS redirect HTTP requests to HTTPs
func redirectTLS(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "https://"+domain+":443"+r.RequestURI,
http.StatusMovedPermanently)
}
// renderTemplate render template using Page or Rows structure
func (s *Serve) renderTemplate(w http.ResponseWriter, templateName string,
p interface{}) {
// Execute selected in function parameters template
err := s.templates.ExecuteTemplate(w, templateName+".html", p)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
// textToHtml converts text to html
func (s *Serve) textToHtml(txt string) string {
fortune = strings.Replace(fortune, "\n", "<br>\n", -1)
fortune = strings.Replace(fortune, "\r", "", -1)
return txt
}
// homeHandler home page handler
func (s *Serve) homeHandler(w http.ResponseWriter, r *http.Request) {
title := "Teonet Fortune"
fortune, _ := s.Fortune()
fortune = s.textToHtml(fortune)
p := &Page{
title, title, s.description, fortune, appName, appVersion, s.Version(),
s.Address(),
}
s.renderTemplate(w, "home", p)
}
// faviconHandler favicon handler
func (s *Serve) faviconHandler(w http.ResponseWriter, r *http.Request) {
file := "static/img/favicon.ico"
data, err := f.ReadFile(file)
if err != nil {
s.Log().Error.Printf("faviconHandler read icon file error: %v", err)
}
w.Header().Set("Content-Type", "image/x-icon")
w.Write(data)
}