Add support CORS for API

This commit is contained in:
Alexey Khit
2022-11-23 20:34:06 +03:00
parent 1ddf7f1a6c
commit bd51069086
3 changed files with 37 additions and 34 deletions
+4 -3
View File
@@ -313,9 +313,10 @@ The HTTP API is the main part for interacting with the application. Default addr
```yaml ```yaml
api: api:
listen: ":1984" # HTTP API port ("" - disabled) listen: ":1984" # HTTP API port ("" - disabled)
base_path: "" # API prefix for serve on suburl base_path: "/rtc" # API prefix for serve on suburl (/api => /rtc/api)
static_dir: "" # folder for static files (custom web interface) static_dir: "www" # folder for static files (custom web interface)
origin: "*" # allow CORS requests (only * supported)
``` ```
**PS. go2rtc** doesn't provide HTTPS or password protection. Use [Nginx](https://nginx.org/) or [Ngrok](#module-ngrok) or [Home Assistant Add-on](#go2rtc-home-assistant-add-on) for this tasks. **PS. go2rtc** doesn't provide HTTPS or password protection. Use [Nginx](https://nginx.org/) or [Ngrok](#module-ngrok) or [Home Assistant Add-on](#go2rtc-home-assistant-add-on) for this tasks.
+29 -11
View File
@@ -17,6 +17,7 @@ func Init() {
Listen string `yaml:"listen"` Listen string `yaml:"listen"`
BasePath string `yaml:"base_path"` BasePath string `yaml:"base_path"`
StaticDir string `yaml:"static_dir"` StaticDir string `yaml:"static_dir"`
Origin string `yaml:"origin"`
} `yaml:"api"` } `yaml:"api"`
} }
@@ -34,7 +35,7 @@ func Init() {
log = app.GetLogger("api") log = app.GetLogger("api")
initStatic(cfg.Mod.StaticDir) initStatic(cfg.Mod.StaticDir)
initWS() initWS(cfg.Mod.Origin)
HandleFunc("api/streams", streamsHandler) HandleFunc("api/streams", streamsHandler)
HandleFunc("api/ws", apiWS) HandleFunc("api/ws", apiWS)
@@ -48,16 +49,18 @@ func Init() {
log.Info().Str("addr", cfg.Mod.Listen).Msg("[api] listen") log.Info().Str("addr", cfg.Mod.Listen).Msg("[api] listen")
s := http.Server{}
s.Handler = http.DefaultServeMux
if log.Trace().Enabled() {
s.Handler = middlewareLog(s.Handler)
}
if cfg.Mod.Origin == "*" {
s.Handler = middlewareCORS(s.Handler)
}
go func() { go func() {
s := http.Server{}
if log.Trace().Enabled() {
s.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Trace().Stringer("url", r.URL).Msgf("[api] %s", r.Method)
http.DefaultServeMux.ServeHTTP(w, r)
})
}
if err = s.Serve(listener); err != nil { if err = s.Serve(listener); err != nil {
log.Fatal().Err(err).Msg("[api] serve") log.Fatal().Err(err).Msg("[api] serve")
} }
@@ -83,10 +86,25 @@ var basePath string
var log zerolog.Logger var log zerolog.Logger
var wsHandlers = make(map[string]WSHandler) var wsHandlers = make(map[string]WSHandler)
func middlewareLog(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Trace().Msgf("[api] %s %s", r.Method, r.URL)
next.ServeHTTP(w, r)
})
}
func middlewareCORS(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
next.ServeHTTP(w, r)
})
}
func streamsHandler(w http.ResponseWriter, r *http.Request) { func streamsHandler(w http.ResponseWriter, r *http.Request) {
src := r.URL.Query().Get("src") src := r.URL.Query().Get("src")
name := r.URL.Query().Get("name") name := r.URL.Query().Get("name")
if name == "" { if name == "" {
name = src name = src
} }
+4 -20
View File
@@ -4,35 +4,19 @@ import (
"github.com/AlexxIT/go2rtc/pkg/streamer" "github.com/AlexxIT/go2rtc/pkg/streamer"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"net/http" "net/http"
"net/url"
"strings"
"sync" "sync"
) )
func initWS() { func initWS(origin string) {
wsUp = &websocket.Upgrader{ wsUp = &websocket.Upgrader{
ReadBufferSize: 1024, ReadBufferSize: 1024,
WriteBufferSize: 512000, WriteBufferSize: 512000,
} }
wsUp.CheckOrigin = func(r *http.Request) bool {
origin := r.Header["Origin"] if origin == "*" {
if len(origin) == 0 { wsUp.CheckOrigin = func(r *http.Request) bool {
return true return true
} }
o, err := url.Parse(origin[0])
if err != nil {
return false
}
if o.Host == r.Host {
return true
}
log.Trace().Msgf("[api.ws] origin: %s, host: %s", o.Host, r.Host)
// some users change Nginx external port using Docker port
// so origin will be with a port and host without
if i := strings.IndexByte(o.Host, ':'); i > 0 {
return o.Host[:i] == r.Host
}
return false
} }
} }