sru

package
v0.11.0 Latest Latest
Warning

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

Go to latest
Published: Jul 2, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package sru is a client for the SRU (Search/Retrieve via URL) protocol, the modern HTTP successor to Z39.50 used by library catalogs for search and retrieval. It performs a searchRetrieve operation over net/http and hands the bibliographic records embedded in the XML response to libcodex's decoders, using only the standard library.

SRU responses embed each record in a recordData element in a negotiated schema. This client decodes MARCXML records into *codex.Record (via the marcxml package) and exposes any other schema's payload (MODS, Dublin Core, ...) as raw XML bytes, since those crosswalks are encode-only in this library. The Reader implements codex.RecordReader, so a catalog search is a drop-in source for codex.Convert:

c := sru.NewClient("http://lx2.loc.gov:210/lcdb")
rd := c.NewReader(ctx, `dc.title = "moby dick"`)
codex.Convert(rd, marcjson.NewWriter(os.Stdout))

It targets SRU 1.1/1.2 (the widely deployed versions); the query is CQL, passed through verbatim -- use Quote to escape a user-supplied term.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Quote

func Quote(term string) string

Quote wraps a CQL search term in double quotes, escaping embedded backslashes and quotes, so a user-supplied term is safe to place in a CQL query:

client.NewReader(ctx, "dc.title = "+sru.Quote(userInput))

This library passes CQL through verbatim; it does not parse or build queries beyond this escaping helper.

Types

type Client

type Client struct {
	BaseURL    string       // SRU endpoint URL (scheme://host/path)
	HTTPClient *http.Client // nil uses http.DefaultClient
	Version    string       // SRU version; "" uses defaultVersion ("1.2")
	Schema     string       // default recordSchema; "" uses "marcxml"
	MaxRecords int          // records requested per page; <=0 uses defaultMaxRecords
}

Client is an SRU endpoint. The zero value is not usable; construct one with NewClient. HTTPClient, Version, Schema and MaxRecords are optional overrides.

func NewClient

func NewClient(baseURL string) *Client

NewClient returns a Client for the SRU endpoint at baseURL with default settings (SRU 1.2, marcxml schema, http.DefaultClient).

func (*Client) NewReader

func (c *Client) NewReader(ctx context.Context, query string) *Reader

NewReader returns a Reader over the result set for query, using the client's default schema and page size. The context governs every underlying HTTP request; cancel it to stop an in-progress stream.

func (*Client) SearchRetrieve

func (c *Client) SearchRetrieve(ctx context.Context, r Request) (*Response, error)

SearchRetrieve runs one searchRetrieve request and parses the response. It returns a transport or parse error with a nil Response; on a well-formed response it returns the Response together with its Response.Err (a *DiagnosticsError when the search failed with diagnostics, else nil), so the records and counts remain available for inspection.

type Diagnostic

type Diagnostic struct {
	URI     string // diagnostic identifier, e.g. info:srw/diagnostic/1/7
	Message string // human-readable message
	Details string // extra context, e.g. the offending value
}

Diagnostic is one SRU diagnostic (an error or warning) from the server.

type DiagnosticsError

type DiagnosticsError struct {
	Diagnostics []Diagnostic
}

DiagnosticsError reports that a searchRetrieve returned diagnostics and no records. It carries every diagnostic the server sent.

func (*DiagnosticsError) Error

func (e *DiagnosticsError) Error() string

Error summarizes the first diagnostic and the count of any others.

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

Reader streams the records of a search result set as *codex.Record, paging through the SRU result set on demand. It implements codex.RecordReader, so an SRU search is a source for codex.Convert. Only MARCXML records decode to codex.Record; records in other schemas are skipped (inspect them with Client.SearchRetrieve instead).

func (*Reader) All

func (rd *Reader) All() iter.Seq2[*codex.Record, error]

All returns an iterator over the remaining records, for use as "for rec, err := range r.All()". It stops at the first error.

func (*Reader) Read

func (rd *Reader) Read() (*codex.Record, error)

Read returns the next MARCXML record as a *codex.Record, fetching further pages as needed, and io.EOF once the result set is exhausted. Records in a non-MARCXML schema are skipped. A transport, parse or diagnostic error is sticky: once returned, every later call returns it too.

type Record

type Record struct {
	Schema   string // normalized record schema: "marcxml", "mods", "dc", or the raw id
	Packing  string // "xml" or "string"
	Position int    // 1-based position in the result set
	Data     []byte // the record payload as XML bytes, in its schema
}

Record is one record carried in a searchRetrieve response.

func (Record) Decode

func (r Record) Decode() (*codex.Record, error)

Decode parses a MARCXML record payload into a *codex.Record. It returns an error for any other schema, whose payload remains available in Data.

type Request

type Request struct {
	Query       string // CQL query, passed through verbatim
	StartRecord int    // 1-based position of the first record; <1 means 1
	MaxRecords  int    // records to return; <=0 uses the Client default
	Schema      string // recordSchema; "" uses the Client default
}

Request is one searchRetrieve page. Only Query is required; the rest fall back to the Client's defaults.

type Response

type Response struct {
	Version            string       // the server's reported protocol version
	NumberOfRecords    int          // total hits in the result set
	NextRecordPosition int          // start of the next page, or 0 when exhausted
	Records            []Record     // the records on this page
	Diagnostics        []Diagnostic // non-fatal or fatal diagnostics the server returned
}

Response is one parsed searchRetrieve response.

func (*Response) Err

func (r *Response) Err() error

Err returns a *DiagnosticsError when the response carries diagnostics but no records (a failed search), or nil otherwise. A response with both records and diagnostics is treated as a successful partial result.

Jump to

Keyboard shortcuts

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