-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
## Development Guide | ||
|
||
### Adding a New Route | ||
|
||
Here’s how you can add routes: | ||
|
||
1. **Create a Route**: Add a new route in the `src/routes` folder. | ||
2. **Update `src/startup.rs`**: Import the new route and include it under the `/api/v1` path in the `src/startup.rs` file. | ||
3. **Document with `utoipa`**: To ensure API documentation is generated, annotate the exposed service function with the `#[utoipa]` attribute. Also, make sure the path is registered in `src/routes/api/v1/mod.rs` so it appears in the API documentation. | ||
4. **Handle Migrations (if necessary)**: If the route involves schema or database changes, create a migration. Use `make migrate-create <migration_info>` to generate a new migration file and then modify it as needed. Run the migration using `make migrate-run`. | ||
5. **Write Tests**: It’s good practice to add tests for your route. Create a new test file in the `tests/api` folder, and refer to existing tests for guidance. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,89 @@ | ||
pub(crate) mod with_code; | ||
use actix_web::{http::StatusCode, ResponseError}; | ||
use serde::Serialize; | ||
use utoipa::{OpenApi, ToSchema}; | ||
|
||
pub(crate) mod with_code_and_clex; | ||
pub(crate) mod with_code_and_constraint; | ||
pub(crate) mod with_code_and_platform; | ||
pub(crate) mod with_platform; | ||
pub(crate) mod with_shared_code; | ||
pub(crate) mod with_shared_id; | ||
|
||
#[derive(OpenApi)] | ||
#[openapi(paths( | ||
crate::routes::api::v1::evaluate::with_code_and_constraint::post_with_code_and_constraint, | ||
crate::routes::api::v1::evaluate::with_code_and_clex::post_with_code_and_clex, | ||
crate::routes::api::v1::evaluate::with_code_and_platform::post_with_code_and_platform, | ||
crate::routes::api::v1::evaluate::with_shared_id::post_with_shared_id, | ||
crate::routes::api::v1::evaluate::with_platform::post_with_platform, | ||
))] | ||
pub(crate) struct EvaluateCodeApiv1; | ||
|
||
#[derive(Serialize, ToSchema)] | ||
struct EvaluateCodeInputDiff { | ||
#[schema(example = "Hello, world!")] | ||
expected_output: String, | ||
|
||
#[schema(example = "Hello, worldd!")] | ||
actual_output: String, | ||
} | ||
|
||
#[derive(Serialize, ToSchema)] | ||
struct EvaluateCodeResponse { | ||
#[schema(example = false)] | ||
has_output_matched: bool, | ||
|
||
#[schema(example = json!(Vec::from([EvaluateCodeInputDiff { | ||
expected_output: "Hello, world!".to_string(), | ||
actual_output: "Hello, worldd!".to_string(), | ||
}])))] | ||
input_diffs: Vec<EvaluateCodeInputDiff>, | ||
} | ||
|
||
#[derive(thiserror::Error)] | ||
pub enum EvaluateAPIError { | ||
#[error("{0}")] | ||
InvalidClex(String), | ||
|
||
#[error("{0}")] | ||
DirtyLanguageInDatabase(String), | ||
|
||
#[error("{0}")] | ||
ShareIdNotFound(String), | ||
|
||
#[error("{0}")] | ||
InvalidShareId(String), | ||
|
||
#[error(transparent)] | ||
UnexpectedError(#[from] anyhow::Error), | ||
} | ||
|
||
impl std::fmt::Debug for EvaluateAPIError { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
error_chain_fmt(self, f) | ||
} | ||
} | ||
|
||
impl ResponseError for EvaluateAPIError { | ||
fn status_code(&self) -> StatusCode { | ||
match self { | ||
EvaluateAPIError::InvalidClex(_) => StatusCode::BAD_REQUEST, | ||
EvaluateAPIError::InvalidShareId(_) => StatusCode::BAD_REQUEST, | ||
EvaluateAPIError::DirtyLanguageInDatabase(_) => StatusCode::INTERNAL_SERVER_ERROR, | ||
EvaluateAPIError::ShareIdNotFound(_) => StatusCode::NOT_FOUND, | ||
EvaluateAPIError::UnexpectedError(_) => StatusCode::INTERNAL_SERVER_ERROR, | ||
} | ||
} | ||
} | ||
|
||
pub fn error_chain_fmt( | ||
e: &impl std::error::Error, | ||
f: &mut std::fmt::Formatter<'_>, | ||
) -> std::fmt::Result { | ||
writeln!(f, "{}\n", e)?; | ||
let mut current = e.source(); | ||
while let Some(cause) = current { | ||
writeln!(f, "Caused by:\n\t{}", cause)?; | ||
current = cause.source(); | ||
} | ||
Ok(()) | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
use actix_web::post; | ||
use actix_web::web::Json; | ||
use actix_web::{web, HttpResponse}; | ||
use ccode_runner::lang_runner::runner::LanguageName; | ||
use serde::{Deserialize, Serialize}; | ||
use sqlx::PgPool; | ||
use utoipa::ToSchema; | ||
|
||
use super::{EvaluateAPIError, EvaluateCodeResponse}; | ||
|
||
#[derive(Serialize, Deserialize, ToSchema, Clone, Debug)] | ||
struct EvaluateCodeWithClexRequest { | ||
#[schema(example = "print('Hello, world!')")] | ||
correct_code: String, | ||
|
||
#[schema(example = "python")] | ||
correct_code_language: LanguageName, | ||
|
||
#[schema(example = "print('Hello, worldd!')")] | ||
test_code: String, | ||
|
||
#[schema(example = "python")] | ||
test_code_language: LanguageName, | ||
|
||
#[schema(example = "N[1,50] S[1, @CH_UPPER@]")] | ||
clex: String, | ||
} | ||
|
||
#[utoipa::path( | ||
responses( | ||
(status = 200, description = "Share_id", body = EvaluateCodeResponse), | ||
(status = 400, description = "Invalid clex", body = String), | ||
(status = 500, description = "Internal server error", body = String), | ||
) | ||
)] | ||
#[post("/with_code_and_clex")] | ||
pub async fn post_with_code_and_clex( | ||
pool: web::Data<PgPool>, | ||
Check failure on line 38 in cpast_api/src/routes/api/v1/evaluate/with_code_and_clex.rs GitHub Actions / Clippy
Check failure on line 38 in cpast_api/src/routes/api/v1/evaluate/with_code_and_clex.rs GitHub Actions / Code coverage
|
||
code_request: Json<EvaluateCodeWithClexRequest>, | ||
Check failure on line 39 in cpast_api/src/routes/api/v1/evaluate/with_code_and_clex.rs GitHub Actions / Clippy
Check failure on line 39 in cpast_api/src/routes/api/v1/evaluate/with_code_and_clex.rs GitHub Actions / Code coverage
|
||
) -> Result<HttpResponse, EvaluateAPIError> { | ||
todo!("Implement post_with_code_and_clex"); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
use actix_web::post; | ||
use actix_web::web::Json; | ||
use actix_web::{web, HttpResponse}; | ||
use ccode_runner::lang_runner::runner::LanguageName; | ||
use serde::{Deserialize, Serialize}; | ||
use sqlx::PgPool; | ||
use utoipa::ToSchema; | ||
|
||
use super::{EvaluateAPIError, EvaluateCodeResponse}; | ||
|
||
#[derive(Serialize, Deserialize, ToSchema, Clone, Debug)] | ||
struct EvaluateCodeWithConstraintRequest { | ||
#[schema(example = "print('Hello,', input(), '!')")] | ||
correct_code: String, | ||
|
||
#[schema(example = "python")] | ||
correct_code_language: LanguageName, | ||
|
||
#[schema(example = "print('Hello, worldd!')")] | ||
test_code: String, | ||
|
||
#[schema(example = "python")] | ||
test_code_language: LanguageName, | ||
|
||
#[schema(example = "Print hello followed by inputted name")] | ||
problem_description: String, | ||
|
||
#[schema(example = "One string input")] | ||
input_format: String, | ||
|
||
#[schema(example = "length of name is less than 50")] | ||
constraints: String, | ||
} | ||
|
||
#[utoipa::path( | ||
responses( | ||
(status = 200, description = "Share_id", body = EvaluateCodeResponse), | ||
(status = 400, description = "Invalid clex", body = String), | ||
(status = 500, description = "Internal server error", body = String), | ||
) | ||
)] | ||
#[post("/with_code_and_constraint")] | ||
pub async fn post_with_code_and_constraint( | ||
pool: web::Data<PgPool>, | ||
Check failure on line 44 in cpast_api/src/routes/api/v1/evaluate/with_code_and_constraint.rs GitHub Actions / Clippy
Check failure on line 44 in cpast_api/src/routes/api/v1/evaluate/with_code_and_constraint.rs GitHub Actions / Code coverage
|
||
code_request: Json<EvaluateCodeWithConstraintRequest>, | ||
Check failure on line 45 in cpast_api/src/routes/api/v1/evaluate/with_code_and_constraint.rs GitHub Actions / Clippy
Check failure on line 45 in cpast_api/src/routes/api/v1/evaluate/with_code_and_constraint.rs GitHub Actions / Code coverage
|
||
) -> Result<HttpResponse, EvaluateAPIError> { | ||
todo!("Implement post_with_code_and_clex"); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
use actix_web::post; | ||
use actix_web::web::Json; | ||
use actix_web::{web, HttpResponse}; | ||
use ccode_runner::lang_runner::runner::LanguageName; | ||
use serde::{Deserialize, Serialize}; | ||
use sqlx::PgPool; | ||
use utoipa::ToSchema; | ||
|
||
use super::{EvaluateAPIError, EvaluateCodeResponse}; | ||
|
||
#[derive(Serialize, Deserialize, ToSchema, Clone, Debug)] | ||
struct EvaluateCodeWithPlatformRequest { | ||
#[schema(example = "print('Hello,', input(), '!')")] | ||
correct_code: String, | ||
|
||
#[schema(example = "python")] | ||
correct_code_language: LanguageName, | ||
|
||
#[schema(example = "print('Hello, worldd!')")] | ||
test_code: String, | ||
|
||
#[schema(example = "python")] | ||
test_code_language: LanguageName, | ||
|
||
// TODO: Use custom in house URL type instead of String | ||
#[schema(example = "https://codeforces.com/problemset/problem/4/A")] | ||
problem_url: String, | ||
} | ||
|
||
#[utoipa::path( | ||
responses( | ||
(status = 200, description = "Share_id", body = EvaluateCodeResponse), | ||
(status = 400, description = "Invalid clex", body = String), | ||
(status = 500, description = "Internal server error", body = String), | ||
) | ||
)] | ||
#[post("/with_code_and_platform")] | ||
pub async fn post_with_code_and_platform( | ||
pool: web::Data<PgPool>, | ||
Check failure on line 39 in cpast_api/src/routes/api/v1/evaluate/with_code_and_platform.rs GitHub Actions / Clippy
Check failure on line 39 in cpast_api/src/routes/api/v1/evaluate/with_code_and_platform.rs GitHub Actions / Code coverage
|
||
code_request: Json<EvaluateCodeWithPlatformRequest>, | ||
Check failure on line 40 in cpast_api/src/routes/api/v1/evaluate/with_code_and_platform.rs GitHub Actions / Clippy
Check failure on line 40 in cpast_api/src/routes/api/v1/evaluate/with_code_and_platform.rs GitHub Actions / Code coverage
|
||
) -> Result<HttpResponse, EvaluateAPIError> { | ||
todo!("Implement post_with_code_and_platform"); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,37 @@ | ||
use actix_web::post; | ||
use actix_web::web::Json; | ||
use actix_web::{web, HttpResponse}; | ||
use ccode_runner::lang_runner::runner::LanguageName; | ||
use serde::{Deserialize, Serialize}; | ||
use sqlx::PgPool; | ||
use utoipa::ToSchema; | ||
|
||
use super::{EvaluateAPIError, EvaluateCodeResponse}; | ||
|
||
#[derive(Serialize, Deserialize, ToSchema, Clone, Debug)] | ||
struct EvaluateCodeWithOnlyPlatformRequest { | ||
#[schema(example = "print('Hello, worldd!')")] | ||
test_code: String, | ||
|
||
#[schema(example = "python")] | ||
test_code_language: LanguageName, | ||
|
||
// TODO: Use custom in house URL type instead of String | ||
#[schema(example = "https://codeforces.com/problemset/problem/4/A")] | ||
problem_url: String, | ||
} | ||
|
||
#[utoipa::path( | ||
responses( | ||
(status = 200, description = "Share_id", body = EvaluateCodeResponse), | ||
(status = 400, description = "Invalid clex", body = String), | ||
(status = 500, description = "Internal server error", body = String), | ||
) | ||
)] | ||
#[post("/with_platform")] | ||
pub async fn post_with_platform( | ||
pool: web::Data<PgPool>, | ||
Check failure on line 33 in cpast_api/src/routes/api/v1/evaluate/with_platform.rs GitHub Actions / Clippy
Check failure on line 33 in cpast_api/src/routes/api/v1/evaluate/with_platform.rs GitHub Actions / Code coverage
|
||
code_request: Json<EvaluateCodeWithOnlyPlatformRequest>, | ||
Check failure on line 34 in cpast_api/src/routes/api/v1/evaluate/with_platform.rs GitHub Actions / Clippy
Check failure on line 34 in cpast_api/src/routes/api/v1/evaluate/with_platform.rs GitHub Actions / Code coverage
|
||
) -> Result<HttpResponse, EvaluateAPIError> { | ||
todo!("Implement post_with_code_and_platform"); | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
use actix_web::post; | ||
use actix_web::web::Json; | ||
use actix_web::{web, HttpResponse}; | ||
use ccode_runner::lang_runner::runner::LanguageName; | ||
use serde::{Deserialize, Serialize}; | ||
use sqlx::PgPool; | ||
use utoipa::ToSchema; | ||
|
||
use super::{EvaluateAPIError, EvaluateCodeResponse}; | ||
|
||
#[derive(Serialize, Deserialize, ToSchema, Clone, Debug)] | ||
struct EvaluateCodeWithOnlySharedIDRequest { | ||
#[schema(example = "print('Hello, worldd!')")] | ||
test_code: String, | ||
|
||
#[schema(example = "python")] | ||
test_code_language: LanguageName, | ||
|
||
#[schema(example = "1e23fdh-sdf23-23sdf")] | ||
share_id: String, | ||
} | ||
|
||
#[utoipa::path( | ||
responses( | ||
(status = 200, description = "Share_id", body = EvaluateCodeResponse), | ||
(status = 400, description = "Invalid clex", body = String), | ||
(status = 500, description = "Internal server error", body = String), | ||
) | ||
)] | ||
#[post("/with_shared_id")] | ||
pub async fn post_with_shared_id( | ||
pool: web::Data<PgPool>, | ||
Check failure on line 32 in cpast_api/src/routes/api/v1/evaluate/with_shared_id.rs GitHub Actions / Clippy
Check failure on line 32 in cpast_api/src/routes/api/v1/evaluate/with_shared_id.rs GitHub Actions / Code coverage
|
||
code_request: Json<EvaluateCodeWithOnlySharedIDRequest>, | ||
Check failure on line 33 in cpast_api/src/routes/api/v1/evaluate/with_shared_id.rs GitHub Actions / Clippy
Check failure on line 33 in cpast_api/src/routes/api/v1/evaluate/with_shared_id.rs GitHub Actions / Code coverage
|
||
) -> Result<HttpResponse, EvaluateAPIError> { | ||
todo!("Implement post_with_code_and_platform"); | ||
} |