diff --git a/Cargo.lock b/Cargo.lock index df27a86..ef954a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -168,18 +168,6 @@ dependencies = [ "trust-dns-resolver 0.19.7", ] -[[package]] -name = "actix-cors" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3e5c769e4d332bfad27f11b8139b5818c4bbddb02c385b8f16344d93ff1a8eb" -dependencies = [ - "actix-service 1.0.6", - "actix-web 3.3.3", - "derive_more", - "futures-util", -] - [[package]] name = "actix-cors" version = "0.6.0-beta.10" @@ -845,7 +833,7 @@ dependencies = [ name = "actix-web-cors" version = "1.0.0" dependencies = [ - "actix-cors 0.6.0-beta.10", + "actix-cors", "actix-web 4.0.0-rc.3", "env_logger 0.9.0", "futures", @@ -3340,9 +3328,11 @@ dependencies = [ name = "juniper-advanced" version = "1.0.0" dependencies = [ - "actix-web 3.3.3", + "actix-cors", + "actix-web 4.0.0-rc.3", + "actix-web-lab", "dotenv", - "env_logger 0.8.4", + "env_logger 0.9.0", "juniper", "log", "mysql", @@ -3357,12 +3347,13 @@ dependencies = [ name = "juniper-example" version = "1.0.0" dependencies = [ - "actix-cors 0.4.1", - "actix-web 3.3.3", - "env_logger 0.8.4", + "actix-cors", + "actix-web 4.0.0-rc.3", + "actix-web-lab", + "env_logger 0.9.0", "juniper", + "log", "serde 1.0.136", - "serde_derive", "serde_json", ] diff --git a/basics/middleware-http-to-https/Cargo.toml b/basics/middleware-http-to-https/Cargo.toml index de47b0b..3bb7437 100644 --- a/basics/middleware-http-to-https/Cargo.toml +++ b/basics/middleware-http-to-https/Cargo.toml @@ -4,7 +4,7 @@ version = "1.0.0" edition = "2021" [dependencies] -actix-web = {version = "4.0.0-beta.21", features = ["rustls"]} +actix-web = { version = "4.0.0-beta.21", features = ["rustls"] } rustls = "0.20.2" -rustls-pemfile = "0.2.1" # these are now in an external library +rustls-pemfile = "0.2.1" futures = "0.3" diff --git a/graphql/juniper-advanced/.env.example b/graphql/juniper-advanced/.env.example index c8f7fc6..61a6ca5 100644 --- a/graphql/juniper-advanced/.env.example +++ b/graphql/juniper-advanced/.env.example @@ -1 +1 @@ -DATABASE_URL=mysql://user:password@127.0.0.1/dbname \ No newline at end of file +DATABASE_URL=mysql://user:password@127.0.0.1/graphql_testing diff --git a/graphql/juniper-advanced/Cargo.toml b/graphql/juniper-advanced/Cargo.toml index db94ea2..d8a5ef1 100644 --- a/graphql/juniper-advanced/Cargo.toml +++ b/graphql/juniper-advanced/Cargo.toml @@ -3,20 +3,20 @@ name = "juniper-advanced" version = "1.0.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] -actix-web = "3" +actix-web = "4.0.0-rc.3" +actix-web-lab = "0.10" +actix-cors = "0.6.0-beta.10" juniper = "0.15" mysql = "17" r2d2 = "0.8" -r2d2_mysql = "17.0" +r2d2_mysql = "17" dotenv = "0.15" -env_logger = "0.8" +env_logger = "0.9" log = "0.4" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" +serde = { version = "1", features = ["derive"] } +serde_json = "1" uuid = { version = "0.8", features = ["serde", "v4"] } diff --git a/graphql/juniper-advanced/README.md b/graphql/juniper-advanced/README.md index 26f4d27..139ef45 100644 --- a/graphql/juniper-advanced/README.md +++ b/graphql/juniper-advanced/README.md @@ -1,28 +1,34 @@ # juniper-advanced -GraphQL Implementation in Rust using Actix, Juniper, and Mysql as Database +GraphQL Implementation in Rust using Actix, Juniper, and MySQL as Database ## Prerequisites -- Rust Installed -- MySql as Database +- MySQL server ## Database Configuration -Create a new database for this project, and import the existing database schema has been provided named ```mysql-schema.sql```. +Create a new database for this project, and import the existing database schema has been provided named `mysql-schema.sql`. -Create ```.env``` file on the root directory of this project and set environment variable named ```DATABASE_URL```, the example file has been provided named ```.env.example```, you can see the format on there. - -## Run +Create `.env` file on the root directory of this project and set environment variable named `DATABASE_URL`, the example file has been provided named `.env.example`, you can see the format in there. + +```sh +cat mysql-schema.sql | mysql -u root -D graphql_testing +``` + +## Usage ```sh -# go to the root dir cd graphql/juniper-advanced +cp .env.example .env +# edit .env and insert your DB credentials cargo run ``` ## GraphQL Playground +GraphQL provides its own documentation. Click the "docs" link in the top right of the GraphiQL UI to see what types of queries and mutations are possible. + +``` +http://localhost:8080/graphiql ``` -http://127.0.0.1:8080/graphiql -``` \ No newline at end of file diff --git a/graphql/juniper-advanced/mysql-schema.sql b/graphql/juniper-advanced/mysql-schema.sql index a20e315..40f5a3a 100644 --- a/graphql/juniper-advanced/mysql-schema.sql +++ b/graphql/juniper-advanced/mysql-schema.sql @@ -1,6 +1,6 @@ -- MySQL dump 10.13 Distrib 8.0.16, for osx10.14 (x86_64) -- --- Host: 127.0.0.1 Database: rust_graphql +-- Host: 127.0.0.1 Database: graphql_testing -- ------------------------------------------------------ -- Server version 8.0.15 diff --git a/graphql/juniper-advanced/src/handlers.rs b/graphql/juniper-advanced/src/handlers.rs index 458c67b..2b693d1 100644 --- a/graphql/juniper-advanced/src/handlers.rs +++ b/graphql/juniper-advanced/src/handlers.rs @@ -1,10 +1,14 @@ -use actix_web::{web, Error, HttpResponse}; -use juniper::http::graphiql::graphiql_source; -use juniper::http::GraphQLRequest; +use actix_web::{get, route, web, Error, HttpResponse, Responder}; +use actix_web_lab::respond::Html; +use juniper::http::{graphiql::graphiql_source, GraphQLRequest}; -use crate::db::Pool; -use crate::schemas::root::{create_schema, Context, Schema}; +use crate::{ + db::Pool, + schemas::root::{create_schema, Context, Schema}, +}; +/// GraphQL endpoint +#[route("/graphql", method = "GET", method = "POST")] pub async fn graphql( pool: web::Data, schema: web::Data, @@ -13,27 +17,21 @@ pub async fn graphql( let ctx = Context { dbpool: pool.get_ref().to_owned(), }; - let res = web::block(move || { - let res = data.execute_sync(&schema, &ctx); - serde_json::to_string(&res) - }) - .await - .map_err(Error::from)?; - Ok(HttpResponse::Ok() - .content_type("application/json") - .body(res)) + let res = data.execute(&schema, &ctx).await; + + Ok(HttpResponse::Ok().json(res)) } -pub async fn graphql_playground() -> HttpResponse { - HttpResponse::Ok() - .content_type("text/html; charset=utf-8") - .body(graphiql_source("/graphql", None)) +/// GraphiQL UI +#[get("/graphiql")] +async fn graphql_playground() -> impl Responder { + Html(graphiql_source("/graphql", None)) } pub fn register(config: &mut web::ServiceConfig) { config - .data(create_schema()) - .route("/graphql", web::post().to(graphql)) - .route("/graphiql", web::get().to(graphql_playground)); + .app_data(web::Data::new(create_schema())) + .service(graphql) + .service(graphql_playground); } diff --git a/graphql/juniper-advanced/src/main.rs b/graphql/juniper-advanced/src/main.rs index a52a413..1cfe895 100644 --- a/graphql/juniper-advanced/src/main.rs +++ b/graphql/juniper-advanced/src/main.rs @@ -1,32 +1,33 @@ #[macro_use] extern crate juniper; -extern crate r2d2; -extern crate r2d2_mysql; -extern crate serde_json; -use actix_web::{middleware, web, App, HttpServer}; - -use crate::db::get_db_pool; -use crate::handlers::register; +use actix_cors::Cors; +use actix_web::{middleware::Logger, web::Data, App, HttpServer}; mod db; mod handlers; mod schemas; +use self::{db::get_db_pool, handlers::register}; + #[actix_web::main] async fn main() -> std::io::Result<()> { dotenv::dotenv().ok(); - std::env::set_var("RUST_LOG", "actix_web=info,info"); - env_logger::init(); + env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); + let pool = get_db_pool(); + log::info!("starting HTTP server on port 8080"); + log::info!("the GraphiQL interface HTTP server at http://localhost:8080/graphiql"); + HttpServer::new(move || { App::new() - .data(pool.clone()) - .wrap(middleware::Logger::default()) + .app_data(Data::new(pool.clone())) .configure(register) - .default_service(web::to(|| async { "404" })) + .wrap(Cors::permissive()) + .wrap(Logger::default()) }) + .workers(2) .bind(("127.0.0.1", 8080))? .run() .await diff --git a/graphql/juniper/src/main.rs b/graphql/juniper/src/main.rs index 3a50ab5..89e2e3b 100644 --- a/graphql/juniper/src/main.rs +++ b/graphql/juniper/src/main.rs @@ -17,9 +17,9 @@ mod schema; use crate::schema::{create_schema, Schema}; -/// GraphiQL UI +/// GraphiQL playground UI #[get("/graphiql")] -async fn graphiql() -> impl Responder { +async fn graphql_playground() -> impl Responder { Html(graphiql_source("/graphql", None)) } @@ -47,7 +47,7 @@ async fn main() -> io::Result<()> { App::new() .app_data(Data::from(schema.clone())) .service(graphql) - .service(graphiql) + .service(graphql_playground) // the graphiql UI requires CORS to be enabled .wrap(Cors::permissive()) .wrap(middleware::Logger::default())