Browse Source

Add support for extra.d directory

To allow muliple plugins, sorted plugin load and general extensibility
of the web client, the server now supports to load an extra.d folder on
startup.

Sub folders inside extra.d, are loaded in alphabetic order and searched
for head.html and body.html, making it possible to append additional
html code into the <head> and <body> elements for the web client.

Example:
```
	extra.d/
	└── my-plugin
	    ├── body.html
	    ├── head.html
	    └── static
	        ├── css
	        │   └── my-plugin.css
	        └── js
	            └── my-plugin.js
```

Example head.html:
```
	<link rel="stylesheet" href="<%.S%>/css/my-plugin.css">
```

Example body.html:
```
	<script data-plugin="<%.S%>/js/my-plugin.js"></script>
```

This makes it possible to extend the web client with additional
components and/or overwrite existing.
pull/304/head
Simon Eisenmann 9 years ago
parent
commit
cfec82384a
  1. 1
      .gitignore
  2. 25
      go/channelling/context.go
  3. 3
      html/head.html
  4. 3
      html/main.html
  5. 8
      server.conf.in
  6. 18
      src/app/spreed-webrtc-server/handler_room.go
  7. 52
      src/app/spreed-webrtc-server/main.go
  8. 23
      src/app/spreed-webrtc-server/utils.go

1
.gitignore vendored

@ -19,6 +19,7 @@ vendor/* @@ -19,6 +19,7 @@ vendor/*
/build/out/
/.sass-cache
/extra
/extra.d
/src/i18n/*.mo
server.key
server.csr

25
go/channelling/context.go

@ -21,14 +21,21 @@ @@ -21,14 +21,21 @@
package channelling
import (
"html/template"
)
type Context struct {
App string // Main client script
Cfg *Config
Host string
Ssl bool
Csp bool
Languages []string
Room string `json:"-"`
Scheme string `json:"-"`
Origin string `json:",omitempty"`
App string // Main client script
Cfg *Config
Host string
Ssl bool
Csp bool
Languages []string
Room string `json:"-"`
Scheme string `json:"-"`
Origin string `json:",omitempty"`
S string `json:",omitempty"`
ExtraDHead template.HTML `json:"-"`
ExtraDBody template.HTML `json:"-"`
}

3
html/head.html

@ -11,4 +11,5 @@ @@ -11,4 +11,5 @@
<link rel="stylesheet" type="text/css" href="<%.Cfg.S%>/css/font-awesome.min.css">
<link rel="stylesheet" type="text/css" href="<%.Cfg.S%>/css/main.min.css">
<%template "extra-head" .%>
<script id="globalcontext" type="application/json"><%$%></script><%end%>
<%.ExtraDHead%>
<script id="globalcontext" type="application/json"><%$%></script><%end%>

3
html/main.html

@ -9,5 +9,6 @@ @@ -9,5 +9,6 @@
<ui></ui>
<script data-main="<%.Cfg.S%>/js/<%.App%>" data-plugin="<%.Cfg.Plugin%>" src="<%.Cfg.S%>/js/libs/require/require.js"></script>
<%template "extra-body" .%>
<%.ExtraDBody%>
</body>
</html><%end%>
</html><%end%>

8
server.conf.in

@ -101,14 +101,20 @@ serverRealm = local @@ -101,14 +101,20 @@ serverRealm = local
; Full path to an extra templates directory. Templates in this directory ending
; with .html will be parsed on startup and can be used to fill the supported
; extra-* template slots. If the extra folder has a sub folder "static", the
; resources in this static folder will be available as /extra/static/filename
; resources in this static folder will be available as /extra/static/...
; relative to your servers base URL.
;extra = /usr/share/spreed-webrtc-server/extra
; Full path to an extra.d directory. Subfolders in this directory will be
; searched for head.html and body.html on startup. If found, those templates
; will be automatically included for the web client. In addition,
; sub-folder/static will be made available by URL at /extra.d/static/<n>/...
; relative to your servers base URL.
; URL relative to the servers base path for a plugin javascript file which is
; automatically loaded on web client start for all users. You can put your
; plugin in the extra/static folder (see above) or provide another folder using
; a front end webserver. Check the doc folder for more info about plugins and
; examples.
;extra.d = /usr/share/spreed-webrtc-server/extra.d
;plugin = extra/static/myplugin.js
; Content-Security-Policy HTTP response header value.
; Spreed WebRTC requires inline styles, WebSocket connection to itself and

18
src/app/spreed-webrtc-server/handler_room.go

@ -70,7 +70,19 @@ func handleRoomView(room string, w http.ResponseWriter, r *http.Request) { @@ -70,7 +70,19 @@ func handleRoomView(room string, w http.ResponseWriter, r *http.Request) {
}
// Prepare context to deliver to HTML..
context := &channelling.Context{Cfg: config, App: "main", Host: r.Host, Scheme: scheme, Ssl: ssl, Csp: csp, Languages: langs, Room: room}
context := &channelling.Context{
Cfg: config,
App: "main",
Host: r.Host,
Scheme: scheme,
Ssl: ssl,
Csp: csp,
Languages: langs,
Room: room,
S: config.S,
ExtraDHead: templatesExtraDHead,
ExtraDBody: templatesExtraDBody,
}
// Get URL parameters.
r.ParseForm()
@ -79,10 +91,10 @@ func handleRoomView(room string, w http.ResponseWriter, r *http.Request) { @@ -79,10 +91,10 @@ func handleRoomView(room string, w http.ResponseWriter, r *http.Request) {
// See https://developers.google.com/webmasters/ajax-crawling/docs/getting-started for details.
if _, ok := r.Form["_escaped_fragment_"]; ok {
// Render crawlerPage template..
err = templates.ExecuteTemplate(w, "crawlerPage", &context)
err = templates.ExecuteTemplate(w, "crawlerPage", context)
} else {
// Render mainPage template.
err = templates.ExecuteTemplate(w, "mainPage", &context)
err = templates.ExecuteTemplate(w, "mainPage", context)
}
if err != nil {

52
src/app/spreed-webrtc-server/main.go

@ -22,11 +22,13 @@ @@ -22,11 +22,13 @@
package main
import (
"bytes"
"crypto/rand"
"encoding/hex"
"flag"
"fmt"
"html/template"
"io/ioutil"
"log"
"net/http"
_ "net/http/pprof"
@ -53,6 +55,8 @@ var version = "unreleased" @@ -53,6 +55,8 @@ var version = "unreleased"
var defaultConfig = "./server.conf"
var templates *template.Template
var templatesExtraDHead template.HTML
var templatesExtraDBody template.HTML
var config *channelling.Config
func runner(runtime phoenix.Runtime) error {
@ -208,6 +212,45 @@ func runner(runtime phoenix.Runtime) error { @@ -208,6 +212,45 @@ func runner(runtime phoenix.Runtime) error {
log.Printf("Loaded extra templates from: %s", extraFolder)
}
// Load extra.d folder
extraDFolder, err := runtime.GetString("app", "extra.d")
if err == nil {
if !httputils.HasDirPath(extraFolder) {
return fmt.Errorf("Configured extra '%s' is not a directory.", extraFolder)
}
var headBuf bytes.Buffer
var bodyBuf bytes.Buffer
context := &channelling.Context{
Cfg: config,
}
if extras, err := ioutil.ReadDir(extraDFolder); err == nil {
// ioutil.ReadDir is sorted by name which is what we want here.
for _, extra := range extras {
if !extra.IsDir() {
continue
}
context.S = fmt.Sprintf("extra.d/%s/%s", config.S, extra.Name())
extraDTemplates := template.New("")
extraDTemplates.Delims("<%", "%>")
extraBase := path.Join(extraDFolder, extra.Name())
extraDTemplates.ParseFiles(path.Join(extraBase, "head.html"), path.Join(extraBase, "body.html"))
if headTemplate := extraDTemplates.Lookup("head.html"); headTemplate != nil {
if err := headTemplate.Execute(&headBuf, context); err != nil {
log.Println("Failed to parse extra.d template", extraBase, "head.html", err)
}
}
if bodyTemplate := extraDTemplates.Lookup("body.html"); bodyTemplate != nil {
if err := bodyTemplate.Execute(&bodyBuf, context); err != nil {
log.Println("Failed to parse extra.d template", extraBase, "body.html", err)
}
}
}
}
templatesExtraDHead = template.HTML(headBuf.String())
templatesExtraDBody = template.HTML(bodyBuf.String())
}
// Define incoming channeling API limit it byte. Larger messages will be discarded.
incomingCodecLimit := 1024 * 1024 // 1MB
@ -326,13 +369,20 @@ func runner(runtime phoenix.Runtime) error { @@ -326,13 +369,20 @@ func runner(runtime phoenix.Runtime) error {
// Add extra/static support if configured and exists.
if extraFolder != "" {
extraFolderStatic := path.Join(extraFolder, "static")
extraFolderStatic, _ := filepath.Abs(path.Join(extraFolder, "static"))
if _, err = os.Stat(extraFolderStatic); err == nil {
r.Handle("/extra/static/{path:.*}", http.StripPrefix(fmt.Sprintf("%sextra", config.B), httputils.FileStaticServer(http.Dir(extraFolder))))
log.Printf("Added URL handler /extra/static/... for static files in %s/...\n", extraFolderStatic)
}
}
// Add extra.d/static support if configured.
if extraDFolder != "" {
extraDFolderStatic, _ := filepath.Abs(extraDFolder)
r.Handle("/extra.d/static/{ver}/{extra}/{path:.*}", http.StripPrefix(fmt.Sprintf("%sextra.d/static", config.B), rewriteExtraDUrl(httputils.FileStaticServer(http.Dir(extraDFolderStatic)))))
log.Printf("Added URL handler /extra.d/static/... for static files in %s/.../static/... \n", extraDFolderStatic)
}
// Finally add websocket handler.
r.Handle("/ws", makeWSHandler(statsManager, sessionManager, codec, channellingAPI, users))

23
src/app/spreed-webrtc-server/utils.go

@ -1,8 +1,11 @@ @@ -1,8 +1,11 @@
package main
import (
"fmt"
"net/http"
"github.com/gorilla/mux"
"github.com/strukturag/goacceptlanguageparser"
)
@ -15,3 +18,23 @@ func getRequestLanguages(r *http.Request, supportedLanguages []string) []string @@ -15,3 +18,23 @@ func getRequestLanguages(r *http.Request, supportedLanguages []string) []string
}
return langs
}
func rewriteExtraDUrl(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
extra, ok := vars["extra"]
if !ok {
http.NotFound(w, r)
return
}
path, ok := vars["path"]
if !ok {
http.NotFound(w, r)
return
}
r.URL.Path = fmt.Sprintf("%s/static/%s", extra, path)
h.ServeHTTP(w, r)
})
}

Loading…
Cancel
Save