Skip to content

Commit

Permalink
feat: add api axum based handlers (ongoing)
Browse files Browse the repository at this point in the history
  • Loading branch information
subotic committed Sep 25, 2023
1 parent fa79cfc commit cb8fee3
Show file tree
Hide file tree
Showing 23 changed files with 146 additions and 85 deletions.
19 changes: 9 additions & 10 deletions src/bin/dsp_meta_server/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@ use std::sync::Arc;

use axum::routing::{get, post};
use axum::Router;
use dsp_meta::api;
use dsp_meta::api::project_metadata_handler;
use dsp_meta::app_state::app_state::AppState;
use dsp_meta::repo::project_metadata_repository::ProjectMetadataRepository;
use dsp_meta::service::project_metadata_service::ProjectMetadataService;
use tracing::{trace, Level};
use tracing_subscriber::FmtSubscriber;

#[derive(Clone)]
pub struct AppState {
project_metadata_service: ProjectMetadataService<ProjectMetadataRepository>,
}

#[tokio::main]
async fn main() {
// configure tracing library
Expand Down Expand Up @@ -41,11 +37,14 @@ async fn main() {
/// without having to create an HTTP server.
fn app(shared_state: Arc<AppState>) -> Router {
Router::new()
.route("/", get(api::get_root).post(api::post_root))
.route("/hello_world", get(api::hello_world))
.route("/foo/bar", get(api::foo_bar))
.route(
"/",
get(project_metadata_handler::get_root).post(project_metadata_handler::post_root),
)
.route("/hello_world", get(project_metadata_handler::hello_world))
.route("/foo/bar", get(project_metadata_handler::foo_bar))
// `POST /users` goes to `create_user`
.route("/users", post(api::create_user))
.route("/users", post(project_metadata_handler::create_user))
.with_state(shared_state)
}

Expand Down
47 changes: 1 addition & 46 deletions src/dsp_meta/api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1 @@
use std::sync::Arc;

use axum::extract::State;
use axum::http::StatusCode;
use axum::Json;
use serde::{Deserialize, Serialize};

// basic handler that responds with a static string
pub async fn hello_world(State(state): State<Arc<AppState>>) -> &'static str {
"Hello, World!"
}

pub async fn get_root() {}

pub async fn post_root() {}

pub async fn foo_bar() {}

pub async fn create_user(
// this argument tells axum to parse the request body
// as JSON into a `CreateUser` type
Json(payload): Json<CreateUser>,
) -> (StatusCode, Json<User>) {
// insert your application logic here
let user = User {
id: 1337,
username: payload.username,
};

// this will be converted into a JSON response
// with a status code of `201 Created`
(StatusCode::CREATED, Json(user))
}

// the input to our `create_user` handler
#[derive(Deserialize)]
pub struct CreateUser {
username: String,
}

// the output to our `create_user` handler
#[derive(Serialize)]
pub struct User {
id: u64,
username: String,
}
pub mod project_metadata_handler;
70 changes: 70 additions & 0 deletions src/dsp_meta/api/project_metadata_handler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use std::sync::Arc;

use axum::extract::State;
use axum::http::StatusCode;
use axum::response::Json;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use tracing::trace;

use crate::app_state::app_state::AppState;
use crate::domain::value::Shortcode;
use crate::service::project_metadata_api_contract::ProjectMetadataApiContract;

/// GET /project_metadata/:shortcode
/// Get project metadata by shortcode
///
/// TODO: Add error handling with correct status codes
/// TODO: Add parameter extraction
pub async fn get_project_metadata_by_shortcode(
shortcode: String,
State(state): State<Arc<AppState>>,
) -> Json<Value> {
trace!("entered dsp_meta::api::get_project_metadata_by_shortcode()");
let project_metadata = state
.project_metadata_service
.get_by_shortcode(Shortcode(shortcode));
Json(serde_json::to_value(project_metadata).unwrap())
}

// basic handler that responds with a static string
pub async fn hello_world(State(state): State<Arc<AppState>>) -> &'static str {
trace!("entered dsp_meta::api::hello_world()");
let _ = state.project_metadata_service;
"Hello, World!"
}

pub async fn get_root() {}

pub async fn post_root() {}

pub async fn foo_bar() {}

pub async fn create_user(
// this argument tells axum to parse the request body
// as JSON into a `CreateUser` type
Json(payload): Json<CreateUser>,
) -> (StatusCode, Json<User>) {
// insert your application logic here
let user = User {
id: 1337,
username: payload.username,
};

// this will be converted into a JSON response
// with a status code of `201 Created`
(StatusCode::CREATED, Json(user))
}

// the input to our `create_user` handler
#[derive(Deserialize)]
pub struct CreateUser {
username: String,
}

// the output to our `create_user` handler
#[derive(Serialize)]
pub struct User {
id: u64,
username: String,
}
7 changes: 7 additions & 0 deletions src/dsp_meta/app_state/app_state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use crate::repo::project_metadata_repository::ProjectMetadataRepository;
use crate::service::project_metadata_service::ProjectMetadataService;

#[derive(Clone)]
pub struct AppState {
pub project_metadata_service: ProjectMetadataService<ProjectMetadataRepository>,
}
1 change: 1 addition & 0 deletions src/dsp_meta/app_state/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod app_state;
4 changes: 3 additions & 1 deletion src/dsp_meta/domain/entity/project.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use serde::Serialize;

use crate::domain::convert::project::{ExtractedProjectAttributes, ExtractedProjectBlocks};
use crate::domain::value::alternative_name::AlternativeName;
use crate::domain::value::description::Description;
Expand All @@ -10,7 +12,7 @@ use crate::domain::value::{
};
use crate::errors::DspMetaError;

#[derive(Debug, Default, Clone, PartialEq)]
#[derive(Debug, Default, Clone, PartialEq, Serialize)]
pub struct Project {
pub created_at: CreatedAt,
pub created_by: CreatedBy,
Expand Down
4 changes: 3 additions & 1 deletion src/dsp_meta/domain/entity/project_metadata.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use serde::Serialize;

use crate::domain::entity::dataset::Dataset;
use crate::domain::entity::grant::Grant;
use crate::domain::entity::organization::Organization;
Expand All @@ -7,7 +9,7 @@ use crate::domain::value::version::Version;
use crate::errors::DspMetaError;

/// The Metadata struct represents the metadata of a DSP project.
#[derive(Debug, Default, Clone, PartialEq)]
#[derive(Debug, Default, Clone, PartialEq, Serialize)]
pub struct ProjectMetadata {
pub version: Version,
pub project: Project,
Expand Down
4 changes: 3 additions & 1 deletion src/dsp_meta/domain/value/alternative_name.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use std::collections::HashMap;

use serde::Serialize;

use crate::domain::value::iso_code::IsoCode;
use crate::domain::value::lang_text_data::LangTextData;
use crate::errors::DspMetaError;

const ALTERNATIVE_NAME_BLOCK_IDENTIFIER: &str = "alternative_name";

#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct AlternativeName(HashMap<IsoCode, String>);

impl Default for AlternativeName {
Expand Down
4 changes: 3 additions & 1 deletion src/dsp_meta/domain/value/description.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use std::collections::HashMap;

use serde::Serialize;

use crate::domain::value::iso_code::IsoCode;
use crate::domain::value::lang_text_data::LangTextData;
use crate::errors::DspMetaError;

const DESCRIPTION_BLOCK_IDENTIFIER: &str = "description";

/// A set of descriptions in different languages.
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct Description(HashMap<IsoCode, String>);

impl Default for Description {
Expand Down
4 changes: 3 additions & 1 deletion src/dsp_meta/domain/value/discipline.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use serde::Serialize;

use crate::domain::value::lang_text_data::LangTextData;
use crate::domain::value::ref_data::RefData;
use crate::errors::DspMetaError;
Expand All @@ -14,7 +16,7 @@ use crate::errors::DspMetaError;
/// url = "https://skos.um.es/unesco6/5501"
/// }
/// ```
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, Serialize)]
pub enum Discipline {
Skos(RefData),
Snf(RefData),
Expand Down
4 changes: 3 additions & 1 deletion src/dsp_meta/domain/value/iso_code.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use std::fmt::{Display, Formatter};

use serde::Serialize;

use crate::errors::DspMetaError;

/// Language codes according to ISO 639-1
/// Not an exhaustive list.
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Serialize)]
pub enum IsoCode {
#[default]
DE, // German
Expand Down
4 changes: 3 additions & 1 deletion src/dsp_meta/domain/value/keyword.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use std::collections::HashMap;

use serde::Serialize;

use crate::domain::value::iso_code::IsoCode;
use crate::domain::value::lang_text_data::LangTextData;
use crate::errors::DspMetaError;

const KEYWORD_BLOCK_IDENTIFIER: &str = "keyword";

#[derive(Clone, Debug, Default, PartialEq)]
#[derive(Clone, Debug, Default, PartialEq, Serialize)]
pub struct Keyword(HashMap<IsoCode, String>);

impl TryFrom<&hcl::Block> for Keyword {
Expand Down
4 changes: 3 additions & 1 deletion src/dsp_meta/domain/value/lang_text_data.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use std::collections::HashMap;

use serde::Serialize;

use crate::domain::value::iso_code::IsoCode;
use crate::errors::DspMetaError;

/// Represents multiple strings in different languages.
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct LangTextData(pub HashMap<IsoCode, String>);

/// FIXME: Move to the API layer where the service adapter will be implemented
Expand Down
20 changes: 11 additions & 9 deletions src/dsp_meta/domain/value/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use serde::Serialize;

pub(crate) mod alternative_name;
pub(crate) mod description;
pub(crate) mod discipline;
Expand All @@ -15,31 +17,31 @@ pub(crate) mod version;
#[derive(Debug, Default, Clone, PartialEq)]
pub struct ID(String);

#[derive(Debug, Default, Clone, PartialEq)]
#[derive(Debug, Default, Clone, PartialEq, Serialize)]
pub struct CreatedAt(pub u64);

#[derive(Debug, Default, Clone, PartialEq)]
#[derive(Debug, Default, Clone, PartialEq, Serialize)]
pub struct CreatedBy(pub String);

#[derive(Debug, Default, Clone, PartialEq)]
#[derive(Debug, Default, Clone, PartialEq, Serialize)]
pub struct Shortcode(pub String);

#[derive(Debug, Default, Clone, PartialEq)]
#[derive(Debug, Default, Clone, PartialEq, Serialize)]
pub struct Name(pub String);

#[derive(Debug, Default, Clone, PartialEq)]
#[derive(Debug, Default, Clone, PartialEq, Serialize)]
pub struct TeaserText(pub String);

#[derive(Debug, Default, Clone, PartialEq)]
#[derive(Debug, Default, Clone, PartialEq, Serialize)]
pub struct HowToCite(pub String);

#[derive(Debug, Default, Clone, PartialEq)]
#[derive(Debug, Default, Clone, PartialEq, Serialize)]
pub struct StartDate(pub String);

#[derive(Debug, Default, Clone, PartialEq)]
#[derive(Debug, Default, Clone, PartialEq, Serialize)]
pub struct EndDate(pub String);

#[derive(Debug, Default, Clone, PartialEq)]
#[derive(Debug, Default, Clone, PartialEq, Serialize)]
pub struct ContactPoint(pub String);

#[derive(Debug, Default, Clone, PartialEq)]
Expand Down
4 changes: 3 additions & 1 deletion src/dsp_meta/domain/value/publication.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use serde::Serialize;

use crate::domain::value::simple_text_data::SimpleTextData;
use crate::errors::DspMetaError;

const PUBLICATION_BLOCK_IDENTIFIER: &str = "publication";

#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Serialize)]
pub enum Publication {
SimpleText(SimpleTextData),
}
Expand Down
3 changes: 2 additions & 1 deletion src/dsp_meta/domain/value/ref_data.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use serde::Serialize;
use tracing::warn;

use crate::errors::DspMetaError;

#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct RefData {
pub(crate) ref_id: String,
pub(crate) description: String,
Expand Down
3 changes: 2 additions & 1 deletion src/dsp_meta/domain/value/simple_text_data.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use serde::Serialize;
use tracing::warn;

use crate::errors::DspMetaError;

const TEXT_ATTRIBUTE_IDENTIFIER: &str = "text";

#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct SimpleTextData(pub String);

impl TryFrom<Vec<&hcl::Attribute>> for SimpleTextData {
Expand Down
3 changes: 2 additions & 1 deletion src/dsp_meta/domain/value/url.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use serde::Serialize;
use tracing::warn;

use crate::errors::DspMetaError;
Expand All @@ -19,7 +20,7 @@ const LABEL_ATTRIBUTE_KEY: &str = "label";
///
/// Use [`Attribute::new`] to construct an [`Attribute`] from a value that is convertible to this
/// crate's [`Expression`] type.
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
pub struct Url {
pub href: url::Url,
pub label: String,
Expand Down
3 changes: 2 additions & 1 deletion src/dsp_meta/domain/value/version.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use hcl::Expression;
use serde::Serialize;

#[derive(Debug, Default, Clone, PartialEq)]
#[derive(Debug, Default, Clone, PartialEq, Serialize)]
pub struct Version(pub u64);

/// Given a list of attributes, try to extract the version.
Expand Down
Loading

0 comments on commit cb8fee3

Please sign in to comment.