// This file is part of September . // Copyright (C) 2022-2022 Fuwn // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, version 3. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // Copyright (C) 2022-2022 Fuwn // SPDX-License-Identifier: GPL-3.0-only use std::{env::var, time::Instant}; use actix_web::{Error, HttpResponse}; use crate::url::make as make_url; #[allow(clippy::unused_async, clippy::future_not_send, clippy::too_many_lines)] pub async fn default( req: actix_web::HttpRequest, ) -> Result { let mut is_proxy = false; // Try to construct a Gemini URL let url = make_url( &format!("{}{}", req.path(), { if !req.query_string().is_empty() || req.uri().to_string().ends_with('?') { format!("?{}", req.query_string()) } else { "".to_string() } }), false, &mut is_proxy, ) .unwrap(); // Make a request to get Gemini content and time it. let mut timer = Instant::now(); let mut response = match gmi::request::make_request(&url) { Ok(response) => response, Err(e) => { return Ok(HttpResponse::Ok().body(e.to_string())); } }; if response.data.is_empty() { response = match gmi::request::make_request( &make_url(req.path(), true, &mut is_proxy).unwrap(), ) { Ok(response) => response, Err(e) => { return Ok(HttpResponse::Ok().body(e.to_string())); } }; } let response_time_taken = timer.elapsed(); // Reset timer for below timer = Instant::now(); // Convert Gemini Response to HTML and time it. let mut html_context = String::from(""); let gemini_html = crate::gemini_to_html::gemini_to_html(&response, &url, is_proxy); let gemini_title = gemini_html.0; let convert_time_taken = timer.elapsed(); // Try to add an external stylesheet from the `CSS_EXTERNAL` environment // variable. if let Ok(css) = var("CSS_EXTERNAL") { html_context.push_str(&format!( "", css )); } // Try to add an external favicon from the `FAVICON_EXTERNAL` environment // variable. if let Ok(favicon) = var("FAVICON_EXTERNAL") { html_context.push_str(&format!( "", favicon )); } // Add a title to HTML response html_context.push_str(&format!("{}", gemini_title)); html_context.push_str(""); match response.status { gmi::protocol::StatusCode::Success(_) => html_context.push_str(&gemini_html.1), _ => html_context.push_str(&format!("

{}

", response.meta)), } // Add proxy information to footer of HTML response html_context.push_str(&format!( "
\nProxy information
Original URL
{0}
Status code
{:?}
Meta
{}
Capsule response time
{} milliseconds
Gemini-to-HTML time
{} milliseconds

This content has been proxied by \ September ({}).

", url, response.status, response.meta, response_time_taken.as_nanos() as f64 / 1_000_000.0, convert_time_taken.as_nanos() as f64 / 1_000_000.0, format_args!("/tree/{}", env!("VERGEN_GIT_SHA")), env!("VERGEN_GIT_SHA").get(0..5).unwrap_or("UNKNOWN"), )); if let Ok(plain_texts) = var("PLAIN_TEXT_ROUTE") { if plain_texts.split(',').any(|r| r == req.path()) { return Ok( HttpResponse::Ok() .body(String::from_utf8_lossy(&response.data).to_string()), ); } } Ok( HttpResponse::Ok() .content_type("text/html; charset=utf-8") .body(html_context), ) }