mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-11-16 09:24:00 +00:00
Remove boilerplate code
This commit is contained in:
parent
8ebcc7ac02
commit
05735b31c0
6 changed files with 120 additions and 225 deletions
6
server/Cargo.lock
generated
vendored
6
server/Cargo.lock
generated
vendored
|
@ -2,7 +2,7 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "activitystreams"
|
name = "activitystreams"
|
||||||
version = "0.5.0-alpha.4"
|
version = "0.5.0-alpha.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"activitystreams-derive 0.5.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"activitystreams-derive 0.5.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1562,7 +1562,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
name = "lemmy_server"
|
name = "lemmy_server"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"activitystreams 0.5.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"activitystreams 0.5.0-alpha.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"actix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"actix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"actix-files 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"actix-files 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -3282,7 +3282,7 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
"checksum activitystreams 0.5.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1f5d1db7f182bc74c9a6d2002cb7a5eb99b001ef41ddc8df1c21750ccc3638fa"
|
"checksum activitystreams 0.5.0-alpha.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a9e82b6649331396e8bd17547a3b775ba7f530a30d574d43cf1d373899dafd94"
|
||||||
"checksum activitystreams-derive 0.5.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f95c948a832a0b7b230b28369bafe79477bb8ebe7306dc97bcaff43832d3cc4d"
|
"checksum activitystreams-derive 0.5.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f95c948a832a0b7b230b28369bafe79477bb8ebe7306dc97bcaff43832d3cc4d"
|
||||||
"checksum actix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4af87564ff659dee8f9981540cac9418c45e910c8072fdedd643a262a38fcaf"
|
"checksum actix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4af87564ff659dee8f9981540cac9418c45e910c8072fdedd643a262a38fcaf"
|
||||||
"checksum actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09e55f0a5c2ca15795035d90c46bd0e73a5123b72f68f12596d6ba5282051380"
|
"checksum actix-codec 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09e55f0a5c2ca15795035d90c46bd0e73a5123b72f68f12596d6ba5282051380"
|
||||||
|
|
2
server/Cargo.toml
vendored
2
server/Cargo.toml
vendored
|
@ -9,7 +9,7 @@ diesel = { version = "1.4.2", features = ["postgres","chrono", "r2d2", "64-colum
|
||||||
diesel_migrations = "1.4.0"
|
diesel_migrations = "1.4.0"
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
bcrypt = "0.6.1"
|
bcrypt = "0.6.1"
|
||||||
activitystreams = "0.5.0-alpha.4"
|
activitystreams = "0.5.0-alpha.7"
|
||||||
chrono = { version = "0.4.7", features = ["serde"] }
|
chrono = { version = "0.4.7", features = ["serde"] }
|
||||||
failure = "0.1.5"
|
failure = "0.1.5"
|
||||||
serde_json = { version = "1.0.45", features = ["preserve_order"]}
|
serde_json = { version = "1.0.45", features = ["preserve_order"]}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::apub::make_apub_endpoint;
|
use crate::apub::{create_apub_response, make_apub_endpoint};
|
||||||
use crate::convert_datetime;
|
use crate::convert_datetime;
|
||||||
use crate::db::community::Community;
|
use crate::db::community::Community;
|
||||||
use crate::db::community_view::CommunityFollowerView;
|
use crate::db::community_view::CommunityFollowerView;
|
||||||
|
@ -12,12 +12,23 @@ use activitystreams::{
|
||||||
use actix_web::body::Body;
|
use actix_web::body::Body;
|
||||||
use actix_web::web::Path;
|
use actix_web::web::Path;
|
||||||
use actix_web::HttpResponse;
|
use actix_web::HttpResponse;
|
||||||
|
use actix_web::{web, Result};
|
||||||
|
use diesel::r2d2::{ConnectionManager, Pool};
|
||||||
|
use diesel::PgConnection;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
impl Community {
|
#[derive(Deserialize)]
|
||||||
pub fn as_group(&self) -> Result<Group, Error> {
|
pub struct CommunityQuery {
|
||||||
let base_url = make_apub_endpoint("c", &self.name);
|
community_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_apub_community(
|
||||||
|
info: Path<CommunityQuery>,
|
||||||
|
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
||||||
|
) -> Result<HttpResponse<Body>, Error> {
|
||||||
|
let community = Community::read_from_name(&&db.get()?, info.community_name.to_owned())?;
|
||||||
|
let base_url = make_apub_endpoint("c", &community.name);
|
||||||
|
|
||||||
let mut group = Group::default();
|
let mut group = Group::default();
|
||||||
let oprops: &mut ObjectProperties = group.as_mut();
|
let oprops: &mut ObjectProperties = group.as_mut();
|
||||||
|
@ -25,14 +36,14 @@ impl Community {
|
||||||
oprops
|
oprops
|
||||||
.set_context_xsd_any_uri(context())?
|
.set_context_xsd_any_uri(context())?
|
||||||
.set_id(base_url.to_owned())?
|
.set_id(base_url.to_owned())?
|
||||||
.set_name_xsd_string(self.title.to_owned())?
|
.set_name_xsd_string(community.title.to_owned())?
|
||||||
.set_published(convert_datetime(self.published))?
|
.set_published(convert_datetime(community.published))?
|
||||||
.set_attributed_to_xsd_any_uri(make_apub_endpoint("u", &self.creator_id))?;
|
.set_attributed_to_xsd_any_uri(make_apub_endpoint("u", &community.creator_id))?;
|
||||||
|
|
||||||
if let Some(u) = self.updated.to_owned() {
|
if let Some(u) = community.updated.to_owned() {
|
||||||
oprops.set_updated(convert_datetime(u))?;
|
oprops.set_updated(convert_datetime(u))?;
|
||||||
}
|
}
|
||||||
if let Some(d) = self.description.to_owned() {
|
if let Some(d) = community.description {
|
||||||
oprops.set_summary_xsd_string(d)?;
|
oprops.set_summary_xsd_string(d)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,15 +53,20 @@ impl Community {
|
||||||
.set_outbox(format!("{}/outbox", &base_url))?
|
.set_outbox(format!("{}/outbox", &base_url))?
|
||||||
.set_followers(format!("{}/followers", &base_url))?;
|
.set_followers(format!("{}/followers", &base_url))?;
|
||||||
|
|
||||||
Ok(group)
|
Ok(create_apub_response(serde_json::to_string(&group)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_followers(&self) -> Result<UnorderedCollection, Error> {
|
pub async fn get_apub_community_followers(
|
||||||
let base_url = make_apub_endpoint("c", &self.name);
|
info: Path<CommunityQuery>,
|
||||||
|
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
||||||
|
) -> Result<HttpResponse<Body>, Error> {
|
||||||
|
let community = Community::read_from_name(&&db.get()?, info.community_name.to_owned())?;
|
||||||
|
let base_url = make_apub_endpoint("c", &community.name);
|
||||||
|
|
||||||
let connection = establish_unpooled_connection();
|
let connection = establish_unpooled_connection();
|
||||||
//As we are an object, we validated that the community id was valid
|
//As we are an object, we validated that the community id was valid
|
||||||
let community_followers = CommunityFollowerView::for_community(&connection, self.id).unwrap();
|
let community_followers =
|
||||||
|
CommunityFollowerView::for_community(&connection, community.id).unwrap();
|
||||||
|
|
||||||
let mut collection = UnorderedCollection::default();
|
let mut collection = UnorderedCollection::default();
|
||||||
let oprops: &mut ObjectProperties = collection.as_mut();
|
let oprops: &mut ObjectProperties = collection.as_mut();
|
||||||
|
@ -60,16 +76,20 @@ impl Community {
|
||||||
collection
|
collection
|
||||||
.collection_props
|
.collection_props
|
||||||
.set_total_items(community_followers.len() as u64)?;
|
.set_total_items(community_followers.len() as u64)?;
|
||||||
Ok(collection)
|
Ok(create_apub_response(serde_json::to_string(&collection)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_outbox(&self) -> Result<OrderedCollection, Error> {
|
pub async fn get_apub_community_outbox(
|
||||||
let base_url = make_apub_endpoint("c", &self.name);
|
info: Path<CommunityQuery>,
|
||||||
|
db: web::Data<Pool<ConnectionManager<PgConnection>>>,
|
||||||
|
) -> Result<HttpResponse<Body>, Error> {
|
||||||
|
let community = Community::read_from_name(&&db.get()?, info.community_name.to_owned())?;
|
||||||
|
let base_url = make_apub_endpoint("c", &community.name);
|
||||||
|
|
||||||
let connection = establish_unpooled_connection();
|
let connection = establish_unpooled_connection();
|
||||||
//As we are an object, we validated that the community id was valid
|
//As we are an object, we validated that the community id was valid
|
||||||
let community_posts: Vec<PostView> = PostQueryBuilder::create(&connection)
|
let community_posts: Vec<PostView> = PostQueryBuilder::create(&connection)
|
||||||
.for_community_id(self.id)
|
.for_community_id(community.id)
|
||||||
.list()
|
.list()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -88,58 +108,5 @@ impl Community {
|
||||||
)?
|
)?
|
||||||
.set_total_items(community_posts.len() as u64)?;
|
.set_total_items(community_posts.len() as u64)?;
|
||||||
|
|
||||||
Ok(collection)
|
Ok(create_apub_response(serde_json::to_string(&collection)?))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct CommunityQuery {
|
|
||||||
community_name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: move all this boilerplate code to routes::federation or such
|
|
||||||
pub async fn get_apub_community(info: Path<CommunityQuery>) -> Result<HttpResponse<Body>, Error> {
|
|
||||||
let connection = establish_unpooled_connection();
|
|
||||||
|
|
||||||
if let Ok(community) = Community::read_from_name(&connection, info.community_name.to_owned()) {
|
|
||||||
Ok(
|
|
||||||
HttpResponse::Ok()
|
|
||||||
.content_type("application/activity+json")
|
|
||||||
.body(serde_json::to_string(&community.as_group()?).unwrap()),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Ok(HttpResponse::NotFound().finish())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_apub_community_followers(
|
|
||||||
info: Path<CommunityQuery>,
|
|
||||||
) -> Result<HttpResponse<Body>, Error> {
|
|
||||||
let connection = establish_unpooled_connection();
|
|
||||||
|
|
||||||
if let Ok(community) = Community::read_from_name(&connection, info.community_name.to_owned()) {
|
|
||||||
Ok(
|
|
||||||
HttpResponse::Ok()
|
|
||||||
.content_type("application/activity+json")
|
|
||||||
.body(serde_json::to_string(&community.get_followers()?).unwrap()),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Ok(HttpResponse::NotFound().finish())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_apub_community_outbox(
|
|
||||||
info: Path<CommunityQuery>,
|
|
||||||
) -> Result<HttpResponse<Body>, Error> {
|
|
||||||
let connection = establish_unpooled_connection();
|
|
||||||
|
|
||||||
if let Ok(community) = Community::read_from_name(&connection, info.community_name.to_owned()) {
|
|
||||||
Ok(
|
|
||||||
HttpResponse::Ok()
|
|
||||||
.content_type("application/activity+json")
|
|
||||||
.body(serde_json::to_string(&community.get_outbox()?).unwrap()),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Ok(HttpResponse::NotFound().finish())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,76 +3,21 @@ pub mod post;
|
||||||
pub mod puller;
|
pub mod puller;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
use crate::Settings;
|
use crate::Settings;
|
||||||
use failure::Error;
|
|
||||||
|
|
||||||
|
use actix_web::body::Body;
|
||||||
|
use actix_web::HttpResponse;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[cfg(test)]
|
fn create_apub_response(json_data: String) -> HttpResponse<Body> {
|
||||||
mod tests {
|
HttpResponse::Ok()
|
||||||
use crate::db::community::Community;
|
.content_type("application/activity+json")
|
||||||
use crate::db::user::User_;
|
.body(json_data)
|
||||||
use crate::db::{ListingType, SortType};
|
|
||||||
use crate::{naive_now, Settings};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_person() {
|
|
||||||
let user = User_ {
|
|
||||||
id: 52,
|
|
||||||
name: "thom".into(),
|
|
||||||
fedi_name: "rrf".into(),
|
|
||||||
preferred_username: None,
|
|
||||||
password_encrypted: "here".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
|
||||||
published: naive_now(),
|
|
||||||
admin: false,
|
|
||||||
banned: false,
|
|
||||||
updated: None,
|
|
||||||
show_nsfw: false,
|
|
||||||
theme: "darkly".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let person = user.as_person();
|
|
||||||
assert_eq!(
|
|
||||||
format!("https://{}/federation/u/thom", Settings::get().hostname),
|
|
||||||
person.unwrap().object_props.get_id().unwrap().to_string()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_community() {
|
|
||||||
let community = Community {
|
|
||||||
id: 42,
|
|
||||||
name: "Test".into(),
|
|
||||||
title: "Test Title".into(),
|
|
||||||
description: Some("Test community".into()),
|
|
||||||
category_id: 32,
|
|
||||||
creator_id: 52,
|
|
||||||
removed: false,
|
|
||||||
published: naive_now(),
|
|
||||||
updated: Some(naive_now()),
|
|
||||||
deleted: false,
|
|
||||||
nsfw: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let group = community.as_group();
|
|
||||||
assert_eq!(
|
|
||||||
format!("https://{}/federation/c/Test", Settings::get().hostname),
|
|
||||||
group.unwrap().object_props.get_id().unwrap().to_string()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this should take an enum community/user/post for `point`
|
// TODO: this should take an enum community/user/post for `point`
|
||||||
// TODO: also not sure what exactly `value` should be (numeric id, name string, ...)
|
// TODO: also not sure what exactly `value` should be (numeric id, name string, ...)
|
||||||
pub fn make_apub_endpoint<S: Display, T: Display>(point: S, value: T) -> Url {
|
fn make_apub_endpoint<S: Display, T: Display>(point: S, value: T) -> Url {
|
||||||
Url::parse(&format!(
|
Url::parse(&format!(
|
||||||
"{}://{}/federation/{}/{}",
|
"{}://{}/federation/{}/{}",
|
||||||
get_apub_protocol_string(),
|
get_apub_protocol_string(),
|
||||||
|
@ -83,13 +28,6 @@ pub fn make_apub_endpoint<S: Display, T: Display>(point: S, value: T) -> Url {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses an ID generated by `make_apub_endpoint()`. Will break when federating with anything
|
fn get_apub_protocol_string() -> &'static str {
|
||||||
/// that is not Lemmy. This is just a crutch until we change the database to store URLs as ID.
|
|
||||||
pub fn parse_apub_endpoint(id: &str) -> Result<(&str, &str), Error> {
|
|
||||||
let split = id.split('/').collect::<Vec<&str>>();
|
|
||||||
Ok((split[4], split[5]))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_apub_protocol_string() -> &'static str {
|
|
||||||
"http"
|
"http"
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ where
|
||||||
{
|
{
|
||||||
// TODO: should cache responses here when we are in production
|
// TODO: should cache responses here when we are in production
|
||||||
// TODO: this function should return a future
|
// TODO: this function should return a future
|
||||||
|
// TODO: in production mode, fail if protocol is not https
|
||||||
let x: Response = reqwest::get(uri)?.json()?;
|
let x: Response = reqwest::get(uri)?.json()?;
|
||||||
Ok(x)
|
Ok(x)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::apub::make_apub_endpoint;
|
use crate::apub::{make_apub_endpoint, create_apub_response};
|
||||||
use crate::convert_datetime;
|
use crate::convert_datetime;
|
||||||
use crate::db::establish_unpooled_connection;
|
|
||||||
use crate::db::user::User_;
|
use crate::db::user::User_;
|
||||||
use activitystreams::{actor::apub::Person, context, object::properties::ObjectProperties};
|
use activitystreams::{actor::apub::Person, context, object::properties::ObjectProperties};
|
||||||
use actix_web::body::Body;
|
use actix_web::body::Body;
|
||||||
|
@ -8,23 +7,33 @@ use actix_web::web::Path;
|
||||||
use actix_web::HttpResponse;
|
use actix_web::HttpResponse;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
use diesel::r2d2::{ConnectionManager, Pool};
|
||||||
|
use diesel::PgConnection;
|
||||||
|
use actix_web::{web, Result};
|
||||||
|
|
||||||
impl User_ {
|
#[derive(Deserialize)]
|
||||||
pub fn as_person(&self) -> Result<Person, Error> {
|
pub struct UserQuery {
|
||||||
let base_url = make_apub_endpoint("u", &self.name);
|
user_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_apub_user(
|
||||||
|
info: Path<UserQuery>,
|
||||||
|
db: web::Data<Pool<ConnectionManager<PgConnection>>>,) -> Result<HttpResponse<Body>, Error> {
|
||||||
|
let user = User_::find_by_email_or_username(&&db.get()?, &info.user_name)?;
|
||||||
|
let base_url = make_apub_endpoint("u", &user.name);
|
||||||
|
|
||||||
let mut person = Person::default();
|
let mut person = Person::default();
|
||||||
let oprops: &mut ObjectProperties = person.as_mut();
|
let oprops: &mut ObjectProperties = person.as_mut();
|
||||||
oprops
|
oprops
|
||||||
.set_context_xsd_any_uri(context())?
|
.set_context_xsd_any_uri(context())?
|
||||||
.set_id(base_url.to_string())?
|
.set_id(base_url.to_string())?
|
||||||
.set_published(convert_datetime(self.published))?;
|
.set_published(convert_datetime(user.published))?;
|
||||||
|
|
||||||
if let Some(u) = self.updated {
|
if let Some(u) = user.updated {
|
||||||
oprops.set_updated(convert_datetime(u))?;
|
oprops.set_updated(convert_datetime(u))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(i) = &self.preferred_username {
|
if let Some(i) = &user.preferred_username {
|
||||||
oprops.set_name_xsd_string(i.to_owned())?;
|
oprops.set_name_xsd_string(i.to_owned())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,25 +44,5 @@ impl User_ {
|
||||||
.set_following(format!("{}/following", &base_url))?
|
.set_following(format!("{}/following", &base_url))?
|
||||||
.set_liked(format!("{}/liked", &base_url))?;
|
.set_liked(format!("{}/liked", &base_url))?;
|
||||||
|
|
||||||
Ok(person)
|
Ok(create_apub_response(serde_json::to_string(&person)?))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct UserQuery {
|
|
||||||
user_name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_apub_user(info: Path<UserQuery>) -> Result<HttpResponse<Body>, Error> {
|
|
||||||
let connection = establish_unpooled_connection();
|
|
||||||
|
|
||||||
if let Ok(user) = User_::find_by_email_or_username(&connection, &info.user_name) {
|
|
||||||
Ok(
|
|
||||||
HttpResponse::Ok()
|
|
||||||
.content_type("application/activity+json")
|
|
||||||
.body(serde_json::to_string(&user.as_person()?).unwrap()),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Ok(HttpResponse::NotFound().finish())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue