📜 ⬆️ ⬇️

Create a REST service on Rust. Part 4: go to the REST API

Last time we implemented the update database.

It remains to make only the REST interface. Let's do this.

Introduction


This part will be, perhaps, the most difficult - we will closely know the types of Send and Sync, as well as the subtleties of work closures and lifetimes. In a different way, I would headline her “bore explores why data must be cloned.” It is useful in that it affects the thin spots of the Rust and shows the causes of some unobvious errors. So if you want to understand thoroughly - welcome.
')
I also want to note: if something is incomprehensible to you regarding the above code or the explanations themselves seem not to be clear enough, feel free to write about it in the comments. The author spent not a minute and not half an hour, trying to understand why the code works exactly in the form in which it was written, and had to go to the IRC and the forum for explanations more than once.

Review code in general


In principle, we want to add a new command that will launch a web server that provides the REST API of our phone book service. We need to provide access points standard for CRUD : GET records, GET records / id, POST records, PUT records / id and DELETE records / id. To do this, we will use the router from the iron framework. Here is the code:

Command add code
"serve" => { let sdb = Arc::new(Mutex::new(db)); let mut router = router::Router::new(); { let sdb_ = sdb.clone(); router.get("/api/v1/records", move |req: &mut Request| handlers::get_records(sdb_.clone(), req)); } { let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); } { let sdb_ = sdb.clone(); router.post("/api/v1/records", move |req: &mut Request| handlers::add_record(sdb_.clone(), req)); } { let sdb_ = sdb.clone(); router.put("/api/v1/records/:id", move |req: &mut Request| handlers::update_record(sdb_.clone(), req)); } { let sdb_ = sdb.clone(); router.delete("/api/v1/records/:id", move |req: &mut Request| handlers::delete_record(sdb_.clone(), req)); } Iron::new(router).http("localhost:3000").unwrap(); } 


This option works, but it looks pretty poor. There are several ways to make it better, but first we will deal with what is happening here. And rewrite it in the next section. The implementation of the handlers will also be reviewed another time.

Wrapping database


In the above code, from the second line, something new:

  let sdb = Arc::new(Mutex::new(db)); 

db here is postgres :: Connection , i.e. the object through which all the work with this database goes.
We wrap it in a mutex, and we put the mutex in the atomic reference counter.

What for? For now, just remember that we want to provide synchronized access to the database from many threads - for this we use a mutex. And in order to share the ownership of the object between several threads, we use the reference counter - the threads die at different moments, and the database will be destroyed when no one needs it anymore.

This restriction is a consequence of the architecture of Iron. A web server can process several requests in parallel, in several threads.

Defining API paths


Next, we define the path for GET requests:

  let mut router = router::Router::new(); { let sdb_ = sdb.clone(); router.get("/api/v1/records", move |req: &mut Request| handlers::get_records(sdb_.clone(), req)); } 

For this we use Router :: get () . This method accepts the glob-pattern of the path (in this case, the entire path is specified rigidly, without variable components) and the request handler for this path.

Description Handler


A handler is any type that implements the Handler type. This type looks relatively simple:

 pub trait Handler: Send + Sync + Any { fn handle(&self, &mut Request) -> IronResult<Response>; } 

Only one method is a handle that accepts a variable reference to the request and returns an HTTP response wrapped in IronResult.

IronResult is a normal Result, in which errors are specialized for Iron itself:

 type IronResult<T> = Result<T, IronError>; pub struct IronError { ... } 

Now let's look at the definition of the type itself:

 pub trait Handler: Send + Sync + Any { 

This code we have not seen. But only one part of the definition is new here: Send + Sync + Any.

This record means that the implementation of the type Handler requires the implementation of the types Send, Sync and Any. So we met with the pillar of Rust: Send and Sync. Any time we are not interested.

Send and Sync


Let's start with sync.

Values ​​that implement Sync can be safely changed from multiple threads simultaneously - i.e. there is no data race.

For example, std :: sync :: atomic :: AtomicIsize is an atomic access integer. This type implements Sync, so we can do AtomicIsize :: fetch_add from multiple threads.

Further information about Sync is here .

Please note that the possibility of synchronized access does not imply the possibility of transferring ownership of the value to another thread. A type that implements Sync does not necessarily implement Send.

Now more about Send . This is a type marker implemented for types that can be safely transferred to other threads. For example, a raw pointer cannot be passed:

 impl<T> !Send for *const T 

! Send here means "type is not implemented."

Why do you need such a record? Then, that Send is implemented for all types by default, if Send is implemented for their component parts. The structure, all fields of which Send, is also Send (the same applies to Sync). Types that are clearly insecure should “unsubscribe” from the implementation of this type.

The absence of Send (and Sync) is also distributed recursively - so if you use a type that does not implement Send inside, your default type will not implement it either.

std :: sync :: atomic :: AtomicPtr can already be transferred to other threads:

 impl<T> Send for AtomicPtr<T> 

At the household level, this means that the value can be given to another thread - for example, when running thread :: spawn . However, this does not mean that access from many threads is synchronized. Send says only that the type must be moved to a memory accessible by another thread.

Send and Sync often go hand in hand - types that implement one type implement the other simultaneously. So, the above-mentioned AtomicPtr is a wrapper over atomic hardware operations, and because of this, it allows not only to transfer the value to another stream, but also to implement secure simultaneous access to the content. AtomicPtr is synchronized - it also implements Sync.

std :: sync :: mpsc :: Sender can also be passed to other threads:

 impl<T: Send> Send for Sender<T> 

However, Sender is a good example of the fact that a type can be sent to another stream, but it is not synchronized. This is the structure that implements the sending side of the channel - there is the corresponding structure Receiver. So, Sender can be transferred to the sending stream after creating a channel, but access to one Sender from many streams is denied.

The <T: Send> record says that for data sent over the channel, the type Send should be implemented. It is logical that in order for the data to be transmitted over the channel, they must be transferred to another stream in principle .

Read more about the Send type here .

Excellent, with types like sort out.

Why we wrapped the database


Take a look at our Arc and Mutex again:

 impl<T> Send for Arc<T> where T: Send + Sync + ?Sized impl<T> Sync for Arc<T> where T: Send + Sync + ?Sized impl<T: ?Sized + Send> Send for Mutex<T> impl<T: ?Sized + Send> Sync for Mutex<T> 

That's why we wrapped db into a mutex: it makes the nested Send and Sync data synchronized and sent to another stream. Only such data can be put in Arc. Arc itself is again synchronized and can be transferred to another stream.

? Sized while we are unfamiliar - consider it another time.

Closures


Now look at our code again. Here he is:

  let sdb = Arc::new(Mutex::new(db)); let mut router = router::Router::new(); { let sdb_ = sdb.clone(); router.get("/api/v1/records", move |req: &mut Request| handlers::get_records(sdb_.clone(), req)); } 

The second argument .get () is a closure. Consider it separately:

  move |req: &mut Request| handlers::get_records(sdb_.clone(), req)); 

Let's start with the arguments - they are inside the vertical lines. We take one argument req, which is a variable reference to the request. We have such arguments, because, as you remember, Iron's Handler must have a signature

 fn handle(&self, &mut Request) -> IronResult<Response>; 

The body of the closure simply makes the call to handlers :: get_records. To this function, we pass the closure argument and a copy of our Arc <Mutex> as part of the environment.

Why copy? Now will be the most interesting.

Let's try not to clone data


To understand this, let's think about what would happen if we passed not a copy to the closure, but sdb_ itself. Like this:

  { let sdb_ = sdb.clone(); router.get("/api/v1/records", move |req: &mut Request| handlers::get_records(sdb_, req)); } 

What does rustc say to this?

 main.rs:120:32: 122: 69 error: the trait `for <'r,' r, 'r> core :: ops :: Fn <(&' r mut iron :: request :: Request <'r , 'r>,)> `not for the type of [closure@main.rs: 121: 36: 122: 68 sdb_: alloc :: arc :: Arc <std :: sync :: mutex :: Mutex < postgres :: Connection >>] `[E0277]
 main.rs:120 router.get ("/ api / v1 / records",
 main.rs:121 move | req: & mut Request |
 main.rs:122 handlers :: get_records (sdb_, req));
 main.rs:120:32: 122: 69 help: run `rustc --explain E0277` to see a detailed explanation

It can be seen, he is very unhappy.

What is the essence of the error? The type Fn (& mut Request,) is not implemented for our closure. What is this type?

Features of the implementation of closures


This is a type implemented for closures that can be called multiple times. Why is it important to know how many times a closure will be caused? Because if you move possession of something from a closure, you can only do it once. Next time there will be no place to move ownership. In this case, your closure implements FnOnce, but not Fn. In our code, we move a copy of sdb_ to the handler itself — handlers :: get_records, since he accepts Arc<Mutex> . , .

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .
   Arc<Mutex>  .       ,    . 

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .
Arc<Mutex> . , .

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .

Arc<Mutex> . , .

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .

Arc<Mutex> . , .

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .
   Arc<Mutex>  .       ,    . 

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .
Arc<Mutex> . , .

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .

Arc<Mutex> . , .

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .

Arc<Mutex> . , .

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .
   Arc<Mutex>  .       ,    . 

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .
Arc<Mutex> . , .

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .
   Arc<Mutex>  .       ,    . 

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .
Arc<Mutex> . , .

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .
   Arc<Mutex>  .       ,    . 

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .
Arc<Mutex> . , .

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .
   Arc<Mutex>  .       ,    . 

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .
Arc<Mutex> . , .

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .

Arc<Mutex> . , .

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .

Arc<Mutex> . , .

, ? Rust |x| x + 1 - . - , . .

Fn? , Handler Iron' Fn:

impl<F> Handler for F where F: Send + Sync + Any + Fn(&mut Request) -> IronResult<Response> { fn handle(&self, req: &mut Request) -> IronResult<Response> { (*self)(req) } }

where - . , F, Send + Sync + Any + Fn(&mut Request) -> IronResult.

, Handler Fn. Iron, , : - , .

Rust! .


- move . move , , . move :

main.rs:121:36: 122:76 error: closure may outlive the current function, but it borrows `sdb_`, which is owned by the current function [E0373] main.rs:121 |req: &mut Request| main.rs:122 handlers::get_records(sdb_.clone(), req)); main.rs:121:36: 122:76 help: run `rustc --explain E0373` to see a detailed explanation main.rs:122:58: 122:62 note: `sdb_` is borrowed here main.rs:122 handlers::get_records(sdb_.clone(), req)); ^~~~ main.rs:121:36: 122:76 help: to force the closure to take ownership of `sdb_` (and any other referenced variables), use the `move` keyword, as shown: main.rs: move |req: &mut Request| main.rs: handlers::get_records(sdb_.clone(), req)); error: aborting due to previous error
sdb_, main - Iron . , , , - main, .

Rust . .


: sdb ?

let sdb_ = sdb.clone();
:

main.rs:125:36: 125:39 error: use of moved value: `sdb` [E0382] main.rs:125 let sdb_ = sdb.clone(); ^~~ main.rs:125:36: 125:39 help: run `rustc --explain E0382` to see a detailed explanation main.rs:119:29: 119:33 note: `sdb` moved here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<postgres::Connection>>`, which is moved by default main.rs:119 let sdb_ = sdb; ^~~~
. , , GET/id:

{ let sdb_ = sdb.clone(); router.get("/api/v1/records/:id", move |req: &mut Request| handlers::get_record(sdb_.clone(), req)); }
:id, Router', URL , .

HTTP- Router' :

Iron::new(router).http("localhost:3000").unwrap();


? ! , Rust. , - Mutex Arc.

- .

Source: https://habr.com/ru/post/268617/


All Articles