Skip to content
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

fix(errors): Downgrade AI/Playground erors to 400 #304

Merged
merged 3 commits into from
Jul 27, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/ai/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use actix_http::StatusCode;
use actix_web::{HttpResponse, ResponseError};
use async_openai::error::OpenAIError;
use thiserror::Error;

use crate::error::ErrorResponse;

#[derive(Error, Debug)]
pub enum AIError {
#[error("OpenAI error: {0}")]
Expand All @@ -16,3 +20,26 @@ pub enum AIError {
#[error("Tiktoken Error: {0}")]
TiktokenError(#[from] anyhow::Error),
}

impl ResponseError for AIError {
fn status_code(&self) -> StatusCode {
match &self {
AIError::OpenAIError(_) | AIError::SqlXError(_) | AIError::TiktokenError(_) => {
StatusCode::INTERNAL_SERVER_ERROR
}
AIError::FlaggedError | AIError::NoUserPrompt | AIError::TokenLimit => {
StatusCode::BAD_REQUEST
}
}
}

fn error_response(&self) -> HttpResponse<actix_http::body::BoxBody> {
let status_code = self.status_code();
let mut builder = HttpResponse::build(status_code);
builder.json(ErrorResponse {
code: status_code.as_u16(),
message: status_code.canonical_reason().unwrap_or("Unknown"),
error: "AI Error",
})
}
}
34 changes: 26 additions & 8 deletions src/api/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::string::FromUtf8Error;

use crate::ai::error::AIError;
use crate::db::error::DbError;
use crate::error::ErrorResponse;

use actix_http::header::HeaderValue;
use actix_web::http::header::HeaderName;
Expand All @@ -10,7 +11,6 @@ use actix_web::middleware::{ErrorHandlerResponse, ErrorHandlers};
use actix_web::{HttpResponse, ResponseError};
use async_openai::error::OpenAIError;
use basket::BasketError;
use serde::Serialize;
use serde_json::json;
use thiserror::Error;
use uuid::Uuid;
Expand Down Expand Up @@ -63,6 +63,28 @@ pub enum PlaygroundError {
SettingsError,
}

impl ResponseError for PlaygroundError {
fn status_code(&self) -> StatusCode {
match &self {
PlaygroundError::CryptError(_)
| PlaygroundError::DecodeError(_)
| PlaygroundError::NoNonceError
| PlaygroundError::UtfDecodeError(_) => StatusCode::BAD_REQUEST,
_ => StatusCode::INTERNAL_SERVER_ERROR,
fiji-flo marked this conversation as resolved.
Show resolved Hide resolved
}
}

fn error_response(&self) -> HttpResponse<actix_http::body::BoxBody> {
let status_code = self.status_code();
let mut builder = HttpResponse::build(status_code);
builder.json(ErrorResponse {
code: status_code.as_u16(),
message: status_code.canonical_reason().unwrap_or("Unknown"),
error: "Playground Error",
})
}
}

#[derive(Error, Debug)]
pub enum ApiError {
#[error("Artificial error")]
Expand Down Expand Up @@ -149,13 +171,6 @@ impl ApiError {
}
}

#[derive(Serialize)]
struct ErrorResponse<'a> {
code: u16,
error: &'a str,
message: &'a str,
}

impl ResponseError for ApiError {
fn status_code(&self) -> StatusCode {
match *self {
Expand All @@ -172,6 +187,8 @@ impl ResponseError for ApiError {
Self::LoginRequiredForFeature(_) => StatusCode::UNAUTHORIZED,
Self::PaymentRequired => StatusCode::PAYMENT_REQUIRED,
Self::NotImplemented => StatusCode::NOT_IMPLEMENTED,
Self::PlaygroundError(ref e) => e.status_code(),
Self::AIError(_) => StatusCode::BAD_REQUEST,
fiji-flo marked this conversation as resolved.
Show resolved Hide resolved
_ => StatusCode::INTERNAL_SERVER_ERROR,
}
}
Expand Down Expand Up @@ -210,6 +227,7 @@ impl ResponseError for ApiError {
message: format!("Please login to use feature: {0}", feature).as_str(),
error: self.name(),
}),
ApiError::PlaygroundError(error) => error.error_response(),
fiji-flo marked this conversation as resolved.
Show resolved Hide resolved
_ if status_code == StatusCode::INTERNAL_SERVER_ERROR => builder.json(ErrorResponse {
code: status_code.as_u16(),
message: "internal server error",
Expand Down
8 changes: 8 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use serde::Serialize;

#[derive(Serialize)]
pub struct ErrorResponse<'a> {
pub code: u16,
pub error: &'a str,
pub message: &'a str,
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use actix_web::{
pub mod ai;
pub mod api;
pub mod db;
pub mod error;
pub mod fxa;
mod helpers;
pub mod ids;
Expand Down
4 changes: 2 additions & 2 deletions tests/api/play.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ async fn test_invalid_id() -> Result<(), Error> {
let service = test::init_service(app).await;
let mut client = TestHttpClient::new(service).await;
let res = client.get("/api/v1/play/sssieddidxsx", None).await;
// This used to panic, now it should just 500
assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);
// This used to panic, now it should just 400
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
Ok(())
}