-
-
Notifications
You must be signed in to change notification settings - Fork 539
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: support to Rocket-Okapi #1071
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
4eb15f5
feat: support to okapi
eum602 f15dade
fix: fmt checks
eum602 ec4bd62
chore: rocket-okapi-example: add required schemas
eum602 7062827
chore: rocket-okapi-example: add dto
eum602 a176556
chore: rocket-okapi-example: add custom error
eum602 85f2c6c
chore: rocket-okapi-example: add api controllers
eum602 6351c21
chore: rocket-okapi-example: add notes in Readme
eum602 acd3123
chore: make rocket_okapi optional
eum602 c08e212
refactor: delete rocket example from rocket_example
eum602 da39d83
chore: rocket-okapi-example: add base files for okapi example
eum602 bf39063
chore: rocket-okapi-example: add controllers and dto
eum602 01c9f32
chore: rocket-okapi-example: add docs
eum602 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[package] | ||
name = "sea-orm-rocket-okapi-example" | ||
version = "0.1.0" | ||
authors = ["Sam Samai <[email protected]>", "Erick Pacheco <[email protected]"] | ||
edition = "2021" | ||
publish = false | ||
|
||
[workspace] | ||
members = [".", "api", "core", "entity", "migration", "dto"] | ||
|
||
[dependencies] | ||
rocket-example-api = { path = "api" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# Rocket and Rocket-API with SeaORM example app | ||
|
||
1. Modify the `url` var in `api/Rocket.toml` to point to your chosen database | ||
|
||
1. Turn on the appropriate database feature for your chosen db in `core/Cargo.toml` (the `"sqlx-postgres",` line) | ||
|
||
1. Execute `cargo run` to start the server | ||
|
||
1. You can go to ```http://localhost:8000/swagger-ui/index.html``` to see the api documentation about this demo project. | ||
![swagger](swagger.png) | ||
1. Additionally, you can navigate to ```http://localhost:8000/rapidoc/index.html``` to see the rapidoc format for api documentation | ||
![rapidoc](rapidoc.png) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
[default] | ||
template_dir = "api/templates/" | ||
|
||
[default.databases.sea_orm] | ||
# Mysql | ||
# make sure to enable "sqlx-mysql" feature in Cargo.toml, i.e default = ["sqlx-mysql"] | ||
# url = "mysql://root:@localhost/rocket_example" | ||
|
||
# Postgres | ||
# make sure to enable "sqlx-postgres" feature in Cargo.toml, i.e default = ["sqlx-postgres"] | ||
url = "postgres://user:pass@localhost:5432/rocket" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
[package] | ||
name = "rocket-example-api" | ||
version = "0.1.0" | ||
authors = ["Sam Samai <[email protected]>"] | ||
edition = "2021" | ||
publish = false | ||
|
||
[dependencies] | ||
async-stream = { version = "^0.3" } | ||
async-trait = { version = "0.1" } | ||
rocket-example-core = { path = "../core" } | ||
futures = { version = "^0.3" } | ||
futures-util = { version = "^0.3" } | ||
rocket = { version = "0.5.0-rc.1", features = [ | ||
"json", | ||
] } | ||
rocket_dyn_templates = { version = "0.1.0-rc.1", features = [ | ||
"tera", | ||
] } | ||
serde_json = { version = "^1" } | ||
entity = { path = "../entity" } | ||
migration = { path = "../migration" } | ||
tokio = "1.20.0" | ||
serde = "1.0" | ||
dto = { path = "../dto" } | ||
|
||
[dependencies.sea-orm-rocket] | ||
path = "../../../sea-orm-rocket/lib" # remove this line in your own project and use the git line | ||
features = ["rocket_okapi"] #enables rocket_okapi so to have open api features enabled | ||
# git = "https://github.com/SeaQL/sea-orm" | ||
|
||
[dependencies.rocket_okapi] | ||
version = "0.8.0-rc.2" | ||
features = ["swagger", "rapidoc","rocket_db_pools"] | ||
|
||
[dependencies.rocket_cors] | ||
git = "https://github.com/lawliet89/rocket_cors.git" | ||
rev = "54fae070" | ||
default-features = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
use rocket::{ | ||
http::{ContentType, Status}, | ||
request::Request, | ||
response::{self, Responder, Response}, | ||
}; | ||
use rocket_okapi::okapi::openapi3::Responses; | ||
use rocket_okapi::okapi::schemars::{self, Map}; | ||
use rocket_okapi::{gen::OpenApiGenerator, response::OpenApiResponderInner, OpenApiError}; | ||
|
||
/// Error messages returned to user | ||
#[derive(Debug, serde::Serialize, schemars::JsonSchema)] | ||
pub struct Error { | ||
/// The title of the error message | ||
pub err: String, | ||
/// The description of the error | ||
pub msg: Option<String>, | ||
// HTTP Status Code returned | ||
#[serde(skip)] | ||
pub http_status_code: u16, | ||
} | ||
|
||
impl OpenApiResponderInner for Error { | ||
fn responses(_generator: &mut OpenApiGenerator) -> Result<Responses, OpenApiError> { | ||
use rocket_okapi::okapi::openapi3::{RefOr, Response as OpenApiReponse}; | ||
|
||
let mut responses = Map::new(); | ||
responses.insert( | ||
"400".to_string(), | ||
RefOr::Object(OpenApiReponse { | ||
description: "\ | ||
# [400 Bad Request](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400)\n\ | ||
The request given is wrongly formatted or data asked could not be fulfilled. \ | ||
" | ||
.to_string(), | ||
..Default::default() | ||
}), | ||
); | ||
responses.insert( | ||
"404".to_string(), | ||
RefOr::Object(OpenApiReponse { | ||
description: "\ | ||
# [404 Not Found](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404)\n\ | ||
This response is given when you request a page that does not exists.\ | ||
" | ||
.to_string(), | ||
..Default::default() | ||
}), | ||
); | ||
responses.insert( | ||
"422".to_string(), | ||
RefOr::Object(OpenApiReponse { | ||
description: "\ | ||
# [422 Unprocessable Entity](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422)\n\ | ||
This response is given when you request body is not correctly formatted. \ | ||
".to_string(), | ||
..Default::default() | ||
}), | ||
); | ||
responses.insert( | ||
"500".to_string(), | ||
RefOr::Object(OpenApiReponse { | ||
description: "\ | ||
# [500 Internal Server Error](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500)\n\ | ||
This response is given when something wend wrong on the server. \ | ||
".to_string(), | ||
..Default::default() | ||
}), | ||
); | ||
Ok(Responses { | ||
responses, | ||
..Default::default() | ||
}) | ||
} | ||
} | ||
|
||
impl std::fmt::Display for Error { | ||
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!( | ||
formatter, | ||
"Error `{}`: {}", | ||
self.err, | ||
self.msg.as_deref().unwrap_or("<no message>") | ||
) | ||
} | ||
} | ||
|
||
impl std::error::Error for Error {} | ||
|
||
impl<'r> Responder<'r, 'static> for Error { | ||
fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> { | ||
// Convert object to json | ||
let body = serde_json::to_string(&self).unwrap(); | ||
Response::build() | ||
.sized_body(body.len(), std::io::Cursor::new(body)) | ||
.header(ContentType::JSON) | ||
.status(Status::new(self.http_status_code)) | ||
.ok() | ||
} | ||
} | ||
|
||
impl From<rocket::serde::json::Error<'_>> for Error { | ||
fn from(err: rocket::serde::json::Error) -> Self { | ||
use rocket::serde::json::Error::*; | ||
match err { | ||
Io(io_error) => Error { | ||
err: "IO Error".to_owned(), | ||
msg: Some(io_error.to_string()), | ||
http_status_code: 422, | ||
}, | ||
Parse(_raw_data, parse_error) => Error { | ||
err: "Parse Error".to_owned(), | ||
msg: Some(parse_error.to_string()), | ||
http_status_code: 422, | ||
}, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
#[macro_use] | ||
extern crate rocket; | ||
|
||
use rocket::fairing::{self, AdHoc}; | ||
use rocket::{Build, Rocket}; | ||
|
||
use migration::MigratorTrait; | ||
use sea_orm_rocket::Database; | ||
|
||
use rocket_okapi::mount_endpoints_and_merged_docs; | ||
use rocket_okapi::okapi::openapi3::OpenApi; | ||
use rocket_okapi::rapidoc::{make_rapidoc, GeneralConfig, HideShowConfig, RapiDocConfig}; | ||
use rocket_okapi::settings::UrlObject; | ||
use rocket_okapi::swagger_ui::{make_swagger_ui, SwaggerUIConfig}; | ||
|
||
use rocket::http::Method; | ||
use rocket_cors::{AllowedHeaders, AllowedOrigins, Cors}; | ||
|
||
mod pool; | ||
use pool::Db; | ||
mod error; | ||
mod okapi_example; | ||
|
||
pub use entity::post; | ||
pub use entity::post::Entity as Post; | ||
|
||
async fn run_migrations(rocket: Rocket<Build>) -> fairing::Result { | ||
let conn = &Db::fetch(&rocket).unwrap().conn; | ||
let _ = migration::Migrator::up(conn, None).await; | ||
Ok(rocket) | ||
} | ||
|
||
#[tokio::main] | ||
async fn start() -> Result<(), rocket::Error> { | ||
let mut building_rocket = rocket::build() | ||
.attach(Db::init()) | ||
.attach(AdHoc::try_on_ignite("Migrations", run_migrations)) | ||
.mount( | ||
"/swagger-ui/", | ||
make_swagger_ui(&SwaggerUIConfig { | ||
url: "../v1/openapi.json".to_owned(), | ||
..Default::default() | ||
}), | ||
) | ||
.mount( | ||
"/rapidoc/", | ||
make_rapidoc(&RapiDocConfig { | ||
title: Some("Rocket/SeaOrm - RapiDoc documentation | RapiDoc".to_owned()), | ||
general: GeneralConfig { | ||
spec_urls: vec![UrlObject::new("General", "../v1/openapi.json")], | ||
..Default::default() | ||
}, | ||
hide_show: HideShowConfig { | ||
allow_spec_url_load: false, | ||
allow_spec_file_load: false, | ||
..Default::default() | ||
}, | ||
..Default::default() | ||
}), | ||
) | ||
.attach(cors()); | ||
|
||
let openapi_settings = rocket_okapi::settings::OpenApiSettings::default(); | ||
let custom_route_spec = (vec![], custom_openapi_spec()); | ||
mount_endpoints_and_merged_docs! { | ||
building_rocket, "/v1".to_owned(), openapi_settings, | ||
"/additional" => custom_route_spec, | ||
"/okapi-example" => okapi_example::get_routes_and_docs(&openapi_settings), | ||
}; | ||
|
||
building_rocket.launch().await.map(|_| ()) | ||
} | ||
|
||
fn cors() -> Cors { | ||
let allowed_origins = | ||
AllowedOrigins::some_exact(&["http://localhost:8000", "http://127.0.0.1:8000"]); | ||
|
||
let cors = rocket_cors::CorsOptions { | ||
allowed_origins, | ||
allowed_methods: vec![Method::Get, Method::Post, Method::Delete] | ||
.into_iter() | ||
.map(From::from) | ||
.collect(), | ||
allowed_headers: AllowedHeaders::all(), | ||
allow_credentials: true, | ||
..Default::default() | ||
} | ||
.to_cors() | ||
.unwrap(); | ||
cors | ||
} | ||
|
||
fn custom_openapi_spec() -> OpenApi { | ||
use rocket_okapi::okapi::openapi3::*; | ||
OpenApi { | ||
openapi: OpenApi::default_version(), | ||
info: Info { | ||
title: "SeaOrm-Rocket-Okapi Example".to_owned(), | ||
description: Some("API Docs for Rocket/SeaOrm example".to_owned()), | ||
terms_of_service: Some("https://github.com/SeaQL/sea-orm#license".to_owned()), | ||
contact: Some(Contact { | ||
name: Some("SeaOrm".to_owned()), | ||
url: Some("https://github.com/SeaQL/sea-orm".to_owned()), | ||
email: None, | ||
..Default::default() | ||
}), | ||
license: Some(License { | ||
name: "MIT".to_owned(), | ||
url: Some("https://github.com/SeaQL/sea-orm/blob/master/LICENSE-MIT".to_owned()), | ||
..Default::default() | ||
}), | ||
version: env!("CARGO_PKG_VERSION").to_owned(), | ||
..Default::default() | ||
}, | ||
servers: vec![ | ||
Server { | ||
url: "http://127.0.0.1:8000/v1".to_owned(), | ||
description: Some("Localhost".to_owned()), | ||
..Default::default() | ||
}, | ||
Server { | ||
url: "https://production-server.com/".to_owned(), | ||
description: Some("Remote development server".to_owned()), | ||
..Default::default() | ||
}, | ||
], | ||
..Default::default() | ||
} | ||
} | ||
|
||
pub fn main() { | ||
let result = start(); | ||
|
||
println!("Rocket: deorbit."); | ||
|
||
if let Some(err) = result.err() { | ||
println!("Error: {}", err); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tyt2y3 I added a new folder to exemplify the usage of rocket_okapi. Hope this is enough otherwise I could make some changes you guys consider to make it better.