* fix(plugins): align the Python HTTP example with the repo's host-call pattern
Bind http_send with raw memory offsets like nowplaying-py does, drop
guards for fields the host always sends, and document how plugins
without a PDK call host services and which built-in HTTP APIs are
disabled.
* docs(plugins): document the private-address rules for HTTP requiredHosts
Explain in the README and manifest schema that named hosts can't reach
private addresses while IP/CIDR entries and a bare "*" can.
* docs(plugins): document the private-address rules for requiredHosts
Explain in the README and manifest schema that named hosts can't reach
private addresses while IP/CIDR entries and a bare "*" can, for both
HTTP and WebSocket. Inline the single-use HTTP isHostAllowed wrapper.
* feat(plugins): derive Default for Rust host service structs
The ndpgen client.rs template now adds Default to the derive list of host
service structs, as the capability and shared types templates already do.
Plugin authors can now set only the fields they need, for example
HTTPRequest { method, url, ..Default::default() }. The webhook-rs and
discord-rich-presence-rs examples use this form now. The golden files and
the generated nd-pdk-host crate are updated to match.
* feat(plugins): deprecate pdk.NewHTTPRequest in the Go PDK
Navidrome no longer enables extism's http_request host function, so a
request built with pdk.NewHTTPRequest always fails. ndpgen now reads a small
deprecation table and writes a Deprecated: paragraph for the listed extism
functions, in both the WASM wrapper and the native stub. Linters and IDEs
now point plugin authors to host.HTTPSend. The PDK example tests used to
teach NewHTTPRequest. They now use host.HTTPSend and host.HTTPMock.
* docs(plugins): correct requiredHosts rules for websocket and private addresses
Two statements in the plugin docs did not match the code.
The WebSocket section claimed requiredHosts behaves like HTTP. It does not:
host_httpclient.go only consults the allowlist when the list is non-empty and
otherwise falls back to allowing public addresses, while host_websocket.go
always calls isHostInAllowlist, so an absent list blocks every connection.
The HTTP section claimed a named host can never reach a private address.
checkPrivateDial scans the whole requiredHosts list, so a named host does
reach a private address when the same list also holds a covering IP or CIDR.
Reworded both, plus the matching requiredHosts descriptions in
manifest-schema.json, and regenerated manifest_gen.go.
|
||
|---|---|---|
| .. | ||
| src | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| README.md | ||
Navidrome Host Function Wrappers for Rust
This directory contains auto-generated Rust wrappers for Navidrome's host services. These wrappers provide idiomatic Rust APIs for interacting with Navidrome from WASM plugins.
⚠️ Auto-Generated Code
Do not edit these files manually. They are generated by the ndpgen tool.
To regenerate:
make gen
Usage
Add this crate as a dependency in your plugin's Cargo.toml:
[dependencies]
nd-host = { path = "../../pdk/rust/host" }
Then import the services you need:
use nd_host::{cache, scheduler, library};
use nd_host::library::Library; // Import the typed struct
#[plugin_fn]
pub fn my_callback(input: String) -> FnResult<String> {
// Use the cache service
cache::set("my_key", b"my_value", 3600)?;
// Schedule a recurring task
scheduler::schedule_recurring("@every 5m", "payload", "task_id")?;
// Access library data with typed structs
let libraries: Vec<Library> = library::get_all_libraries()?;
for lib in &libraries {
info!("Library: {} with {} songs", lib.name, lib.total_songs);
}
Ok("done".to_string())
}
Typed Structs
Services that work with domain objects provide typed Rust structs instead of
serde_json::Value. This enables compile-time type checking and IDE
autocompletion.
For example, the library module provides a Library struct:
use nd_host::library::Library;
let libs: Vec<Library> = library::get_all_libraries()?;
println!("First library: {} ({} songs)", libs[0].name, libs[0].total_songs);
All structs derive Debug, Clone, Serialize, and Deserialize for
convenient use with logging and serialization.
Available Services
| Module | Description |
|---|---|
artwork |
Access album and artist artwork |
cache |
Temporary key-value storage with TTL |
kvstore |
Persistent key-value storage |
library |
Access the music library (albums, artists, tracks) |
scheduler |
Schedule one-time and recurring tasks |
subsonicapi |
Make Subsonic API calls |
websocket |
Send real-time messages to clients |
Building Plugins
Rust plugins must be compiled to WebAssembly:
cargo build --target wasm32-wasip1 --release
See the webhook-rs example for a complete plugin implementation.