chore: refac examples

This commit is contained in:
Dmitriy Pleshevskiy 2022-07-21 20:10:31 +03:00
parent 287a956073
commit ddf7f58e93
Signed by: pleshevskiy
GPG Key ID: 1B59187B161C0215
19 changed files with 641 additions and 706 deletions

View File

@ -1,18 +0,0 @@
language: rust
rust:
- stable
- beta
- nightly
cache:
directories:
- $HOME/.cargo
- $HOME/.rustup
before_cache:
- rm -rf /home/travis/.cargo/registry
script:
- |
rustc --version &&
cargo test --all-features
matrix:
allow_failures:
- rust: nightly

915
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -3,13 +3,5 @@ members = [
"itconfig",
"itconfig-macro",
"itconfig-tests",
"examples/diesel",
"examples/rocket", # nightly
"examples/hyper",
]
default-members = [
"itconfig",
"itconfig-macro",
"itconfig-tests",
]

View File

@ -1,16 +0,0 @@
# Diesel
This example shows how you can use itconfig with diesel.
### Usage
```bash
cd examples/diesel
docker-compose -p itconfig-diesel-example -f docker-compose.example.yml up -d
diesel migration run
cargo run
```

View File

@ -2,4 +2,4 @@
# see diesel.rs/guides/configuring-diesel-cli
[print_schema]
file = "src/schema.rs"
file = "schema.rs"

View File

@ -2,10 +2,10 @@ version: '3'
services:
postgresql:
image: postgres:11-alpine
image: postgres:12-alpine
ports:
- 5534:5432
environment:
POSTGRES_PASSWORD: test
POSTGRES_USER: user
POSTGRES_DB: db
POSTGRES_DB: db

View File

@ -1,16 +1,12 @@
#[macro_use]
extern crate diesel;
mod db;
mod models;
mod schema;
use crate::models::*;
use diesel::prelude::*;
use dotenv::dotenv;
use itconfig::config;
config! {
itconfig::config! {
DATABASE_URL,
}
@ -18,7 +14,7 @@ fn main() {
dotenv().expect("dotenv setup to be successful");
config::init();
let connection = db::establish_connection();
let connection = establish_connection();
let posts = get_posts(&connection);
println!("Displaying {} posts", posts.len());
@ -39,3 +35,17 @@ fn get_posts(connection: &PgConnection) -> Vec<Post> {
.get_results::<Post>(connection)
.expect("Error loading posts")
}
fn establish_connection() -> PgConnection {
let database_url = config::DATABASE_URL();
PgConnection::establish(database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", database_url))
}
#[derive(Queryable)]
struct Post {
pub id: i32,
pub title: String,
pub body: String,
pub published: bool,
}

View File

@ -1,9 +0,0 @@
use super::config;
use diesel::pg::PgConnection;
use diesel::prelude::*;
pub fn establish_connection() -> PgConnection {
let database_url = config::DATABASE_URL();
PgConnection::establish(database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", database_url))
}

View File

@ -1,7 +0,0 @@
#[derive(Queryable)]
pub struct Post {
pub id: i32,
pub title: String,
pub body: String,
pub published: bool,
}

43
examples/hyper.rs Normal file
View File

@ -0,0 +1,43 @@
use std::convert::Infallible;
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Request, Response, Server};
itconfig::config! {
hyper {
static HOST < (
ADDR => "127.0.0.1",
":",
PORT => 8000,
),
}
}
async fn hello(_: Request<Body>) -> Result<Response<Body>, Infallible> {
Ok(Response::new(Body::from("Hello World!")))
}
#[tokio::main]
pub async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
config::init();
pretty_env_logger::init();
// For every connection, we must make a `Service` to handle all
// incoming HTTP requests on said connection.
let make_svc = make_service_fn(|_conn| {
// This is the `Service` that will handle the connection.
// `service_fn` is a helper to convert a function that
// returns a Response into a `Service`.
async { Ok::<_, Infallible>(service_fn(hello)) }
});
let addr = config::hyper::HOST().parse()?;
let server = Server::bind(&addr).serve(make_svc);
println!("Listening on http://{}", addr);
server.await?;
Ok(())
}

View File

@ -1,18 +0,0 @@
[package]
name = "itconfig-hyper-example"
version = "0.1.0"
authors = ["Dmitriy Pleshevskiy <dmitriy@ideascup.me>"]
edition = "2018"
publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
itconfig = { path = "../../itconfig", features = ["macro"] }
hyper = { version = "0.14.4", features = ["full"] }
serde_json = "1.0.62"
tokio = { version = "1.2.0", features = ["macros", "rt-multi-thread"] }
bytes = "1.0.1"
futures-util = { version = "0.3.13", default-features = false }
pretty_env_logger = "0.4.0"
lazy_static = "1.4.0"

View File

@ -1,18 +0,0 @@
# Hyper
This example shows how you can use itconfig with hyper server.
Example was taken from the [official hyper example].
[official hyper example]: https://github.com/hyperium/hyper/blob/master/examples/web_api.rs
### Usage
```bash
cd examples/hyper
cargo run
```

View File

@ -1,138 +0,0 @@
use bytes::Buf;
use futures_util::{stream, StreamExt};
use hyper::client::HttpConnector;
use hyper::service::{make_service_fn, service_fn};
use hyper::{header, Body, Client, Method, Request, Response, Server, StatusCode};
use itconfig::config;
config! {
hyper {
PREFER_SCHEMA: String => "http",
static HOST < (
ADDR => "127.0.0.1",
":",
PORT => 8000,
),
static JSON_API_URL < (
HYPER_PREFER_SCHEMA,
"://",
HYPER_HOST,
"/json_api",
),
}
}
type GenericError = Box<dyn std::error::Error + Send + Sync>;
type Result<T> = std::result::Result<T, GenericError>;
static INDEX: &[u8] = b"<a href=\"test.html\">test.html</a>";
static INTERNAL_SERVER_ERROR: &[u8] = b"Internal Server Error";
static NOT_FOUND: &[u8] = b"Not Found";
static POST_DATA: &str = r#"{"original": "data"}"#;
async fn client_request_response(client: &Client<HttpConnector>) -> Result<Response<Body>> {
let url = format!("{}/json_api", config::hyper::HOST());
let req = Request::builder()
.method(Method::POST)
.uri(url)
.header(header::CONTENT_TYPE, "application/json")
.body(POST_DATA.into())
.unwrap();
let web_res = client.request(req).await?;
// Compare the JSON we sent (before) with what we received (after):
let before = stream::once(async {
Ok(format!(
"<b>POST request body</b>: {}<br><b>Response</b>: ",
POST_DATA,
)
.into())
});
let after = web_res.into_body();
let body = Body::wrap_stream(before.chain(after));
Ok(Response::new(body))
}
async fn api_post_response(req: Request<Body>) -> Result<Response<Body>> {
// Aggregate the body...
let whole_body = hyper::body::aggregate(req).await?;
// Decode as JSON...
let mut data: serde_json::Value = serde_json::from_reader(whole_body.reader())?;
// Change the JSON...
data["test"] = serde_json::Value::from("test_value");
// And respond with the new JSON.
let json = serde_json::to_string(&data)?;
let response = Response::builder()
.status(StatusCode::OK)
.header(header::CONTENT_TYPE, "application/json")
.body(Body::from(json))?;
Ok(response)
}
async fn api_get_response() -> Result<Response<Body>> {
let data = vec!["foo", "bar"];
let res = match serde_json::to_string(&data) {
Ok(json) => Response::builder()
.header(header::CONTENT_TYPE, "application/json")
.body(Body::from(json))
.unwrap(),
Err(_) => Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(INTERNAL_SERVER_ERROR.into())
.unwrap(),
};
Ok(res)
}
async fn response_examples(
req: Request<Body>,
client: Client<HttpConnector>,
) -> Result<Response<Body>> {
match (req.method(), req.uri().path()) {
(&Method::GET, "/") | (&Method::GET, "/index.html") => Ok(Response::new(INDEX.into())),
(&Method::GET, "/test.html") => client_request_response(&client).await,
(&Method::POST, "/json_api") => api_post_response(req).await,
(&Method::GET, "/json_api") => api_get_response().await,
_ => {
// Return 404 not found response.
Ok(Response::builder()
.status(StatusCode::NOT_FOUND)
.body(NOT_FOUND.into())
.unwrap())
}
}
}
#[tokio::main]
async fn main() -> Result<()> {
config::init();
pretty_env_logger::init();
let addr = config::hyper::HOST().parse().unwrap();
// Share a `Client` with all `Service`s
let client = Client::new();
let new_service = make_service_fn(move |_| {
// Move a clone of `client` into the `service_fn`.
let client = client.clone();
async {
Ok::<_, GenericError>(service_fn(move |req| {
// Clone again to ensure that client outlives this closure.
response_examples(req, client.to_owned())
}))
}
});
let server = Server::bind(&addr).serve(new_service);
println!("Listening on http://{}", addr);
server.await?;
Ok(())
}

51
examples/readme.md Normal file
View File

@ -0,0 +1,51 @@
# Diesel
This example shows how you can use itconfig with diesel.
### Usage
```bash
cd examples/diesel
docker-compose -p itconfig-diesel-example -f docker-compose.example.yml up -d
diesel migration run
cargo run --example diesel
```
# Hyper
This example shows how you can use itconfig with hyper server.
Example was taken from the [official hyper example].
[official hyper example]: https://github.com/hyperium/hyper/blob/master/examples/web_api.rs
### Usage
```bash
cargo run --example hyper
```
# Rocket
### Installation
To install a nightly version of Rust, we recommend using rustup. Install rustup
by following the instructions on its website. Once rustup is installed,
configure Rust nightly as your default toolchain by running the command:
`rustup default nightly`
If you prefer, once we setup a project directory in the following section, you
can use per-directory overrides to use the nightly version only for your Rocket
project by running the following command in the directory:
`rustup override set nightly`
### Usage
```bash
cargo run --example roket
```

View File

@ -1,5 +1,3 @@
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use]
extern crate rocket;

View File

@ -1,12 +0,0 @@
[package]
name = "itconfig-rocket-example"
version = "0.1.0"
authors = ["Dmitriy Pleshevskiy <dmitriy@ideascup.me>"]
edition = "2018"
publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rocket = "0.5.0-rc.1"
itconfig = { path = '../../itconfig', features = ["macro"] }

View File

@ -1,23 +0,0 @@
# itconfig rocket example
### Installation
To install a nightly version of Rust, we recommend using rustup. Install rustup by following the instructions on its website. Once rustup is installed, configure Rust nightly as your default toolchain by running the command:
`rustup default nightly`
If you prefer, once we setup a project directory in the following section, you can use per-directory overrides to use the nightly version only for your Rocket project by running the following command in the directory:
`rustup override set nightly`
### Usage
```bash
cd examples/rocket
cargo run
```

View File

@ -14,13 +14,6 @@ readme = "../README.md"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde_json = { version = "1", optional = true }
itconfig-macro = { version = "1.1", path = "../itconfig-macro", optional = true }
[dev-dependencies]
lazy_static = "1.4.0"
[features]
default = ["primitives"]
@ -54,12 +47,42 @@ bool = []
# deprecated since 1.1
json_array = ["serde_json"]
[dependencies]
serde_json = { version = "1", optional = true }
itconfig-macro = { version = "1.1", path = "../itconfig-macro", optional = true }
[dev-dependencies]
lazy_static = "1.4.0"
# required for examples
rocket = "0.5.0-rc.2"
hyper = { version = "0.14.4", features = ["full"] }
serde_json = "1.0.62"
tokio = { version = "1.2.0", features = ["macros", "rt-multi-thread"] }
bytes = "1.0.1"
futures-util = { version = "0.3.13", default-features = false }
pretty_env_logger = "0.4.0"
dotenv = "0.15.0"
diesel = { version = "1.4.8", features = ["postgres"] }
[badges]
travis-ci = { repository = "icetemple/itconfig-rs" }
maintenance = { status = "passively-maintained" }
# https://docs.rs/about
[package.metadata.docs.rs]
all-features = true
[[example]]
name = "diesel"
path = "../examples/diesel/main.rs"
required-features = ["macro"]
[[example]]
name = "hyper"
path = "../examples/hyper.rs"
required-features = ["macro"]
[[example]]
name = "rocket"
path = "../examples/rocket.rs"
required-features = ["macro"]