Skip to main content
This example shows how you can make a custom resource. The example resource we’ll be making will be a Plain Data Object (which we will refer to as pdo), and outputs the value that you pass into the “name” attribute for the resource. We are using the Axum framework in main.rs so we can showcase the resource in action, but the implementation is entirely separate from what web framework you use so you can add your custom resource to any Shuttle-hosted resource. You can clone the example below by running the following (you’ll need shuttle CLI installed):
shuttle init --from https://github.com/shuttle-hq/shuttle-examples --subfolder custom-resource/pdo
use axum::{extract::State, routing::get, Router};
use pdo::{Builder, Pdo};
use std::sync::Arc;

async fn hello_world(State(pdo): State<Arc<Pdo>>) -> String {
    pdo.name.clone()
}

#[shuttle_runtime::main]
async fn axum(#[Builder(name = "John")] pdo: Pdo) -> shuttle_axum::ShuttleAxum {
    let state = Arc::new(pdo);
    let router = Router::new().route("/", get(hello_world)).with_state(state);

    Ok(router.into())
}
use async_trait::async_trait;
use serde::Serialize;
use shuttle_service::{resource::Type, Error, Factory, IntoResource, ResourceBuilder};

#[derive(Default, Serialize)]
pub struct Builder {
    name: String,
}

pub struct Pdo {
    pub name: String,
}

impl Builder {
    /// Name to give resource
    pub fn name(mut self, name: &str) -> Self {
        self.name = name.to_string();
        self
    }
}

#[async_trait]
impl ResourceBuilder for Builder {
    const TYPE: Type = Type::Custom;
    type Config = Self;
    type Output = String;

    fn config(&self) -> &Self::Config {
        self
    }

    async fn output(self, _factory: &mut dyn Factory) -> Result<Self::Output, Error> {
        // factory can be used to get resources from Shuttle
        Ok(self.name)
    }
}

#[async_trait]
impl IntoResource<Pdo> for String {
    async fn into_resource(self) -> Result<Pdo, Error> {
        Ok(Pdo { name: self })
    }
}
[package]
name = "pdo"
version = "0.1.0"
edition = "2021"

[dependencies]
async-trait = "0.1.56"
axum = "0.7.3"
serde = { version = "1.0.148", default-features = false, features = ["derive"] }
shuttle-service = "0.57.0"
shuttle-axum = "0.57.0"
shuttle-runtime = "0.57.0"
tokio = "1.28.2"