mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-12-31 15:21:31 +00:00
Move into subfolders
This commit is contained in:
parent
56ab67f804
commit
05843fb7b5
5 changed files with 78 additions and 69 deletions
|
@ -2,7 +2,6 @@ use actix_web::{
|
|||
body::{BodyStream, BoxBody},
|
||||
http::{
|
||||
header::{HeaderName, ACCEPT_ENCODING, HOST},
|
||||
Method,
|
||||
StatusCode,
|
||||
},
|
||||
web::*,
|
||||
|
@ -10,8 +9,6 @@ use actix_web::{
|
|||
HttpResponse,
|
||||
Responder,
|
||||
};
|
||||
use futures::stream::{Stream, StreamExt};
|
||||
use http::HeaderValue;
|
||||
use lemmy_api_common::{context::LemmyContext, request::PictrsResponse};
|
||||
use lemmy_db_schema::source::{
|
||||
images::{LocalImage, LocalImageForm, RemoteImage},
|
||||
|
@ -24,6 +21,9 @@ use reqwest_middleware::RequestBuilder;
|
|||
use serde::Deserialize;
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
use utils::{convert_header, convert_method, convert_status, make_send};
|
||||
|
||||
mod utils;
|
||||
|
||||
trait ProcessUrl {
|
||||
/// If thumbnail or format is given, this uses the pictrs process endpoint.
|
||||
|
@ -223,7 +223,10 @@ pub async fn delete_image(
|
|||
Ok(HttpResponse::build(convert_status(res.status())).body(BodyStream::new(res.bytes_stream())))
|
||||
}
|
||||
|
||||
pub async fn pictrs_healthz(req: HttpRequest, context: Data<LemmyContext>) -> LemmyResult<HttpResponse> {
|
||||
pub async fn pictrs_healthz(
|
||||
req: HttpRequest,
|
||||
context: Data<LemmyContext>,
|
||||
) -> LemmyResult<HttpResponse> {
|
||||
let pictrs_config = context.settings().pictrs_config()?;
|
||||
let url = format!("{}healthz", pictrs_config.url);
|
||||
|
||||
|
@ -264,60 +267,3 @@ pub async fn image_proxy(
|
|||
Ok(Either::Right(image(processed_url, req, &context).await?))
|
||||
}
|
||||
}
|
||||
|
||||
fn make_send<S>(mut stream: S) -> impl Stream<Item = S::Item> + Send + Unpin + 'static
|
||||
where
|
||||
S: Stream + Unpin + 'static,
|
||||
S::Item: Send,
|
||||
{
|
||||
// NOTE: the 8 here is arbitrary
|
||||
let (tx, rx) = tokio::sync::mpsc::channel(8);
|
||||
|
||||
// NOTE: spawning stream into a new task can potentially hit this bug:
|
||||
// - https://github.com/actix/actix-web/issues/1679
|
||||
//
|
||||
// Since 4.0.0-beta.2 this issue is incredibly less frequent. I have not personally reproduced it.
|
||||
// That said, it is still technically possible to encounter.
|
||||
actix_web::rt::spawn(async move {
|
||||
while let Some(res) = stream.next().await {
|
||||
if tx.send(res).await.is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
SendStream { rx }
|
||||
}
|
||||
|
||||
struct SendStream<T> {
|
||||
rx: tokio::sync::mpsc::Receiver<T>,
|
||||
}
|
||||
|
||||
impl<T> Stream for SendStream<T>
|
||||
where
|
||||
T: Send,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
fn poll_next(
|
||||
mut self: std::pin::Pin<&mut Self>,
|
||||
cx: &mut std::task::Context<'_>,
|
||||
) -> std::task::Poll<Option<Self::Item>> {
|
||||
std::pin::Pin::new(&mut self.rx).poll_recv(cx)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove these conversions after actix-web upgrades to http 1.0
|
||||
#[allow(clippy::expect_used)]
|
||||
fn convert_status(status: http::StatusCode) -> StatusCode {
|
||||
StatusCode::from_u16(status.as_u16()).expect("status can be converted")
|
||||
}
|
||||
|
||||
#[allow(clippy::expect_used)]
|
||||
fn convert_method(method: &Method) -> http::Method {
|
||||
http::Method::from_bytes(method.as_str().as_bytes()).expect("method can be converted")
|
||||
}
|
||||
|
||||
fn convert_header<'a>(name: &'a http::HeaderName, value: &'a HeaderValue) -> (&'a str, &'a [u8]) {
|
||||
(name.as_str(), value.as_bytes())
|
||||
}
|
63
crates/routes/src/images/utils.rs
Normal file
63
crates/routes/src/images/utils.rs
Normal file
|
@ -0,0 +1,63 @@
|
|||
use actix_web::http::{Method, StatusCode};
|
||||
use futures::stream::{Stream, StreamExt};
|
||||
use http::HeaderValue;
|
||||
|
||||
pub(super) fn make_send<S>(mut stream: S) -> impl Stream<Item = S::Item> + Send + Unpin + 'static
|
||||
where
|
||||
S: Stream + Unpin + 'static,
|
||||
S::Item: Send,
|
||||
{
|
||||
// NOTE: the 8 here is arbitrary
|
||||
let (tx, rx) = tokio::sync::mpsc::channel(8);
|
||||
|
||||
// NOTE: spawning stream into a new task can potentially hit this bug:
|
||||
// - https://github.com/actix/actix-web/issues/1679
|
||||
//
|
||||
// Since 4.0.0-beta.2 this issue is incredibly less frequent. I have not personally reproduced it.
|
||||
// That said, it is still technically possible to encounter.
|
||||
actix_web::rt::spawn(async move {
|
||||
while let Some(res) = stream.next().await {
|
||||
if tx.send(res).await.is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
SendStream { rx }
|
||||
}
|
||||
|
||||
pub(super) struct SendStream<T> {
|
||||
rx: tokio::sync::mpsc::Receiver<T>,
|
||||
}
|
||||
|
||||
impl<T> Stream for SendStream<T>
|
||||
where
|
||||
T: Send,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
fn poll_next(
|
||||
mut self: std::pin::Pin<&mut Self>,
|
||||
cx: &mut std::task::Context<'_>,
|
||||
) -> std::task::Poll<Option<Self::Item>> {
|
||||
std::pin::Pin::new(&mut self.rx).poll_recv(cx)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove these conversions after actix-web upgrades to http 1.0
|
||||
#[allow(clippy::expect_used)]
|
||||
pub(super) fn convert_status(status: http::StatusCode) -> StatusCode {
|
||||
StatusCode::from_u16(status.as_u16()).expect("status can be converted")
|
||||
}
|
||||
|
||||
#[allow(clippy::expect_used)]
|
||||
pub(super) fn convert_method(method: &Method) -> http::Method {
|
||||
http::Method::from_bytes(method.as_str().as_bytes()).expect("method can be converted")
|
||||
}
|
||||
|
||||
pub(super) fn convert_header<'a>(
|
||||
name: &'a http::HeaderName,
|
||||
value: &'a HeaderValue,
|
||||
) -> (&'a str, &'a [u8]) {
|
||||
(name.as_str(), value.as_bytes())
|
||||
}
|
|
@ -18,7 +18,7 @@ pub fn markdown_rewrite_image_links(mut src: String) -> (String, Vec<Url>) {
|
|||
// If link points to remote domain, replace with proxied link
|
||||
if parsed.domain() != Some(&SETTINGS.hostname) {
|
||||
let mut proxied = format!(
|
||||
"{}/api/v4/image_proxy?url={}",
|
||||
"{}/api/v4/image/proxy?url={}",
|
||||
SETTINGS.get_protocol_and_hostname(),
|
||||
encode(url),
|
||||
);
|
||||
|
@ -115,7 +115,7 @@ mod tests {
|
|||
(
|
||||
"remote image proxied",
|
||||
"![link](http://example.com/image.jpg)",
|
||||
"![link](https://lemmy-alpha/api/v4/image_proxy?url=http%3A%2F%2Fexample.com%2Fimage.jpg)",
|
||||
"![link](https://lemmy-alpha/api/v4/image/proxy?url=http%3A%2F%2Fexample.com%2Fimage.jpg)",
|
||||
),
|
||||
(
|
||||
"local image unproxied",
|
||||
|
@ -125,7 +125,7 @@ mod tests {
|
|||
(
|
||||
"multiple image links",
|
||||
"![link](http://example.com/image1.jpg) ![link](http://example.com/image2.jpg)",
|
||||
"![link](https://lemmy-alpha/api/v4/image_proxy?url=http%3A%2F%2Fexample.com%2Fimage1.jpg) ![link](https://lemmy-alpha/api/v4/image_proxy?url=http%3A%2F%2Fexample.com%2Fimage2.jpg)",
|
||||
"![link](https://lemmy-alpha/api/v4/image/proxy?url=http%3A%2F%2Fexample.com%2Fimage1.jpg) ![link](https://lemmy-alpha/api/v4/image/proxy?url=http%3A%2F%2Fexample.com%2Fimage2.jpg)",
|
||||
),
|
||||
(
|
||||
"empty link handled",
|
||||
|
@ -135,7 +135,7 @@ mod tests {
|
|||
(
|
||||
"empty label handled",
|
||||
"![](http://example.com/image.jpg)",
|
||||
"![](https://lemmy-alpha/api/v4/image_proxy?url=http%3A%2F%2Fexample.com%2Fimage.jpg)"
|
||||
"![](https://lemmy-alpha/api/v4/image/proxy?url=http%3A%2F%2Fexample.com%2Fimage.jpg)"
|
||||
),
|
||||
(
|
||||
"invalid image link removed",
|
||||
|
@ -145,12 +145,12 @@ mod tests {
|
|||
(
|
||||
"label with nested markdown handled",
|
||||
"![a *b* c](http://example.com/image.jpg)",
|
||||
"![a *b* c](https://lemmy-alpha/api/v4/image_proxy?url=http%3A%2F%2Fexample.com%2Fimage.jpg)"
|
||||
"![a *b* c](https://lemmy-alpha/api/v4/image/proxy?url=http%3A%2F%2Fexample.com%2Fimage.jpg)"
|
||||
),
|
||||
(
|
||||
"custom emoji support",
|
||||
r#"![party-blob](https://www.hexbear.net/pictrs/image/83405746-0620-4728-9358-5f51b040ffee.gif "emoji party-blob")"#,
|
||||
r#"![party-blob](https://lemmy-alpha/api/v4/image_proxy?url=https%3A%2F%2Fwww.hexbear.net%2Fpictrs%2Fimage%2F83405746-0620-4728-9358-5f51b040ffee.gif "emoji party-blob")"#
|
||||
r#"![party-blob](https://lemmy-alpha/api/v4/image/proxy?url=https%3A%2F%2Fwww.hexbear.net%2Fpictrs%2Fimage%2F83405746-0620-4728-9358-5f51b040ffee.gif "emoji party-blob")"#
|
||||
)
|
||||
];
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ use lemmy_utils::rate_limit::RateLimitCell;
|
|||
|
||||
// Deprecated, use api v4 instead.
|
||||
// When removing api v3, we also need to rewrite all links in database with
|
||||
// `/api/v3/image_proxy` to use `/api/v4/image_proxy` instead.
|
||||
// `/api/v3/image_proxy` to use `/api/v4/image/proxy` instead.
|
||||
pub fn config(cfg: &mut ServiceConfig, rate_limit: &RateLimitCell) {
|
||||
cfg
|
||||
.service(
|
||||
|
|
|
@ -172,7 +172,6 @@ pub fn config(cfg: &mut ServiceConfig, rate_limit: &RateLimitCell) {
|
|||
cfg.service(
|
||||
scope("/api/v4")
|
||||
.wrap(rate_limit.message())
|
||||
.route("/image_proxy", get().to(image_proxy))
|
||||
// Site
|
||||
.service(
|
||||
scope("/site")
|
||||
|
@ -401,6 +400,7 @@ pub fn config(cfg: &mut ServiceConfig, rate_limit: &RateLimitCell) {
|
|||
.wrap(rate_limit.image())
|
||||
.route(post().to(upload_image)),
|
||||
)
|
||||
.route("/proxy", get().to(image_proxy))
|
||||
.route("/{filename}", get().to(get_full_res_image))
|
||||
.route("{token}/{filename}", delete().to(delete_image))
|
||||
.route("/healthz", get().to(pictrs_healthz)),
|
||||
|
|
Loading…
Reference in a new issue