opds

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 23, 2026 License: MIT Imports: 4 Imported by: 0

README

opds

A Go library for building, implementing, and embedding OPDS (Open Publication Distribution System) catalog services — the standard ebook readers and library systems use to browse, search, and acquire publications.

You model your catalog once, with version-neutral types, and the library serializes it to either supported wire format, chosen by content negotiation:

Version Format Status Clients
OPDS 1.2 Atom (XML) stable, universal Calibre, KOReader, Thorium, FBReader, Foliate, Aldiko, Moon+, …
OPDS 2.0 JSON (Readium Web Publication Manifest) current draft Thorium, Readium toolkits, Palace/SimplyE, newer apps

Zero dependencies — only the Go standard library.

Install

go get github.com/ophymx/opds

Packages

Package Purpose
opds Version-neutral domain model, constants, and fluent builders.
opds/opds1 Encodes the model to OPDS 1.2 (Atom XML).
opds/opds2 Encodes the model to OPDS 2.0 (JSON).
opds/opensearch Generates OpenSearch description documents (1.x search).
opds/opdshttp Embeddable http.Handler: routing, content negotiation, pagination, search.

Quick start

Implement the opds.Source interface (and optionally opds.Searcher), hand it to opdshttp, and you have a catalog that speaks both OPDS versions.

package main

import (
	"context"
	"net/http"

	"github.com/ophymx/opds"
	"github.com/ophymx/opds/opdshttp"
)

type catalog struct{}

func (catalog) Root(_ context.Context, _ opds.FeedRequest) (*opds.Feed, error) {
	return opds.NewFeed("urn:cat:root", "My Library").
		AddNav("All Books", "/opds/feed/all", opds.MediaTypeAcquisition, opds.RelSortNew), nil
}

func (catalog) Feed(_ context.Context, req opds.FeedRequest) (*opds.Feed, error) {
	if req.ID != "all" {
		return nil, opds.ErrNotFound
	}
	book := opds.NewPublication("urn:isbn:9780134190440", "The Go Programming Language").
		By("Alan Donovan").By("Brian Kernighan").
		In("en").ISBN("9780134190440").About("Computers").
		Cover("/covers/gopl.jpg", "image/jpeg").
		OpenAccess("/download/gopl.epub", "application/epub+zip")
	return opds.NewFeed("urn:cat:all", "All Books").Add(*book), nil
}

func (catalog) Publication(_ context.Context, id string) (*opds.Publication, error) {
	return nil, opds.ErrNotFound // serve standalone entry documents if you like
}

func main() {
	h := opdshttp.New(catalog{}, opdshttp.WithPrefix("/opds"))
	http.Handle("/opds/", h)
	http.ListenAndServe(":8080", nil)
}
curl localhost:8080/opds/                                    # OPDS 1.2 (default)
curl -H 'Accept: application/opds+json' localhost:8080/opds/ # OPDS 2.0
curl 'localhost:8080/opds/?version=2'                        # OPDS 2.0 via query

A complete runnable catalog with multiple feeds, subjects, and search lives in examples/bookstore: go run ./examples/bookstore.

The domain model

Both OPDS versions express the same concepts, so you build them once:

  • Feed — a navigation feed (entries link to sub-feeds via AddNav) or an acquisition feed (entries are publications via Add).
  • Publication — bibliographic metadata, cover images, and acquisition links.
  • Acquisition — how to obtain a publication: open-access, buy, borrow, sample, or subscribe, with prices, indirect acquisition (e.g. LCP → EPUB), and library-lending availability / holds / copies.
  • Facet / Group — filtered/sorted views and labelled sections.
  • Pagination via Feed.Page(total, perPage, startIndex).

Fluent builders keep construction terse:

p := opds.NewPublication("urn:isbn:9781503280786", "Moby-Dick").
	By("Herman Melville").In("en").ISBN("9781503280786").
	PublishedAt(pubDate).About("Fiction").
	Summarize("The voyage of the Pequod.").
	Cover("/covers/moby.jpg", "image/jpeg").
	Buy("/buy/moby", "application/epub+zip", "USD", 4.99)

// Library lending with availability, a hold queue, and copy counts:
pos := 5
p.Acquire(opds.Acquisition{
	Rel:          opds.AcquireBorrow,
	Href:         "/borrow/moby",
	Type:         "application/epub+zip",
	Availability: &opds.Availability{State: opds.StateUnavailable, Until: dueDate},
	Holds:        &opds.Holds{Total: 12, Position: &pos},
	Copies:       &opds.Copies{Total: 3, Available: 0},
})

If your Source also implements opds.Searcher, the handler automatically:

  • serves search results at {prefix}/search?q=...,
  • serves an OpenSearch description at {prefix}/opensearch.xml (for 1.x clients),
  • advertises a search link in every feed (OpenSearch for 1.2, a templated link for 2.0).
func (catalog) Search(_ context.Context, req opds.SearchRequest) (*opds.Feed, error) {
	results := db.Query(req.Terms) // also: req.Author, req.Title, req.Page
	f := opds.NewFeed("urn:cat:search", "Results")
	for _, b := range results {
		f.Add(toPublication(b))
	}
	return f, nil
}

func (catalog) SearchDescription() opds.SearchDescription {
	return opds.SearchDescription{ShortName: "My Library", Description: "Search the catalog"}
}

Content negotiation

The handler picks the version per request, in priority order:

  1. ?version=1 / ?version=2 (or ?f=atom / ?f=json) query parameter.
  2. The Accept header (application/opds+json → 2.0; atom+xml → 1.2).
  3. The configured default (WithDefaultVersion, defaulting to 1.2 for maximum client compatibility).

URL layout

opdshttp.Handler serves this layout relative to its mount prefix. Use the FeedPath, PublicationPath, and SearchPath helpers (or the handler's FeedURL etc. methods) to build matching hrefs in your Source:

{prefix}/                  root feed
{prefix}/feed/{id}         a feed by id
{prefix}/publication/{id}  a single publication document
{prefix}/search            search results
{prefix}/opensearch.xml    OpenSearch description

Using the encoders directly

You don't have to use opdshttp. The encoders turn a *opds.Feed into bytes, so they drop into any framework or static-generation pipeline:

xmlBytes, _ := opds1.Marshal(feed)  // OPDS 1.2 Atom
jsonBytes, _ := opds2.Marshal(feed) // OPDS 2.0 JSON

Conformance

The encoders are tested against the official OPDS schemas, not just hand-written expectations:

  • OPDS 2.0 output is validated against the official JSON Schemas from opds-community/specs and the Readium Web Publication Manifest schemas they reference. These tests are pure Go (using a vendored copy of the schemas) and run under go test ./....
  • OPDS 1.2 output is validated against the official RELAX NG schema (opds.rnc) with Jing — the reference validator behind the official OPDS validator. These tests need a JRE and skip automatically when Java/Jing are absent, so go test ./... still passes everywhere.

To run the 1.2 RELAX NG tests, which fetch Jing into tools/ on first run:

scripts/conformance.sh

Vendored schema provenance (and the one documented upstream-typo fix in opds.rnc) is recorded in the testdata/schema/*/SOURCES.md files.

Status / scope

  • OPDS 1.2 and 2.0 feeds, navigation and acquisition — validated against the official schemas (see Conformance).
  • Acquisition model including prices, nested indirect acquisition, and library lending (availability/holds/copies).
  • Facets, groups, pagination, OpenSearch.

A note on library lending in 1.2: opds:availability/holds/copies are standard in OPDS 2.0 but are not part of the official OPDS 1.2 RELAX NG schema — they are a de-facto 1.x extension (Library Simplified/Palace). The library emits them in both versions because real library clients rely on them; just be aware that a 1.2 feed using them intentionally goes beyond the core 1.2 schema.

Not yet included: the OPDS Authentication document flow (the model leaves room for it). Contributions welcome.

References

License

MIT © 2026 Jeffrey T. Peckham

Documentation

Overview

Package opds provides a version-neutral domain model and helpers for building OPDS (Open Publication Distribution System) catalog services.

OPDS is a syndication format for electronic publications. Two wire formats are in wide use:

  • OPDS 1.2, an Atom (XML) based format. Universally supported by readers such as Calibre, KOReader, Thorium, FBReader and many others.
  • OPDS 2.0, a JSON format built on the Readium Web Publication Manifest.

Both express the same conceptual model, so this library models a catalog once, with version-neutral types, and lets pluggable encoders serialize to either format:

  • Package opds the domain model, constants and builders (this package).
  • Package opds/opds1 encodes the model to OPDS 1.2 (Atom XML).
  • Package opds/opds2 encodes the model to OPDS 2.0 (JSON).
  • Package opds/opensearch generates OpenSearch description documents (1.x search).
  • Package opds/opdshttp an embeddable http.Handler tying it together.

To expose a catalog you implement the Source interface (and, optionally, Searcher) and hand it to opds/opdshttp, or drive the encoders directly.

Index

Constants

View Source
const (
	// MediaTypeNavigation is the media type of an OPDS 1.x navigation feed.
	MediaTypeNavigation = "application/atom+xml;profile=opds-catalog;kind=navigation"
	// MediaTypeAcquisition is the media type of an OPDS 1.x acquisition feed.
	MediaTypeAcquisition = "application/atom+xml;profile=opds-catalog;kind=acquisition"
	// MediaTypeEntry is the media type of a standalone OPDS 1.x entry document.
	MediaTypeEntry = "application/atom+xml;type=entry;profile=opds-catalog"

	// MediaTypeFeed is the media type of an OPDS 2.0 feed.
	MediaTypeFeed = "application/opds+json"
	// MediaTypePublication is the media type of an OPDS 2.0 publication.
	MediaTypePublication = "application/opds-publication+json"

	// MediaTypeOpenSearch is the media type of an OpenSearch description document.
	MediaTypeOpenSearch = "application/opensearchdescription+xml"
)

Media types used by OPDS catalogs.

View Source
const (
	NSAtom       = "http://www.w3.org/2005/Atom"
	NSOPDS       = "http://opds-spec.org/2010/catalog"
	NSDCTerms    = "http://purl.org/dc/terms/"
	NSOpenSearch = "http://a9.com/-/spec/opensearch/1.1/"
	NSThreading  = "http://purl.org/syndication/thread/1.0"
)

XML namespace URIs used by OPDS 1.x (Atom) feeds.

View Source
const (
	RelSelf       = "self"
	RelStart      = "start"
	RelUp         = "up"
	RelNext       = "next"
	RelPrevious   = "previous"
	RelFirst      = "first"
	RelLast       = "last"
	RelSearch     = "search"
	RelAlternate  = "alternate"
	RelRelated    = "related"
	RelSubsection = "subsection"
	RelCollection = "collection"

	RelImage     = "http://opds-spec.org/image"
	RelThumbnail = "http://opds-spec.org/image/thumbnail"

	RelFacet         = "http://opds-spec.org/facet"
	RelGroup         = "http://opds-spec.org/group"
	RelSortNew       = "http://opds-spec.org/sort/new"
	RelSortPopular   = "http://opds-spec.org/sort/popular"
	RelFeatured      = "http://opds-spec.org/featured"
	RelRecommended   = "http://opds-spec.org/recommended"
	RelShelf         = "http://opds-spec.org/shelf"
	RelSubscriptions = "http://opds-spec.org/subscriptions"
	RelCrawlable     = "http://opds-spec.org/crawlable"
)

Standard (RFC 5988 / Atom) and OPDS-specific link relations.

The structural relations (RelSelf, RelStart, ...) are bare tokens shared by both OPDS versions. The relations carrying the "http://opds-spec.org/" prefix are OPDS-specific and identical across versions 1.2 and 2.0.

View Source
const (
	// StateAvailable means the publication can be borrowed immediately.
	StateAvailable = "available"
	// StateUnavailable means all copies are loaned out.
	StateUnavailable = "unavailable"
	// StateReserved means the user holds a reservation in the queue.
	StateReserved = "reserved"
	// StateReady means a hold is ready to be borrowed by the user.
	StateReady = "ready"
)

Availability states for library lending (used by AcquireBorrow links).

Variables

View Source
var ErrNotFound = errors.New("opds: not found")

ErrNotFound is returned by a Source when a requested feed or publication does not exist. The HTTP layer maps it to 404 Not Found.

Functions

This section is empty.

Types

type Acquisition

type Acquisition struct {
	// Rel is the acquisition relation. Defaults to AcquireGeneric when empty.
	Rel AcquisitionRel
	// Href is the acquisition URL. Required.
	Href string
	// Type is the media type acquired. For indirect acquisition this is the
	// media type of the intermediate resource (e.g. an HTML purchase page).
	Type string
	// Title is an optional label.
	Title string

	// Prices lists the cost(s) of acquisition. Required for AcquireBuy.
	Prices []Price
	// Indirect describes formats obtained after following the link
	// (e.g. an LCP license that yields an EPUB).
	Indirect []IndirectAcquisition
	// Availability describes lending availability (AcquireBorrow).
	Availability *Availability
	// Holds describes the reservation queue (library lending).
	Holds *Holds
	// Copies describes copy counts (library lending).
	Copies *Copies
}

Acquisition describes one way to obtain a publication.

type AcquisitionRel

type AcquisitionRel string

AcquisitionRel identifies how a publication may be acquired. The values are the full relation URIs used (identically) in OPDS 1.2 and 2.0.

const (
	// AcquireGeneric is a generic acquisition relation; the acquisition method
	// is unspecified.
	AcquireGeneric AcquisitionRel = "http://opds-spec.org/acquisition"
	// AcquireOpenAccess is freely accessible without payment or authentication.
	AcquireOpenAccess AcquisitionRel = "http://opds-spec.org/acquisition/open-access"
	// AcquireBuy must be purchased; carries at least one Price.
	AcquireBuy AcquisitionRel = "http://opds-spec.org/acquisition/buy"
	// AcquireBorrow is borrowed for a limited period (library lending).
	AcquireBorrow AcquisitionRel = "http://opds-spec.org/acquisition/borrow"
	// AcquireSample provides a sample or preview of the publication.
	AcquireSample AcquisitionRel = "http://opds-spec.org/acquisition/sample"
	// AcquireSubscribe is acquired through a subscription.
	AcquireSubscribe AcquisitionRel = "http://opds-spec.org/acquisition/subscribe"
)

type Author

type Author struct {
	// Name is the display name. Required.
	Name string
	// URI optionally links to the author (a feed of their works, a homepage).
	URI string
	// SortAs is an optional collation key (2.0).
	SortAs string
}

Author identifies a person or organization responsible for a feed or publication.

type Availability

type Availability struct {
	// State is one of StateAvailable, StateUnavailable, StateReserved, StateReady.
	State string
	// Since is when the current state began (e.g. loan start). Optional.
	Since time.Time
	// Until is when the current state ends (e.g. loan or hold expiry). Optional.
	Until time.Time
}

Availability describes whether a borrowable publication can currently be obtained.

type Copies

type Copies struct {
	// Total is the number of copies owned.
	Total int
	// Available is the number of copies currently available to borrow.
	Available int
}

Copies describes copy counts for a borrowable publication.

type Facet

type Facet struct {
	// Group names the facet group this facet belongs to (e.g. "Language").
	Group string
	// Title is the facet label (e.g. "French"). Required.
	Title string
	// Href is the URL of the filtered/sorted feed. Required.
	Href string
	// Type is the media type of the target feed.
	Type string
	// Count is an optional hint at the number of items behind the facet.
	Count int
	// Active marks the facet as the one currently applied.
	Active bool
}

Facet is an alternate filtered or sorted view of a feed, grouped with other facets under a common Group label.

type Feed

type Feed struct {
	// ID is a stable, unique identifier for the feed (e.g. a URN or URL).
	// Maps to atom:id in 1.2; used as metadata.identifier in 2.0.
	ID string
	// Title is the human-readable feed title. Required by both versions.
	Title string
	// Subtitle is an optional secondary title (atom:subtitle).
	Subtitle string
	// Updated is the last time the feed changed. Defaults to time.Now when zero.
	Updated time.Time
	// Icon is an optional URL to a feed icon (atom:icon).
	Icon string
	// Authors describe who is responsible for the feed.
	Authors []Author
	// Links are feed-level links (self, start, up, next, search, ...).
	Links []Link

	// Navigation holds the entries of a navigation feed.
	Navigation []NavEntry
	// Publications holds the entries of an acquisition feed.
	Publications []Publication
	// Groups partition an acquisition feed into labelled sections (2.0 groups;
	// emitted via opds:group links in 1.2).
	Groups []Group
	// Facets describe alternate filtered/sorted views of the same feed.
	Facets []Facet

	// Pagination. Zero values are treated as "unset" and omitted.
	TotalResults int // total number of items across all pages
	ItemsPerPage int // number of items per page
	StartIndex   int // 1-based index of the first item on this page (1.x)
	CurrentPage  int // 1-based page number (2.0)
}

Feed is a version-neutral OPDS feed (an Atom feed in 1.2, a collection in 2.0). A feed is either a navigation feed (Navigation populated) or an acquisition feed (Publications populated); both may be present but most clients expect one or the other.

func NewFeed

func NewFeed(id, title string) *Feed

NewFeed returns a feed with the given id and title and Updated set to now.

func (*Feed) Add

func (f *Feed) Add(pubs ...Publication) *Feed

Add appends one or more publications to the feed.

func (*Feed) AddFacet

func (f *Feed) AddFacet(group, title, href, mediaType string, count int, active bool) *Feed

AddFacet appends a facet to the feed.

func (*Feed) AddGroup

func (f *Feed) AddGroup(g Group) *Feed

AddGroup appends a group to the feed.

func (*Feed) AddNav

func (f *Feed) AddNav(title, href, mediaType, rel string) *Feed

AddNav appends a navigation entry. rel may be empty (defaults to subsection).

func (*Feed) AddNavEntry

func (f *Feed) AddNavEntry(e NavEntry) *Feed

AddNavEntry appends a fully specified navigation entry.

func (*Feed) At

func (f *Feed) At(t time.Time) *Feed

At sets the feed's Updated timestamp.

func (*Feed) By

func (f *Feed) By(name string) *Feed

By adds an author to the feed.

func (*Feed) IsAcquisition

func (f *Feed) IsAcquisition() bool

IsAcquisition reports whether the feed is an acquisition feed (contains publications) as opposed to a navigation feed. It is used to select the correct OPDS 1.x media type.

func (f *Feed) Link(rel, href, mediaType string) *Feed

Link adds a feed-level link.

func (*Feed) Next

func (f *Feed) Next(href, mediaType string) *Feed

Next adds a next-page link.

func (*Feed) Page

func (f *Feed) Page(total, perPage, start int) *Feed

Page sets pagination links and counters. self/next/prev hrefs that are empty are skipped. total and perPage are recorded as counters; start is the 1-based index of the first item on this page.

func (*Feed) Prev

func (f *Feed) Prev(href, mediaType string) *Feed

Prev adds a previous-page link.

func (f *Feed) SearchLink(href, mediaType string, templated bool) *Feed

SearchLink adds a search link. For 1.x mediaType should be MediaTypeOpenSearch; for 2.0 use MediaTypeFeed with a templated href.

func (*Feed) Self

func (f *Feed) Self(href, mediaType string) *Feed

Self adds a self link.

func (*Feed) Start

func (f *Feed) Start(href string) *Feed

Start adds a start (catalog root) link.

func (*Feed) SubtitledBy

func (f *Feed) SubtitledBy(s string) *Feed

SubtitledBy sets the feed subtitle.

func (*Feed) Up

func (f *Feed) Up(href, mediaType string) *Feed

Up adds an up (parent) link.

type FeedRequest

type FeedRequest struct {
	// ID identifies the requested feed (empty for the root). For the HTTP layer
	// this is the path segment after the feed prefix.
	ID string
	// Page is the requested 1-based page number (1 if unspecified).
	Page int
	// Version is the OPDS version the response will be encoded in, as
	// negotiated by the caller. Implementations may use it to tailor hrefs.
	Version Version
	// BaseURL is the absolute base URL of the catalog (scheme://host), if known.
	BaseURL string
	// Query holds the raw query parameters of the request (facet selections,
	// sort orders, and so on).
	Query url.Values
}

FeedRequest carries the parameters of a request for a feed.

type Group

type Group struct {
	// Title is the section label.
	Title string
	// Href is an optional link to the full feed for this group.
	Href string
	// Type is the media type of the group's full feed.
	Type string
	// Rel is an optional relation for the group's link.
	Rel string
	// Navigation holds the group's navigation entries.
	Navigation []NavEntry
	// Publications holds the group's publications.
	Publications []Publication
}

Group is a labelled section of a feed (2.0 groups). A group typically links to a fuller feed via Href and shows a preview of its contents.

type Holds

type Holds struct {
	// Total is the number of holds placed.
	Total int
	// Position is the requesting user's position in the queue, if known.
	Position *int
}

Holds describes a reservation queue for a borrowable publication.

type Image

type Image struct {
	// Href is the image URL. Required.
	Href string
	// Type is the image media type (e.g. "image/jpeg").
	Type string
	// Width and Height are optional pixel dimensions (2.0).
	Width, Height int
	// Thumbnail marks this as a reduced-size image. In 1.2 it selects the
	// image/thumbnail relation; in 2.0 all images share the images collection.
	Thumbnail bool
}

Image is a cover image or thumbnail.

type IndirectAcquisition

type IndirectAcquisition struct {
	// Type is the media type that will ultimately be acquired.
	Type string
	// Child holds further levels of indirection.
	Child []IndirectAcquisition
}

IndirectAcquisition declares a media type obtainable after following an acquisition link. Entries may nest to express multiple levels of indirection.

type Link struct {
	// Rel is the link relation (see the Rel* constants).
	Rel string
	// Href is the target URL or, when Templated is true, a URI template.
	Href string
	// Type is the media type of the target.
	Type string
	// Title is an optional human-readable label.
	Title string
	// Templated indicates Href is an RFC 6570 URI template (2.0 only).
	Templated bool
}

Link is a generic hypermedia link.

type NavEntry struct {
	// ID is a stable identifier. Synthesized from Href for 1.2 if empty.
	ID string
	// Title is the entry label. Required.
	Title string
	// Updated is the entry's last-modified time. Defaults to the feed's when zero.
	Updated time.Time
	// Content is an optional description of the target.
	Content string
	// Href is the URL of the target feed or resource. Required.
	Href string
	// Type is the media type of the target (e.g. MediaTypeAcquisition).
	Type string
	// Rel is an optional relation for the target link (e.g. RelSortNew,
	// RelSubsection, RelFeatured). Defaults to RelSubsection when empty.
	Rel string
	// Images are optional thumbnails/tiles for the entry.
	Images []Image
}

NavEntry is an entry in a navigation feed: a link to another feed or resource, with a title and optional description.

type Price

type Price struct {
	// Currency is an ISO 4217 currency code (e.g. "USD").
	Currency string
	// Value is the amount.
	Value float64
}

Price is a monetary amount in a specific currency.

type Publication

type Publication struct {
	// ID is a stable, unique identifier (atom:id; metadata.identifier in 2.0).
	ID string
	// Title is the publication title. Required.
	Title string
	// SortAs is an optional collation key for the title (2.0 metadata.sortAs).
	SortAs string
	// Updated is when the entry last changed (atom:updated; metadata.modified).
	Updated time.Time
	// Published is the publication date (dcterms:issued; metadata.published).
	Published time.Time
	// Languages are ISO 639 language codes.
	Languages []string
	// Identifiers are external identifiers such as ISBN URNs (dcterms:identifier).
	Identifiers []string
	// Publisher is the publishing entity.
	Publisher string
	// Authors are the publication's authors.
	Authors []Author
	// Contributors are other contributors (editors, translators, ...).
	Contributors []Author
	// Subjects are categories/genres.
	Subjects []Subject
	// Summary is a short plain-text description (atom:summary).
	Summary string
	// Description is a longer description, may contain HTML (atom:content).
	Description string
	// Rights is a copyright/licensing statement (atom:rights).
	Rights string
	// Series places the publication within a series (2.0 belongsTo.series).
	Series *Series

	// Images are cover images. By convention the first is the primary cover.
	Images []Image
	// Acquisitions are the ways the publication can be acquired. An acquisition
	// feed entry should have at least one.
	Acquisitions []Acquisition
	// Links are additional links (self, alternate to the full entry, related, ...).
	Links []Link
}

Publication is a single catalog entry describing a publication and how to acquire it.

func NewPublication

func NewPublication(id, title string) *Publication

NewPublication returns a publication with the given id and title and Updated set to now.

func (*Publication) About

func (p *Publication) About(name string) *Publication

About adds a subject/category.

func (*Publication) Acquire

func (p *Publication) Acquire(a Acquisition) *Publication

Acquire appends a fully specified acquisition.

func (*Publication) Author

func (p *Publication) Author(a Author) *Publication

Author adds a fully specified author.

func (*Publication) Borrow

func (p *Publication) Borrow(href, mediaType, state string) *Publication

Borrow adds a borrow acquisition with the given availability state.

func (*Publication) Buy

func (p *Publication) Buy(href, mediaType, currency string, value float64) *Publication

Buy adds a buy acquisition with a single price.

func (*Publication) By

func (p *Publication) By(name string) *Publication

By adds an author.

func (*Publication) Categorize

func (p *Publication) Categorize(name, code, scheme string) *Publication

Categorize adds a subject with a controlled-vocabulary code and scheme.

func (*Publication) Cover

func (p *Publication) Cover(href, mediaType string) *Publication

Cover adds a primary cover image.

func (*Publication) Describe

func (p *Publication) Describe(s string) *Publication

Describe sets the long description.

func (*Publication) From

func (p *Publication) From(publisher string) *Publication

From sets the publisher.

func (*Publication) ISBN

func (p *Publication) ISBN(isbn string) *Publication

ISBN adds an ISBN identifier as a URN.

func (*Publication) Identifier

func (p *Publication) Identifier(id string) *Publication

Identifier adds a raw identifier.

func (*Publication) In

func (p *Publication) In(langs ...string) *Publication

In sets one or more languages.

func (p *Publication) Link(rel, href, mediaType string) *Publication

Link adds an arbitrary link to the publication.

func (*Publication) OpenAccess

func (p *Publication) OpenAccess(href, mediaType string) *Publication

OpenAccess adds an open-access (free download) acquisition.

func (*Publication) PartOf

func (p *Publication) PartOf(series string, position float64) *Publication

PartOf places the publication in a series at the given position.

func (*Publication) PublishedAt

func (p *Publication) PublishedAt(t time.Time) *Publication

PublishedAt sets the publication date.

func (*Publication) Sample

func (p *Publication) Sample(href, mediaType string) *Publication

Sample adds a sample/preview acquisition.

func (*Publication) Summarize

func (p *Publication) Summarize(s string) *Publication

Summarize sets the short summary.

func (*Publication) Thumbnail

func (p *Publication) Thumbnail(href, mediaType string) *Publication

Thumbnail adds a thumbnail image.

func (*Publication) UpdatedAt

func (p *Publication) UpdatedAt(t time.Time) *Publication

UpdatedAt sets the entry's last-modified time.

type SearchDescription

type SearchDescription struct {
	// ShortName is a brief name for the search engine (OpenSearch ShortName).
	ShortName string
	// Description is a human-readable description of the search.
	Description string
	// Template is the search URL template using RFC 6570 / OpenSearch syntax,
	// e.g. "/search?q={searchTerms}". If it contains no parameters the library
	// appends "?q={searchTerms}". Extra params such as {author} and {title}
	// are advertised when present.
	Template string
}

SearchDescription describes a catalog's search interface. It drives the OpenSearch description document (1.x) and the templated search link (2.0).

type SearchRequest

type SearchRequest struct {
	// Terms is the free-text query (the OpenSearch {searchTerms}).
	Terms string
	// Author optionally narrows the search by author.
	Author string
	// Title optionally narrows the search by title.
	Title string
	// Page is the requested 1-based page number (1 if unspecified).
	Page int
	// Version is the negotiated OPDS version of the response.
	Version Version
	// BaseURL is the absolute base URL of the catalog, if known.
	BaseURL string
	// Query holds the raw query parameters of the request.
	Query url.Values
}

SearchRequest carries the parameters of a search.

type Searcher

type Searcher interface {
	// Search returns a feed of results for the given request.
	Search(ctx context.Context, req SearchRequest) (*Feed, error)

	// SearchDescription returns metadata describing the search interface,
	// used to generate the OpenSearch document and the 2.0 search link.
	SearchDescription() SearchDescription
}

Searcher is an optional interface a Source may also implement to support search. When present, the HTTP layer advertises a search link and routes search requests to it.

type Series

type Series struct {
	// Name is the series title.
	Name string
	// Position is the publication's position in the series (0 if unknown).
	Position float64
}

Series places a publication within a sequence.

type Source

type Source interface {
	// Root returns the catalog's root feed (usually a navigation feed).
	Root(ctx context.Context, req FeedRequest) (*Feed, error)

	// Feed returns the feed identified by req.ID. It should return ErrNotFound
	// if no such feed exists.
	Feed(ctx context.Context, req FeedRequest) (*Feed, error)

	// Publication returns the full entry for a single publication. It should
	// return ErrNotFound if no such publication exists. A Source that never
	// serves standalone publication documents may return ErrNotFound always.
	Publication(ctx context.Context, id string) (*Publication, error)
}

Source is the backend a catalog implements. It returns version-neutral Feed and Publication values; the library handles serialization to OPDS 1.2 or 2.0, content negotiation, and HTTP wiring.

Implementations are responsible for the URLs (hrefs) they place in feeds: the library does not rewrite them. Use FeedRequest.PageURL and the BaseURL to build consistent links, or construct them however suits the backend.

type Subject

type Subject struct {
	// Name is the human-readable label.
	Name string
	// Code is an optional controlled-vocabulary term (e.g. a BISAC code).
	Code string
	// Scheme optionally identifies the vocabulary the Code belongs to.
	Scheme string
}

Subject is a category, genre or keyword.

type Version

type Version int

Version identifies an OPDS wire format version.

const (
	// Version1 is OPDS 1.2 (Atom XML).
	Version1 Version = iota
	// Version2 is OPDS 2.0 (JSON).
	Version2
)

func (Version) String

func (v Version) String() string

Directories

Path Synopsis
examples
bookstore command
Command bookstore is a runnable example OPDS catalog backed by an in-memory list of books.
Command bookstore is a runnable example OPDS catalog backed by an in-memory list of books.
Package opds1 encodes the version-neutral opds model to OPDS 1.2 feeds and entry documents, serialized as Atom (XML) with the OPDS extension namespaces.
Package opds1 encodes the version-neutral opds model to OPDS 1.2 feeds and entry documents, serialized as Atom (XML) with the OPDS extension namespaces.
Package opds2 encodes the version-neutral opds model to OPDS 2.0, the JSON format built on the Readium Web Publication Manifest.
Package opds2 encodes the version-neutral opds model to OPDS 2.0, the JSON format built on the Readium Web Publication Manifest.
Package opdshttp provides an embeddable http.Handler that exposes an opds.Source as an OPDS catalog, handling routing, content negotiation between OPDS 1.2 and 2.0, pagination, and search.
Package opdshttp provides an embeddable http.Handler that exposes an opds.Source as an OPDS catalog, handling routing, content negotiation between OPDS 1.2 and 2.0, pagination, and search.
Package opensearch generates OpenSearch description documents, the mechanism OPDS 1.x catalogs use to advertise their search interface.
Package opensearch generates OpenSearch description documents, the mechanism OPDS 1.x catalogs use to advertise their search interface.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL