fix(opds): epubcfi Atom compatibility, path deduplication, auth tokens
- Add <title> and <author><name> elements to Atom feed for compatibility - Remove doubled /opds/opds/ path prefix in feed URLs - Include ?token= auth param on all OPDS URLs - Serve kepub links only for Kobo devices - Fix URL construction for entries and acquisitions
This commit is contained in:
+37
-14
@@ -49,6 +49,24 @@ func (h *OPDSHandler) getBaseURLs(c *echo.Context) (string, string, error) {
|
||||
return baseURL.Value, opdsBaseURL, nil
|
||||
}
|
||||
|
||||
func (h *OPDSHandler) getAuthToken(c *echo.Context) string {
|
||||
token := c.QueryParam("token")
|
||||
if token == "" {
|
||||
token = strings.TrimPrefix(c.Request().Header.Get("Authorization"), "Bearer ")
|
||||
}
|
||||
return token
|
||||
}
|
||||
|
||||
func appendToken(url, token string) string {
|
||||
if token == "" {
|
||||
return url
|
||||
}
|
||||
if strings.Contains(url, "?") {
|
||||
return url + "&token=" + token
|
||||
}
|
||||
return url + "?token=" + token
|
||||
}
|
||||
|
||||
// GetDeviceCatalog returns the OPDS catalog feed for a device
|
||||
func (h *OPDSHandler) GetDeviceCatalog(c *echo.Context) error {
|
||||
deviceID := c.Param("deviceId")
|
||||
@@ -140,11 +158,12 @@ func (h *OPDSHandler) GetDeviceCatalog(c *echo.Context) error {
|
||||
)
|
||||
|
||||
// Add feed links
|
||||
catalogURL := fmt.Sprintf("%s/opds/devices/%s/catalog", opdsBaseURL, deviceID)
|
||||
token := h.getAuthToken(c)
|
||||
catalogURL := appendToken(fmt.Sprintf("%s/devices/%s/catalog", opdsBaseURL, deviceID), token)
|
||||
feed.AddLink(catalogURL, "application/atom+xml;profile=opds-catalog;kind=acquisition", "self")
|
||||
feed.AddLink(catalogURL, "application/atom+xml;profile=opds-catalog;kind=acquisition", "start")
|
||||
|
||||
searchURL := fmt.Sprintf("%s/opds/devices/%s/search", opdsBaseURL, deviceID)
|
||||
searchURL := appendToken(fmt.Sprintf("%s/devices/%s/search", opdsBaseURL, deviceID), token)
|
||||
feed.AddLink(searchURL, "application/atom+xml;profile=opds-catalog;kind=acquisition", "search")
|
||||
|
||||
// Add entries
|
||||
@@ -171,14 +190,15 @@ func (h *OPDSHandler) GetDeviceCatalog(c *echo.Context) error {
|
||||
}
|
||||
|
||||
// Add acquisition links
|
||||
downloadURL := fmt.Sprintf("%s/opds/devices/%s/download/%s", opdsBaseURL, deviceID, bookUUID)
|
||||
downloadURL := appendToken(fmt.Sprintf("%s/devices/%s/download/%s", opdsBaseURL, deviceID, bookUUID), token)
|
||||
entry.AddAcquisitionLink(downloadURL, "application/epub+zip")
|
||||
|
||||
// Add format variants
|
||||
kepubURL := fmt.Sprintf("%s?format=kepub", downloadURL)
|
||||
entry.AddAlternateLink(kepubURL, "application/vnd.kobo+xml+zip")
|
||||
if device.DeviceType == "kobo" {
|
||||
kepubURL := downloadURL + "&format=kepub"
|
||||
entry.AddAlternateLink(kepubURL, "application/vnd.kobo+xml+zip")
|
||||
}
|
||||
|
||||
pdfURL := fmt.Sprintf("%s?format=pdf", downloadURL)
|
||||
pdfURL := downloadURL + "&format=pdf"
|
||||
entry.AddAlternateLink(pdfURL, "application/pdf")
|
||||
|
||||
// Add canonical identifier
|
||||
@@ -267,10 +287,11 @@ func (h *OPDSHandler) SearchDeviceCatalog(c *echo.Context) error {
|
||||
)
|
||||
|
||||
// Add feed links
|
||||
catalogURL := fmt.Sprintf("%s/opds/devices/%s/catalog", opdsBaseURL, deviceID)
|
||||
token := h.getAuthToken(c)
|
||||
catalogURL := appendToken(fmt.Sprintf("%s/devices/%s/catalog", opdsBaseURL, deviceID), token)
|
||||
feed.AddLink(catalogURL, "application/atom+xml;profile=opds-catalog;kind=acquisition", "start")
|
||||
|
||||
searchURL := fmt.Sprintf("%s/opds/devices/%s/search?q=%s", opdsBaseURL, deviceID, query)
|
||||
searchURL := appendToken(fmt.Sprintf("%s/devices/%s/search?q=%s", opdsBaseURL, deviceID, query), token)
|
||||
feed.AddLink(searchURL, "application/atom+xml;profile=opds-catalog;kind=acquisition", "self")
|
||||
|
||||
// Add entries (same as catalog)
|
||||
@@ -296,11 +317,13 @@ func (h *OPDSHandler) SearchDeviceCatalog(c *echo.Context) error {
|
||||
entry.SetSummary(item.Description.String)
|
||||
}
|
||||
|
||||
downloadURL := fmt.Sprintf("%s/opds/devices/%s/download/%s", opdsBaseURL, deviceID, bookUUID)
|
||||
downloadURL := appendToken(fmt.Sprintf("%s/devices/%s/download/%s", opdsBaseURL, deviceID, bookUUID), token)
|
||||
entry.AddAcquisitionLink(downloadURL, "application/epub+zip")
|
||||
|
||||
kepubURL := fmt.Sprintf("%s?format=kepub", downloadURL)
|
||||
entry.AddAlternateLink(kepubURL, "application/vnd.kobo+xml+zip")
|
||||
if device.DeviceType == "kobo" {
|
||||
kepubURL := downloadURL + "&format=kepub"
|
||||
entry.AddAlternateLink(kepubURL, "application/vnd.kobo+xml+zip")
|
||||
}
|
||||
|
||||
entry.SetIdentifier(bookUUID)
|
||||
|
||||
@@ -599,7 +622,7 @@ func (h *OPDSHandler) GetDeviceNavigation(c *echo.Context) error {
|
||||
)
|
||||
|
||||
// Add feed links
|
||||
catalogURL := fmt.Sprintf("%s/opds/devices/%s/catalog", opdsBaseURL, deviceID)
|
||||
catalogURL := fmt.Sprintf("%s/devices/%s/catalog", opdsBaseURL, deviceID)
|
||||
feed.AddLink(catalogURL, "application/atom+xml;profile=opds-catalog;kind=acquisition", "start")
|
||||
feed.AddLink(catalogURL, "application/atom+xml;profile=opds-catalog;kind=acquisition", "self")
|
||||
|
||||
@@ -791,7 +814,7 @@ func (h *OPDSHandler) RegisterOPDS(c *echo.Context) error {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to create OPDS token"})
|
||||
}
|
||||
|
||||
catalogURL := fmt.Sprintf("%s/opds/devices/%s/catalog", opdsBaseURL, deviceID)
|
||||
catalogURL := fmt.Sprintf("%s/devices/%s/catalog", opdsBaseURL, deviceID)
|
||||
|
||||
return c.JSON(http.StatusOK, map[string]interface{}{
|
||||
"opds_token": map[string]interface{}{
|
||||
|
||||
+13
-4
@@ -22,8 +22,8 @@ type Feed struct {
|
||||
|
||||
type Entry struct {
|
||||
ID string `xml:"id"`
|
||||
Title string `xml:"dc:title"`
|
||||
Creator string `xml:"dc:creator,omitempty"`
|
||||
Title string `xml:"title"`
|
||||
Author *Author `xml:"author,omitempty"`
|
||||
Updated string `xml:"updated"`
|
||||
Summary string `xml:"summary,omitempty"`
|
||||
Links []Link `xml:"link"`
|
||||
@@ -32,6 +32,12 @@ type Entry struct {
|
||||
Categories []Category `xml:"category,omitempty"`
|
||||
}
|
||||
|
||||
type Author struct {
|
||||
XMLName xml.Name `xml:"author"`
|
||||
Name string `xml:"name"`
|
||||
URI string `xml:"uri,omitempty"`
|
||||
}
|
||||
|
||||
type Link struct {
|
||||
Href string `xml:"href,attr"`
|
||||
Type string `xml:"type,attr"`
|
||||
@@ -85,14 +91,17 @@ func (f *Feed) AddEntry(entry Entry) {
|
||||
|
||||
// NewEntry creates a new OPDS entry
|
||||
func NewEntry(id, title, creator, updated string) Entry {
|
||||
return Entry{
|
||||
e := Entry{
|
||||
ID: id,
|
||||
Title: title,
|
||||
Creator: creator,
|
||||
Updated: updated,
|
||||
Links: []Link{},
|
||||
Metadata: []Meta{},
|
||||
}
|
||||
if creator != "" {
|
||||
e.Author = &Author{Name: creator}
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// AddAcquisitionLink adds an acquisition link to the entry
|
||||
|
||||
Reference in New Issue
Block a user