@@ -27,11 +27,12 @@ use std::env;
2727
2828use crate :: app_config:: AppConfig ;
2929use actix_multipart:: form:: { tempfile:: TempFile , MultipartForm } ;
30- use actix_web:: { guard, web} ;
30+ use actix_web:: { guard, web, HttpResponse } ;
3131use serde:: { Deserialize , Serialize } ;
3232use sqlx:: PgPool ;
3333use std:: sync:: Arc ;
3434use strum:: { Display , EnumString } ;
35+ use url:: Url ;
3536use utoipa:: {
3637 openapi:: security:: { ApiKey , ApiKeyValue , SecurityScheme } ,
3738 IntoParams , Modify , OpenApi , ToSchema ,
@@ -41,6 +42,18 @@ use crate::{Difficulty, GachaType, GiGachaType, Language, ZzzGachaType};
4142
4243type ApiResult < T > = Result < T , Box < dyn std:: error:: Error > > ;
4344
45+ pub ( crate ) fn validate_import_url ( raw_url : & str ) -> Result < Url , HttpResponse > {
46+ let Ok ( url) = Url :: parse ( raw_url) else {
47+ return Err ( HttpResponse :: BadRequest ( ) . body ( "Invalid URL" ) ) ;
48+ } ;
49+
50+ if !matches ! ( url. scheme( ) , "http" | "https" ) || url. host_str ( ) . is_none ( ) {
51+ return Err ( HttpResponse :: BadRequest ( ) . body ( "Invalid URL" ) ) ;
52+ }
53+
54+ Ok ( url)
55+ }
56+
4457#[ derive( OpenApi ) ]
4558#[ openapi( tags( ( name = "pinned" ) ) , components( schemas( Language , GachaType , ZzzGachaType , GiGachaType , File , Difficulty ) ) , modifiers( & PrivateAddon ) ) ]
4659struct ApiDoc ;
0 commit comments