Skip to content

Commit

Permalink
feat: add API to fetch eventData from event String (#258)
Browse files Browse the repository at this point in the history
* feat: add API to fetch eventData from event String

* fix: formatting

* fix: code smell

* feat: additional status code addition

* fix: status code

* fix: regenrated server to comply with new autogool

* fix: updated out of date Csrgo.toml

---------

Co-authored-by: Samika Kashyap <[email protected]>
  • Loading branch information
samika98 and Samika Kashyap authored Feb 6, 2024
1 parent dc01c95 commit dba11da
Show file tree
Hide file tree
Showing 12 changed files with 1,057 additions and 544 deletions.
1,151 changes: 634 additions & 517 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion api-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ To see how to make this your own, look here:
[README]((https://openapi-generator.tech))

- API version: 0.9.0
- Build date: 2024-01-31T10:10:25.973864005-07:00[America/Denver]
- Build date: 2024-02-06T23:45:19.070674+05:30[Asia/Kolkata]



Expand Down Expand Up @@ -62,6 +62,7 @@ cargo run --example server
To run a client, follow one of the following simple steps:

```
cargo run --example client EventsEventIdGet
cargo run --example client InterestsSortKeySortValuePost
cargo run --example client LivenessGet
cargo run --example client SubscribeSortKeySortValueGet
Expand Down Expand Up @@ -99,6 +100,7 @@ All URIs are relative to */ceramic*

Method | HTTP request | Description
------------- | ------------- | -------------
[****](docs/default_api.md#) | **GET** /events/{event_id} | Get event data
[****](docs/default_api.md#) | **POST** /events | Creates a new event
[****](docs/default_api.md#) | **POST** /interests/{sort_key}/{sort_value} | Register interest for a sort key
[****](docs/default_api.md#) | **GET** /liveness | Test the liveness of the Ceramic node
Expand Down
25 changes: 25 additions & 0 deletions api-server/api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,31 @@ paths:
"204":
description: success
summary: Creates a new event
/events/{event_id}:
get:
parameters:
- description: identifier of the event
explode: false
in: path
name: event_id
required: true
schema:
type: string
style: simple
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/Event'
description: success
"404":
content:
text/plain:
schema:
type: string
description: Event not found
summary: Get event data
/interests/{sort_key}/{sort_value}:
post:
parameters:
Expand Down
26 changes: 26 additions & 0 deletions api-server/docs/default_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,39 @@ All URIs are relative to */ceramic*

Method | HTTP request | Description
------------- | ------------- | -------------
****](default_api.md#) | **GET** /events/{event_id} | Get event data
****](default_api.md#) | **POST** /events | Creates a new event
****](default_api.md#) | **POST** /interests/{sort_key}/{sort_value} | Register interest for a sort key
****](default_api.md#) | **GET** /liveness | Test the liveness of the Ceramic node
****](default_api.md#) | **GET** /subscribe/{sort_key}/{sort_value} | Get events for a stream
****](default_api.md#) | **POST** /version | Get the version of the Ceramic node


# ****
> models::Event (event_id)
Get event data

### Required Parameters

Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**event_id** | **String**| identifier of the event |

### Return type

[**models::Event**](Event.md)

### Authorization

No authorization required

### HTTP request headers

- **Content-Type**: Not defined
- **Accept**: application/json, text/plain

[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

# ****
> (event)
Creates a new event
Expand Down
13 changes: 11 additions & 2 deletions api-server/examples/client/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

#[allow(unused_imports)]
use ceramic_api_server::{
models, Api, ApiNoContext, Client, ContextWrapperExt, EventsPostResponse,
InterestsSortKeySortValuePostResponse, LivenessGetResponse,
models, Api, ApiNoContext, Client, ContextWrapperExt, EventsEventIdGetResponse,
EventsPostResponse, InterestsSortKeySortValuePostResponse, LivenessGetResponse,
SubscribeSortKeySortValueGetResponse, VersionPostResponse,
};
use clap::{App, Arg};
Expand Down Expand Up @@ -34,6 +34,7 @@ fn main() {
Arg::with_name("operation")
.help("Sets the operation to run")
.possible_values(&[
"EventsEventIdGet",
"InterestsSortKeySortValuePost",
"LivenessGet",
"SubscribeSortKeySortValueGet",
Expand Down Expand Up @@ -93,6 +94,14 @@ fn main() {
let mut rt = tokio::runtime::Runtime::new().unwrap();

match matches.value_of("operation") {
Some("EventsEventIdGet") => {
let result = rt.block_on(client.events_event_id_get("event_id_example".to_string()));
info!(
"{:?} (X-Span-ID: {:?})",
result,
(client.context() as &dyn Has<XSpanIdString>).get().clone()
);
}
/* Disabled because there's no example.
Some("EventsPost") => {
let result = rt.block_on(client.events_post(
Expand Down
18 changes: 16 additions & 2 deletions api-server/examples/server/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ impl<C> Server<C> {

use ceramic_api_server::server::MakeService;
use ceramic_api_server::{
Api, EventsPostResponse, InterestsSortKeySortValuePostResponse, LivenessGetResponse,
SubscribeSortKeySortValueGetResponse, VersionPostResponse,
Api, EventsEventIdGetResponse, EventsPostResponse, InterestsSortKeySortValuePostResponse,
LivenessGetResponse, SubscribeSortKeySortValueGetResponse, VersionPostResponse,
};
use std::error::Error;
use swagger::ApiError;
Expand All @@ -112,6 +112,20 @@ impl<C> Api<C> for Server<C>
where
C: Has<XSpanIdString> + Send + Sync,
{
/// Get event data
async fn events_event_id_get(
&self,
event_id: String,
context: &C,
) -> Result<EventsEventIdGetResponse, ApiError> {
info!(
"events_event_id_get(\"{}\") - X-Span-ID: {:?}",
event_id,
context.get().0.clone()
);
Err(ApiError("Generic failure".into()))
}

/// Creates a new event
async fn events_post(
&self,
Expand Down
104 changes: 101 additions & 3 deletions api-server/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ const FRAGMENT_ENCODE_SET: &AsciiSet = &percent_encoding::CONTROLS
const ID_ENCODE_SET: &AsciiSet = &FRAGMENT_ENCODE_SET.add(b'|');

use crate::{
Api, EventsPostResponse, InterestsSortKeySortValuePostResponse, LivenessGetResponse,
SubscribeSortKeySortValueGetResponse, VersionPostResponse,
Api, EventsEventIdGetResponse, EventsPostResponse, InterestsSortKeySortValuePostResponse,
LivenessGetResponse, SubscribeSortKeySortValueGetResponse, VersionPostResponse,
};

/// Convert input into a base path, e.g. "http://example:123". Also checks the scheme as it goes.
Expand Down Expand Up @@ -390,6 +390,105 @@ where
}
}

async fn events_event_id_get(
&self,
param_event_id: String,
context: &C,
) -> Result<EventsEventIdGetResponse, ApiError> {
let mut client_service = self.client_service.clone();
let mut uri = format!(
"{}/ceramic/events/{event_id}",
self.base_path,
event_id = utf8_percent_encode(&param_event_id.to_string(), ID_ENCODE_SET)
);

// Query parameters
let query_string = {
let mut query_string = form_urlencoded::Serializer::new("".to_owned());
query_string.finish()
};
if !query_string.is_empty() {
uri += "?";
uri += &query_string;
}

let uri = match Uri::from_str(&uri) {
Ok(uri) => uri,
Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))),
};

let mut request = match Request::builder()
.method("GET")
.uri(uri)
.body(Body::empty())
{
Ok(req) => req,
Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))),
};

let header = HeaderValue::from_str(Has::<XSpanIdString>::get(context).0.as_str());
request.headers_mut().insert(
HeaderName::from_static("x-span-id"),
match header {
Ok(h) => h,
Err(e) => {
return Err(ApiError(format!(
"Unable to create X-Span ID header value: {}",
e
)))
}
},
);

let response = client_service
.call((request, context.clone()))
.map_err(|e| ApiError(format!("No response received: {}", e)))
.await?;

match response.status().as_u16() {
200 => {
let body = response.into_body();
let body = body
.into_raw()
.map_err(|e| ApiError(format!("Failed to read response: {}", e)))
.await?;
let body = str::from_utf8(&body)
.map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?;
let body = serde_json::from_str::<models::Event>(body).map_err(|e| {
ApiError(format!("Response body did not match the schema: {}", e))
})?;
Ok(EventsEventIdGetResponse::Success(body))
}
404 => {
let body = response.into_body();
let body = body
.into_raw()
.map_err(|e| ApiError(format!("Failed to read response: {}", e)))
.await?;
let body = str::from_utf8(&body)
.map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?;
let body = body.to_string();
Ok(EventsEventIdGetResponse::EventNotFound(body))
}
code => {
let headers = response.headers().clone();
let body = response.into_body().take(100).into_raw().await;
Err(ApiError(format!(
"Unexpected response code {}:\n{:?}\n\n{}",
code,
headers,
match body {
Ok(body) => match String::from_utf8(body) {
Ok(body) => body,
Err(e) => format!("<Body was not UTF8: {:?}>", e),
},
Err(e) => format!("<Failed to read body: {}>", e),
}
)))
}
}
}

async fn events_post(
&self,
param_event: models::Event,
Expand Down Expand Up @@ -422,7 +521,6 @@ where
Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))),
};

// Body parameter
let body = serde_json::to_string(&param_event).expect("impossible to fail to serialize");
*request.body_mut() = Body::from(body);

Expand Down
31 changes: 31 additions & 0 deletions api-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ type ServiceError = Box<dyn Error + Send + Sync + 'static>;
pub const BASE_PATH: &str = "/ceramic";
pub const API_VERSION: &str = "0.9.0";

#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[must_use]
pub enum EventsEventIdGetResponse {
/// success
Success(models::Event),
/// Event not found
EventNotFound(String),
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub enum EventsPostResponse {
/// success
Expand Down Expand Up @@ -63,6 +72,13 @@ pub trait Api<C: Send + Sync> {
Poll::Ready(Ok(()))
}

/// Get event data
async fn events_event_id_get(
&self,
event_id: String,
context: &C,
) -> Result<EventsEventIdGetResponse, ApiError>;

/// Creates a new event
async fn events_post(
&self,
Expand Down Expand Up @@ -110,6 +126,12 @@ pub trait ApiNoContext<C: Send + Sync> {

fn context(&self) -> &C;

/// Get event data
async fn events_event_id_get(
&self,
event_id: String,
) -> Result<EventsEventIdGetResponse, ApiError>;

/// Creates a new event
async fn events_post(&self, event: models::Event) -> Result<EventsPostResponse, ApiError>;

Expand Down Expand Up @@ -165,6 +187,15 @@ impl<T: Api<C> + Send + Sync, C: Clone + Send + Sync> ApiNoContext<C> for Contex
ContextWrapper::context(self)
}

/// Get event data
async fn events_event_id_get(
&self,
event_id: String,
) -> Result<EventsEventIdGetResponse, ApiError> {
let context = self.context().clone();
self.api().events_event_id_get(event_id, &context).await
}

/// Creates a new event
async fn events_post(&self, event: models::Event) -> Result<EventsPostResponse, ApiError> {
let context = self.context().clone();
Expand Down
Loading

0 comments on commit dba11da

Please sign in to comment.