Compare commits
No commits in common. "b7e08687b49e1196043b1d8e1116b2a02733b2ea" and "227066b7f56910e1171c85c70c85b717fc9aa5f7" have entirely different histories.
b7e08687b4
...
227066b7f5
|
|
@ -61,10 +61,10 @@ services:
|
||||||
postgres:
|
postgres:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: "curl --fail http://127.0.0.1:9999/health || exit 1"
|
test: [ "CMD", "nc", "-z", "localhost", "9999" ]
|
||||||
interval: 5s
|
interval: 5s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 12
|
retries: 6
|
||||||
environment:
|
environment:
|
||||||
# There are a lot of options to configure GoTrue. You can reference the example config:
|
# There are a lot of options to configure GoTrue. You can reference the example config:
|
||||||
# https://github.com/supabase/gotrue/blob/master/example.env
|
# https://github.com/supabase/gotrue/blob/master/example.env
|
||||||
|
|
@ -165,9 +165,6 @@ services:
|
||||||
- ADMIN_FRONTEND_REDIS_URL=${ADMIN_FRONTEND_REDIS_URL:-redis://redis:6379}
|
- ADMIN_FRONTEND_REDIS_URL=${ADMIN_FRONTEND_REDIS_URL:-redis://redis:6379}
|
||||||
- ADMIN_FRONTEND_GOTRUE_URL=${ADMIN_FRONTEND_GOTRUE_URL:-http://gotrue:9999}
|
- ADMIN_FRONTEND_GOTRUE_URL=${ADMIN_FRONTEND_GOTRUE_URL:-http://gotrue:9999}
|
||||||
- ADMIN_FRONTEND_APPFLOWY_CLOUD_URL=${ADMIN_FRONTEND_APPFLOWY_CLOUD_URL:-http://appflowy_cloud:8000}
|
- ADMIN_FRONTEND_APPFLOWY_CLOUD_URL=${ADMIN_FRONTEND_APPFLOWY_CLOUD_URL:-http://appflowy_cloud:8000}
|
||||||
depends_on:
|
|
||||||
appflowy_cloud:
|
|
||||||
condition: service_started
|
|
||||||
|
|
||||||
ai:
|
ai:
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ services:
|
||||||
test: [ "CMD", "pg_isready", "-U", "${POSTGRES_USER}" ]
|
test: [ "CMD", "pg_isready", "-U", "${POSTGRES_USER}" ]
|
||||||
interval: 5s
|
interval: 5s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 12
|
retries: 6
|
||||||
volumes:
|
volumes:
|
||||||
- ./migrations/before:/docker-entrypoint-initdb.d
|
- ./migrations/before:/docker-entrypoint-initdb.d
|
||||||
- postgres_data:/var/lib/postgresql/data
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
|
@ -55,10 +55,10 @@ services:
|
||||||
postgres:
|
postgres:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: "curl --fail http://127.0.0.1:9999/health || exit 1"
|
test: [ "CMD", "nc", "-z", "localhost", "9999" ]
|
||||||
interval: 5s
|
interval: 5s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 12
|
retries: 6
|
||||||
image: appflowyinc/gotrue:${GOTRUE_VERSION:-latest}
|
image: appflowyinc/gotrue:${GOTRUE_VERSION:-latest}
|
||||||
environment:
|
environment:
|
||||||
# There are a lot of options to configure GoTrue. You can reference the example config:
|
# There are a lot of options to configure GoTrue. You can reference the example config:
|
||||||
|
|
@ -144,9 +144,6 @@ services:
|
||||||
args:
|
args:
|
||||||
FEATURES: ""
|
FEATURES: ""
|
||||||
image: appflowyinc/appflowy_cloud:${APPFLOWY_CLOUD_VERSION:-latest}
|
image: appflowyinc/appflowy_cloud:${APPFLOWY_CLOUD_VERSION:-latest}
|
||||||
depends_on:
|
|
||||||
gotrue:
|
|
||||||
condition: service_healthy
|
|
||||||
|
|
||||||
admin_frontend:
|
admin_frontend:
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
|
|
@ -159,9 +156,6 @@ services:
|
||||||
- ADMIN_FRONTEND_REDIS_URL=${ADMIN_FRONTEND_REDIS_URL:-redis://redis:6379}
|
- ADMIN_FRONTEND_REDIS_URL=${ADMIN_FRONTEND_REDIS_URL:-redis://redis:6379}
|
||||||
- ADMIN_FRONTEND_GOTRUE_URL=${ADMIN_FRONTEND_GOTRUE_URL:-http://gotrue:9999}
|
- ADMIN_FRONTEND_GOTRUE_URL=${ADMIN_FRONTEND_GOTRUE_URL:-http://gotrue:9999}
|
||||||
- ADMIN_FRONTEND_APPFLOWY_CLOUD_URL=${ADMIN_FRONTEND_APPFLOWY_CLOUD_URL:-http://appflowy_cloud:8000}
|
- ADMIN_FRONTEND_APPFLOWY_CLOUD_URL=${ADMIN_FRONTEND_APPFLOWY_CLOUD_URL:-http://appflowy_cloud:8000}
|
||||||
depends_on:
|
|
||||||
appflowy_cloud:
|
|
||||||
condition: service_started
|
|
||||||
|
|
||||||
ai:
|
ai:
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
|
|
@ -171,9 +165,6 @@ services:
|
||||||
- APPFLOWY_AI_SERVER_PORT=${AI_SERVER_PORT}
|
- APPFLOWY_AI_SERVER_PORT=${AI_SERVER_PORT}
|
||||||
- APPFLOWY_AI_DATABASE_URL=${AI_DATABASE_URL}
|
- APPFLOWY_AI_DATABASE_URL=${AI_DATABASE_URL}
|
||||||
- APPFLOWY_AI_REDIS_URL=${AI_REDIS_URL}
|
- APPFLOWY_AI_REDIS_URL=${AI_REDIS_URL}
|
||||||
depends_on:
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
|
|
||||||
appflowy_worker:
|
appflowy_worker:
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
|
|
@ -199,9 +190,6 @@ services:
|
||||||
- APPFLOWY_MAILER_SMTP_USERNAME=${APPFLOWY_MAILER_SMTP_USERNAME}
|
- APPFLOWY_MAILER_SMTP_USERNAME=${APPFLOWY_MAILER_SMTP_USERNAME}
|
||||||
- APPFLOWY_MAILER_SMTP_EMAIL=${APPFLOWY_MAILER_SMTP_EMAIL}
|
- APPFLOWY_MAILER_SMTP_EMAIL=${APPFLOWY_MAILER_SMTP_EMAIL}
|
||||||
- APPFLOWY_MAILER_SMTP_PASSWORD=${APPFLOWY_MAILER_SMTP_PASSWORD}
|
- APPFLOWY_MAILER_SMTP_PASSWORD=${APPFLOWY_MAILER_SMTP_PASSWORD}
|
||||||
depends_on:
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
volumes:
|
volumes:
|
||||||
postgres_data:
|
postgres_data:
|
||||||
minio_data:
|
minio_data:
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ RUN rm /go/src/supabase/auth/migrations/20240612123726_enable_rls_update_grants.
|
||||||
FROM alpine:3.20
|
FROM alpine:3.20
|
||||||
RUN adduser -D -u 1000 supabase
|
RUN adduser -D -u 1000 supabase
|
||||||
|
|
||||||
RUN apk add --no-cache ca-certificates curl
|
RUN apk add --no-cache ca-certificates
|
||||||
USER supabase
|
USER supabase
|
||||||
|
|
||||||
COPY --from=base /auth .
|
COPY --from=base /auth .
|
||||||
|
|
|
||||||
|
|
@ -430,7 +430,6 @@ pub enum ErrorCode {
|
||||||
DecodeUpdateError = 1055,
|
DecodeUpdateError = 1055,
|
||||||
ApplyUpdateError = 1056,
|
ApplyUpdateError = 1056,
|
||||||
ActionTimeout = 1057,
|
ActionTimeout = 1057,
|
||||||
AIImageResponseLimitExceeded = 1058,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ErrorCode {
|
impl ErrorCode {
|
||||||
|
|
|
||||||
|
|
@ -117,10 +117,6 @@ pub struct WorkspaceUsageAndLimit {
|
||||||
pub single_upload_unlimited: bool,
|
pub single_upload_unlimited: bool,
|
||||||
pub ai_responses_count: i64,
|
pub ai_responses_count: i64,
|
||||||
pub ai_responses_count_limit: i64,
|
pub ai_responses_count_limit: i64,
|
||||||
#[serde(default)]
|
|
||||||
pub ai_image_responses_count: i64,
|
|
||||||
#[serde(default)]
|
|
||||||
pub ai_image_responses_count_limit: i64,
|
|
||||||
|
|
||||||
pub local_ai: bool,
|
pub local_ai: bool,
|
||||||
pub ai_responses_unlimited: bool,
|
pub ai_responses_unlimited: bool,
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
dotenvy::dotenv().ok();
|
dotenvy::dotenv().ok();
|
||||||
|
|
||||||
let listener = TcpListener::bind("0.0.0.0:4001").await.unwrap();
|
let listener = TcpListener::bind("0.0.0.0:4001").await.unwrap();
|
||||||
let config = Config::from_env()?;
|
let config = Config::from_env().expect("failed to load config");
|
||||||
run_server(listener, config).await
|
run_server(listener, config).await
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ async fn stream_complete_text_handler(
|
||||||
) -> actix_web::Result<HttpResponse> {
|
) -> actix_web::Result<HttpResponse> {
|
||||||
let ai_model = ai_model_from_header(&req);
|
let ai_model = ai_model_from_header(&req);
|
||||||
let params = payload.into_inner();
|
let params = payload.into_inner();
|
||||||
state.metrics.ai_metrics.record_total_completion_count(1);
|
|
||||||
|
|
||||||
match state
|
match state
|
||||||
.ai_client
|
.ai_client
|
||||||
|
|
@ -81,7 +80,6 @@ async fn summarize_row_handler(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
state.metrics.ai_metrics.record_total_summary_row_count(1);
|
|
||||||
let ai_model = ai_model_from_header(&req);
|
let ai_model = ai_model_from_header(&req);
|
||||||
let result = state.ai_client.summarize_row(&content, ai_model).await;
|
let result = state.ai_client.summarize_row(&content, ai_model).await;
|
||||||
let resp = match result {
|
let resp = match result {
|
||||||
|
|
@ -107,7 +105,6 @@ async fn translate_row_handler(
|
||||||
) -> actix_web::Result<Json<AppResponse<TranslateRowResponse>>> {
|
) -> actix_web::Result<Json<AppResponse<TranslateRowResponse>>> {
|
||||||
let params = payload.into_inner();
|
let params = payload.into_inner();
|
||||||
let ai_model = ai_model_from_header(&req);
|
let ai_model = ai_model_from_header(&req);
|
||||||
state.metrics.ai_metrics.record_total_translate_row_count(1);
|
|
||||||
match state.ai_client.translate_row(params.data, ai_model).await {
|
match state.ai_client.translate_row(params.data, ai_model).await {
|
||||||
Ok(resp) => Ok(AppResponse::Ok().with_data(resp).into()),
|
Ok(resp) => Ok(AppResponse::Ok().with_data(resp).into()),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ use aws_sdk_s3::types::{
|
||||||
BucketInfo, BucketLocationConstraint, BucketType, CreateBucketConfiguration,
|
BucketInfo, BucketLocationConstraint, BucketType, CreateBucketConfiguration,
|
||||||
};
|
};
|
||||||
use mailer::config::MailerSetting;
|
use mailer::config::MailerSetting;
|
||||||
|
use openssl::ssl::{SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod};
|
||||||
|
use openssl::x509::X509;
|
||||||
use secrecy::{ExposeSecret, Secret};
|
use secrecy::{ExposeSecret, Secret};
|
||||||
use sqlx::{postgres::PgPoolOptions, PgPool};
|
use sqlx::{postgres::PgPoolOptions, PgPool};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
@ -70,6 +72,7 @@ use crate::config::config::{
|
||||||
use crate::mailer::AFCloudMailer;
|
use crate::mailer::AFCloudMailer;
|
||||||
use crate::middleware::metrics_mw::MetricsMiddleware;
|
use crate::middleware::metrics_mw::MetricsMiddleware;
|
||||||
use crate::middleware::request_id::RequestIdMiddleware;
|
use crate::middleware::request_id::RequestIdMiddleware;
|
||||||
|
use crate::self_signed::create_self_signed_certificate;
|
||||||
use crate::state::{AppMetrics, AppState, GoTrueAdmin, UserCache};
|
use crate::state::{AppMetrics, AppState, GoTrueAdmin, UserCache};
|
||||||
|
|
||||||
pub struct Application {
|
pub struct Application {
|
||||||
|
|
@ -116,6 +119,11 @@ pub async fn run_actix_server(
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
let pair = get_certificate_and_server_key(&config);
|
||||||
|
let key = pair
|
||||||
|
.as_ref()
|
||||||
|
.map(|(_, server_key)| Key::from(server_key.expose_secret().as_bytes()))
|
||||||
|
.unwrap_or_else(Key::generate);
|
||||||
|
|
||||||
let storage = state.collab_access_control_storage.clone();
|
let storage = state.collab_access_control_storage.clone();
|
||||||
|
|
||||||
|
|
@ -142,7 +150,7 @@ pub async fn run_actix_server(
|
||||||
.wrap(MetricsMiddleware)
|
.wrap(MetricsMiddleware)
|
||||||
.wrap(IdentityMiddleware::default())
|
.wrap(IdentityMiddleware::default())
|
||||||
.wrap(
|
.wrap(
|
||||||
SessionMiddleware::builder(redis_store.clone(), Key::generate())
|
SessionMiddleware::builder(redis_store.clone(), key.clone())
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
.wrap(RequestIdMiddleware)
|
.wrap(RequestIdMiddleware)
|
||||||
|
|
@ -170,11 +178,24 @@ pub async fn run_actix_server(
|
||||||
.app_data(Data::new(state.published_collab_store.clone()))
|
.app_data(Data::new(state.published_collab_store.clone()))
|
||||||
});
|
});
|
||||||
|
|
||||||
server = server.listen(listener)?;
|
server = match pair {
|
||||||
|
None => server.listen(listener)?,
|
||||||
|
Some((certificate, _)) => {
|
||||||
|
server.listen_openssl(listener, make_ssl_acceptor_builder(certificate))?
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
Ok(server.run())
|
Ok(server.run())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_certificate_and_server_key(config: &Config) -> Option<(Secret<String>, Secret<String>)> {
|
||||||
|
if config.application.use_tls {
|
||||||
|
Some(create_self_signed_certificate().unwrap())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn init_state(config: &Config, rt_cmd_tx: CLCommandSender) -> Result<AppState, Error> {
|
pub async fn init_state(config: &Config, rt_cmd_tx: CLCommandSender) -> Result<AppState, Error> {
|
||||||
// Print the feature flags
|
// Print the feature flags
|
||||||
|
|
||||||
|
|
@ -502,3 +523,22 @@ async fn get_gotrue_client(setting: &GoTrueSetting) -> Result<gotrue::api::Clien
|
||||||
.map_err(|e| anyhow::anyhow!("Failed to connect to GoTrue: {}", e));
|
.map_err(|e| anyhow::anyhow!("Failed to connect to GoTrue: {}", e));
|
||||||
Ok(gotrue_client)
|
Ok(gotrue_client)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_ssl_acceptor_builder(certificate: Secret<String>) -> SslAcceptorBuilder {
|
||||||
|
let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
|
||||||
|
let x509_cert = X509::from_pem(certificate.expose_secret().as_bytes()).unwrap();
|
||||||
|
builder.set_certificate(&x509_cert).unwrap();
|
||||||
|
builder
|
||||||
|
.set_private_key_file("./cert/key.pem", SslFiletype::PEM)
|
||||||
|
.unwrap();
|
||||||
|
builder
|
||||||
|
.set_certificate_chain_file("./cert/cert.pem")
|
||||||
|
.unwrap();
|
||||||
|
builder
|
||||||
|
.set_min_proto_version(Some(openssl::ssl::SslVersion::TLS1_2))
|
||||||
|
.unwrap();
|
||||||
|
builder
|
||||||
|
.set_max_proto_version(Some(openssl::ssl::SslVersion::TLS1_3))
|
||||||
|
.unwrap();
|
||||||
|
builder
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,6 @@ pub struct AIMetrics {
|
||||||
total_stream_count: Counter,
|
total_stream_count: Counter,
|
||||||
failed_stream_count: Counter,
|
failed_stream_count: Counter,
|
||||||
stream_image_count: Counter,
|
stream_image_count: Counter,
|
||||||
total_completion_count: Counter,
|
|
||||||
total_summary_row_count: Counter,
|
|
||||||
total_translate_row_count: Counter,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AIMetrics {
|
impl AIMetrics {
|
||||||
|
|
@ -31,21 +28,6 @@ impl AIMetrics {
|
||||||
"Total count of image streams processed",
|
"Total count of image streams processed",
|
||||||
metrics.stream_image_count.clone(),
|
metrics.stream_image_count.clone(),
|
||||||
);
|
);
|
||||||
realtime_registry.register(
|
|
||||||
"total_completion_count",
|
|
||||||
"Total count of completions processed",
|
|
||||||
metrics.total_completion_count.clone(),
|
|
||||||
);
|
|
||||||
realtime_registry.register(
|
|
||||||
"total_summary_row_count",
|
|
||||||
"Total count of summary rows processed",
|
|
||||||
metrics.total_summary_row_count.clone(),
|
|
||||||
);
|
|
||||||
realtime_registry.register(
|
|
||||||
"total_translate_row_count",
|
|
||||||
"Total count of translation rows processed",
|
|
||||||
metrics.total_translate_row_count.clone(),
|
|
||||||
);
|
|
||||||
|
|
||||||
metrics
|
metrics
|
||||||
}
|
}
|
||||||
|
|
@ -61,16 +43,4 @@ impl AIMetrics {
|
||||||
pub fn record_stream_image_count(&self, count: u64) {
|
pub fn record_stream_image_count(&self, count: u64) {
|
||||||
self.stream_image_count.inc_by(count);
|
self.stream_image_count.inc_by(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn record_total_completion_count(&self, count: u64) {
|
|
||||||
self.total_completion_count.inc_by(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn record_total_summary_row_count(&self, count: u64) {
|
|
||||||
self.total_summary_row_count.inc_by(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn record_total_translate_row_count(&self, count: u64) {
|
|
||||||
self.total_translate_row_count.inc_by(count);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,8 @@ impl AppFlowyAISetting {
|
||||||
pub struct ApplicationSetting {
|
pub struct ApplicationSetting {
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
pub host: String,
|
pub host: String,
|
||||||
|
pub server_key: Secret<String>,
|
||||||
|
pub use_tls: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
@ -207,6 +209,10 @@ pub fn get_configuration() -> Result<Config, anyhow::Error> {
|
||||||
application: ApplicationSetting {
|
application: ApplicationSetting {
|
||||||
port: get_env_var("APPFLOWY_APPLICATION_PORT", "8000").parse()?,
|
port: get_env_var("APPFLOWY_APPLICATION_PORT", "8000").parse()?,
|
||||||
host: get_env_var("APPFLOWY_APPLICATION_HOST", "0.0.0.0"),
|
host: get_env_var("APPFLOWY_APPLICATION_HOST", "0.0.0.0"),
|
||||||
|
use_tls: get_env_var("APPFLOWY_APPLICATION_USE_TLS", "false")
|
||||||
|
.parse()
|
||||||
|
.context("fail to get APPFLOWY_APPLICATION_USE_TLS")?,
|
||||||
|
server_key: get_env_var("APPFLOWY_APPLICATION_SERVER_KEY", "server_key").into(),
|
||||||
},
|
},
|
||||||
websocket: WebsocketSetting {
|
websocket: WebsocketSetting {
|
||||||
heartbeat_interval: get_env_var("APPFLOWY_WEBSOCKET_HEARTBEAT_INTERVAL", "6").parse()?,
|
heartbeat_interval: get_env_var("APPFLOWY_WEBSOCKET_HEARTBEAT_INTERVAL", "6").parse()?,
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,6 @@ pub mod config;
|
||||||
pub mod domain;
|
pub mod domain;
|
||||||
pub mod mailer;
|
pub mod mailer;
|
||||||
pub mod middleware;
|
pub mod middleware;
|
||||||
|
mod self_signed;
|
||||||
pub mod state;
|
pub mod state;
|
||||||
pub mod telemetry;
|
pub mod telemetry;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
use actix_http::Payload;
|
||||||
|
use actix_service::{forward_ready, Service, Transform};
|
||||||
|
use actix_web::{dev::ServiceRequest, dev::ServiceResponse, Error};
|
||||||
|
use bytes::Bytes;
|
||||||
|
use bytes::BytesMut;
|
||||||
|
use futures::future::Ready;
|
||||||
|
use futures_util::future::{ready, LocalBoxFuture};
|
||||||
|
use futures_util::{stream, StreamExt};
|
||||||
|
|
||||||
|
pub struct DecryptPayloadMiddleware;
|
||||||
|
|
||||||
|
impl<S, B> Transform<S, ServiceRequest> for DecryptPayloadMiddleware
|
||||||
|
where
|
||||||
|
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||||
|
S::Future: 'static,
|
||||||
|
B: 'static,
|
||||||
|
{
|
||||||
|
type Response = ServiceResponse<B>;
|
||||||
|
type Error = Error;
|
||||||
|
type Transform = DecryptPayloadMiddlewareService<S>;
|
||||||
|
type InitError = ();
|
||||||
|
type Future = Ready<Result<Self::Transform, Self::InitError>>;
|
||||||
|
|
||||||
|
fn new_transform(&self, service: S) -> Self::Future {
|
||||||
|
ready(Ok(DecryptPayloadMiddlewareService { service }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DecryptPayloadMiddlewareService<S> {
|
||||||
|
service: S,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S, B> Service<ServiceRequest> for DecryptPayloadMiddlewareService<S>
|
||||||
|
where
|
||||||
|
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||||
|
S::Future: 'static,
|
||||||
|
B: 'static,
|
||||||
|
{
|
||||||
|
type Response = ServiceResponse<B>;
|
||||||
|
type Error = Error;
|
||||||
|
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
|
||||||
|
|
||||||
|
forward_ready!(service);
|
||||||
|
|
||||||
|
fn call(&self, req: ServiceRequest) -> Self::Future {
|
||||||
|
let (http_req, mut payload) = req.into_parts();
|
||||||
|
let payload_stream = stream::once(async move {
|
||||||
|
let mut body = BytesMut::new();
|
||||||
|
while let Some(chunk) = payload.next().await {
|
||||||
|
body.extend_from_slice(&chunk?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Bytes::from(body))
|
||||||
|
});
|
||||||
|
|
||||||
|
let payload = Box::pin(payload_stream);
|
||||||
|
let new_req = ServiceRequest::from_parts(http_req, Payload::Stream { payload });
|
||||||
|
let fut = self.service.call(new_req);
|
||||||
|
Box::pin(fut)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
|
pub mod encrypt_mw;
|
||||||
pub mod metrics_mw;
|
pub mod metrics_mw;
|
||||||
pub mod request_id;
|
pub mod request_id;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
use rcgen::{Certificate, CertificateParams, KeyPair, RcgenError, SanType};
|
||||||
|
use secrecy::Secret;
|
||||||
|
|
||||||
|
pub const CA_CRT: &str = include_str!("../cert/cert.pem");
|
||||||
|
pub const CA_KEY: &str = include_str!("../cert/key.pem");
|
||||||
|
|
||||||
|
pub fn create_self_signed_certificate() -> Result<(Secret<String>, Secret<String>), RcgenError> {
|
||||||
|
let key = KeyPair::from_pem(CA_KEY)?;
|
||||||
|
let params = CertificateParams::from_ca_cert_pem(CA_CRT, key)?;
|
||||||
|
let ca_cert = Certificate::from_params(params)?;
|
||||||
|
|
||||||
|
let mut params = CertificateParams::default();
|
||||||
|
params
|
||||||
|
.subject_alt_names
|
||||||
|
.push(SanType::IpAddress("127.0.0.1".parse().unwrap()));
|
||||||
|
params
|
||||||
|
.subject_alt_names
|
||||||
|
.push(SanType::IpAddress("0.0.0.0".parse().unwrap()));
|
||||||
|
params
|
||||||
|
.subject_alt_names
|
||||||
|
.push(SanType::DnsName("localhost".to_string()));
|
||||||
|
|
||||||
|
// Generate a certificate that's valid for:
|
||||||
|
// 1. localhost
|
||||||
|
// 2. 127.0.0.1
|
||||||
|
let gen_cert = Certificate::from_params(params)?;
|
||||||
|
let server_crt = Secret::new(gen_cert.serialize_pem_with_signer(&ca_cert)?);
|
||||||
|
let server_key = Secret::new(gen_cert.serialize_private_key_pem());
|
||||||
|
Ok((server_crt, server_key))
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue