forked from Ivasoft/opds-proxy
feat: server-side feed credentials
If a feed requires credentials, OPDS Proxy can transparently set them server side by reading the feed configuration. This is useful in scenarios where the server operator sets up their own authentication in front of OPDS Proxy and doesn't want to have users remember separate credentials for each of the configured feeds.
This commit is contained in:
11
main.go
11
main.go
@@ -26,8 +26,14 @@ type auth struct {
|
||||
}
|
||||
|
||||
type feedConfig struct {
|
||||
Name string `koanf:"name"`
|
||||
Url string `koanf:"url"`
|
||||
Name string `koanf:"name"`
|
||||
Url string `koanf:"url"`
|
||||
Username string `koanf:"username"`
|
||||
Password string `koanf:"password"`
|
||||
}
|
||||
|
||||
func (f feedConfig) HasCredentials() bool {
|
||||
return f.Username != "" && f.Password != ""
|
||||
}
|
||||
|
||||
var k = koanf.New(".")
|
||||
@@ -70,7 +76,6 @@ func main() {
|
||||
|
||||
config.Auth.HashKey = hashKey
|
||||
config.Auth.BlockKey = blockKey
|
||||
|
||||
}
|
||||
|
||||
server, err := NewServer(&config)
|
||||
|
||||
43
server.go
43
server.go
@@ -57,7 +57,7 @@ func NewServer(config *config) (*Server, error) {
|
||||
|
||||
router := http.NewServeMux()
|
||||
router.HandleFunc("GET /{$}", handleHome(config.Feeds))
|
||||
router.HandleFunc("GET /feed", handleFeed("tmp/", s))
|
||||
router.HandleFunc("GET /feed", handleFeed("tmp/", config.Feeds, s))
|
||||
router.HandleFunc("/auth", handleAuth(s))
|
||||
router.Handle("GET /static/", http.FileServer(http.FS(html.StaticFiles())))
|
||||
|
||||
@@ -87,7 +87,7 @@ func handleHome(feeds []feedConfig) http.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
func handleFeed(outputDir string, s *securecookie.SecureCookie) http.HandlerFunc {
|
||||
func handleFeed(outputDir string, feeds []feedConfig, s *securecookie.SecureCookie) http.HandlerFunc {
|
||||
kepubConverter := &convert.KepubConverter{}
|
||||
mobiConverter := &convert.MobiConverter{}
|
||||
|
||||
@@ -110,7 +110,7 @@ func handleFeed(outputDir string, s *securecookie.SecureCookie) http.HandlerFunc
|
||||
queryURL = replaceSearchPlaceHolder(queryURL, searchTerm)
|
||||
}
|
||||
|
||||
resp, err := fetchFromUrl(queryURL, getCredentials(r, s))
|
||||
resp, err := fetchFromUrl(queryURL, getCredentials(r, feeds, s))
|
||||
if err != nil {
|
||||
handleError(r, w, "Failed to fetch", err)
|
||||
return
|
||||
@@ -231,7 +231,33 @@ func handleAuth(s *securecookie.SecureCookie) http.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
func getCredentials(r *http.Request, s *securecookie.SecureCookie) *Credentials {
|
||||
func getCredentials(r *http.Request, feeds []feedConfig, s *securecookie.SecureCookie) *Credentials {
|
||||
if !r.URL.Query().Has("q") {
|
||||
return nil
|
||||
}
|
||||
|
||||
feedUrl, err := url.Parse(r.URL.Query().Get("q"))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Try to get credentials from the config first
|
||||
for _, feed := range feeds {
|
||||
if !feed.HasCredentials() {
|
||||
continue
|
||||
}
|
||||
|
||||
configUrl, err := url.Parse(feed.Url)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if configUrl.Hostname() == feedUrl.Hostname() {
|
||||
return &Credentials{Username: feed.Username, Password: feed.Password}
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, try to get credentials from the cookie
|
||||
cookie, err := r.Cookie("auth-creds")
|
||||
if err != nil {
|
||||
return nil
|
||||
@@ -242,15 +268,6 @@ func getCredentials(r *http.Request, s *securecookie.SecureCookie) *Credentials
|
||||
return nil
|
||||
}
|
||||
|
||||
if !r.URL.Query().Has("q") {
|
||||
return nil
|
||||
}
|
||||
|
||||
feedUrl, err := url.Parse(r.URL.Query().Get("q"))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return value[feedUrl.Hostname()]
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user