Networking
Declare "NETWORK_REQUESTS" in plugin.json capabilities to enable networking.
Consuming
Networking is provided via the HttpClientAPI host service, but you never use it directly. Instead, obtain it in main() and wrap it in a SpotrClient, then pass the Spotr client to your service implementations:
import dev.krtirtho.plugin_interfaces.host_apis.HttpClientAPI
import dev.krtirtho.plugin_interfaces.host_apis.HttpClientAPI_SERVICE_NAME
import dev.krtirtho.plugin_interfaces.extras.spotor.SpotrClient
fun main() {
val httpClient = zipline.take<HttpClientAPI>(HttpClientAPI_SERVICE_NAME)
val spotr = SpotrClient(httpClient) {
defaultUrl = "https://api.example.com"
}
zipline.bind<MetadataSearchAPI>(MetadataSearchAPI_SERVICE_NAME, RealMetadataSearchAPI(spotr))
}
Each service that needs HTTP receives the SpotrClient via its constructor. See the Spotr documentation for the full client API.
Spotr HTTP client
Spotr is the primary HTTP API for plugins. It wraps the underlying HttpClientAPI host service with a Ktor-like builder DSL, automatic kotlinx.serialization JSON support, and interceptor chains.
Never call
HttpClientAPI.request()directly - always create aSpotrClientwrapper.
Setup
Create one client per API provider, or a shared client with a default base URL:
val client = SpotrClient(httpClient) {
defaultUrl = "https://api.example.com"
defaultHeaders {
set("Authorization", "Bearer $token")
}
}
Making requests
All HTTP methods are available with a builder DSL for URL, headers, body, and parameters:
val response = client.get {
url { encodedPath = "/v1/search" }
parameter("q", query)
parameter("type", "track")
}
val data: SearchResponse = response.body()
POST with a JSON body:
val response = client.post {
url("https://api.example.com/v1/tracks/save")
jsonBody(SaveRequest(trackIds))
}
Response handling
SpotrHttpResponse provides three ways to access the body:
The body<T>() method uses kotlinx.serialization. If you've set a default serializer on the client config, it uses that; otherwise pass one explicitly.
Interceptors
Interceptors sit between your request and the network. Common uses: logging, adding auth headers, retrying, measuring latency.
val client = SpotrClient(httpClient) {
interceptor { context ->
logger.d { "--> ${context.request.method} ${context.request.url}" }
val response = context.proceed()
logger.i { "<-- ${response.statusCode}" }
response
}
interceptor { context ->
context.request.headers.set("Authorization", "Bearer ${getAccessToken()}")
context.proceed()
}
}
Interceptors run in registration order. Call context.proceed() to continue the chain, or return early to short-circuit.
URL builder
For fine-grained URL construction:
client.get {
url {
protocol = "https"
host = "api.example.com"
encodedPath = "/v2/tracks"
parameter("market", "US")
}
}
Use url("...") for simple URLs, or url { ... } for the builder DSL.
Custom serialization
Spotr uses JsonContentSerializer by default (ignores unknown keys). To customize:
val client = SpotrClient(httpClient) {
serializer = JsonContentSerializer(Json {
ignoreUnknownKeys = true
isLenient = true
explicitNulls = false
})
}
Implement ContentSerializer for non-JSON formats.