❝Верьте в силу веры ❞
Всем привет,яда«Семь, восемь, девять»。
существовать Доизиспользовать Rust строить React Server Components из Web серверяихвыгодаиспользовать ПонятноAxum
строить ПонятноRSC
изсервер。Также расчетдаиспользоватьRust
существоватьстроитьWeb
Служитьначальствоиз Проверьте свои навыки。
ХотяAxum
существоватьRust Web
отвечатьиспользовать Выдающийся среди всех。нода,рынокначальство Также есть много различийизрешение。так,сегодняяих就比较一些 Rust
рамка,Выделите их соответствующие преимущества и недостатки.,помочьяихдля Проект стал мудрымизпринятие решений。Без сравнения нет выбора.,Нам остается только по-настоящему понять преимущества и недостатки каждой кадры и адаптироваться к сцене.,существовать Только в будущем развитии мы сможем иметь безопасный выбор.
в тексте,яих会介绍很多Rust
рамка。и будет следующимизпопулярностьиз В плане порядка。
Ладно, уже поздно, давайте приступим к делу.
❝
❞
Axum[1] да Rust
Имеет особый статус в экосистеме Web Прикладная программа в рамке (это видно по количеству скачиваний). это да Tokio проект[2]изчасть,Tokio
даделатьиспользовать Rust
писать«Асинхронное сетевое приложение использует программу во время выполнения»。Axum
не только использовать Tokio
Поскольку его асинхронная среда выполнения также работает с Tokio
Экосистема из Интеграция других библиотек, выгода от использования Hyper[3] как это HTTP
сервер и Tower[4] в качестве промежуточного программного обеспечения. Делая это, мы можем повторно использовать Tokio
В экосистеме существуют существующие библиотеки и инструменты.
Axum
«Не зависит от макросов»,идавыгодаиспользовать Rust
изсистема типов
Обеспечить безопасность и удобство использованияиз API. Это определяет реализацию базовой абстракции кадра путем создания атрибута use, например Handler
характеристика,использовать В«Определение должно использовать исходную логику программы»。этотдобрыйметодпозволятьяих轻松地「отменьшеизкомпонентысерединакомбинацияотвечатьиспользоватьпрограмма」,Эти компоненты можно использовать в нескольких приложениях.
существовать Axum
середина,иметь дело спрограмма(handler
)даодин«Принять запрос и вернуть ответ»изфункция。этоти Другие бэкэндырамкапохожий,ноделатьиспользовать Axum
из FromRequest
Свойства, мы можем указать тип данных, которые будут извлечены из запроса. Тип возвращаемого значения должен быть реализован. IntoResponse
характеристика(trait
),Уже существует множество типов, реализующих эту функцию.,Включает тип кортежа, который позволяет легко изменять ответ по коду состояния и типу кортежа.
Rust
изсистема типов、Дженерики,особеннодасуществоватьtraits
серединаделатьиспользоватьасинхронный метод(или Более конкретнодавозвращатьсяиз Future
),когда не удовлетворенtrait
Когда ограничено,Rust
из Сообщения об ошибках могут быть сложными。особенныйда При попытке сопоставить абстрактноеtrait
Когда ограничено,Часто вы получаете кучу трудно интерпретируемыхизтекст。дляэтотAxum
поставлять Понятноодин С вспомогательным Макросиз Библиотека,ВоляError размещается там, где действительно произошла ошибка.,Облегчает понимание того, что пошло не так.
ХотяAxum
Делать Понятномного правизиметь значение,может легкозапускатьвыполнять множество задачизотвечатьиспользоватьпрограмма。нода,Есть некоторыеиметь значениенуждатьсяособенный Уведомление。Axum
Версиявсе еще низкий В 1.0
,Это означаетAxum
Команда зарезервированасуществоватьмежду версиями«Принципиально изменить API избесплатно」,Это может вызвать серьезные проблемы с нашим приложением.
Ниже показан WebSocket
иметь дело спрограмма,Он будет повторять любое полученное сообщение.
// #[tokio::main] Макрос с тегами `main` Функция, указывающая, что эта асинхронная программа из `Tokio` должна использовать программу.
#[tokio::main]
async fn main() {
// Впервые создан один `TcpListener` Слушатель, привязанный к адресу "127.0.0.1:3000" начальство
// Затем пройдите `await` Дождитесь завершения привязки прослушивателя
// Если привязка не удалась, она пройдет `unwrap` Метод выдает ошибку.
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
.await
.unwrap();
println!("listening on {}", listener.local_addr().unwrap());
// делатьиспользовать `axum::serve` запускать Axum рамкаизсервер,
// Послушать предыдущее творение из `TcpListener`。
// `app()` функциявозвращатьсяиздаодин `Router`
// Он определяет простой одиниз маршрут, который преобразует путь "/a" Карта для обработки функции `a_handler`。
axum::serve(listener, app()).await.unwrap();
}
// Возврат один `Маршрутизатор`, который имеет только одно правило маршрутизации,
// Воля "/a" путь, сопоставленный с `a_handler` иметь дело сфункция
fn app() -> Router {
Router::new()
.route("/a", get(a_handler))
}
// Один обработчик WebSocket, который будет отображать любое полученное сообщение.
// Определен как один обработчик WebSocket,
// он получает один `WebSocketUpgrade` Параметр, указывающий обновление WebSocket.
async fn a_handler(ws: WebSocketUpgrade) -> Response {
// настраиватьиспользовать ВоляWebSocketПосле обновленияизобъектперешел к `a_handle_socket` иметь дело сфункция。
ws.on_upgrade(a_handle_socket)
}
async fn a_handle_socket(mut socket: WebSocket) {
// делатьиспользовать while let цикл, продолжающийся с WebSocket Получайте сообщения в соединении.
// socket.recv().await Принимать сообщения асинхронно,Возврат один Result,
// в Ok(msg) Указывает, что сообщение было успешно получено.
while let Some(Ok(msg)) = socket.recv().await {
// делатьиспользовать if let Сопоставьте и определите, является ли полученное сообщение да текстовым сообщением.
// Сообщения WebSocket могут быть разных типов, здесь мы имеем дело только с текстовыми сообщениями.
if let Message::Text(msg) = msg {
// структураодинэхо-сообщение,Воляклиентотправлятьизсообщение содержитсуществоватьэхо-сообщениесередина。
// Затем,делатьиспользовать socket.send метод Воляэхо-сообщениеотправлятьразклиент。
// await Дождитесь завершения операции отправки.
if socket
.send(Message::Text(format!("You said: {msg}")))
.await
// исследовать send Операция да Нет возвращает ошибку.
// Если при отправке сообщения произошла ошибка (например, соединение отключено),
// Просто пройди break Выйдите из цикла и завершите функцию обработки.
.is_err()
{
break;
}
}
}
}
Tokio
、Tower
и Hyper
Создайте мощную экосистему.0.x
версию и поэтому может претерпевать существенные изменения.Actix Web[5] да Rust
Существование Zhongde существует уже давно и пользуется большой популярностью. Web рамка№1。как любой хорошийиз Открытый исходный кодпроект Такой же,оно прошло через множество итераций,ноужедостигли Понятноосновная версия
(больше никогдада 0.x
),другими словами:существоватьосновная версия
Внутри,Это гарантирует отсутствие деструктивных изменений.
на первый взгляд,Actix Web
и Rust
серединаиз Другие Web
рамкаочень похоже。яихделатьиспользоватьМакрос
определить HTTP-метод
имаршрутизация
(похожий В Rocket
),иделатьиспользоватьэкстрактор(extractors
)отпроситьсередина Получить данные(похожий В Axum
)。и Axum
по сравнению с,Между ними есть значительное сходство,дажесуществоватьони называют понятияихарактеристикаиз Способначальствотоже очень похоже。максимумизразницада Actix Web
Нет Воля СобственныйиTokio
Экосистемы прочно связаны и существуют вместе. Хотя Tokio
Все еще да Actix Web
Базовая среда выполнения имеет свои собственные абстрактные функции, а также собственный набор crates
экосистема. В этом есть как плюсы, так и минусы. С одной стороны, мы можем убедиться, что все работает хорошо, с другой стороны, мы можем упустить Tokio
Многие функции уже доступны в экосистеме.
Actix Web
Реализовать себя из Service
характеристика,это основнойначальствои Tower
из Service
То же самое, но все еще несовместимо. Это значит существовать Tower
Большая часть доступного промежуточного программного обеспечения в экосистеме существует. Actix
Недоступно в .
еслисуществовать Actix Web
Некоторые специальные задачи необходимо реализовать в , и нам нужно реализовать их самостоятельно. Мы можем столкнуться с запуском кадрасерединаiz. Actor
Модель. Это может вызвать некоторые непредвиденные проблемы.
но Actix Web
Сообщество отличное. Фреймворк поддерживает HTTP/2
и WebSocket
модернизация, предусматривает Web
Самые распространенные задачи в кадризе crates
и Руководство,и отличная документация,ии очень быстро。Actix Web
Изтакпопулярный,да, есть причина,«Если нам нужно гарантировать версию,Обратите внимание, что на данный момент это может быть нашим лучшим вариантом.。
существовать Actix Web
Средний, один простойиз WebSocket
Эхо-сервер выглядит так:
use actix::{Actor, StreamHandler};
use actix_web::{
web,
App,
Error,
HttpRequest,
HttpResponse,
HttpServer
};
use actix_web_actors::ws;
/// Определить HTTP Actor
// один определяется как MyWs из структуры,этот ВоляиспользоватьделатьWebSocketизActix Actor。
// Actors да Actixрамка из модуля параллелизма, использовать для обработки асинхронных сообщений
struct MyWs;
// для MyWs Структура реализована Actor черта, указанная WebsocketContext делатьдляначальствотип контекста。
impl Actor for MyWs {
type Context = ws::WebsocketContext<Self>;
}
/// Обработка сообщения ws::Message из обработчика
// для MyWs Структура реализована StreamHandler черта, обрабатывает сообщения в WebSocketсоединять.
impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for MyWs {
// Обработку полученных сообщений разного типа руководить. Например, для Ping сообщение, отправить Pong информацияделатьдлякольцоотвечать。
fn handle(&mut self, msg: Result<ws::Message, ws::ProtocolError>, ctx: &mut Self::Context) {
match msg {
Ok(ws::Message::Ping(msg)) => ctx.pong(&msg),
Ok(ws::Message::Text(text)) => ctx.text(text),
Ok(ws::Message::Binary(bin)) => ctx.binary(bin),
_ => (),
}
}
}
// один определен для асинхронной обработки HTTP-запросов.
async fn index(req: HttpRequest, stream: web::Payload) -> Result<HttpResponse, Error> {
// ВоляWebSocketсоединятьобновление,И Воляпросить поручено MyWs Actor иметь дело с.
let resp = ws::start(MyWs {}, &req, stream);
println!("{:?}", resp);
resp
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
// Создано один HttpServer например, через App::new() Создать одинотвечатьиспользовать,// Здесь следует использовать только один маршрут,Воляпуть "/ws/" Карта для обработки функции index начальство。
HttpServer::new(|| App::new().route("/ws/", web::get().to(index)))
// Привязать сервер к адресу "127.0.0.1" и порт 8080。
.bind(("127.0.0.1", 8080))?
// запускатьсервери Подождите, пока он завершит работу。
.run()
.await
}
Actor
Модель.Rocket[6] существовать Rust Web
Уже некоторое время находится в экосистеме рамок: это основные функции основеМакросизмаршрутизация
、Встроенные формы
иметь дело с、к данным Библиотекаи Управление статусамиизподдерживать,и его Собственный Версияизшаблон!Rocket
Делайте все возможное, чтобы построить один Web Все необходимое для программы должно быть включено.
Однако,Rocket
Амбиции также сопряжены с некоторыми издержками. Несмотря на то, что он все еще находится в активной разработке, выпуски выходят не так часто, как раньше. Это значит, что пользователи «рамазиспользовать» упустят много важного.
также,Благодаря комплексному подходу,яихвозвращатьсянуждаться Понятноразвязать Rocket
извыполнить Способ。Rocket
отвечатьиспользоватьпрограммаиметьодин"жизненный цикл",Строительные блоки особым образом,если что-то пойдет не так,Нам нужно понять, в чем заключается проблема.
Rocket
даодин — отличная израмка, если мы хотим начать использовать Rust
руководить Web развивать,этодаодиночень хорошийизвыбирать。«Для многих из нас,Rocket
даэнтер Rust
«Первый шаг»,Пусть это будет по-прежнему весело.
иметь дело сформаиз Rocket
Процедуру следует упростить:
// один определяется как Password из структуры, которая выводит Debug и FromForm traits。
// FromForm trait use используется для извлечения данных из данных формы.
// Эта структура содержит два поля first и второй соответственно представляет собой вторую часть пароля из одини.
#[derive(Debug, FromForm)]
struct Password<'v> {
// Представляет пару полейиздлинаруководить Понятнопроверять,Требоватьдлинасуществовать6символы, начинающиеся сначальство
#[field(validate = len(6..))]
// Указывает, что одно поле должно быть равно второму полю.
#[field(validate = eq(self.second))]
first: &'v str,
// Указывает, что второе поле должно быть равно одиночному полю.
#[field(validate = eq(self.first))]
second: &'v str,
}
// Опустите другие структуры и реализуйте...
// one обрабатывает запросы GET для определенной функции index,Возврат один Template объект.
// Эта функцияиспользовать используется для отображения домашней страницы.
#[get("/")]
fn index() -> Template {
Template::render("index", &Context::default())
}
// one обрабатывает POST-запросы из-за определенной функции submit。
// Эта функция принимает один Form объект,в Включать Понятноформаизданные
#[post("/", data = "<form>")]
fn submit(form: Form<Submit<'_>>) -> (Status, Template) {
// проходитьисследовать form.value да Содержит ли он Some(ref submission) Чтобы определить, отправлена ли форма.
let template = match form.value {
// Если форма отправлена, распечатайте отправленное содержимое и отобразите его. "success" страница;
Some(ref submission) => {
println!("submission: {:#?}", submission);
Template::render("success", &form.context)
}
// В противном случае визуализируйте "index" страница.
None => Template::render("index", &form.context),
};
(form.context.status(), template)
}
// определение ПонятнозапускатьRocketотвечатьиспользоватьпрограммаизфункция。
#[launch]
fn rocket() -> _ {
// делатьиспользовать rocket::build() Создать экземпляр приложения OneRocket, использовать экземпляр программы
rocket::build()
// и пройти .mount() Способ монтирования маршрутов.
// routes![index, submit] Определены два маршрута,
// соответственно сопоставлено с index и submit функция。
.mount("/", routes![index, submit])
// Добавлена обработка одного шаблона изFairing (изmiddleware в Rocket)
.attach(Template::fairing())
// Волястатические файлы Служитьмонтировать накореньпуть。
.mount("/", FileServer::from(relative!("/static")))
}
Warp[7] даодинстроитьсуществовать Tokio
Изначальствоиз Web Рамка, даодин, очень хорошее израмка. Он сильно отличается от других, которые мы видели раньше.
Warp
и Axum
Есть что-то общее из Функции: она строит существование. Tokio
и Hyper
выше и использовал Tower
серединапромежуточное программное обеспечение。Однако,этосуществоватьметодначальство Существует большойиздругой。Warp
да Учреждатьсуществовать Filter
trait Изначальствоиз。
существовать Warp
середина,яихстроитьсерияотвечатьиспользовать Ввходящийпроситьизфильтр
,и Воляпроситьпередается в трубу, пока не будет достигнут конец。фильтр Могу связать,Их можно комбинировать. Это позволяет нам строить очень сложные трубопроводы.,но все равно легко понять.
Warp
также, чем Axum
ближе Tokio
Экосистема, а это означает, что мы сможем справиться с большим количеством ситуаций без каких-либо обязательных свойств. Tokio
Структура и концепция.
Warp
Выбиратьиспользовать Очень функциональныйизметод,Если это стиль программирования,яих Волянравиться Warp
из Выразительные способности и Композиционность. когда мы просматриваем Warp
Фрагмент кода обычно читается как существование именно того, что произошло из истории, что существует Rust
То, чего можно достичь в да, интересно и удивительно.
Однако,Благодаря этим различным функциям фильтры связаны друг с другом.,Warp
серединаиз Типы становятся очень длинными и очень сложными.,И сложно понять. То же самое касается сообщения об ошибке,Да может быть трудно понять из-за большого объема текста.
Warp
даодин великолепен.,это«Это не самый подходящий вариант для новичков и не самый популярный»。этотиметь в видуяих可能существоватьищу помощии Ресурсы будут сложнее。ноэто Очень«Подходит для быстрых небольших приложений»!
Со склада Примериз WebSocket Чат из Warp Процедуру следует упростить:
// определен одинстатикизированный атом usize прилавок,использовать Вдлякаждыйсоединятьизиспользовать Распределение счетов уникальноизиспользоватьсемьяID。
static NEXT_USER_ID: AtomicUsize = AtomicUsize::new(1);
// текущийсоединятьиспользоватьсемьяизсостояние。
// определен один псевдоним типа Пользователи, это даодин атомарный кавычек использовать счетчик нечитаемой блокировки записи HashMap,ВоляиспользоватьсемьяIDкарта к сообщениюизотправлятьустройство。
// Arc ссылка на даатом использует счетчик интеллектуальных указателей, RwLock да блокировка чтения-записи.
// - идентификатор ключа
// - Значение da`warp::ws::Message`изsender
type Users = Arc<RwLock<HashMap<usize, mpsc::UnboundedSender<Message>>>>;
#[tokio::main]
async fn main() {
// Создано один users Переменная,use используется для хранения информации о пользователе.
let users = Users::default();
// Воляит упакован как Warp Фильтруйте так, чтобы различные маршруты существовали совместно с использованием статуса пользователя.
let users = warp::any().map(move || users.clone());
// chat обработка маршрутизации WebSocket рукопожатие
let chat = warp::path("chat")
// `ws()`фильтр Воля ПодготовитьWebSocketрукопожатие...
.and(warp::ws())
.and(users)
// настраиватьиспользовать user_connected функцияиметь дело с WebSocket соединять。
.map(|ws: warp::ws::Ws, users| {
// еслирукопожатиеуспех,Волянастраиватьиспользоватьяихизфункция。
ws.on_upgrade(move |socket| user_connected(socket, users))
});
// иметь дело с HTTP GET просить,Возврат один Содержит ссылку на чат HTML страница
let index = warp::path::end().map(|| warp::reply::html(INDEX_HTML));
let routes = index.or(chat);
warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
}
async fn user_connected(ws: WebSocket, users: Users) {
// делатьиспользоватьприлавокдляэтотиспользоватьсемьявыделить новыеизтолькоID。
let my_id = NEXT_USER_ID.fetch_add(1, Ordering::Relaxed);
eprintln!("new chat user: {}", my_id);
// Воляраскол розеткидляинформацияизотправлятьустройствоиполучатель。
let (mut user_ws_tx, mut user_ws_rx) = ws.split();
// Создать новый канал сообщений (mpsc::unbounded_channel) использовать ВВоляиспользоватьсемьяизинформация Трансляция другимиспользоватьсемья
let (tx, rx) = mpsc::unbounded_channel();
let mut rx = UnboundedReceiverStream::new(rx);
tokio::task::spawn(async move {
// Постоянно получать сообщения. Этот цикл будет завершен, как только пользователь отключится.
while let Some(message) = rx.next().await {
user_ws_tx
.send(message)
.unwrap_or_else(|e| {
eprintln!("websocket send error: {}", e);
})
.await;
}
});
//Воляотправлятьустройстводержатьсуществоватьяихизужесоединятьиспользоватьсемьясписоксередина。
users.write().await.insert(my_id, tx);
// Возврат одинбазовыйначальстводауправлятьэтотидентификацияиспользоватьсемьясоединятьизсостояниемашинаиз“Future”。
// в любое времяиспользоватьсемьяотправлятьинформациячас,Воляитс транслирует на
// Все остальные используют домохозяйства...
while let Some(result) = user_ws_rx.next().await {
let msg = match result {
Ok(msg) => msg,
Err(e) => {
eprintln!("websocket error(uid={}): {}", my_id, e);
break;
}
};
user_message(my_id, msg, &users).await;
}
// если бы толькоиспользоватьсемья Держатьсоединять,Поток user_ws_rx будет продолжаться дело с.Как только они отключатсоединять,Так...
user_disconnected(my_id, &users).await;
}
// иметь дело сиспользоватьсемьяотправлятьизинформация。этопропустить нетекстинформация,Волятекстинформацияформатдля <User#ID>: Message,Затем Воляитс транслирует навседругойиспользоватьсемья。
async fn user_message(my_id: usize, msg: Message, users: &Users) {
// Пропускать любые нетекстовые сообщения...
let msg = if let Ok(s) = msg.to_str() {
s
} else {
return;
};
let new_msg = format!("<User#{}>: {}", my_id, msg);
// Приходитьсэтотиспользоватьсемьяизновыйинформация,Воля Чтоотправлять Даватьвседругойиспользоватьсемья(удалять Понятнотакой жеизuid)...
for (&uid, tx) in users.read().await.iter() {
if my_id != uid {
if let Err(_disconnected) = tx.send(Message::text(new_msg.clone())) {
// Передатчик был отключен для подключения, мы ввели код `user_disconnected`
// Если будет выполнена еще одна миссия, делать здесь больше нечего.
}
}
}
}
async fn user_disconnected(my_id: usize, users: &Users) {
eprintln!("good bye user: {}", my_id);
// Поток закрыт и поэтому удален из списка пользователей.
users.write().await.remove(&my_id);
}
Tokio
、Tower
и Hyper
Создайте мощную экосистему.Tide[8] даодин Учреждатьсуществовать async-std
运行час Изначальствоиз«Минималистический веб-фреймворк»。минимализмизметодиметь в видуяих得приезжать Понятноодиночень маленькийиз API поверхность。Tide
серединаизиметь дело сфункцияда async fn
,приниматьодин Request
и Возврат один Response
из tide::Result
。Извлечение данныхилиотправлятьправильныйизкольцоотвечать Отформатированояихс行完成。
Хотя для нас это может быть больше работы,но это также более прямолинейно,Это значит, что мы имеем полный контроль над происходящим. существуют в некоторых случаях,в состоянии уйти HTTP проситьикольцоотвечатьнравитьсяэтотзакрыватьдаудовольствие,Облегчает задачу.
Tide
из метода Middleware и начнем с Tower
Похоже на китайское слово из, но Tide
Опубликовано async trait
crate, что упрощает реализацию.
Со склада Примеризиспользоватьсемьясессия Пример:
// async-std crate Обеспечить асинхронный main функция。это Возврат один Результат, указывающий на возможную ошибку.
#[async_std::main]
async fn main() -> Result<(), std::io::Error> {
// делатьиспользовать femme crate Кай использовать цветной журнал. Эта даодинизированная библиотека журналирования делает вывод журнала более читабельным.
femme::start();
// Создать один Tide Пример приложения
let mut app = tide::new();
// Добавлено одно промежуточное программное обеспечение для журнала, позволяющее записывать запросы и ответы из информации журнала.
app.with(tide::log::LogMiddleware::new());
// добавить водинсессиясерединапромежуточное программное обеспечение,использовать Виметь дело сданные сеанса。этотвнутриделатьиспользовать Внутрижитьхранилище,и предоставьте один ключ (TIDE_SECRET),использовать для шифрования и проверки данных сеанса.
app.with(tide::sessions::SessionMiddleware::new(
tide::sessions::MemoryStore::new(),
std::env::var("TIDE_SECRET")
.ожидать(
«Пожалуйста, укажите значение TIDE_SECRET в \
не менее 32 байтов для запуска этого примера",
)
.as_bytes(),
));
// Добавляем один перед промежуточным программным обеспечением,этосуществоватьиметь дело спросить Доосуществлять。существоватьэтотвнутри,Ituse используется для увеличения количества посещений,хранилищесуществоватьсессиясередина。
app.with(tide::utils::Before(
|mut request: tide::Request<()>| async move {
let session = request.session_mut();
let visits: usize = session.get("visits").unwrap_or_default();
session.insert("visits", visits + 1).unwrap();
request
},
));
// определение Понятноодиниметь дело скорень Путь из запроса GET из маршрута. Этот маршрут проходит async move Приходитьиметь дело спросить,Получить количество доступов в сеансе,и Возврат один содержит количество посещений из строки.
app.at("/").get(|req: tide::Request<()>| async move {
let visits: usize = req.session().get("visits").unwrap();
Ok(format!("you have visited this website {} times", visits))
});
// определение Понятноодиниметь дело с "/reset" Путь из запроса GET из маршрута. Этот маршрут проходит async move иметь дело спросить,Воляданные сеанса清удалять,Затемперенаправить накореньпуть
app.at("/reset")
.get(|mut req: tide::Request<()>| async move {
req.session_mut().destroy();
Ok(tide::Redirect::new("/"))
});
// запускатьотвечатьиспользоватьпрограммаимониторсуществовать "127.0.0.1:8080" адресначальство。делатьиспользовать await? иметь дело возможно неправильно иззапускаю.
app.listen("127.0.0.1:8080").await?;
Ok(())
}
async-std
время выполнения.Poem[9] Утверждает, что он полностью функционален, но прост в использовании. Web рамка. На первый взгляд, это дает возможность использовать Axum
очень похоже,толькоизразницадаэтонуждатьсяделатьиспользовать Взаимноотвечатьиз Макросотметкаиметь дело спрограммафункция。этовозвращаться Учреждатьсуществовать Tokio
и Hyper
выше, полностью совместим с Tower
промежуточное программное обеспечение, но при этом подвергается воздействию функций промежуточного программного обеспечения.
Poem
изсерединапромежуточное программное обеспечениехарактеристика也Очень Простойлегкийиспользовать。яих可以直接длявсеилиидентификацияиз Endpoint
(Poem Выразите, что со всем можно справиться HTTP Метод запроса) для реализации этой возможности автору достаточно написать один Accept Endpoint
делатьдляпараметризасинхронныйфункция。
Poem
Он не только совместим со многими функциями более широкой экосистемы, но также обладает богатыми функциональными возможностями, включая поддержку OpenAPI
и Swagger
Документация и полная поддержка. это не ограничивается основе HTTP
из Web услуги также можно использовать на основе Tonic
из gRPC
Служить,дажесуществовать Lambda
функционировать без переключения кадров. добавить пару OpenTelemetry
、Redis
、Prometheus
Как только из будет поддерживаться, мы сможем проверить все современные корпоративные приложения. Web оформить все коробки.
Poem
все еще в 0.x
версию, но если вы сохраните темп и добьетесь отличных результатов 1.0 Версия,этот Волядаодинценностьсосредоточиться наизрамка!
Со склада Примериз WebSocket Чат изаббревиатура Версия:
// 注развязать表示этотдаодиниметь дело сустройствофункция,использовать Виметь дело с WebSocket просить
#[handler]
fn ws(
// Извлечено WebSocket параметр isname в пути
Path(name): Path<String>,
// WebSocket объект, представление и клиент изоединять
ws: WebSocket,
// даодин экстрактор данных, используемый для получения канала вещания с передатчика.
sender: Data<&tokio::sync::broadcast::Sender<String>>,
) -> impl IntoResponse {
// Клонировать канал вещания из передатчика sender。
let sender = sender.clone();
// этоподписка Понятновещательный канал,Создано одинполучатель receiver
let mut receiver = sender.subscribe();
// иметь дело с WebSocket соединятьобновление ws.on_upgrade(move |socket| async move {
// Волясоединятьиз разделения чтения и письма для sink и stream
let (mut sink, mut stream) = socket.split();
// от WebSocket Клиент получает сообщение
// еслидатекстинформация,Потом Воля его форматировал под {name}: {text} изформа,и пройтивещательный каналотправлять。
// Если отправка не удалась (например, канал закрыт), задача завершается.
tokio::spawn(async move {
while let Some(Ok(msg)) = stream.next().await {
if let Message::Text(text) = msg {
if sender.send(format!("{name}: {text}")).is_err() {
break;
}
}
}
});
// отвещательный канал接收информация,и Воля Чтоотправлятьприезжать WebSocket клиент
tokio::spawn(async move {
while let Ok(msg) = receiver.recv().await {
if sink.send(Message::Text(msg)).await.is_err() {
break;
}
}
});
})
}
#[tokio::main]
async fn main() -> Result<(), std::io::Error> {
// делатьиспользовать tide::Route Создано одинмаршрутизация,ввключает в себя двапуть:
// - / путьиметь дело с HTTP GET просить,настраиватьиспользовать index функция。
// - /ws/:name путьиметь дело с WebSocket просить,настраиватьиспользовать ws функция。
let app = Route::new().at("/", get(index)).at(
"/ws/:name",
// проходить tokio::sync::broadcast::channel Создать один канал вещания;
// и пройти tokio::sync::broadcast::channel::<String>(32).0
// 获取Чтоотправлятьустройство,Воля Чтоделатьдляданные передаются в ws иметь дело сфункция
get(ws.data(tokio::sync::broadcast::channel::<String>(32).0)),
);
// Создано одинсервер Примеры
Server::new(TcpListener::bind("127.0.0.1:3000"))
// запускатьсервер,и дождитесь завершения работы.
.run(приложение)
.жду
}
как мы видим,Rust Web
Мир рамкииз очень разнообразен. Не существует единого решения, подходящего для всех ситуаций, нам нужно выбрать то, которое лучше всего соответствует нашим потребностям. Если мы только начинаем, я предлагаю выбрать Actix
или Axum
,потому чтодляэтоихдабольшинствоподходящий Подходит для начинающихизрамка,ииэтоихиметь着Отличная документация.
«Поделитесь своим мнением»。
«Весь текст окончен,Теперь, когда вы это увидели,Если ты чувствуешь себя хорошо,Смело ставьте лайк и «существовать к просмотру». "
[1]
Axum: https://github.com/tokio-rs/axum
[2]
Проект Токио: https://tokio.rs/
[3]
Hyper: https://hyper.rs/
[4]
Tower: https://docs.rs/tower/0.4.13/tower/
[5]
Actix Web: https://actix.rs/
[6]
Rocket: https://rocket.rs/
[7]
Warp: https://github.com/seanmonstar/warp
[8]
Tide: https://github.com/http-rs/tide
[9]
Poem: https://github.com/poem-web/poem