chore: refac examples
This commit is contained in:
parent
287a956073
commit
ddf7f58e93
19 changed files with 641 additions and 706 deletions
18
.travis.yml
18
.travis.yml
|
@ -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
915
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -3,13 +3,5 @@ members = [
|
||||||
"itconfig",
|
"itconfig",
|
||||||
"itconfig-macro",
|
"itconfig-macro",
|
||||||
"itconfig-tests",
|
"itconfig-tests",
|
||||||
"examples/diesel",
|
|
||||||
"examples/rocket", # nightly
|
|
||||||
"examples/hyper",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
default-members = [
|
|
||||||
"itconfig",
|
|
||||||
"itconfig-macro",
|
|
||||||
"itconfig-tests",
|
|
||||||
]
|
|
||||||
|
|
|
@ -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
|
|
||||||
```
|
|
|
@ -2,4 +2,4 @@
|
||||||
# see diesel.rs/guides/configuring-diesel-cli
|
# see diesel.rs/guides/configuring-diesel-cli
|
||||||
|
|
||||||
[print_schema]
|
[print_schema]
|
||||||
file = "src/schema.rs"
|
file = "schema.rs"
|
||||||
|
|
|
@ -2,10 +2,10 @@ version: '3'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
postgresql:
|
postgresql:
|
||||||
image: postgres:11-alpine
|
image: postgres:12-alpine
|
||||||
ports:
|
ports:
|
||||||
- 5534:5432
|
- 5534:5432
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_PASSWORD: test
|
POSTGRES_PASSWORD: test
|
||||||
POSTGRES_USER: user
|
POSTGRES_USER: user
|
||||||
POSTGRES_DB: db
|
POSTGRES_DB: db
|
||||||
|
|
|
@ -1,16 +1,12 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate diesel;
|
extern crate diesel;
|
||||||
|
|
||||||
mod db;
|
|
||||||
mod models;
|
|
||||||
mod schema;
|
mod schema;
|
||||||
|
|
||||||
use crate::models::*;
|
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
use itconfig::config;
|
|
||||||
|
|
||||||
config! {
|
itconfig::config! {
|
||||||
DATABASE_URL,
|
DATABASE_URL,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +14,7 @@ fn main() {
|
||||||
dotenv().expect("dotenv setup to be successful");
|
dotenv().expect("dotenv setup to be successful");
|
||||||
config::init();
|
config::init();
|
||||||
|
|
||||||
let connection = db::establish_connection();
|
let connection = establish_connection();
|
||||||
let posts = get_posts(&connection);
|
let posts = get_posts(&connection);
|
||||||
|
|
||||||
println!("Displaying {} posts", posts.len());
|
println!("Displaying {} posts", posts.len());
|
||||||
|
@ -39,3 +35,17 @@ fn get_posts(connection: &PgConnection) -> Vec<Post> {
|
||||||
.get_results::<Post>(connection)
|
.get_results::<Post>(connection)
|
||||||
.expect("Error loading posts")
|
.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,
|
||||||
|
}
|
|
@ -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))
|
|
||||||
}
|
|
|
@ -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
43
examples/hyper.rs
Normal 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(())
|
||||||
|
}
|
|
@ -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"
|
|
|
@ -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
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
51
examples/readme.md
Normal 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
|
||||||
|
```
|
|
@ -1,5 +1,3 @@
|
||||||
#![feature(proc_macro_hygiene, decl_macro)]
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
|
|
|
@ -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"] }
|
|
|
@ -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
|
|
||||||
```
|
|
|
@ -14,13 +14,6 @@ readme = "../README.md"
|
||||||
|
|
||||||
# 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
|
||||||
|
|
||||||
[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]
|
[features]
|
||||||
default = ["primitives"]
|
default = ["primitives"]
|
||||||
|
|
||||||
|
@ -54,12 +47,42 @@ bool = []
|
||||||
# deprecated since 1.1
|
# deprecated since 1.1
|
||||||
json_array = ["serde_json"]
|
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]
|
[badges]
|
||||||
travis-ci = { repository = "icetemple/itconfig-rs" }
|
|
||||||
maintenance = { status = "passively-maintained" }
|
maintenance = { status = "passively-maintained" }
|
||||||
|
|
||||||
|
|
||||||
# https://docs.rs/about
|
# https://docs.rs/about
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
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"]
|
||||||
|
|
||||||
|
|
Reference in a new issue