feat(server): add landing page (#26)

* feat(server): add landing page

Fixes orhun/rustypaste#13

* feat(server): allow using {REPOSITORY} in landing page

* fix(server): Get rid of unused import, add line about expiration

* chore(fmt): cargo fmt

* fix(tests): inject app data for fixing index test

* feat(server): redirect to GitHub repository if landing page is not specified

* test(fixtures): add fixture test for landing page

Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
This commit is contained in:
TheTechRobo 2022-10-03 17:27:35 -04:00 committed by GitHub
parent 1e1da30b83
commit 37cb4d3fcb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 6 deletions

View File

@ -7,6 +7,21 @@ address="127.0.0.1:8000"
max_content_length="10MB" max_content_length="10MB"
upload_path="./upload" upload_path="./upload"
timeout="30s" timeout="30s"
landing_page="""Submit files via HTTP POST here:
curl -F 'file=@example.txt' <server>"
This will return the finished URL.
The server administrator might remove any pastes that they do not personally
want to host.
If you are the server administrator and want to change this page, just go
into your config file and change it! If you change the expiry time, it is
recommended that you do.
Check out the GitHub repository at https://github.com/orhun/rustypaste
By default, pastes expire every hour. The server admin may or may not have
changed this."""
[paste] [paste]
random_url = { enabled = true, type = "petname", words = 2, separator = "-" } random_url = { enabled = true, type = "petname", words = 2, separator = "-" }

View File

@ -0,0 +1,10 @@
[server]
address="127.0.0.1:8000"
max_content_length="10MB"
upload_path="./upload"
landing_page="awesome_landing"
[paste]
random_url = { enabled = false, type = "petname", words = 2, separator = "-" }
default_extension = "txt"
duplicate_files = false

View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
landing_page="awesome_landing"
setup() {
:;
}
run_test() {
result=$(curl -s localhost:8000)
test "$landing_page" = "$result"
}
teardown() {
:;
}

View File

@ -41,6 +41,8 @@ pub struct ServerConfig {
pub timeout: Option<Duration>, pub timeout: Option<Duration>,
/// Authentication token. /// Authentication token.
pub auth_token: Option<String>, pub auth_token: Option<String>,
/// Landing page text.
pub landing_page: Option<String>,
} }
/// Paste configuration. /// Paste configuration.

View File

@ -8,7 +8,7 @@ use crate::util;
use crate::AUTH_TOKEN_ENV; use crate::AUTH_TOKEN_ENV;
use actix_files::NamedFile; use actix_files::NamedFile;
use actix_multipart::Multipart; use actix_multipart::Multipart;
use actix_web::{error, get, post, web, Error, HttpRequest, HttpResponse, Responder}; use actix_web::{error, get, post, web, Error, HttpRequest, HttpResponse};
use awc::Client; use awc::Client;
use byte_unit::Byte; use byte_unit::Byte;
use futures_util::stream::StreamExt; use futures_util::stream::StreamExt;
@ -19,10 +19,16 @@ use std::sync::RwLock;
/// Shows the landing page. /// Shows the landing page.
#[get("/")] #[get("/")]
async fn index() -> impl Responder { async fn index(config: web::Data<RwLock<Config>>) -> Result<HttpResponse, Error> {
HttpResponse::Found() let config = config
.append_header(("Location", env!("CARGO_PKG_HOMEPAGE"))) .read()
.finish() .map_err(|_| error::ErrorInternalServerError("cannot acquire config"))?;
match &config.server.landing_page {
Some(page) => Ok(HttpResponse::Ok().body(page.clone())),
None => Ok(HttpResponse::Found()
.append_header(("Location", env!("CARGO_PKG_HOMEPAGE")))
.finish()),
}
} }
/// Serves a file from the upload directory. /// Serves a file from the upload directory.
@ -260,7 +266,13 @@ mod tests {
#[actix_web::test] #[actix_web::test]
async fn test_index() { async fn test_index() {
let app = test::init_service(App::new().service(index)).await; let config = Config::default();
let app = test::init_service(
App::new()
.app_data(Data::new(RwLock::new(config)))
.service(index),
)
.await;
let request = TestRequest::default() let request = TestRequest::default()
.insert_header(("content-type", "text/plain")) .insert_header(("content-type", "text/plain"))
.to_request(); .to_request();
@ -268,6 +280,25 @@ mod tests {
assert_eq!(StatusCode::FOUND, response.status()); assert_eq!(StatusCode::FOUND, response.status());
} }
#[actix_web::test]
async fn test_index_with_landing_page() -> Result<(), Error> {
let mut config = Config::default();
config.server.landing_page = Some(String::from("landing page"));
let app = test::init_service(
App::new()
.app_data(Data::new(RwLock::new(config)))
.service(index),
)
.await;
let request = TestRequest::default()
.insert_header(("content-type", "text/plain"))
.to_request();
let response = test::call_service(&app, request).await;
assert_eq!(StatusCode::OK, response.status());
assert_body(response, "landing page").await?;
Ok(())
}
#[actix_web::test] #[actix_web::test]
async fn test_auth() -> Result<(), Error> { async fn test_auth() -> Result<(), Error> {
let mut config = Config::default(); let mut config = Config::default();