-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
219 additions
and
224 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
root = true | ||
|
||
[*] | ||
charset = utf-8 | ||
end_of_line = lf | ||
indent_style = space | ||
indent_size = 4 | ||
insert_final_newline = true | ||
trim_trailing_whitespace = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,75 +1,51 @@ | ||
use std::io; | ||
use std::path::Path as StdPath; | ||
|
||
use anyhow::{Context, Result}; | ||
use axum::{extract::Path, http::StatusCode, response::IntoResponse, Json}; | ||
use axum::extract::Path; | ||
use axum::http::StatusCode; | ||
use axum::Json; | ||
use axum::response::IntoResponse; | ||
use cached::proc_macro::cached; | ||
use reqwest::Client; | ||
use tokio::{fs::{File, OpenOptions}, io::{AsyncReadExt, AsyncWriteExt}}; | ||
|
||
use super::versions::{fetch_versions, Version}; | ||
use crate::manifest::ManifestKind; | ||
use crate::utils::{read_from_json_file, write_to_json_file}; | ||
use super::versions::{fetch_versions, Version}; | ||
|
||
|
||
pub async fn manifest(Path(id): Path<String>) -> impl IntoResponse { | ||
match fetch_manifest(id).await { | ||
pub async fn manifest(Path(version): Path<String>) -> impl IntoResponse { | ||
match fetch_manifest(version).await { | ||
Ok(Some(data)) => Json(data.into_latest()).into_response(), | ||
Ok(None) => (StatusCode::NOT_FOUND).into_response(), | ||
Err(err) => (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()).into_response(), | ||
Ok(data) => match data { | ||
Some(data) => Json(data.into_latest()).into_response(), | ||
None => (StatusCode::NOT_FOUND).into_response(), | ||
}, | ||
} | ||
} | ||
|
||
#[cached(time = 600, result = true)] | ||
#[cached(time = 86400, result = true)] | ||
pub async fn fetch_manifest(version: String) -> Result<Option<ManifestKind>> { | ||
let versions = fetch_versions().await.context("Failed to fetch versions")?; | ||
match versions.into_iter().find(|entry| entry.version == version) { | ||
None => Ok(None), | ||
Some(version) => { | ||
if let Ok(manifest) = fetch_manifest_from_github(&version).await { | ||
Ok(Some(manifest)) | ||
} else { | ||
fetch_manifest_from_disk(&version).await.map(Some) | ||
} | ||
|
||
} | ||
} | ||
} | ||
|
||
async fn fetch_manifest_from_disk(version: &Version) -> Result<ManifestKind> { | ||
let mut file = File::open(format!("data/{}/manifest.json", version.version)).await | ||
.context("Failed to load manifest.json")?; | ||
if let Some(version) = versions.into_iter().find(|entry| entry.version == version) { | ||
let disk_path = format!("data/{}/manifest.json", version.version); | ||
|
||
let mut buffer = Vec::new(); | ||
file.read_to_end(&mut buffer).await | ||
.context("Failed to read manifest.json")?; | ||
let manifest: ManifestKind = serde_json::from_slice(&buffer) | ||
.context("Failed to parse manifest.json")?; | ||
return match fetch_manifest_from_github(&version).await { | ||
Ok(manifest) => { | ||
if !StdPath::new(&disk_path).exists() { | ||
write_to_json_file(&disk_path, &manifest).await?; | ||
} | ||
Ok(Some(manifest)) | ||
}, | ||
Err(_) => read_from_json_file(&disk_path).await.map(Some), | ||
}; | ||
} | ||
|
||
Ok(manifest) | ||
Ok(None) | ||
} | ||
|
||
async fn fetch_manifest_from_github(version: &Version) -> Result<ManifestKind> { | ||
let client = Client::new(); | ||
let response = client.get(&version.manifest).send().await | ||
.context("Failed to send request to Github")?; | ||
|
||
let manifest: ManifestKind = response.json().await | ||
.context("Failed to parse response from Github")?; | ||
|
||
write_manifest_to_disk(&manifest, version).await?; | ||
let response = client.get(&version.manifest).send().await?; | ||
let manifest: ManifestKind = response.json().await?; | ||
|
||
Ok(manifest) | ||
} | ||
|
||
async fn write_manifest_to_disk(manifest: &ManifestKind, version: &Version) -> io::Result<()> { | ||
let data = serde_json::to_string(manifest)?; | ||
let mut file = OpenOptions::new() | ||
.write(true) | ||
.truncate(true) | ||
.create(true) | ||
.open(format!("data/{}/manifest.json", version.version)) | ||
.await?; | ||
|
||
file.write_all(data.as_bytes()).await | ||
} |
Oops, something went wrong.