navidrome/plugins/cmd/ndpgen/testdata/comprehensive_client_expected.rs
Deluan Quintão 1072e9f7eb
chore(plugins): document requiredHosts rules and deprecate pdk.NewHTTPRequest (#6129)
* 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.
2026-09-12 13:59:46 -04:00

423 lines
11 KiB
Rust

// Code generated by ndpgen. DO NOT EDIT.
//
// This file contains client wrappers for the Comprehensive host service.
// It is intended for use in Navidrome plugins built with extism-pdk.
use extism_pdk::*;
use serde::{Deserialize, Serialize};
use base64::Engine as _;
use base64::engine::general_purpose::STANDARD as BASE64;
mod base64_bytes {
use serde::{self, Deserialize, Deserializer, Serializer};
use base64::Engine as _;
use base64::engine::general_purpose::STANDARD as BASE64;
pub fn serialize<S>(bytes: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&BASE64.encode(bytes))
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
BASE64.decode(&s).map_err(serde::de::Error::custom)
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct User2 {
pub id: String,
pub name: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Filter2 {
pub active: bool,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct ComprehensiveSimpleParamsRequest {
name: String,
count: i32,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ComprehensiveSimpleParamsResponse {
#[serde(default)]
result: String,
#[serde(default)]
error: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct ComprehensiveStructParamRequest {
user: User2,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ComprehensiveStructParamResponse {
#[serde(default)]
error: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct ComprehensiveMixedParamsRequest {
id: String,
filter: Filter2,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ComprehensiveMixedParamsResponse {
#[serde(default)]
result: i32,
#[serde(default)]
error: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct ComprehensiveNoErrorRequest {
name: String,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ComprehensiveNoErrorResponse {
#[serde(default)]
result: String,
#[serde(default)]
error: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ComprehensiveNoParamsResponse {
#[serde(default)]
error: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ComprehensiveNoParamsNoReturnsResponse {
#[serde(default)]
error: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct ComprehensivePointerParamsRequest {
id: Option<String>,
user: Option<User2>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ComprehensivePointerParamsResponse {
#[serde(default)]
result: Option<User2>,
#[serde(default)]
error: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct ComprehensiveMapParamsRequest {
data: std::collections::HashMap<String, serde_json::Value>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ComprehensiveMapParamsResponse {
#[serde(default)]
result: serde_json::Value,
#[serde(default)]
error: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct ComprehensiveMultipleReturnsRequest {
query: String,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ComprehensiveMultipleReturnsResponse {
#[serde(default)]
results: Vec<User2>,
#[serde(default)]
total: i32,
#[serde(default)]
error: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct ComprehensiveByteSliceRequest {
#[serde(with = "base64_bytes")]
data: Vec<u8>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ComprehensiveByteSliceResponse {
#[serde(default)]
#[serde(with = "base64_bytes")]
result: Vec<u8>,
#[serde(default)]
error: Option<String>,
}
#[host_fn]
extern "ExtismHost" {
fn comprehensive_simpleparams(input: Json<ComprehensiveSimpleParamsRequest>) -> Json<ComprehensiveSimpleParamsResponse>;
fn comprehensive_structparam(input: Json<ComprehensiveStructParamRequest>) -> Json<ComprehensiveStructParamResponse>;
fn comprehensive_mixedparams(input: Json<ComprehensiveMixedParamsRequest>) -> Json<ComprehensiveMixedParamsResponse>;
fn comprehensive_noerror(input: Json<ComprehensiveNoErrorRequest>) -> Json<ComprehensiveNoErrorResponse>;
fn comprehensive_noparams(input: Json<serde_json::Value>) -> Json<ComprehensiveNoParamsResponse>;
fn comprehensive_noparamsnoreturns(input: Json<serde_json::Value>) -> Json<ComprehensiveNoParamsNoReturnsResponse>;
fn comprehensive_pointerparams(input: Json<ComprehensivePointerParamsRequest>) -> Json<ComprehensivePointerParamsResponse>;
fn comprehensive_mapparams(input: Json<ComprehensiveMapParamsRequest>) -> Json<ComprehensiveMapParamsResponse>;
fn comprehensive_multiplereturns(input: Json<ComprehensiveMultipleReturnsRequest>) -> Json<ComprehensiveMultipleReturnsResponse>;
fn comprehensive_byteslice(input: Json<ComprehensiveByteSliceRequest>) -> Json<ComprehensiveByteSliceResponse>;
}
/// Calls the comprehensive_simpleparams host function.
///
/// # Arguments
/// * `name` - String parameter.
/// * `count` - i32 parameter.
///
/// # Returns
/// The result value.
///
/// # Errors
/// Returns an error if the host function call fails.
pub fn simple_params(name: &str, count: i32) -> Result<String, Error> {
let response = unsafe {
comprehensive_simpleparams(Json(ComprehensiveSimpleParamsRequest {
name: name.to_owned(),
count: count,
}))?
};
if let Some(err) = response.0.error {
return Err(Error::msg(err));
}
Ok(response.0.result)
}
/// Calls the comprehensive_structparam host function.
///
/// # Arguments
/// * `user` - User2 parameter.
///
/// # Errors
/// Returns an error if the host function call fails.
pub fn struct_param(user: User2) -> Result<(), Error> {
let response = unsafe {
comprehensive_structparam(Json(ComprehensiveStructParamRequest {
user: user,
}))?
};
if let Some(err) = response.0.error {
return Err(Error::msg(err));
}
Ok(())
}
/// Calls the comprehensive_mixedparams host function.
///
/// # Arguments
/// * `id` - String parameter.
/// * `filter` - Filter2 parameter.
///
/// # Returns
/// The result value.
///
/// # Errors
/// Returns an error if the host function call fails.
pub fn mixed_params(id: &str, filter: Filter2) -> Result<i32, Error> {
let response = unsafe {
comprehensive_mixedparams(Json(ComprehensiveMixedParamsRequest {
id: id.to_owned(),
filter: filter,
}))?
};
if let Some(err) = response.0.error {
return Err(Error::msg(err));
}
Ok(response.0.result)
}
/// Calls the comprehensive_noerror host function.
///
/// # Arguments
/// * `name` - String parameter.
///
/// # Returns
/// The result value.
///
/// # Errors
/// Returns an error if the host function call fails.
pub fn no_error(name: &str) -> Result<String, Error> {
let response = unsafe {
comprehensive_noerror(Json(ComprehensiveNoErrorRequest {
name: name.to_owned(),
}))?
};
if let Some(err) = response.0.error {
return Err(Error::msg(err));
}
Ok(response.0.result)
}
/// Calls the comprehensive_noparams host function.
///
/// # Errors
/// Returns an error if the host function call fails.
pub fn no_params() -> Result<(), Error> {
let response = unsafe {
comprehensive_noparams(Json(serde_json::json!({})))?
};
if let Some(err) = response.0.error {
return Err(Error::msg(err));
}
Ok(())
}
/// Calls the comprehensive_noparamsnoreturns host function.
///
/// # Errors
/// Returns an error if the host function call fails.
pub fn no_params_no_returns() -> Result<(), Error> {
let response = unsafe {
comprehensive_noparamsnoreturns(Json(serde_json::json!({})))?
};
if let Some(err) = response.0.error {
return Err(Error::msg(err));
}
Ok(())
}
/// Calls the comprehensive_pointerparams host function.
///
/// # Arguments
/// * `id` - Option<String> parameter.
/// * `user` - Option<User2> parameter.
///
/// # Returns
/// The result value.
///
/// # Errors
/// Returns an error if the host function call fails.
pub fn pointer_params(id: Option<String>, user: Option<User2>) -> Result<Option<User2>, Error> {
let response = unsafe {
comprehensive_pointerparams(Json(ComprehensivePointerParamsRequest {
id: id,
user: user,
}))?
};
if let Some(err) = response.0.error {
return Err(Error::msg(err));
}
Ok(response.0.result)
}
/// Calls the comprehensive_mapparams host function.
///
/// # Arguments
/// * `data` - std::collections::HashMap<String, serde_json::Value> parameter.
///
/// # Returns
/// The result value.
///
/// # Errors
/// Returns an error if the host function call fails.
pub fn map_params(data: std::collections::HashMap<String, serde_json::Value>) -> Result<serde_json::Value, Error> {
let response = unsafe {
comprehensive_mapparams(Json(ComprehensiveMapParamsRequest {
data: data,
}))?
};
if let Some(err) = response.0.error {
return Err(Error::msg(err));
}
Ok(response.0.result)
}
/// Calls the comprehensive_multiplereturns host function.
///
/// # Arguments
/// * `query` - String parameter.
///
/// # Returns
/// A tuple of (results, total).
///
/// # Errors
/// Returns an error if the host function call fails.
pub fn multiple_returns(query: &str) -> Result<(Vec<User2>, i32), Error> {
let response = unsafe {
comprehensive_multiplereturns(Json(ComprehensiveMultipleReturnsRequest {
query: query.to_owned(),
}))?
};
if let Some(err) = response.0.error {
return Err(Error::msg(err));
}
Ok((response.0.results, response.0.total))
}
/// Calls the comprehensive_byteslice host function.
///
/// # Arguments
/// * `data` - Vec<u8> parameter.
///
/// # Returns
/// The result value.
///
/// # Errors
/// Returns an error if the host function call fails.
pub fn byte_slice(data: Vec<u8>) -> Result<Vec<u8>, Error> {
let response = unsafe {
comprehensive_byteslice(Json(ComprehensiveByteSliceRequest {
data: data,
}))?
};
if let Some(err) = response.0.error {
return Err(Error::msg(err));
}
Ok(response.0.result)
}