mirror of
https://github.com/lifegpc/pixiv_downloader.git
synced 2026-07-08 01:32:41 +08:00
Update
This commit is contained in:
14
src/server/context.rs
Normal file
14
src/server/context.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
use super::cors::CorsContext;
|
||||
use std::default::Default;
|
||||
|
||||
pub struct ServerContext {
|
||||
pub cors: CorsContext,
|
||||
}
|
||||
|
||||
impl Default for ServerContext {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
cors: CorsContext::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,13 @@
|
||||
use crate::gettext;
|
||||
use crate::opthelper::get_helper;
|
||||
use http::uri::InvalidUri;
|
||||
use http::uri::Scheme;
|
||||
use http::Uri;
|
||||
use json::JsonValue;
|
||||
use std::cmp::PartialEq;
|
||||
use std::convert::From;
|
||||
use std::convert::TryFrom;
|
||||
use std::default::Default;
|
||||
use std::fmt::Display;
|
||||
use std::net::SocketAddr;
|
||||
use std::str::FromStr;
|
||||
@@ -165,6 +168,28 @@ impl TryFrom<String> for CorsEntry {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&JsonValue> for CorsEntry {
|
||||
type Error = CorsError;
|
||||
fn try_from(value: &JsonValue) -> Result<Self, Self::Error> {
|
||||
match value.as_str() {
|
||||
Some(s) => Self::try_from(s),
|
||||
None => Err(CorsError::from(gettext("Object is not a string."))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_cors_entries(v: &JsonValue) -> Result<Vec<CorsEntry>, CorsError> {
|
||||
if v.is_array() {
|
||||
let mut list = Vec::new();
|
||||
for i in v.members() {
|
||||
list.push(CorsEntry::try_from(i)?);
|
||||
}
|
||||
Ok(list)
|
||||
} else {
|
||||
Err(CorsError::from(gettext("Object is not an array.")))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
/// Current host
|
||||
pub struct CorsHost {
|
||||
@@ -322,6 +347,75 @@ impl From<&str> for CorsError {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, derive_more::Display, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum CorsResult {
|
||||
Allowed,
|
||||
AllowedAll,
|
||||
NotAllowed,
|
||||
}
|
||||
|
||||
pub struct CorsContext {
|
||||
allow_all: bool,
|
||||
entries: Vec<CorsEntry>,
|
||||
hosts: Vec<CorsHost>,
|
||||
}
|
||||
|
||||
impl CorsContext {
|
||||
pub fn matches<T: Clone>(&self, host: T) -> CorsResult
|
||||
where
|
||||
CorsEntry: PartialEq<T>,
|
||||
CorsHost: PartialEq<T>,
|
||||
{
|
||||
if self.is_in_hosts(host.clone()) || self.is_in_entries(host.clone()) {
|
||||
CorsResult::Allowed
|
||||
} else if self.is_all_allowed() {
|
||||
CorsResult::AllowedAll
|
||||
} else {
|
||||
CorsResult::NotAllowed
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if every domain allowed
|
||||
pub fn is_all_allowed(&self) -> bool {
|
||||
self.allow_all
|
||||
}
|
||||
|
||||
pub fn is_in_entries<T>(&self, host: T) -> bool
|
||||
where
|
||||
CorsEntry: PartialEq<T>,
|
||||
{
|
||||
for ent in self.entries.iter() {
|
||||
if *ent == host {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn is_in_hosts<T>(&self, host: T) -> bool
|
||||
where
|
||||
CorsHost: PartialEq<T>,
|
||||
{
|
||||
for h in self.hosts.iter() {
|
||||
if *h == host {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CorsContext {
|
||||
fn default() -> Self {
|
||||
let helper = get_helper();
|
||||
Self {
|
||||
allow_all: false,
|
||||
entries: helper.cors_entries(),
|
||||
hosts: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cors_entry() {
|
||||
let ent = CorsEntry::try_from("https://.test.com").unwrap();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod context;
|
||||
/// CORS Handle
|
||||
pub mod cors;
|
||||
/// Routes
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use super::context::ServerContext;
|
||||
use super::traits::MatchRoute;
|
||||
use super::traits::ResponseFor;
|
||||
use super::version::VersionRoute;
|
||||
use hyper::Body;
|
||||
use hyper::Request;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub type RouteType = dyn MatchRoute<Body, Body> + Send + Sync;
|
||||
pub type ResponseForType = dyn ResponseFor<Body, Body> + Send + Sync;
|
||||
@@ -18,10 +20,14 @@ impl ServerRoutes {
|
||||
Self { routes }
|
||||
}
|
||||
|
||||
pub fn match_route(&self, req: &Request<Body>) -> Option<Box<ResponseForType>> {
|
||||
pub fn match_route(
|
||||
&self,
|
||||
req: &Request<Body>,
|
||||
ctx: &Arc<ServerContext>,
|
||||
) -> Option<Box<ResponseForType>> {
|
||||
for i in self.routes.iter() {
|
||||
if i.match_route(req) {
|
||||
return Some(i.get_route());
|
||||
return Some(i.get_route(Arc::clone(ctx)));
|
||||
}
|
||||
}
|
||||
None
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use super::context::ServerContext;
|
||||
use super::route::ServerRoutes;
|
||||
use hyper::server::conn::AddrIncoming;
|
||||
use hyper::server::Server;
|
||||
@@ -13,12 +14,13 @@ use std::task::Context;
|
||||
use std::task::Poll;
|
||||
|
||||
pub struct PixivDownloaderSvc {
|
||||
context: Arc<ServerContext>,
|
||||
routes: Arc<ServerRoutes>,
|
||||
}
|
||||
|
||||
impl PixivDownloaderSvc {
|
||||
pub fn new(routes: Arc<ServerRoutes>) -> Self {
|
||||
Self { routes }
|
||||
pub fn new(routes: Arc<ServerRoutes>, context: Arc<ServerContext>) -> Self {
|
||||
Self { routes, context }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +35,7 @@ impl Service<Request<Body>> for PixivDownloaderSvc {
|
||||
|
||||
fn call(&mut self, req: Request<Body>) -> Self::Future {
|
||||
println!("{} {}", req.method(), req.uri());
|
||||
match self.routes.match_route(&req) {
|
||||
match self.routes.match_route(&req, &self.context) {
|
||||
Some(route) => Box::pin(async move {
|
||||
match route.response(req).await {
|
||||
Ok(data) => Ok(data),
|
||||
@@ -54,12 +56,14 @@ impl Service<Request<Body>> for PixivDownloaderSvc {
|
||||
}
|
||||
|
||||
pub struct PixivDownloaderMakeSvc {
|
||||
context: Arc<ServerContext>,
|
||||
routes: Arc<ServerRoutes>,
|
||||
}
|
||||
|
||||
impl PixivDownloaderMakeSvc {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
context: Arc::new(ServerContext::default()),
|
||||
routes: Arc::new(ServerRoutes::new()),
|
||||
}
|
||||
}
|
||||
@@ -76,7 +80,8 @@ impl<T> Service<T> for PixivDownloaderMakeSvc {
|
||||
|
||||
fn call(&mut self, _: T) -> Self::Future {
|
||||
let routes = Arc::clone(&self.routes);
|
||||
let fut = async move { Ok(PixivDownloaderSvc::new(routes)) };
|
||||
let context = Arc::clone(&self.context);
|
||||
let fut = async move { Ok(PixivDownloaderSvc::new(routes, context)) };
|
||||
Box::pin(fut)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
use super::context::ServerContext;
|
||||
use crate::error::PixivDownloaderError;
|
||||
use hyper::Body;
|
||||
use hyper::Request;
|
||||
use hyper::Response;
|
||||
use json::JsonValue;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait MatchRoute<T, R> {
|
||||
fn get_route(&self) -> Box<dyn ResponseFor<T, R> + Send + Sync>;
|
||||
fn get_route(&self, ctx: Arc<ServerContext>) -> Box<dyn ResponseFor<T, R> + Send + Sync>;
|
||||
fn match_route(&self, req: &Request<T>) -> bool;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use super::context::ServerContext;
|
||||
use super::route::ResponseForType;
|
||||
use super::traits::MatchRoute;
|
||||
use super::traits::ResponseJsonFor;
|
||||
@@ -8,14 +9,15 @@ use hyper::Response;
|
||||
use json::JsonValue;
|
||||
use proc_macros::filter_http_methods;
|
||||
use regex::Regex;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct VersionContext {
|
||||
_unused: [u8; 0],
|
||||
ctx: Arc<ServerContext>,
|
||||
}
|
||||
|
||||
impl VersionContext {
|
||||
pub fn new() -> Self {
|
||||
Self { _unused: [] }
|
||||
pub fn new(ctx: Arc<ServerContext>) -> Self {
|
||||
Self { ctx }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +27,10 @@ impl ResponseJsonFor<Body> for VersionContext {
|
||||
&self,
|
||||
req: Request<Body>,
|
||||
) -> Result<Response<JsonValue>, PixivDownloaderError> {
|
||||
filter_http_methods!(req, json::object! {}, true, GET, OPTIONS, POST);
|
||||
Ok(Response::new(json::object! {"version": [0, 0, 1, 0]}))
|
||||
filter_http_methods!(req, json::object! {}, true, self.ctx, GET, OPTIONS, POST);
|
||||
Ok(builder
|
||||
.body(json::object! {"version": [0, 0, 1, 0]})
|
||||
.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,8 +47,8 @@ impl VersionRoute {
|
||||
}
|
||||
|
||||
impl MatchRoute<Body, Body> for VersionRoute {
|
||||
fn get_route(&self) -> Box<ResponseForType> {
|
||||
Box::new(VersionContext::new())
|
||||
fn get_route(&self, ctx: Arc<ServerContext>) -> Box<ResponseForType> {
|
||||
Box::new(VersionContext::new(ctx))
|
||||
}
|
||||
|
||||
fn match_route(&self, req: &http::Request<Body>) -> bool {
|
||||
|
||||
Reference in New Issue
Block a user