Merge all the server components
This commit is contained in:
parent
85b5603d9d
commit
f5f2ac1a03
25 changed files with 365 additions and 352 deletions
|
|
@ -4,11 +4,16 @@ import (
|
|||
"embed"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component/instances"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/core"
|
||||
)
|
||||
|
||||
type Dis struct {
|
||||
component.ComponentBase
|
||||
|
||||
Instances *instances.Instances
|
||||
|
||||
ResolverFile string
|
||||
}
|
||||
|
||||
func (dis Dis) Name() string {
|
||||
|
|
@ -35,7 +40,9 @@ func (dis Dis) Stack() component.Installable {
|
|||
"GLOBAL_AUTHORIZED_KEYS_FILE": dis.Config.GlobalAuthorizedKeysFile,
|
||||
"SELF_OVERRIDES_FILE": dis.Config.SelfOverridesFile,
|
||||
},
|
||||
CopyContextFiles: []string{dis.Config.CurrentExecutable()},
|
||||
|
||||
TouchFiles: []string{dis.ResolverFile},
|
||||
CopyContextFiles: []string{core.Executable},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
26
internal/component/dis/info.go
Normal file
26
internal/component/dis/info.go
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
package dis
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/tkw1536/goprogram/stream"
|
||||
)
|
||||
|
||||
func (dis Dis) info(io stream.IOStream) (http.Handler, error) {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
all, err := dis.Instances.All()
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte("internal server error"))
|
||||
io.EPrintln(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, wk := range all {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(wk.Slug))
|
||||
w.Write([]byte("\n"))
|
||||
}
|
||||
|
||||
}), nil
|
||||
}
|
||||
61
internal/component/dis/resolver.go
Normal file
61
internal/component/dis/resolver.go
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
package dis
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
||||
"github.com/FAU-CDI/wdresolve"
|
||||
"github.com/FAU-CDI/wdresolve/resolvers"
|
||||
"github.com/tkw1536/goprogram/stream"
|
||||
)
|
||||
|
||||
func (dis Dis) ResolverConfigPath() string {
|
||||
return filepath.Join(dis.Dir, dis.ResolverFile)
|
||||
}
|
||||
|
||||
func (dis Dis) resolver(io stream.IOStream) (p wdresolve.ResolveHandler, err error) {
|
||||
p.TrustXForwardedProto = true
|
||||
|
||||
fallback := &resolvers.Regexp{
|
||||
Data: map[string]string{},
|
||||
}
|
||||
|
||||
// handle the default domain name!
|
||||
domainName := dis.Config.DefaultDomain
|
||||
if domainName != "" {
|
||||
fallback.Data[fmt.Sprintf("^https?://(.*)\\.%s", regexp.QuoteMeta(domainName))] = fmt.Sprintf("https://$1.%s", domainName)
|
||||
io.Printf("registering default domain %s\n", domainName)
|
||||
}
|
||||
|
||||
// handle the extra domains!
|
||||
for _, domain := range dis.Config.SelfExtraDomains {
|
||||
fallback.Data[fmt.Sprintf("^https?://(.*)\\.%s", regexp.QuoteMeta(domain))] = fmt.Sprintf("https://$1.%s", domainName)
|
||||
io.Printf("registering legacy domain %s\n", domain)
|
||||
}
|
||||
|
||||
// open the prefix file
|
||||
prefixFile := dis.ResolverConfigPath()
|
||||
fs, err := os.Open(prefixFile)
|
||||
io.Println("loading prefixes from ", prefixFile)
|
||||
if err != nil {
|
||||
return p, err
|
||||
}
|
||||
defer fs.Close()
|
||||
|
||||
// read the prefixes
|
||||
// TODO: Do we want to load these without a file?
|
||||
prefixes, err := resolvers.ReadPrefixes(fs)
|
||||
if err != nil {
|
||||
return p, err
|
||||
}
|
||||
|
||||
// and use that as the resolver!
|
||||
p.Resolver = resolvers.InOrder{
|
||||
prefixes,
|
||||
fallback,
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
137
internal/component/dis/self.go
Normal file
137
internal/component/dis/self.go
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
package dis
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/tkw1536/goprogram/stream"
|
||||
)
|
||||
|
||||
// self returns the handler for the self overrides
|
||||
func (dis Dis) self(io stream.IOStream) (redirect Redirect, err error) {
|
||||
// open the overrides file
|
||||
overrides, err := os.Open(dis.Config.SelfOverridesFile)
|
||||
io.Printf("loading overrides from %q\n", dis.Config.SelfOverridesFile)
|
||||
if err != nil {
|
||||
return redirect, err
|
||||
}
|
||||
defer overrides.Close()
|
||||
|
||||
// decode the overrides file
|
||||
if err := json.NewDecoder(overrides).Decode(&redirect.Overrides); err != nil {
|
||||
return redirect, err
|
||||
}
|
||||
|
||||
if redirect.Overrides == nil {
|
||||
redirect.Overrides = make(map[string]string)
|
||||
}
|
||||
redirect.Overrides["/"] = dis.Config.SelfRedirect.String()
|
||||
|
||||
// create a redirect server
|
||||
redirect.Fallback, err = dis.selfFallback()
|
||||
if err != nil {
|
||||
return redirect, err
|
||||
}
|
||||
redirect.Absolute = false
|
||||
redirect.Overrides = nil
|
||||
redirect.Permanent = false
|
||||
|
||||
// and return!
|
||||
return redirect, nil
|
||||
}
|
||||
|
||||
func (dis *Dis) selfFallback() (http.Handler, error) {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
dis.serveFallback(w, r)
|
||||
}), nil
|
||||
}
|
||||
|
||||
var notFoundText = []byte("not found")
|
||||
|
||||
func (dis *Dis) serveFallback(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
slug := dis.Config.SlugFromHost(r.Host)
|
||||
if slug == "" {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write(notFoundText)
|
||||
return
|
||||
}
|
||||
|
||||
if ok, _ := dis.Instances.Has(slug); !ok {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
fmt.Fprintf(w, "WissKI %q not found\n", slug)
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusBadGateway)
|
||||
fmt.Fprintf(w, "WissKI %q is currently offline\n", slug)
|
||||
|
||||
}
|
||||
|
||||
// Redirect implements a redirect server that redirects all requests.
|
||||
// It implements http.Handler.
|
||||
type Redirect struct {
|
||||
// Target is the target URL to redirect to.
|
||||
Target string
|
||||
|
||||
// Fallback is used when target is the empty string.
|
||||
Fallback http.Handler
|
||||
|
||||
// Absolute determines if the request path should be appended to the target URL when redirecting.
|
||||
// By default this path is always appended, set Absolute to true to prevent this.
|
||||
Absolute bool
|
||||
|
||||
// Overrides is a map from paths to URLs that should override the default target.
|
||||
Overrides map[string]string
|
||||
|
||||
// Permanent determines if the redirect responses issued should return
|
||||
// Permanent Redirect (Status Code 308) or Temporary Redirect (Status Code 307).
|
||||
Permanent bool
|
||||
}
|
||||
|
||||
// Redirect determines the redirect URL for a specific incoming request
|
||||
// If it returns the empty string, the fallback is used.
|
||||
func (redirect Redirect) Redirect(r *http.Request) string {
|
||||
// if we have an override for this URL, use it immediatly
|
||||
url := strings.TrimSuffix(r.URL.Path, "/")
|
||||
if override, ok := redirect.Overrides[url]; ok {
|
||||
return override
|
||||
}
|
||||
|
||||
if redirect.Target == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// if we are in absolute redirect mode, always return the absolute URL
|
||||
if redirect.Absolute {
|
||||
return redirect.Target
|
||||
}
|
||||
|
||||
// return the target + the redirected URL
|
||||
dest := strings.TrimSuffix(redirect.Target, "/") + r.URL.Path
|
||||
if len(r.URL.RawQuery) > 0 {
|
||||
dest += "?" + r.URL.RawQuery
|
||||
}
|
||||
return dest
|
||||
}
|
||||
|
||||
// ServeHTTP implements the http.Handler interface and redirects a single request to redirect.Target.
|
||||
func (redirect Redirect) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
dest := redirect.Redirect(r)
|
||||
if dest == "" {
|
||||
redirect.Fallback.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// determine if we are temporary or permanent redirect
|
||||
status := http.StatusTemporaryRedirect
|
||||
if redirect.Permanent {
|
||||
status = http.StatusPermanentRedirect
|
||||
}
|
||||
|
||||
// and do the redirect
|
||||
http.Redirect(w, r, dest, status)
|
||||
}
|
||||
39
internal/component/dis/server.go
Normal file
39
internal/component/dis/server.go
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
package dis
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/tkw1536/goprogram/stream"
|
||||
)
|
||||
|
||||
// Server returns an http.Mux that implements the main server instance
|
||||
func (dis Dis) Server(io stream.IOStream) (http.Handler, error) {
|
||||
// self server
|
||||
self, err := dis.self(io)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resolver, err := dis.resolver(io)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info, err := dis.info(io)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// resolver
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/", self)
|
||||
|
||||
mux.Handle("/go/", resolver)
|
||||
mux.Handle("/wisski/navigate", resolver)
|
||||
|
||||
// TODO: Fix me!
|
||||
mux.Handle("/dis/", info)
|
||||
|
||||
return mux, nil
|
||||
}
|
||||
|
|
@ -2,4 +2,4 @@ FROM docker.io/library/alpine
|
|||
|
||||
COPY wdcli /wdcli
|
||||
EXPOSE 8888
|
||||
CMD ["/wdcli","--internal-in-docker","--config","${CONFIG_PATH}","dis_server","--bind","0.0.0.0:8888"]
|
||||
CMD ["/wdcli","--internal-in-docker","--config","${CONFIG_PATH}","server","--bind","0.0.0.0:8888"]
|
||||
|
|
@ -8,7 +8,6 @@ services:
|
|||
# port and hostname for this image to use
|
||||
VIRTUAL_HOST: ${VIRTUAL_HOST}
|
||||
VIRTUAL_PORT: 8888
|
||||
VIRTUAL_PATH: /dis/
|
||||
|
||||
CONFIG_PATH: ${CONFIG_PATH}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue