- ache,
Coucou,
J’essaye de me mettre au Rust. Je tente des petits trucs de temps en temps.
Là, j’essaye de faire un serveur HTTP léger et rapide. J’essaye d’utiliser "hyper" et un système de template "handlebars".
J’ai un problème que je ne comprend pas trop. Pour l’instant j’ai ce code là :
extern crate futures;
extern crate hyper;
extern crate handlebars;
use std::collections::BTreeMap;
use std::fs::File;
use std::io::prelude::*;
use handlebars::Handlebars;
use futures::Future;
use hyper::{Body, Response, Server};
use hyper::service::service_fn_ok;
fn main() {
let addr = "127.0.0.1:2337".parse().unwrap();
let service = || {
service_fn_ok(|_| {
let mut handlebars = Handlebars::new();
let mut file = File::open("test.html").ok().expect("");
let mut contents = String::new();
file.read_to_string(&mut contents);
assert!(handlebars.register_template_string("main", contents).is_ok());
let handlebars = handlebars;
let mut data = BTreeMap::new();
data.insert("title".to_string(), "Super micro service !");
Response::new(Body::from(handlebars.render("main", &data).unwrap()))
})
};
let server = Server::bind(&addr)
.serve(service)
.map_err(|e| eprintln!("Error: {}", e));
hyper::rt::run(server);
}
Mais là, je crée un objet handelbars
à chaque requête alors que le fichier est toujours le même (les données varient parfois, mais là même pas).
Du coup, j’ai essayé de sortir l’allocation de handlebars hors de la closure…
extern crate futures;
extern crate hyper;
extern crate handlebars;
use std::collections::BTreeMap;
use std::fs::File;
use std::io::prelude::*;
use handlebars::Handlebars;
use futures::Future;
use hyper::{Body, Response, Server};
use hyper::service::service_fn_ok;
fn main() {
let addr = "127.0.0.1:2337".parse().unwrap();
let mut handlebars = Handlebars::new();
let mut file = File::open("test.html").ok().expect("");
let mut contents = String::new();
file.read_to_string(&mut contents);
assert!(handlebars.register_template_string("main", contents).is_ok());
let handlebars = handlebars;
let service = || {
service_fn_ok(|_| {
let mut data = BTreeMap::new();
data.insert("title".to_string(), "Super micro service !");
Response::new(Body::from(handlebars.render("main", &data).unwrap()))
})
};
let server = Server::bind(&addr)
.serve(service)
.map_err(|e| eprintln!("Error: {}", e));
hyper::rt::run(server);
}
Mais j’ai cette erreur :
error[E0597]: `handlebars` does not live long enough
--> src/main.rs:29:38
|
24 | let service = || {
| -- value captured here
25 | / service_fn_ok(|_| {
26 | | let mut data = BTreeMap::new();
27 | | data.insert("title".to_string(), "Super micro service !");
28 | |
29 | | Response::new(Body::from(handlebars.render("main", &data).unwrap()))
| | ^^^^^^^^^^ borrowed value does not live long enough
30 | | })
| |__________- returning this value requires that `handlebars` is borrowed for `'static`
...
39 | }
| - `handlebars` dropped here while still borrowed
Ce que je ne comprend pas c’est que justement handlebars
a déjà la plus grosse portée possible, elle est dans la fonction main ! Plus grosses que ça, c’est globale hors de toute fonction (j’ai jamais essayé mais ce n’est pas ce que je souhaite ici).
Bref, il y a quelque chose qui m’échappe ici. La première closure « emprunte » la variable handlerbars
et donc la seconde closure n’est pas capable de l’emprunter à nouveau ?
J’ai bien cet exemple pour m’aider. Mais Registrery
(le type de handlebars) n’implémente pas le traie Copy.
Bref, je suis un peu perdu, si quelqu’un à une idée de comment mettre en cache handlebars
pour toutes les connections. (Sachant que si je place l’allocation dans la première closure ça compile mais par-contre, l’allocation se fait à chaque connexion. Ce qui concrètement m’est très peu utile1).
Merci d’avance !
-
Ça me permet de faire
↩curl localhost:2337 localhost:2337
, mais concrètement, je vais souvent fermer puis réouvrir la connexion.