mirror of
https://github.com/benbusby/farside.git
synced 2025-03-15 11:46:32 -04:00

BreezeWiki requires the subdomain of a fandom link to be preserved when routing, otherwise the redirect doesn't work correctly. Cleaned up readme examples
149 lines
3.2 KiB
Go
149 lines
3.2 KiB
Go
package server
|
|
|
|
import (
|
|
_ "embed"
|
|
"encoding/json"
|
|
"html/template"
|
|
"log"
|
|
"net/http"
|
|
"net/url"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/benbusby/farside/db"
|
|
"github.com/benbusby/farside/services"
|
|
)
|
|
|
|
//go:embed index.html
|
|
var indexHTML string
|
|
|
|
//go:embed route.html
|
|
var routeHTML string
|
|
|
|
type indexData struct {
|
|
LastUpdated time.Time
|
|
ServiceList []services.Service
|
|
}
|
|
|
|
type routeData struct {
|
|
InstanceURL string
|
|
}
|
|
|
|
func home(w http.ResponseWriter, r *http.Request) {
|
|
serviceList := db.GetServiceList()
|
|
data := indexData{
|
|
LastUpdated: db.LastUpdate,
|
|
ServiceList: serviceList,
|
|
}
|
|
|
|
tmpl, err := template.New("").Parse(indexHTML)
|
|
if err != nil {
|
|
log.Println(err)
|
|
http.Error(w, "Error parsing template", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "text/html")
|
|
|
|
err = tmpl.Execute(w, data)
|
|
if err != nil {
|
|
log.Println(err)
|
|
http.Error(w, "Error executing template", http.StatusInternalServerError)
|
|
}
|
|
}
|
|
|
|
func state(w http.ResponseWriter, r *http.Request) {
|
|
storedServices := db.GetServiceList()
|
|
jsonData, _ := json.Marshal(storedServices)
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_, _ = w.Write(jsonData)
|
|
}
|
|
|
|
func baseRouting(w http.ResponseWriter, r *http.Request) {
|
|
routing(w, r, false)
|
|
}
|
|
|
|
func jsRouting(w http.ResponseWriter, r *http.Request) {
|
|
r.URL.Path = strings.Replace(r.URL.Path, "/_", "", 1)
|
|
routing(w, r, true)
|
|
}
|
|
|
|
func routing(w http.ResponseWriter, r *http.Request, jsEnabled bool) {
|
|
value := r.PathValue("routing")
|
|
if len(value) == 0 {
|
|
value = r.URL.Path
|
|
}
|
|
|
|
url, _ := url.Parse(value)
|
|
path := strings.TrimPrefix(url.Path, "/")
|
|
segments := strings.Split(path, "/")
|
|
|
|
target, err := services.MatchRequest(segments[0])
|
|
if err != nil {
|
|
log.Printf("Error during match request: %v\n", err)
|
|
http.Error(w, "No routing found for "+target, http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var servicePath string
|
|
if target == "breezewiki" {
|
|
// Breezewiki requires the subdomain of the instance to be
|
|
// preserved for correct routing
|
|
splitDomain := strings.Split(path, ".")
|
|
if len(splitDomain) > 2 {
|
|
servicePath = strings.Split(path, ".")[0]
|
|
}
|
|
}
|
|
|
|
instance, err := db.GetInstance(target, servicePath)
|
|
if err != nil {
|
|
log.Printf("Error fetching instance from db: %v\n", err)
|
|
http.Error(
|
|
w,
|
|
"Error fetching instance for "+target,
|
|
http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if len(segments) > 1 {
|
|
targetPath := strings.Join(segments[1:], "/")
|
|
instance = instance + "/" + targetPath
|
|
}
|
|
|
|
w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0")
|
|
w.Header().Set("Pragma", "no-cache")
|
|
w.Header().Set("Expires", "0")
|
|
|
|
if jsEnabled {
|
|
data := routeData{
|
|
InstanceURL: instance,
|
|
}
|
|
tmpl, _ := template.New("").Parse(routeHTML)
|
|
w.Header().Set("Content-Type", "text/html")
|
|
_ = tmpl.Execute(w, data)
|
|
} else {
|
|
http.Redirect(w, r, instance, http.StatusFound)
|
|
}
|
|
}
|
|
|
|
func RunServer() {
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("/{$}", home)
|
|
mux.HandleFunc("/state/{$}", state)
|
|
mux.HandleFunc("/{routing...}", baseRouting)
|
|
mux.HandleFunc("/_/{routing...}", jsRouting)
|
|
|
|
port := os.Getenv("FARSIDE_PORT")
|
|
if len(port) == 0 {
|
|
port = "4001"
|
|
}
|
|
|
|
log.Println("Starting server on http://localhost:" + port)
|
|
|
|
err := http.ListenAndServe(":"+port, mux)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|