R3 Good practices applied

Scalability and performance

Defining compressing for data exchange

// Defining default Compress level for data exchange
 .wrap(middleware::Compress::new(ContentEncoding::Gzip))

Static Configuration and default config

  1. First we look for a distributed configuration server (etcd)
  2. If it fails, we take the configuration values located in an .env file
  3. And if this also fails, we have the default configuration (initialized variables)
let mut port: String = String::from("3030");
let mut host: String = String::from("127.0.0.1");

let client_etcd = Client::connect(["localhost:2379"], None).await;

if client_etcd.is_ok(){
    let mut client_unwrap = client_etcd.unwrap();
    let resp_etc_host = client_unwrap.get("HOST", None).await;
    let resp_etc_port = client_unwrap.get("PORT", None).await;

    host = String::from(resp_etc_host.unwrap().kvs().first().unwrap().value_str().unwrap().to_string().as_str());
    port = String::from(resp_etc_port.unwrap().kvs().first().unwrap().value_str().unwrap().to_string().as_str());

    log::info!("Host from etcd: {:?}", host);
    log::info!("Port from etcd: {:?}", port);
}else{
    log::info!("No client etc, we will use .env");
}

dotenv().ok();

port = env::var("PORT").expect("PORT must be set");
host = env::var("HOST").expect("HOST must be set");

Security

Define a subset of accepted verbs (the ones we use, the rest are not accepted)

.wrap(middleware::DefaultHeaders::new().header("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE"))

Preventing XSS Attempt (Not useful if request is not from browser)

.wrap(middleware::DefaultHeaders::new().header("X-XSS-Protection", "1; mode=block"))

Preventing embedding

.wrap(middleware::DefaultHeaders::new().header("X-Frame-Options","Deny"))
Only allow our same origin scripts
.wrap(middleware::DefaultHeaders::new().header("Content-Security-Policy","script-src 'self'"))
Preventing CSRF attacks
.wrap(middleware::DefaultHeaders::new().header("Access-Control-Allow-Headers", "X-Requested-Width"))

Functionality

Only JSON exchange

.wrap(middleware::DefaultHeaders::new().header("Content-Type", "application/json"))

Use of (customs) logs (and inject them in api) for every event in backend

// Define format of our logs
env_logger::Builder::from_env(Env::default().default_filter_or("info").write_style_or("auto", "always"))
    .format(|buf, record| {
        writeln!(
            buf,
            "{} {}: {}",
            record.level(),
            //Format like you want to: <-----------------
            Local::now().format("%Y-%m-%d %H:%M:%S%.3f"),
            record.args()
        )
    })
    .init();


log::info!("Welcome to cloudbanking API {}", VERSION_ENV);
log::info!("Server is listening in {}", binding_uri);

Same in kotlin

import org.jboss.logging.Logger

companion object {
    private val LOG = Logger.getLogger(FundResource::class.java)
}

LOG.info("POST -> Fund was created")