htsget protocol server implementation in Rust with Python bindings
Project description
htsgetr
A Rust implementation of the htsget protocol (v1.3) for serving genomic data over HTTP. Built with noodles for bioinformatics I/O and axum for the web server.
Features
- htsget 1.3 compliant - GET/POST endpoints for reads and variants
- Multiple formats - BAM, CRAM, VCF, BCF via noodles
- Extensions - FASTA/FASTQ support beyond the spec
- Multiple storage backends - Local filesystem, S3, and HTTP/HTTPS
- JWT authentication - Optional Bearer token auth with JWKS/static keys
- Python bindings - PyO3 integration via maturin
- Async - Built on tokio for high concurrency
Installation
From source (Rust)
git clone https://github.com/bolu-atx/htsgetr.git
cd htsgetr
cargo install --path .
Python
pip install maturin
maturin develop --features python
Quick Start
# Create a data directory with some BAM/VCF files
mkdir -p data
cp /path/to/sample.bam data/
cp /path/to/sample.bam.bai data/
# Start the server
htsgetr --data-dir ./data
# Query reads
curl http://localhost:8080/reads/sample
Usage
Server
# Start server with default settings
htsgetr --data-dir /path/to/data
# Custom host/port
htsgetr --host 0.0.0.0 --port 8080 --data-dir /path/to/data
# With explicit base URL (for proxied setups)
htsgetr --data-dir /path/to/data --base-url https://example.com/htsget
Configuration
| Environment Variable | CLI Flag | Default | Description |
|---|---|---|---|
HTSGET_HOST |
--host |
0.0.0.0 |
Bind address |
HTSGET_PORT |
--port |
8080 |
Listen port |
HTSGET_DATA_DIR |
--data-dir |
./data |
Directory containing genomic files |
HTSGET_BASE_URL |
--base-url |
auto | Base URL for ticket URLs |
HTSGET_CORS |
--cors |
true |
Enable CORS |
HTSGET_STORAGE |
--storage |
local |
Storage backend: local, s3, or http |
RUST_LOG |
--log-level |
info |
Log level |
S3 Storage
cargo build --features s3
HTSGET_STORAGE=s3 \
HTSGET_S3_BUCKET=my-genomics-bucket \
HTSGET_S3_PREFIX=samples/ \
htsgetr
| Environment Variable | Default | Description |
|---|---|---|
HTSGET_S3_BUCKET |
required | S3 bucket name |
HTSGET_S3_REGION |
auto | AWS region (uses AWS_REGION if not set) |
HTSGET_S3_PREFIX |
"" |
Key prefix for files |
HTSGET_S3_ENDPOINT |
- | Custom endpoint (for MinIO, LocalStack) |
HTSGET_PRESIGNED_URL_EXPIRY |
3600 |
Presigned URL TTL in seconds |
HTSGET_CACHE_DIR |
/tmp/htsgetr-cache |
Local cache for index files |
HTTP Storage
cargo build --features http
HTSGET_STORAGE=http \
HTSGET_HTTP_BASE_URL=https://files.example.com/genomics/ \
htsgetr
| Environment Variable | Default | Description |
|---|---|---|
HTSGET_HTTP_BASE_URL |
required | Base URL for data files |
HTSGET_HTTP_INDEX_BASE_URL |
- | Base URL for index files (defaults to data URL) |
Authentication
Enable JWT/Bearer token authentication by building with the auth feature:
cargo build --features auth
HTSGET_AUTH_ENABLED=true \
HTSGET_AUTH_ISSUER=https://auth.example.com \
htsgetr --features auth
| Environment Variable | Default | Description |
|---|---|---|
HTSGET_AUTH_ENABLED |
false |
Enable authentication |
HTSGET_AUTH_ISSUER |
- | JWT issuer URL (JWKS fetched from {issuer}/.well-known/jwks.json) |
HTSGET_AUTH_AUDIENCE |
- | Expected aud claim |
HTSGET_AUTH_JWKS_URL |
auto | Explicit JWKS URL (overrides issuer-derived URL) |
HTSGET_AUTH_PUBLIC_KEY |
- | Static RSA/EC PEM public key (alternative to JWKS) |
HTSGET_AUTH_PUBLIC_ENDPOINTS |
/,/service-info |
Comma-separated paths that don't require auth |
HTSGET_DATA_URL_SECRET |
generated | HMAC secret for signing data URLs |
HTSGET_DATA_URL_EXPIRY |
3600 |
Signed data URL TTL in seconds |
When auth is enabled:
- Public endpoints (root, service-info) don't require authentication
- All other endpoints require a valid
Authorization: Bearer <token>header - Data URLs in tickets are HMAC-signed with expiry to prevent unauthorized access
Data Directory Structure
Place files in the data directory with standard extensions:
data/
├── sample1.bam
├── sample1.bam.bai
├── sample2.vcf.gz
├── sample2.vcf.gz.tbi
├── reference.fa
└── reference.fa.fai
API Reference
Reads Endpoint
# Get all reads
curl http://localhost:8080/reads/sample1
# Get reads for a region
curl "http://localhost:8080/reads/sample1?referenceName=chr1&start=0&end=1000000"
# Header only
curl "http://localhost:8080/reads/sample1?class=header"
# Request CRAM format
curl "http://localhost:8080/reads/sample1?format=CRAM"
# POST with multiple regions
curl -X POST http://localhost:8080/reads/sample1 \
-H "Content-Type: application/json" \
-d '{
"format": "BAM",
"regions": [
{"referenceName": "chr1", "start": 0, "end": 1000000},
{"referenceName": "chr2", "start": 0, "end": 500000}
]
}'
Variants Endpoint
# Get all variants
curl http://localhost:8080/variants/sample2
# Get variants for a region
curl "http://localhost:8080/variants/sample2?referenceName=chr1&start=0&end=1000000"
Sequences Endpoint (Extension)
# Get FASTA sequence
curl http://localhost:8080/sequences/reference
Service Info
curl http://localhost:8080/service-info
Response Format
Successful responses return a JSON ticket per the htsget spec:
{
"htsget": {
"format": "BAM",
"urls": [
{
"url": "http://localhost:8080/data/reads/sample1",
"class": "body"
}
]
}
}
Error responses:
{
"htsget": {
"error": "NotFound",
"message": "not found: sample1"
}
}
Python Bindings
from htsgetr import HtsgetServer, HtsgetClient
# Start a server
server = HtsgetServer("/path/to/data", port=8080)
server.run() # Blocking
# Use the client
client = HtsgetClient("http://localhost:8080")
ticket = client.reads("sample1", reference_name="chr1", start=0, end=1000000)
Roadmap
- Server scaffold with axum
- htsget 1.3 types and error handling
- Local filesystem storage backend
- Reads endpoint (BAM/CRAM)
- Variants endpoint (VCF/BCF)
- Sequences endpoint (FASTA/FASTQ extension)
- Index-based byte range queries (BAI, TBI, CSI)
- S3 storage backend with pre-signed URLs
- HTTP/HTTPS storage backend
- JWT/Bearer token authentication
- CRAM reference resolution
- GCS storage backend
- Python bindings (full implementation)
- Docker image
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Related Projects
- htsget-rs - Another Rust htsget implementation
- noodles - Bioinformatics I/O libraries in Rust
- htslib - C library for HTS formats
License
MIT License - see LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file htsgetr-0.1.0.tar.gz.
File metadata
- Download URL: htsgetr-0.1.0.tar.gz
- Upload date:
- Size: 955.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af996b6291491a03b26a279a8d98dee9c99474c616ef3e18ed2d380d4016df02
|
|
| MD5 |
ba63a6b8560a175a8a576a7e76bb515f
|
|
| BLAKE2b-256 |
93412df6b60ddbf3143382cb90ee972652ab4c6087074c0191af6808e7bb42a1
|
File details
Details for the file htsgetr-0.1.0-cp311-cp311-win_amd64.whl.
File metadata
- Download URL: htsgetr-0.1.0-cp311-cp311-win_amd64.whl
- Upload date:
- Size: 8.1 MB
- Tags: CPython 3.11, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e874220488e72eaaf4d2db6a4434d5fb5bd3052eb370ed4880dfaceee9618ce9
|
|
| MD5 |
c3eb6f71b3df0cbb08de7be9c0617431
|
|
| BLAKE2b-256 |
efe0015012afd8205dc58d9524b42c25f71b1a8674c92930340c0e2c5d7c98e8
|
File details
Details for the file htsgetr-0.1.0-cp311-cp311-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: htsgetr-0.1.0-cp311-cp311-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 10.1 MB
- Tags: CPython 3.11, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2286e2705288566c44233475356312b1dc6b8e57677d04636d8c5a1418efeba4
|
|
| MD5 |
5150d7867f468950e90db3fddf0d8f03
|
|
| BLAKE2b-256 |
2faf87b12f8df13a2a8c4dc1129736cef493e4c4f6ccc54bcf50b36bf2cb2941
|
File details
Details for the file htsgetr-0.1.0-cp311-cp311-manylinux_2_28_aarch64.whl.
File metadata
- Download URL: htsgetr-0.1.0-cp311-cp311-manylinux_2_28_aarch64.whl
- Upload date:
- Size: 10.5 MB
- Tags: CPython 3.11, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
646d2d7a6ce450206b6d6355f4e78892226715a2c5dc1ec9e444bd4496590fe9
|
|
| MD5 |
ce40fd7417b70c8aaff50b1eef310dd4
|
|
| BLAKE2b-256 |
4ea0e838351f50d612e6f18f94bb7f2a7c8272073e385b55500acc9d09a9577b
|
File details
Details for the file htsgetr-0.1.0-cp311-cp311-macosx_11_0_arm64.whl.
File metadata
- Download URL: htsgetr-0.1.0-cp311-cp311-macosx_11_0_arm64.whl
- Upload date:
- Size: 9.1 MB
- Tags: CPython 3.11, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4cdf2319abf77a77856f261b9d180d56ec4c56764d5675cfb0ddfba85407da6d
|
|
| MD5 |
077db0bbb3a58e7736b3388ef500f71e
|
|
| BLAKE2b-256 |
e80975b448ec5708110878e561826065f0a72d36341f64ff1624de00f0363311
|