diff --git a/_examples/shttp/proxy/main.go b/_examples/shttp/proxy/main.go index 3de63adc8..6bbc68b5e 100644 --- a/_examples/shttp/proxy/main.go +++ b/_examples/shttp/proxy/main.go @@ -25,7 +25,7 @@ func main() { // parseUDPAddr validates if the address is a SCION address // which we can use to proxy to SCION if _, err := snet.ParseUDPAddr(*remote); err == nil { - proxyHandler, err := shttp.NewSingleSCIONHostReverseProxy(*remote, &tls.Config{InsecureSkipVerify: true}) + proxyHandler, err := shttp.NewSingleSCIONHostReverseProxy(*remote, &tls.Config{InsecureSkipVerify: true, NextProtos: []string{"H3-22"}}) if err != nil { log.Fatalf("Failed to create SCION reverse proxy %s", err) } @@ -50,5 +50,4 @@ func main() { log.Printf("Listen on HTTP %s\n", *local) log.Fatalf("%s", http.ListenAndServe(*local, mux)) } - } diff --git a/go.sum b/go.sum index 0844c4bf1..59e272952 100644 --- a/go.sum +++ b/go.sum @@ -384,4 +384,4 @@ rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= zombiezen.com/go/capnproto2 v0.0.0-20190813022230-ddfb9bb855fa h1:oaUsHxHA/DGY+XtWA4i5FLMxwWheqW21Az6xSLS1OzY= -zombiezen.com/go/capnproto2 v0.0.0-20190813022230-ddfb9bb855fa/go.mod h1:lwDtzVwsLXcHGddc2q1vAWPfocWiFh07Mmeqo/Oatko= +zombiezen.com/go/capnproto2 v0.0.0-20190813022230-ddfb9bb855fa/go.mod h1:lwDtzVwsLXcHGddc2q1vAWPfocWiFh07Mmeqo/Oatko= \ No newline at end of file diff --git a/webapp/web/static/css/style.css b/webapp/web/static/css/style.css index 972abee1e..d8f086727 100644 --- a/webapp/web/static/css/style.css +++ b/webapp/web/static/css/style.css @@ -220,3 +220,37 @@ img { [tooltip]:hover:before, [tooltip]:hover:after { display: block; } + +.card { + /* Add shadows to create the "card" effect */ + box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2); + transition: 0.3s; + max-width: 300px; + text-align: center; + } + + /* On mouse-over, add a deeper shadow */ + .card:hover { + box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2); + } + + /* Add some padding inside the card container */ + .text-container { + padding: 2px 16px; + } + +.cards { + display: flex; +} + +.link { + cursor: pointer; +} + +.link:hover { + transform: scale(1.1); +} + +#tabs { + padding: 1em; +} \ No newline at end of file diff --git a/webapp/web/template/header.html b/webapp/web/template/header.html index c28c6f409..33ec9b541 100644 --- a/webapp/web/template/header.html +++ b/webapp/web/template/header.html @@ -53,6 +53,7 @@
  • Trust
  • Files
  • About
  • +
  • SCION HTTP
  • diff --git a/webapp/web/template/webview.html b/webapp/web/template/webview.html new file mode 100644 index 000000000..6a2a9ca19 --- /dev/null +++ b/webapp/web/template/webview.html @@ -0,0 +1,105 @@ +{{define "webview"}} {{template "header" .}} + +
    + +

    SCION HTTP

    +This page provides some default SCION HTTP endpoints and a searchbar for SCION HTTP URLs, to provide easy access to those resources. +
    +
    + + + +
    + + +
    +

    Trending:

    +
    +
    + Avatar +
    +

    DVB-T2 Live Stream

    + +
    +
    +
    +
    + + +{{template "footer" .}} {{end}} \ No newline at end of file diff --git a/webapp/webapp.go b/webapp/webapp.go index 58c54ffbd..91d43be05 100644 --- a/webapp/webapp.go +++ b/webapp/webapp.go @@ -18,12 +18,15 @@ package main import ( "bufio" + "crypto/tls" "encoding/json" "errors" "fmt" "html/template" "io" "net/http" + "net/http/httputil" + "net/url" "os" "os/exec" "path" @@ -38,6 +41,9 @@ import ( lib "github.com/netsec-ethz/scion-apps/webapp/lib" model "github.com/netsec-ethz/scion-apps/webapp/models" . "github.com/netsec-ethz/scion-apps/webapp/util" + + "github.com/netsec-ethz/scion-apps/pkg/shttp" + "github.com/scionproto/scion/go/lib/snet" ) var settings lib.UserSetting @@ -82,6 +88,53 @@ type Page struct { var options lib.CmdOptions +var proxy *httputil.ReverseProxy + +// Can be overwritte by api calls +type ProxyConfig struct { + Remote string `json:"remote"` +} + +//TODO: Thread safe/Routine safe +func setProxyConfig(wr http.ResponseWriter, r *http.Request) { + var newConfig ProxyConfig + + // Try to decode the request body into the struct. If there is an error, + // respond to the client with the error message and a 400 status code. + err := json.NewDecoder(r.Body).Decode(&newConfig) + if err != nil { + http.Error(wr, err.Error(), http.StatusBadRequest) + return + } + + setRemote(&newConfig.Remote) +} + +func proxyWrapper(rw http.ResponseWriter, req *http.Request) { + req.URL.Path = strings.Replace(req.URL.Path, "__proxy/", "", 1) + proxy.ServeHTTP(rw, req) +} + +func setRemote(remote *string) { + // parseUDPAddr validates if the address is a SCION address + // which we can use to proxy to SCION + if _, err := snet.ParseUDPAddr(*remote); err == nil { + proxy, err = shttp.NewSingleSCIONHostReverseProxy(*remote, &tls.Config{InsecureSkipVerify: true, NextProtos: []string{"H3-22"}}) + if err != nil { + log.Crit("Failed to create SCION reverse proxy %s", err) + } + + fmt.Printf("Proxy to SCION remote %s\n", *remote) + } else { + u, err := url.Parse(*remote) + if err != nil { + log.Crit(fmt.Sprintf("Failed parse remote %s, %s", *remote, err)) + } + fmt.Printf("Proxy to HTTP remote %s\n", *remote) + proxy = httputil.NewSingleHostReverseProxy(u) + } +} + func ensurePath(srcpath, staticDir string) string { dir := path.Join(srcpath, staticDir) if _, err := os.Stat(dir); os.IsNotExist(err) { @@ -188,6 +241,7 @@ func initServeHandlers() { http.HandleFunc("/", mainHandler) http.HandleFunc("/about", aboutHandler) http.HandleFunc("/apps", appsHandler) + http.HandleFunc("/webview", webviewHandler) http.HandleFunc("/astopo", astopoHandler) http.HandleFunc("/trc", trcHandler) fsStatic := http.FileServer(http.Dir(path.Join(options.StaticRoot, "static"))) @@ -217,6 +271,9 @@ func initServeHandlers() { http.HandleFunc("/getpathtopo", getPathInfoHandler) http.HandleFunc("/getastopo", getAsTopoHandler) http.HandleFunc("/gettrc", getTrcInfoHandler) + + http.HandleFunc("/__proxy/setconfig", setProxyConfig) + http.HandleFunc("/__proxy/", proxyWrapper) } func logRequestHandler(handler http.Handler) http.Handler { @@ -237,6 +294,7 @@ func prepareTemplates(srcpath string) *template.Template { path.Join(srcpath, "template/about.html"), path.Join(srcpath, "template/astopo.html"), path.Join(srcpath, "template/trc.html"), + path.Join(srcpath, "template/webview.html"), )) } @@ -275,6 +333,10 @@ func appsHandler(w http.ResponseWriter, r *http.Request) { display(w, "apps", &Page{Title: "SCIONLab Apps", MyIA: settings.MyIA}) } +func webviewHandler(w http.ResponseWriter, r *http.Request) { + display(w, "webview", &Page{Title: "SCION HTTP", MyIA: settings.MyIA}) +} + func astopoHandler(w http.ResponseWriter, r *http.Request) { display(w, "astopo", &Page{Title: "SCIONLab AS Topology", MyIA: settings.MyIA}) }