# web-z3950 An HTTP-to-Z39.50 gateway — a minimal Node.js proof-of-concept that bridges HTTP requests to the [Z39.50](https://www.niso.org/publications/ansiniso-z3950-2003-s2014) library catalog protocol using IndexData's `yaz-client` CLI tool. A containerized Node.js service exposing Z39.50 library catalogue search through a simple HTTP API. Originally deployed on Heroku, the service was later packaged as a reproducible Docker image for portable deployment. A live demo is available at [https://web-z3950-master.onrender.com/] ## Table of Contents - [Architecture](#architecture) - [Prerequisites](#prerequisites) - [Files](#files) - [Installation & Running Locally](#installation--running-locally) - [API Usage](#api-usage) - [Demo Page](#demo-page) - [Limitations](#limitations) - [Key Z39.50 Servers](#key-z3950-servers) - [Credits](#credits) ## Architecture The project is intentionally minimal: - A single Node.js server file (`main.js`, ~80 lines) using only built-in modules: `http`, `child_process`, and `fs` - **Zero npm dependencies** - Spawns `yaz-client` via a bash shell to connect to Z39.50 servers - Accepts HTTP GET requests with query parameters, returns MARC record data as `text/plain` - Signals ISBNs that returned no results via a custom `Void` HTTP response header - Serves a demo HTML page at `/demo.html` with a client-side batch ISBN lookup form - If called without the three mandatory parameters, serves this README as help text - Writes temporary MARC output files to disk, serves them, then deletes them ## Prerequisites - **Node.js** >= 12.0.0 - **yaz-client** — the IndexData YAZ toolkit must be installed on the system. On Debian/Ubuntu: ```bash sudo apt install yaz ``` The command `yaz-client` must be available in your `PATH`. ## Files | File | Description | | --------------- | ------------------------------------------------- | | `main.js` | HTTP server and Z39.50 binding logic | | `demo.html` | Client-side demo page with batch ISBN lookup form | | `style.css` | Stylesheet for the demo page | | `package.json` | Minimal metadata, no scripts or dependencies | | `Dockerfile` | Docker container definition | | `.dockerignore` | Files excluded from the Docker image | ## Installation & Running Locally ```bash # Clone the repository git clone https://github.com/corbin-c/web-z3950.git cd web-z3950 # Install yaz-client (Debian/Ubuntu example) sudo apt install yaz # Start the server node main.js ``` The server starts on **port 5000** by default. You can configure the port via the `PORT` environment variable: ```bash PORT=8080 node main.js ``` Access the service at `http://localhost:5000/`. ### Running with Docker ```bash # Build the image docker build -t web-z3950 . # Run the container docker run -p 5000:5000 web-z3950 ``` The container includes `yaz-client` so no system-level installation is needed. The server starts on port 5000 by default, configurable via the `PORT` environment variable. ## API Usage The service requires **three mandatory query parameters**: - **`server`** — Z39.50 server in the form `address:port/database` (e.g., `lx2.loc.gov:210/LCDB`) - **`isbn`** — Comma-separated list of ISBNs (e.g., `0066620724,0596001312`) - **`format`** — Desired MARC output format, typically `usmarc` (MARC 21) or `unimarc` ### Example Request ``` http://localhost:5000/?server=lx2.loc.gov:210/LCDB&isbn=0066620724,0596001312&format=usmarc ``` ### Response Headers The `Void` response header lists any ISBNs that returned zero hits, comma-separated. For example: ``` Void: 0596001312 ``` If all ISBNs returned results, the `Void` header will be empty. ## Demo Page Navigate to `/demo.html` for a browser-based batch lookup tool. The page provides: - A textarea to paste multiple ISBNs (one per line) - A field to configure the Z39.50 server address - Radio buttons to choose the MARC output format (**MARC 21** or **UNIMARC**) - Automatic download of results as a `.mrc` file ### SUDOC Quick-Start Append `?sudoc` to the demo URL to pre-fill the French SUDOC catalog server: ``` http://localhost:5000/demo.html?sudoc ``` This sets the server field to `carmin.sudoc.abes.fr:10646/abes-z39-public`. > **Note:** The demo page batches ISBNs in groups of 100 and issues parallel requests. Any ISBNs that return no results are surfaced in an alert after the download completes. ## Limitations > **This is a proof of concept, not production-ready software.** - Only supports **ISBN searches** using the hardcoded Z39.50 attribute set `@attr 1=7` - **No error handling** for malformed inputs or unreachable servers - **No authentication, rate limiting, or security measures** — do not expose to untrusted networks without a reverse proxy - Spawns a **new shell process per request**, which is not efficient for high traffic - Uses **temporary files on disk** with no cleanup guarantee if the Node process crashes - **Single-threaded** with no explicit concurrency handling ## Key Z39.50 Servers | Catalog | Server Address | | --------------------------------- | -------------------------------------------- | | Library of Congress | `lx2.loc.gov:210/LCDB` | | SUDOC (French academic libraries) | `carmin.sudoc.abes.fr:10646/abes-z39-public` | ## Credits This tool is based on the [ZOOM API](http://zoom.z3950.org/), used through [YAZ by IndexData](https://www.indexdata.com/resources/software/yaz/). Developed by **Clément CORBIN** —