Multiple listeners

This commit is contained in:
LittleSheep 2024-02-13 20:32:13 +08:00
parent 3fbe1db1ef
commit 12add73ecb
13 changed files with 126 additions and 75 deletions

View File

@ -9,7 +9,7 @@ WORKDIR /source/pkg/sideload/view
RUN npm install RUN npm install
RUN npm run build RUN npm run build
WORKDIR /source WORKDIR /source
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -buildvcs -o /dist ./pkg/cmd/server/main.go RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -buildvcs -o /dist ./pkg/cmd/server.rs/main.go
# Runtime # Runtime
FROM golang:alpine FROM golang:alpine

View File

@ -74,9 +74,9 @@ rds cli with this command.
```shell ```shell
rds connect <id> <url> <password> rds connect <id> <url> <password>
# ID will allow you find this server in after commands. # ID will allow you find this server.rs in after commands.
# URL is to your roadsign server sideload api. # URL is to your roadsign server.rs sideload api.
# Password is your roadsign server credential. # Password is your roadsign server.rs credential.
# ====================================================================== # ======================================================================
# !WARNING! All these things will storage in your $HOME/.roadsignrc.yaml # !WARNING! All these things will storage in your $HOME/.roadsignrc.yaml
# ====================================================================== # ======================================================================
@ -85,8 +85,8 @@ rds connect <id> <url> <password>
Then, sync your local config to remote. Then, sync your local config to remote.
```shell ```shell
rds sync <server id> <site id> <config file> rds sync <server.rs id> <site id> <config file>
# Server ID is your server added by last command. # Server ID is your server.rs added by last command.
# Site ID is your new site id or old site id if you need update it. # Site ID is your new site id or old site id if you need update it.
# Config File is your local config file path. # Config File is your local config file path.
``` ```

View File

@ -1,10 +1,15 @@
regions = "./regions" regions = "./regions"
secret = "aEXcED5xJ3" secret = "aEXcED5xJ3"
[listen] [sideload]
proxies = "0.0.0.0:80" bind_addr = "0.0.0.0:81"
proxies_tls = "0.0.0.0:443"
sideload = "0.0.0.0:81" [[proxies.bind]]
addr = "0.0.0.0:80"
tls = false
[[proxies.bind]]
addr = "0.0.0.0:443"
tls = false
[[certificates]] [[certificates]]
domain = "localhost" domain = "localhost"

View File

@ -1,21 +1,20 @@
extern crate core;
mod config; mod config;
mod proxies; mod proxies;
mod sideload; mod sideload;
pub mod warden; mod warden;
mod tls; mod server;
pub mod tls;
use std::error; use std::error;
use actix_web::{App, HttpServer, web};
use actix_web::middleware::Logger;
use actix_web_httpauth::extractors::AuthenticationError;
use actix_web_httpauth::headers::www_authenticate::basic::Basic;
use actix_web_httpauth::middleware::HttpAuthentication;
use awc::Client;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use proxies::RoadInstance; use proxies::RoadInstance;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use tokio::task::JoinSet;
use tracing::{error, info, Level}; use tracing::{error, info, Level};
use crate::proxies::route; use crate::proxies::server::build_proxies;
use crate::sideload::server::build_sideload;
lazy_static! { lazy_static! {
static ref ROAD: Mutex<RoadInstance> = Mutex::new(RoadInstance::new()); static ref ROAD: Mutex<RoadInstance> = Mutex::new(RoadInstance::new());
@ -43,50 +42,15 @@ async fn main() -> Result<(), Box<dyn error::Error>> {
} }
}; };
let mut server_set = JoinSet::new();
// Proxies // Proxies
let proxies_server = HttpServer::new(|| { for server in build_proxies().await? {
App::new() server_set.spawn(server);
.wrap(Logger::default()) }
.app_data(web::Data::new(Client::default()))
.route("/", web::to(route::handle))
}).bind_rustls_0_22(
config::CFG
.read()
.await
.get_string("listen.proxies_tls")?,
tls::use_rustls().await?,
)?.bind(
config::CFG
.read()
.await
.get_string("listen.proxies")?
)?.run();
// Sideload // Sideload
let sideload_server = HttpServer::new(|| { server_set.spawn(build_sideload().await?);
App::new()
.wrap(HttpAuthentication::basic(|req, credentials| async move {
let password = match config::CFG
.read()
.await
.get_string("secret") {
Ok(val) => val,
Err(_) => return Err((AuthenticationError::new(Basic::new()).into(), req))
};
if credentials.password().unwrap_or("") != password {
Err((AuthenticationError::new(Basic::new()).into(), req))
} else {
Ok(req)
}
}))
.service(sideload::service())
}).bind(
config::CFG
.read()
.await
.get_string("listen.sideload")
.unwrap_or("0.0.0.0:81".to_string())
)?.workers(1).run();
// Process manager // Process manager
{ {
@ -98,7 +62,8 @@ async fn main() -> Result<(), Box<dyn error::Error>> {
app.warden.start().await; app.warden.start().await;
} }
tokio::try_join!(proxies_server, sideload_server)?; // Wait for web servers
server_set.join_next().await;
Ok(()) Ok(())
} }

View File

@ -17,6 +17,7 @@ pub mod loader;
pub mod metrics; pub mod metrics;
pub mod responder; pub mod responder;
pub mod route; pub mod route;
pub mod server;
#[derive(Debug, Display)] #[derive(Debug, Display)]
pub enum ProxyError { pub enum ProxyError {

39
src/proxies/server.rs Normal file
View File

@ -0,0 +1,39 @@
use std::error;
use actix_web::{App, HttpServer, web};
use actix_web::dev::Server;
use actix_web::middleware::Logger;
use awc::Client;
use crate::config::CFG;
use crate::proxies::route;
use crate::server::ServerBindConfig;
use crate::tls::{load_certificates, use_rustls};
pub async fn build_proxies() -> Result<Vec<Server>, Box<dyn error::Error>> {
load_certificates().await?;
let cfg = CFG
.read()
.await
.get::<Vec<ServerBindConfig>>("proxies.bind")?;
let mut tasks = Vec::new();
for item in cfg {
tasks.push(build_single_proxy(item)?);
}
Ok(tasks)
}
pub fn build_single_proxy(cfg: ServerBindConfig) -> Result<Server, Box<dyn error::Error>> {
let server = HttpServer::new(|| {
App::new()
.wrap(Logger::default())
.app_data(web::Data::new(Client::default()))
.route("/", web::to(route::handle))
});
if cfg.tls {
Ok(server.bind_rustls_0_22(cfg.addr, use_rustls()?)?.run())
} else {
Ok(server.bind(cfg.addr)?.run())
}
}

7
src/server.rs Normal file
View File

@ -0,0 +1,7 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct ServerBindConfig {
pub addr: String,
pub tls: bool,
}

View File

@ -4,6 +4,7 @@ use crate::sideload::regions::list_region;
mod overview; mod overview;
mod regions; mod regions;
pub mod server;
static ROOT: &str = ""; static ROOT: &str = "";

35
src/sideload/server.rs Normal file
View File

@ -0,0 +1,35 @@
use std::error;
use actix_web::dev::Server;
use actix_web::{App, HttpServer};
use actix_web_httpauth::extractors::AuthenticationError;
use actix_web_httpauth::headers::www_authenticate::basic::Basic;
use actix_web_httpauth::middleware::HttpAuthentication;
use crate::sideload;
pub async fn build_sideload() -> Result<Server, Box<dyn error::Error>> {
Ok(
HttpServer::new(|| {
App::new()
.wrap(HttpAuthentication::basic(|req, credentials| async move {
let password = match crate::config::CFG
.read()
.await
.get_string("secret") {
Ok(val) => val,
Err(_) => return Err((AuthenticationError::new(Basic::new()).into(), req))
};
if credentials.password().unwrap_or("") != password {
Err((AuthenticationError::new(Basic::new()).into(), req))
} else {
Ok(req)
}
}))
.service(sideload::service())
}).bind(
crate::config::CFG
.read()
.await
.get_string("sideload.bind_addr")?
)?.workers(1).run()
)
}

View File

@ -67,9 +67,7 @@ pub async fn load_certificates() -> Result<(), ConfigError> {
Ok(()) Ok(())
} }
pub async fn use_rustls() -> Result<rustls::ServerConfig, ConfigError> { pub fn use_rustls() -> Result<rustls::ServerConfig, ConfigError> {
load_certificates().await?;
Ok( Ok(
rustls::ServerConfig::builder() rustls::ServerConfig::builder()
.with_no_client_auth() .with_no_client_auth()

View File

@ -10,7 +10,7 @@ const ClientAddressNotAvailable = {
const StaticClientAddressNotAvailable = { const StaticClientAddressNotAvailable = {
name: "StaticClientAddressNotAvailable", name: "StaticClientAddressNotAvailable",
title: "`Astro.clientAddress` is not available in static mode.", title: "`Astro.clientAddress` is not available in static mode.",
message: "`Astro.clientAddress` is only available when using `output: 'server'` or `output: 'hybrid'`. Update your Astro config if you need SSR features.", message: "`Astro.clientAddress` is only available when using `output: 'server.rs'` or `output: 'hybrid'`. Update your Astro config if you need SSR features.",
hint: "See https://docs.astro.build/en/guides/server-side-rendering/ for more information on how to enable SSR." hint: "See https://docs.astro.build/en/guides/server-side-rendering/ for more information on how to enable SSR."
}; };
const NoMatchingStaticPathFound = { const NoMatchingStaticPathFound = {
@ -212,7 +212,7 @@ const CantRenderPage = {
name: "CantRenderPage", name: "CantRenderPage",
title: "Astro can't render the route.", title: "Astro can't render the route.",
message: "Astro cannot find any content to render for this route. There is no file or redirect associated with this route.", message: "Astro cannot find any content to render for this route. There is no file or redirect associated with this route.",
hint: "If you expect to find a route here, this may be an Astro bug. Please file an issue/restart the dev server" hint: "If you expect to find a route here, this may be an Astro bug. Please file an issue/restart the dev server.rs"
}; };
function normalizeLF(code) { function normalizeLF(code) {
@ -524,7 +524,7 @@ function extractDirectives(inputProps, clientDirectives) {
propsWithoutTransitionAttributes: {} propsWithoutTransitionAttributes: {}
}; };
for (const [key, value] of Object.entries(inputProps)) { for (const [key, value] of Object.entries(inputProps)) {
if (key.startsWith("server:")) { if (key.startsWith("server.rs:")) {
if (key === "server:root") { if (key === "server:root") {
extracted.isPage = true; extracted.isPage = true;
} }

View File

@ -10,7 +10,7 @@ import buffer from 'node:buffer';
import crypto from 'node:crypto'; import crypto from 'node:crypto';
import http from 'node:http'; import http from 'node:http';
import https$1 from 'https'; import https$1 from 'https';
import enableDestroy from 'server-destroy'; import enableDestroy from 'server.rs-destroy';
import path from 'node:path'; import path from 'node:path';
import url from 'node:url'; import url from 'node:url';
import send from 'send'; import send from 'send';
@ -1972,7 +1972,7 @@ class NodeApp extends App {
* import { NodeApp } from 'astro/app/node'; * import { NodeApp } from 'astro/app/node';
* import { createServer } from 'node:http'; * import { createServer } from 'node:http';
* *
* const server = createServer(async (req, res) => { * const server.rs = createServer(async (req, res) => {
* const request = NodeApp.createRequest(req); * const request = NodeApp.createRequest(req);
* const response = await app.render(request); * const response = await app.render(request);
* await NodeApp.writeResponse(response, res); * await NodeApp.writeResponse(response, res);
@ -2003,7 +2003,7 @@ class NodeApp extends App {
* import { NodeApp } from 'astro/app/node'; * import { NodeApp } from 'astro/app/node';
* import { createServer } from 'node:http'; * import { createServer } from 'node:http';
* *
* const server = createServer(async (req, res) => { * const server.rs = createServer(async (req, res) => {
* const request = NodeApp.createRequest(req); * const request = NodeApp.createRequest(req);
* const response = await app.render(request); * const response = await app.render(request);
* await NodeApp.writeResponse(response, res); * await NodeApp.writeResponse(response, res);
@ -2032,7 +2032,7 @@ class NodeApp extends App {
result = await reader.read(); result = await reader.read();
} }
} catch { } catch {
destination.write("Internal server error"); destination.write("Internal server.rs error");
} }
} }
destination.end(); destination.end();
@ -2116,7 +2116,7 @@ function createStaticHandler(app, options) {
if (forwardError) { if (forwardError) {
console.error(err.toString()); console.error(err.toString());
res.writeHead(500); res.writeHead(500);
res.end("Internal server error"); res.end("Internal server.rs error");
return; return;
} }
ssr(); ssr();
@ -2340,7 +2340,7 @@ const _manifest = Object.assign(manifest, {
pageMap, pageMap,
renderers, renderers,
}); });
const _args = {"mode":"standalone","client":"file:///Users/littlesheep/Documents/Projects/Capital/dist/client/","server":"file:///Users/littlesheep/Documents/Projects/Capital/dist/server/","host":false,"port":4321,"assets":"_astro"}; const _args = {"mode":"standalone","client":"file:///Users/littlesheep/Documents/Projects/Capital/dist/client/","server":"file:///Users/littlesheep/Documents/Projects/Capital/dist/server.rs/","host":false,"port":4321,"assets":"_astro"};
const _exports = createExports(_manifest, _args); const _exports = createExports(_manifest, _args);
const handler = _exports['handler']; const handler = _exports['handler'];

View File

@ -1,5 +1,5 @@
import React, { createElement } from 'react'; import React, { createElement } from 'react';
import ReactDOM from 'react-dom/server'; import ReactDOM from 'react-dom/server.rs';
/** /**
* Astro passes `children` as a string of HTML, so we need * Astro passes `children` as a string of HTML, so we need
@ -258,6 +258,6 @@ const _renderer0 = {
supportsAstroStaticSlot: true, supportsAstroStaticSlot: true,
}; };
const renderers = [Object.assign({"name":"@astrojs/react","clientEntrypoint":"@astrojs/react/client.js","serverEntrypoint":"@astrojs/react/server.js"}, { ssr: _renderer0 }),]; const renderers = [Object.assign({"name":"@astrojs/react","clientEntrypoint":"@astrojs/react/client.js","serverEntrypoint":"@astrojs/react/server.rs.js"}, { ssr: _renderer0 }),];
export { renderers }; export { renderers };