Compare commits

...

7 Commits

Author SHA1 Message Date
d74ca76e44 bigger changements
All checks were successful
build docker container automatically / build (push) Successful in 4m14s
2026-04-17 16:57:18 +02:00
031d0e39df test latest tag
All checks were successful
build docker container automatically / build (push) Successful in 3m17s
2026-04-17 16:48:15 +02:00
b739780c13 test latest tag
All checks were successful
build docker container automatically / build (push) Successful in 3m15s
2026-04-17 16:40:41 +02:00
ad8183e10b fix CD fr fr
All checks were successful
build docker container automatically / build (push) Successful in 3m19s
2026-04-17 16:19:46 +02:00
ec1323a1b4 fix CD fr this time (please)
Some checks failed
build docker container automatically / build (push) Failing after 2m1s
2026-04-17 16:14:01 +02:00
3854c09577 fix CD 2026-04-17 16:11:23 +02:00
fc3806c334 add CD, fix warnings 2026-04-17 16:09:42 +02:00
12 changed files with 90 additions and 35 deletions

View File

@ -0,0 +1,35 @@
name: build docker container automatically
run-name: docker build
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: get commit hash
id: get_hash
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
registry: git.tmoron.fr
username: ${{ secrets.PUSH_USERNAME }}
password: ${{ secrets.PUSH_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: "{{defaultContext}}:${{ input.path }}"
push: true
tags: git.tmoron.fr/${{ gitea.repository }}:latest

View File

@ -3,6 +3,8 @@ name = "httpserver"
version = "0.1.0" version = "0.1.0"
authors = ["tomoron <tomoron@student.42angouleme.fr>"] authors = ["tomoron <tomoron@student.42angouleme.fr>"]
edition = "2021" edition = "2021"
description = "a rewrite of my http server in rust"
repository = "https://git.tmoron.fr/tom/httpserver"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

24
Dockerfile Normal file
View File

@ -0,0 +1,24 @@
FROM lewimbes/dioxus AS builder
RUN mkdir /build
WORKDIR /build
LABEL stage="builder"
RUN apt-get update && apt-get install -y \
libpq-dev \
default-libmysqlclient-dev \
sqlite3 libsqlite3-dev && \
rm -rf /var/lib/apt/lists/*
COPY . .
RUN dx build -r
RUN cp /build/target/dx/httpserver/release/web /app -r
WORKDIR /app
RUN rm -rf /build
ENV IP="0.0.0.0"
CMD ["./server"]

View File

@ -1,2 +1,2 @@
mod component; //mod component;
pub use component::*; //pub use component::*;

View File

@ -12,9 +12,11 @@ use crate::config::ClientConfig;
use std::time::Duration; use std::time::Duration;
#[cfg(feature = "server")]
use std::fs; use std::fs;
use std::fs::File; #[cfg(feature = "server")]
use std::io::Write; use std::io::Write;
#[cfg(feature = "server")]
use futures::StreamExt; use futures::StreamExt;
@ -44,7 +46,7 @@ async fn upload_file(mut upload: FileStream) -> Result<String, HttpError> {
let filename: String = loop { let filename: String = loop {
let cur = random_string::generate(20, "ABCDEFGHIJKLMNOPQRTSTUVWXYZ0123456789"); let cur = random_string::generate(20, "ABCDEFGHIJKLMNOPQRTSTUVWXYZ0123456789");
if (!fs::exists(s_config.upload_folder.clone() + &cur).expect("can't check if file exists")) { if !fs::exists(s_config.upload_folder.clone() + &cur).expect("can't check if file exists") {
break cur; break cur;
} }
}; };
@ -74,7 +76,7 @@ async fn upload_file(mut upload: FileStream) -> Result<String, HttpError> {
break; break;
} }
if file.write(&bytes).is_err() { error == Some("failed write"); break; }; if file.write(&bytes).is_err() { error = Some("failed write"); break; };
}, },
Err(_) => { error = Some("unknown"); break; } Err(_) => { error = Some("unknown"); break; }
} }
@ -82,8 +84,8 @@ async fn upload_file(mut upload: FileStream) -> Result<String, HttpError> {
match error { match error {
Some(err)=> { Some(err)=> {
file.sync_data(); let _ = file.sync_data();
fs::remove_file(s_config.upload_folder.clone() + &filename); let _ = fs::remove_file(s_config.upload_folder.clone() + &filename);
HttpError::internal_server_error(err)? HttpError::internal_server_error(err)?
} }
None => { None => {

View File

@ -1,9 +1,6 @@
use std::fs::create_dir;
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus::fullstack::FileStream; use dioxus::fullstack::FileStream;
#[cfg(feature = "server")]
use httpserver::models::GetFile;
#[cfg(feature = "server")] #[cfg(feature = "server")]
use diesel::prelude::*; use diesel::prelude::*;
#[cfg(feature = "server")] #[cfg(feature = "server")]
@ -15,6 +12,7 @@ use httpserver::schema;
#[cfg(feature = "server")] #[cfg(feature = "server")]
use crate::config::ServerConfig; use crate::config::ServerConfig;
#[cfg(feature = "server")]
use std::path::Path; use std::path::Path;
@ -39,10 +37,10 @@ async fn download_file(id: String) -> Result<FileStream, HttpError> {
use schema::file; use schema::file;
let s_config = ServerConfig::load(); let s_config = ServerConfig::load();
let result = DB.with(|pool| schema::file::table.select((file::filename)) let result = DB.with(|pool| schema::file::table.select(file::filename)
.filter(file::stored_filename.eq(id.clone())) .filter(file::stored_filename.eq(id.clone()))
.filter(file::deleted.eq(false)) .filter(file::deleted.eq(false))
.load::<(String)>(&mut pool.get().unwrap())); .load::<String>(&mut pool.get().unwrap()));
if let Err(_) = result { if let Err(_) = result {
return HttpError::internal_server_error("Database request failed"); return HttpError::internal_server_error("Database request failed");

View File

@ -1,20 +1,17 @@
use std::time::SystemTime;
use chrono::DateTime; use chrono::DateTime;
use chrono::Utc; use chrono::Utc;
use dioxus::fullstack::httperror;
use dioxus::prelude::*; use dioxus::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use httpserver::utils::byte_to_human_size; use httpserver::utils::byte_to_human_size;
#[cfg(feature = "server")]
use httpserver::models::GetFile;
#[cfg(feature = "server")] #[cfg(feature = "server")]
use diesel::prelude::*; use diesel::prelude::*;
#[cfg(feature = "server")] #[cfg(feature = "server")]
use httpserver::DB; use httpserver::DB;
#[cfg(feature = "server")]
use std::time::SystemTime;
#[cfg(feature = "server")] #[cfg(feature = "server")]
use httpserver::schema; use httpserver::schema;

View File

@ -1,7 +1,5 @@
use dioxus::prelude::*; use dioxus::prelude::*;
#[cfg(feature = "server")]
use httpserver::models::GetFile;
#[cfg(feature = "server")] #[cfg(feature = "server")]
use diesel::prelude::*; use diesel::prelude::*;
#[cfg(feature = "server")] #[cfg(feature = "server")]
@ -9,17 +7,14 @@ use httpserver::DB;
#[cfg(feature = "server")] #[cfg(feature = "server")]
use diesel::dsl; use diesel::dsl;
#[cfg(feature = "server")]
use httpserver::schema;
#[cfg(feature = "server")] #[cfg(feature = "server")]
use crate::config::ServerConfig; use crate::config::ServerConfig;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[cfg(feature = "server")]
use bigdecimal::{BigDecimal, ToPrimitive}; use bigdecimal::{BigDecimal, ToPrimitive};
use httpserver::utils::byte_to_human_size;
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
struct UploadServerStats { struct UploadServerStats {
total_limit_soft: u64, total_limit_soft: u64,
@ -43,8 +38,8 @@ async fn get_upload_stats() -> Result<UploadServerStats, HttpError> {
_ => return HttpError::internal_server_error("wth ?") _ => return HttpError::internal_server_error("wth ?")
}; };
let total_files = match DB.with(|pool| file::table.select((dsl::count(file::id))) let total_files = match DB.with(|pool| file::table.select(dsl::count(file::id))
.first::<(i64)>(&mut pool.get().unwrap())) { .first::<i64>(&mut pool.get().unwrap())) {
Ok(val) => val, Ok(val) => val,
_ => return HttpError::internal_server_error("wth ?") _ => return HttpError::internal_server_error("wth ?")
}; };

View File

@ -12,10 +12,10 @@ impl ServerConfig {
pub fn load() -> Self { pub fn load() -> Self {
Self { Self {
upload_folder: "./test/".to_string(), upload_folder: "./test/".to_string(),
db_url: std::env::var("DATABASE_URL").expect("missing DATABASE_URL"), db_url: std::env::var("HTTPSERVER_DATABASE_URL").expect("missing HTTPSERVER_DATABASE_URL"),
upload_storage_limit_soft: 1024 * 1024 * 1024 * 200, upload_storage_limit_soft: 1024 * 1024 * 1024 * 200,
upload_storage_limit_hard: 1024 * 1024 * 1024 * 300, upload_storage_limit_hard: 1024 * 1024 * 1024 * 250,
} }
} }

View File

@ -1,7 +1,5 @@
#[cfg(feature = "server")] #[cfg(feature = "server")]
use diesel::pg::PgConnection; use diesel::pg::PgConnection;
#[cfg(feature = "server")]
use diesel::prelude::*;
pub mod utils; pub mod utils;
@ -18,17 +16,15 @@ pub mod schema;
#[cfg(feature = "server")] #[cfg(feature = "server")]
use diesel::r2d2::{ConnectionManager, Pool}; use diesel::r2d2::{ConnectionManager, Pool};
#[cfg(feature = "server")]
use diesel::result::Error;
#[cfg(feature = "server")] #[cfg(feature = "server")]
thread_local! { thread_local! {
pub static DB: diesel::r2d2::Pool<ConnectionManager<PgConnection>> = { pub static DB: Pool<ConnectionManager<PgConnection>> = {
let s_config = ServerConfig::load(); let s_config = ServerConfig::load();
let db_url = s_config.db_url.clone(); let db_url = s_config.db_url.clone();
let manager = ConnectionManager::<PgConnection>::new(&db_url); let manager = ConnectionManager::<PgConnection>::new(&db_url);
diesel::r2d2::Pool::builder() Pool::builder()
.build(manager) .build(manager)
.unwrap_or_else(|_| panic!("Error creating pool for {}", db_url)) .unwrap_or_else(|_| panic!("Error creating pool for {}", db_url))
}; };

View File

@ -8,6 +8,9 @@ use crate::components::toast::ToastProvider;
use crate::views::{Upload, UploadInfo, Home}; use crate::views::{Upload, UploadInfo, Home};
#[cfg(feature = "server")]
use crate::config::ServerConfig;
mod components; mod components;
mod views; mod views;
@ -27,6 +30,9 @@ const FAVICON: Asset = asset!("/assets/favicon.ico");
const TAILWIND_CSS: Asset = asset!("/assets/tailwind.css"); const TAILWIND_CSS: Asset = asset!("/assets/tailwind.css");
fn main() { fn main() {
#[cfg(feature = "server")]
let _ = ServerConfig::load();
dioxus::logger::init(Level::INFO).expect("failed to init logger"); dioxus::logger::init(Level::INFO).expect("failed to init logger");
dioxus::launch(App); dioxus::launch(App);
} }