Skip to content
This repository has been archived by the owner on Apr 29, 2024. It is now read-only.

Commit

Permalink
httpd: Improve data-uri support
Browse files Browse the repository at this point in the history
We were just using `strip_prefix` with a hardcoded value, which wasn't
able to adjust to URIs that start with `data:image/png` or other content
and types.

Signed-off-by: Sebastian Martinez <[email protected]>
  • Loading branch information
sebastinez authored and cloudhead committed Sep 26, 2023
1 parent e57dbc3 commit 5acfffb
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 29 deletions.
29 changes: 28 additions & 1 deletion radicle-httpd/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ use axum::http::Method;
use axum::response::{IntoResponse, Json};
use axum::routing::get;
use axum::Router;
use base64::prelude::{Engine, BASE64_STANDARD};
use serde::{Deserialize, Serialize};
use serde_json::json;
use tokio::sync::RwLock;
use tower_http::cors::{self, CorsLayer};

use radicle::cob::issue;
use radicle::cob::patch;
use radicle::cob::{issue, Uri};
use radicle::identity::Id;
use radicle::node::routing::Store;
use radicle::storage::{ReadRepository, ReadStorage};
Expand Down Expand Up @@ -204,3 +205,29 @@ mod project {
pub trackings: usize,
}
}

/// A `data:` URI.
#[derive(Debug, Clone)]
pub struct DataUri(Vec<u8>);

impl From<DataUri> for Vec<u8> {
fn from(value: DataUri) -> Self {
value.0
}
}

impl TryFrom<&Uri> for DataUri {
type Error = Uri;

fn try_from(value: &Uri) -> Result<Self, Self::Error> {
if let Some(data_uri) = value.as_str().strip_prefix("data:") {
let (_, uri_data) = data_uri.split_once(',').ok_or(value.clone())?;
let uri_data = BASE64_STANDARD
.decode(uri_data)
.map_err(|_| value.clone())?;

return Ok(DataUri(uri_data));
}
Err(value.clone())
}
}
41 changes: 13 additions & 28 deletions radicle-httpd/src/api/v1/projects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use axum::response::IntoResponse;
use axum::routing::{get, patch, post};
use axum::{Json, Router};
use axum_auth::AuthBearer;
use base64::prelude::{Engine, BASE64_STANDARD};
use hyper::StatusCode;
use radicle_surf::blob::{Blob, BlobRef};
use serde::{Deserialize, Serialize};
Expand All @@ -25,7 +24,7 @@ use radicle_surf::{diff, Glob, Oid, Repository};

use crate::api::error::Error;
use crate::api::project::Info;
use crate::api::{self, CobsQuery, Context, PaginationQuery};
use crate::api::{self, CobsQuery, Context, DataUri, PaginationQuery};
use crate::axum_extra::{Path, Query};

const CACHE_1_HOUR: &str = "public, max-age=3600, must-revalidate";
Expand Down Expand Up @@ -534,18 +533,11 @@ async fn issue_create_handler(
.embeds
.into_iter()
.filter_map(|embed| {
if let Some(content) = embed
.content
.as_str()
.strip_prefix("data:content/type;base64,")
{
return BASE64_STANDARD.decode(content).ok().map(|content| Embed {
name: embed.name,
content,
});
}

None
let content = TryInto::<DataUri>::try_into(&embed.content).ok()?;
Some(Embed {
name: embed.name,
content: content.into(),
})
})
.collect();

Expand Down Expand Up @@ -604,18 +596,11 @@ async fn issue_update_handler(
let embeds: Vec<Embed> = embeds
.into_iter()
.filter_map(|embed| {
if let Some(content) = embed
.content
.as_str()
.strip_prefix("data:content/type;base64,")
{
return BASE64_STANDARD.decode(content).ok().map(|content| Embed {
name: embed.name,
content,
});
}

None
let content = TryInto::<DataUri>::try_into(&embed.content).ok()?;
Some(Embed {
name: embed.name,
content: content.into(),
})
})
.collect();
if let Some(to) = reply_to {
Expand Down Expand Up @@ -1848,7 +1833,7 @@ mod routes {
"embeds": [
{
"name": "example.html",
"content": "data:content/type;base64,PGh0bWw+SGVsbG8gV29ybGQhPC9odG1sPg=="
"content": "data:image/png;base64,PGh0bWw+SGVsbG8gV29ybGQhPC9odG1sPg=="
}
],
"assignees": [],
Expand Down Expand Up @@ -1924,7 +1909,7 @@ mod routes {
"embeds": [
{
"name": "image.jpg",
"content": "data:content/type;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4//8/AAX+Av4N70a4AAAAAElFTkSuQmCC"
"content": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4//8/AAX+Av4N70a4AAAAAElFTkSuQmCC"
}
],
"replyTo": CONTRIBUTOR_ISSUE_ID,
Expand Down

0 comments on commit 5acfffb

Please sign in to comment.