I want to use the crate rocket_cors for Rocket v0.5.0-rc.2 but it does not compile because "the trait bound 'Cors: Fairing' is not satisfied".
Here is my Cargo.toml:
# --snip--
[dependencies]
rocket = { version = "0.5.0-rc.2", features = [ "json" ] }
rocket_cors = { version = "0.5.2", default-features = false }
# --snip--
And here is my rocket() function:
fn rocket() -> _ {
let cors = rocket_cors::CorsOptions {
allowed_origins: AllowedOrigins::all(),
allowed_headers: AllowedHeaders::some(&["Authorization", "Accept"]),
allow_credentials: true,
..Default::default()
}
.to_cors()
.unwrap();
rocket::build()
.attach(DbConnection::fairing())
.attach(cors) // <- Here's the error: "the trait `Fairing` is not implemented for `Cors`"
.mount("/", routes![get_tasks])
}
I won't have a problem if the solution is using another CORS crate either.
Related
I want to add some error handler in the rust function, so I define the rust function response like this so that I could return the error message if encount the recoverable error:
pub fn add_bill_book() -> Result<BillBook,String> {
return Err("failed".parse().unwrap())
}
and box the result to return to client like this;
fn main() {
let result = add_bill_book();
box_rest_response(result);
}
but when I compile the project, shows error like this:
➜ rust-learn git:(multiple-statement) ✗ cargo build
Compiling rust-learn v0.1.0 (/Users/xiaoqiangjiang/source/reddwarf/backend/rust-learn)
error[E0277]: the trait bound `Result<BillBook, std::string::String>: std::default::Default` is not satisfied
--> src/main.rs:8:23
|
8 | box_rest_response(result);
| ----------------- ^^^^^^ the trait `std::default::Default` is not implemented for `Result<BillBook, std::string::String>`
| |
| required by a bound introduced by this call
|
note: required by a bound in `box_rest_response`
--> src/main.rs:11:87
|
11 | pub fn box_rest_response<T>(data: T) -> content::RawJson<String> where T: Serialize + Default {
| ^^^^^^^ required by this bound in `box_rest_response`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `rust-learn` due to previous error
what should I do to fix it? I think it is hard to implement the default trait for all type of Result. This is the full minimal reproduce example:
use rocket::response::content;
use rust_wheel::model::response::api_response::ApiResponse;
use serde::Serialize;
use serde::Deserialize;
fn main() {
let result = add_bill_book();
box_rest_response(result);
}
pub fn box_rest_response<T>(data: T) -> content::RawJson<String> where T: Serialize + Default {
let res = ApiResponse {
result: data,
..Default::default()
};
let response_json = serde_json::to_string(&res).unwrap();
return content::RawJson(response_json);
}
#[derive(Debug,Serialize,Deserialize,Default,Clone)]
pub struct BillBook {
pub id: i64,
pub created_time: i64,
pub updated_time: i64,
pub deleted: i32,
pub creator: i64,
pub bill_book_template_id: i32,
pub remark: Option<String>,
pub contents: Option<String>,
}
pub fn add_bill_book() -> Result<BillBook,String> {
return Err("failed".parse().unwrap())
}
and this is the Cargo.toml dependencies:
[package]
name = "rust-learn"
version = "0.1.0"
edition = "2018"
[dependencies]
rocket = { version = "=0.5.0-rc.2", features = ["json"] }
serde = { version = "1.0.64", features = ["derive"] }
serde_json = "1.0.64"
serde_derive = "1.0"
# database
diesel = { version = "1.4.7", features = ["postgres","serde_json"] }
dotenv = "0.15.0"
jsonwebtoken = "7"
chrono = "0.4"
config = "0.11"
ring = "0.16.20"
md5 = "0.7.0"
data-encoding = "2.3.2"
# reddwarf public component
rust_wheel = { git = "https://github.com/jiangxiaoqiang/rust_wheel.git" }
I tried this way to solve this problem:
return match contents {
Ok(_) => {
box_rest_response(contents.unwrap())
},
Err(_) => {
box_rest_response(contents.unwrap_err())
}
}
but the new problem is that I have to match the result in many places, is it possible to optimized it? I tried to add a new function in public lib like this:
pub fn box_rest_result<T,E>(result: Result<T,E>) -> content::RawJson<String> where T: Serialize + Default, E: std::default::Default{
return match result {
Ok(_) => {
box_rest_response(result.unwrap())
},
Err(_) => {
box_rest_response(result.unwrap_err())
}
}
}
still facing the same problem.
Result does not implement Default because there is no one-fits-all default value.
You can create a newtype struct and implement Default on it, as in How do I implement a trait I don't own for a type I don't own?.
Note that match with unwrap() is a very bad idea, since match can already extract the value:
match contents {
Ok(v) => box_rest_response(v),
Err(e) => box_rest_response(e),
}
I’m trying to write a client to communicate with my grpc server written with tonic using Rust, but I’m having trouble understanding where to define and connect to the client, thus getting errors with my import statement. I’ve followed several tutorials and am having trouble finding information on how to create and import a client. My error is:
error[E0432]: unresolved import `user::client`
--> user/src/client.rs:2:36
|
2 | use user::client::{UserClient};
| ^^^^^^ could not find `client` in `user`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0432`.
error: could not compile `user`
In my proto.rs file:
syntax = "proto3";
package user;
message CreateUser {
string name = 1;
}
[package]
name = "user"
version = "0.1.0"
edition = "2018"
[lib]
[[bin]]
name = "server"
path = "src/server.rs"
[[bin]]
name = "client"
path = "src/client.rs"
[dependencies]
tonic = "0.5"
prost = "0.8"
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
[build-dependencies]
tonic-build = "0.5"
My lib.rs file:
pub mod user {
tonic::include_proto!("user");
}
pub mod server;
pub mod client{
tonic::include_proto!("user");
}
main.rs:
use user::server;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing::info!(message = "Started user server");
server::start_server().await?;
Ok(())
}
client.rs:
use user::{UserRequest };
use user::client::{UserClient}; // what should this import be, where does the client et created?
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = UserClient::connect("http://[::1]:50051").await?; // how do I create UserClient
let request = tonic::Request::new(UserRequest {
id: "1".into(),
});
println!("Sending request to gRPC Server...");
let response = client.create_user(request).await?;
println!("RESPONSE={:?}", response);
Ok(())
}
For reference, I’m following:
https://tjtelan.com/blog/lets-build-a-single-binary-grpc-server-client-with-rust-in-2020/
https://blog.logrocket.com/rust-and-grpc-a-complete-guide/
https://dev.to/anshulgoyal15/a-beginners-guide-to-grpc-with-rust-3c7o
Why is the document object unknown. In fact, everything, even the window.document call is not linted. Linting is quite important for me to lean a new programming language/library.
lib.rs
use wasm_bindgen::prelude::*;
#[wasm_bindgen(start)]
pub fn run() -> Result<(), JsValue> {
let window = web_sys::window().expect("could not get window handle");
let document = window.document().expect("could not get document handle");
let body = document.body().expect("could not get body handle");
let val = document.create_element("p")?;
val.set_text_content(Some("Hello from rust"));
body.append_child(&val)?;
Ok(())
}
cargo.toml
[lib]
crate-type = ["cdylib"]
[dependencies]
serde = { version = "1.0", features = ["derive"] }
wasm-bindgen = { version = "0.2", features = ["serde-serialize"] }
[dependencies.web-sys]
version = "0.3.53"
features = [
"Document",
"Element",
"HtmlElement",
"Node",
"Window",
]
I am upgrading tokio-tungstenite from 0.9 to 0.10, which no longer has the peer_addr method. I am dealing with WebSocketStream. I have tried this, which would have worked before:
use tokio_tungstenite::connect_async;
fn main() {
async fn test() {
println!("Hello, world!");
let url = "wss://echo.websocket.org".to_string();
let (ws_stream, ws_response) = connect_async(url).await.unwrap();
let addr = ws_stream.peer_addr();
println!("peer addr {:?}", addr);
}
}
peer_addr() no longer exists and I can see no replacement or instructions on what to do now. I've tried searching the documentation and GitHub.
Cargo.toml:
futures = { version = "0.3" }
tungstenite = {version="0.11.0", features=["tls"] }
tokio-tungstenite = { version="0.10.1", features = ["tls"] }
tokio = {version ="0.2.21", features = [ "full" ] }
url = "2.0"
The documentation on docs.rs is incorrect. If you build the docs locally, you'll see the correct signature of connect_async:
pub async fn connect_async<R>(
request: R
) -> Result<(WebSocketStream<MaybeTlsStream<TcpStream>>, Response), Error>
where
R: IntoClientRequest + Unpin,
You need to get to the TcpStream to get access to the peer address:
use tokio_tungstenite::{connect_async, stream::Stream};
#[tokio::main]
async fn main() {
let (ws_stream, _) = connect_async("wss://echo.websocket.org").await.unwrap();
let tcp_stream = match ws_stream.get_ref() {
Stream::Plain(s) => s,
Stream::Tls(t) => t.get_ref(),
};
let addr = tcp_stream
.peer_addr()
.expect("connected streams should have a peer address");
println!("peer addr {:?}", addr);
}
Cargo.toml:
[dependencies]
tokio-tungstenite = { version = "0.10.1", features = ["tls"] }
tokio = { version = "0.2.21", features = [ "full" ] }
Note that your original Cargo.toml contains two different versions of tungstenite and you really don't want that. See also Why is a trait not implemented for a type that clearly has it implemented?.
I'm trying to use the setup as outlined in the serde_with docs here to deserialize nested json into my struct: https://docs.rs/serde_with/1.4.0/serde_with/json/nested/index.html
After a few tries Cargo.toml file looks like:
[dependencies]
serde = { version = "1.0", features = ["derive"] }
//serde_with = { version = "1.4.0", features = ["..."] } // this doesn't work even though that's what the serde_with README calls for
serde_with = { version = "1.4.0", optional = true }
serde_json = "1.0"
Trying the above I get an error such as:
#[serde(default, rename(deserialize = "Plan"), with="serde_with::json::nested")]
^^^^^^^^^^^^^^^^^^^^^^^^^^ use of undeclared type or module `serde_with`
What am I doing wrong?
In your example the module serde_with is not optional and must provide the feature json.
Replace
serde_with = { version = "1.4.0", optional = true}
with
serde_with = { version = "1.4.0", features = ["json"]}
Full example:
Cargo.toml
[dependencies]
serde = { version = "1.0" }
serde_json = "1.0"
serde_derive = "1.0"
serde_with = { version = "1.4.0", features = ["json"]}
main.rs
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
#[derive(Deserialize, Serialize)]
struct A {
#[serde(with = "serde_with::json::nested")]
other_struct: B,
}
#[derive(Deserialize, Serialize)]
struct B {
value: usize,
}
fn main() {
let v: A = serde_json::from_str(r#"{"other_struct":"{\"value\":5}"}"#).unwrap();
assert_eq!(5, v.other_struct.value);
let x = A {
other_struct: B { value: 10 },
};
assert_eq!(r#"{"other_struct":"{\"value\":10}"}"#, serde_json::to_string(&x).unwrap());
}