{"id":463069,"date":"2025-06-12T15:00:34","date_gmt":"2025-06-12T15:00:34","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=463069"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=463069","title":{"rendered":"<span>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432 hyper: \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><code>hyper<\/code> &#8212; \u044d\u0442\u043e \u043d\u0438\u0437\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u0430\u044f HTTP-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043d\u0430 Rust. \u041e\u0431\u044b\u0447\u043d\u043e \u043e\u043d\u0430 \u0441\u043b\u0443\u0436\u0438\u0442 \u0441\u0442\u0440\u043e\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0431\u043b\u043e\u043a\u043e\u043c \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0432\u044b\u0441\u043e\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a <a href=\"https:\/\/crates.io\/crates\/axum\" rel=\"noopener noreferrer nofollow\"><code>axum<\/code><\/a>, <a href=\"https:\/\/crates.io\/crates\/tonic\" rel=\"noopener noreferrer nofollow\"><code>tonic<\/code><\/a>, <a href=\"https:\/\/crates.io\/crates\/reqwest\" rel=\"noopener noreferrer nofollow\"><code>reqwest<\/code><\/a> \u0438 \u0434\u0440\u0443\u0433\u0438\u0445. \u041d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u0437\u043d\u0430\u043d\u0438\u0435 <code>hyper<\/code> \u043c\u043e\u0433\u0443\u0442 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c \u0432 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u044f\u0445.<\/p>\n<p> <code>hyper<\/code> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 api \u043a\u0430\u043a \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u0442\u0430\u043a \u0438 \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043d\u043e \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u043c\u0441\u044f \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438.<\/p>\n<h2>\u041f\u0435\u0440\u0432\u044b\u0439 &#171;Hello, World!&#187;<\/h2>\n<p>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442:<\/p>\n<pre><code>cargo new hyper-server<\/code><\/pre>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 <code>Cargo.toml<\/code>:<\/p>\n<pre><code>[dependencies] hyper = { version = \"1.6.0\", features = [\"server\", \"http1\"] }      hyper-util = { version = \"0.1\", features = [\"full\"] } http-body-util = \"0.1.3\"   tokio = { version = \"1.44.2\", features = [\"rt-multi-thread\", \"macros\"] }<\/code><\/pre>\n<p>\u0427\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043a\u0430\u0436\u0434\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430:<\/p>\n<ul>\n<li>\n<p><code>hyper<\/code> &#8212; \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f HTTP-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0444\u0438\u0447\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 HTTP\/1.1-\u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/p>\n<\/li>\n<li>\n<p><code>hyper-util<\/code> &#8212; \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0443\u0442\u0438\u043b\u0438\u0442\u044b \u0438 \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u044b \u043f\u043e\u0432\u0435\u0440\u0445 <code>hyper<\/code>, \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0449\u0438\u0435 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p><code>http-body-util<\/code> &#8212; \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 HTTP-body <\/p>\n<\/li>\n<li>\n<p><code>tokio<\/code> &#8212; \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u0440\u0430\u043d\u0442\u0430\u0439\u043c. \u0421 \u0432\u0435\u0440\u0441\u0438\u0438 1.0 <code>hyper<\/code> <a href=\"https:\/\/hyper.rs\/guides\/1\/init\/runtime\/\" rel=\"noopener noreferrer nofollow\">\u0431\u044b\u043b<\/a> \u043e\u0442\u0432\u044f\u0437\u0430\u043d \u043e\u0442 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0430 <code>tokio<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0440\u0430\u043d\u0442\u0430\u0439\u043c<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u044b:<\/p>\n<pre><code class=\"rust\">use hyper::{       Request, Response,       body::{Bytes, Incoming},       server::conn::http1,       service::service_fn,   };   use hyper_util::{Full, rt::TokioIo};   use std::{convert::Infallible, net::SocketAddr};   use tokio::net::TcpListener;<\/code><\/pre>\n<p>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p><code>Request<\/code> &#8212; \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441<\/p>\n<\/li>\n<li>\n<p><code>Response<\/code> &#8212; \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 HTTP-\u043e\u0442\u0432\u0435\u0442<\/p>\n<\/li>\n<li>\n<p><code>Bytes<\/code> &#8212; \u0442\u0438\u043f \u0434\u043b\u044f \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0445 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<li>\n<p><code>Incoming<\/code> &#8212; \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0431\u0430\u0439\u0442\u043e\u0432, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0442\u0435\u043b\u043e HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0449\u0435\u0435 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430<\/p>\n<\/li>\n<li>\n<p><code>http1<\/code> &#8212; \u043c\u043e\u0434\u0443\u043b\u044c \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 HTTP\/1.1-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f\u043c\u0438<\/p>\n<\/li>\n<li>\n<p><code>service_fn<\/code> &#8212; \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0430\u0434\u0430\u043f\u0442\u0435\u0440, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0430\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c <code>Service<\/code> \u0438\u0437 \u043e\u0431\u044b\u0447\u043d\u043e\u0439 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><code>Full<\/code> &#8212; \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043e\u0431\u0451\u0440\u0442\u043a\u0430 \u0434\u043b\u044f \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e <code>Body<\/code><\/p>\n<\/li>\n<li>\n<p><code>TokioIo<\/code> &#8212; \u0430\u0434\u0430\u043f\u0442\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 <code>tokio::net::TcpStream<\/code> \u0432 \u0442\u0438\u043f, \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u0441 <code>hyper<\/code><\/p>\n<\/li>\n<li>\n<p><code>Infallible<\/code> &#8212; \u0442\u0438\u043f \u043e\u0448\u0438\u0431\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442<\/p>\n<\/li>\n<li>\n<p><code>SocketAddr<\/code> &#8212; \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0430\u044f IP-\u0430\u0434\u0440\u0435\u0441 \u0438 \u043f\u043e\u0440\u0442<\/p>\n<\/li>\n<li>\n<p><code>TcpListener<\/code>&#8212; \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 TCP-\u0441\u0435\u0440\u0432\u0435\u0440<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u0430:<\/p>\n<pre><code class=\"rust\">async fn hello(_: Request&lt;Incoming&gt;) -&gt; Result&lt;Response&lt;Full&lt;Bytes&gt;&gt;, Infallible&gt; {       Ok(Response::new(Full::new(Bytes::from(\"Hello, World!\"))))   }<\/code><\/pre>\n<p>\u0421 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0432\u0437\u0433\u043b\u044f\u0434\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0433\u0440\u043e\u043c\u043e\u0437\u0434\u043a\u0438\u043c:<\/p>\n<ul>\n<li>\n<p><code>_: Request&lt;Incoming&gt;<\/code><em> &#8212; \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0439 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043d\u0438\u0436\u043d\u0435\u0435 \u043f\u043e\u0434\u0447\u0451\u0440\u043a\u0438\u0432\u0430\u043d\u0438\u0435<\/em>, \u0447\u0442\u043e\u0431\u044b \u044f\u0432\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u0442\u0432\u0435\u0442 \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435<\/p>\n<\/li>\n<li>\n<p><code>Result&lt;Response&lt;Full&lt;Bytes&gt;&gt;, Infallible&gt;<\/code> &#8212; \u0442\u0438\u043f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430: <\/p>\n<ul>\n<li>\n<p><code>Response&lt;Full&lt;Bytes&gt;&gt;<\/code> &#8212; HTTP-\u043e\u0442\u0432\u0435\u0442 \u0441 \u0442\u0435\u043b\u043e\u043c, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u043c \u0431\u043b\u043e\u043a \u0431\u0430\u0439\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p><code>Infallible<\/code> &#8212; \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043d\u0430\u0448 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><code>Response::new(Full::new(Bytes::from(\"Hello, World!\")))<\/code> &#8212; \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443 \u0432 \u0431\u0430\u0439\u0442\u044b \u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0438\u0445 \u0432 \u0442\u0435\u043b\u043e \u043e\u0442\u0432\u0435\u0442\u0430<\/p>\n<\/li>\n<\/ul>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430:<\/p>\n<pre><code class=\"rust\">#[tokio::main]   async fn main() -&gt; Result&lt;(), Box&lt;dyn std::error::Error + Send + Sync&gt;&gt; {       \/\/ IP-\u0430\u0434\u0440\u0435\u0441 \u0438 \u043f\u043e\u0440\u0442, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440    let addr = SocketAddr::from(([0, 0, 0, 0], 3000));        \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 TCP-\u0441\u0435\u0440\u0432\u0435\u0440       let listener = TcpListener::bind(addr).await?;          \/\/ \u0411\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0446\u0438\u043a\u043b: \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u043c \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f       loop {          \/\/ \u0416\u0434\u0451\u043c \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430           let (stream, _) = listener.accept().await?;              \/\/ \u0410\u0434\u0430\u043f\u0442\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 `TcpStream` \u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u0435\u0433\u043e \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u043c \u0441 hyper         let io = TokioIo::new(stream);              \/\/ \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430           tokio::task::spawn(async move {              \/\/ HTTP\/1.1 \u0441\u0435\u0440\u0432\u0435\u0440, \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443 `hello`               if let Err(err) = http1::Builder::new()                   .serve_connection(io, service_fn(hello))                   .await               {               \/\/ \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438                 eprintln!(\"Error serving connection: {:?}\", err);               }           });       }   }<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440:<\/p>\n<pre><code>cargo run<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0430:<\/p>\n<pre><code>curl http:\/\/127.0.0.1:3000<\/code><\/pre>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043c\u043e\u0434\u0443\u043b\u044c <code>http1<\/code>. \u0415\u0441\u043b\u0438 \u0432\u0430\u043d \u043d\u0443\u0436\u0435\u043d <code>http2<\/code>, \u0442\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0432 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u043c <a href=\"https:\/\/github.com\/hyperium\/hyper\/blob\/master\/examples\/hello-http2.rs\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0438\u043c\u0435\u0440\u0435<\/a>.<\/p>\n<h2>\u042d\u0445\u043e \u0441\u0435\u0440\u0432\u0435\u0440<\/h2>\n<p>\u041d\u043e\u0432\u044b\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u044b:<\/p>\n<pre><code class=\"rust\">use hyper::{ body::{Body, Frame}, Method, StatusCode } use http_body_util::{Empty, combinators::BoxBody, BodyExt}; <\/code><\/pre>\n<p>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p><code>Body<\/code> &#8212; \u0442\u0440\u0435\u0439\u0442, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0439 <code>HTTP<\/code> \u0442\u0435\u043b\u043e<\/p>\n<\/li>\n<li>\n<p><code>Frame<\/code> &#8212; \u0435\u0434\u0438\u043d\u0438\u0446\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0442\u0435\u043b\u0435 HTTP-\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043b\u0438\u0431\u043e \u0447\u0430\u0441\u0442\u0438 \u0442\u0435\u043b\u0430 (<code>Bytes<\/code>), \u043b\u0438\u0431\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u043a\u043e\u043d\u0446\u0430 \u043f\u043e\u0442\u043e\u043a\u0430<\/p>\n<\/li>\n<li>\n<p><code>Method<\/code> &#8212; \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 HTTP-\u043c\u0435\u0442\u043e\u0434\u043e\u0432 (<code>GET<\/code>, <code>POST<\/code>, <code>PUT<\/code>, <code>DELETE<\/code> \u0438 \u0442.\u0434.)<\/p>\n<\/li>\n<li>\n<p><code>StatusCode<\/code> &#8212; \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 HTTP-\u0441\u0442\u0430\u0442\u0443\u0441\u043e\u0432 (<code>200 OK<\/code>, <code>404 Not Found<\/code>, <code>500 Internal Server Error<\/code> \u0438 \u0442.\u0434.)<\/p>\n<\/li>\n<li>\n<p><code>Empty<\/code> &#8212;  \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043e\u0431\u0451\u0440\u0442\u043a\u0430 \u0434\u043b\u044f \u043f\u0443\u0441\u0442\u043e\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e <code>Body<\/code><\/p>\n<\/li>\n<li>\n<p><code>BoxBody<\/code> &#8212; \u043e\u0431\u043e\u0431\u0449\u0451\u043d\u043d\u044b\u0439 \u0442\u0438\u043f \u0442\u0435\u043b\u0430 \u043e\u0442\u0432\u0435\u0442\u0430. \u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0438\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0440\u0430\u0437\u043d\u044b\u0435 \u0442\u0438\u043f\u044b <code>Body<\/code><\/p>\n<\/li>\n<li>\n<p><code>BodyExt<\/code> &#8212; \u043d\u0430\u0431\u043e\u0440 \u0443\u0434\u043e\u0431\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0435\u043b\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0430<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u043d\u044b\u0445 \u0438 \u043f\u0443\u0441\u0442\u044b\u0445 \u0442\u0435\u043b \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432:<\/p>\n<pre><code class=\"rust\">\/\/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u0442 \u043f\u0443\u0441\u0442\u043e\u0435 \u0442\u0435\u043b\u043e \u043e\u0442\u0432\u0435\u0442\u0430 fn empty() -&gt; BoxBody&lt;Bytes, hyper::Error&gt; {       Empty::&lt;Bytes&gt;::new()           .map_err(|never| match never {})           .boxed()   }    \/\/\/ \u041e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0439 chunk (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, `&amp;str` \u0438\u043b\u0438 `Vec&lt;u8&gt;`) \u0432 \u0442\u0435\u043b\u043e \u043e\u0442\u0432\u0435\u0442\u0430 fn full&lt;T: Into&lt;Bytes&gt;&gt;(chunk: T) -&gt; BoxBody&lt;Bytes, hyper::Error&gt; {       Full::new(chunk.into())           .map_err(|never| match never {})           .boxed()   } <\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438:<\/p>\n<pre><code class=\"rust\">\/\/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0442\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.    fn echo(req: Request&lt;Incoming&gt;) -&gt; Result&lt;Response&lt;BoxBody&lt;Bytes, hyper::Error&gt;&gt;, hyper::Error&gt; {       Ok(Response::new(req.into_body().boxed()))   }      \/\/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430,   \/\/\/ \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0432 \u0432\u0435\u0440\u0445\u043d\u0438\u0439 ASCII-\u0440\u0435\u0433\u0438\u0441\u0442\u0440   async fn echo_uppercase(req: Request&lt;Incoming&gt;) -&gt; Result&lt;Response&lt;BoxBody&lt;Bytes, hyper::Error&gt;&gt;, hyper::Error&gt; {       \/\/ \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u043f\u043e\u0442\u043e\u043a \u0442\u0435\u043b\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u043e \u0447\u0430\u0441\u0442\u044f\u043c       let frame_stream = req.into_body().map_frame(|frame| {           let frame = if let Ok(data) = frame.into_data() {               \/\/ \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0431\u0430\u0439\u0442 \u0432 \u0432\u0435\u0440\u0445\u043d\u0438\u0439 ASCII-\u0440\u0435\u0433\u0438\u0441\u0442\u0440               data.iter()                   .map(|byte| byte.to_ascii_uppercase())                   .collect::&lt;Bytes&gt;()           } else {               Bytes::new()           };              Frame::data(frame)       });          Ok(Response::new(frame_stream.boxed()))   }      \/\/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u043f\u0435\u0440\u0435\u0432\u0451\u0440\u043d\u0443\u0442\u043e\u043c \u0432\u0438\u0434\u0435   async fn echo_reversed(req: Request&lt;Incoming&gt;) -&gt; Result&lt;Response&lt;BoxBody&lt;Bytes, hyper::Error&gt;&gt;, hyper::Error&gt; {       \/\/ \u0417\u0430\u0449\u0438\u0442\u0430 \u043e\u0442 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0442\u0435\u043b       let upper = req.body().size_hint().upper().unwrap_or(u64::MAX);       \/\/ \u0415\u0441\u043b\u0438 \u0440\u0430\u0437\u043c\u0435\u0440 \u0442\u0435\u043b\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0435\u0442 64 \u041a\u0411, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443 `413 Payload Too Large`       if upper &gt; 1024 * 64 {           let response = Response::builder()               .status(StatusCode::PAYLOAD_TOO_LARGE)               .body(full(\"Body too big\"))               .unwrap();              return Ok(response);       }          \/\/ \u0427\u0438\u0442\u0430\u0435\u043c \u0432\u0441\u0451 \u0442\u0435\u043b\u043e \u0446\u0435\u043b\u0438\u043a\u043e\u043c       let whole_body = req.collect().await?.to_bytes();          \/\/ \u0420\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u0431\u0430\u0439\u0442\u044b \u0432 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435       let reversed_body = whole_body.iter()           .rev()           .cloned()           .collect::&lt;Vec&lt;u8&gt;&gt;();          Ok(Response::new(full(reversed_body)))   }      \/\/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0442 `404 Not Found` \u0441 \u043f\u0443\u0441\u0442\u044b\u043c \u0442\u0435\u043b\u043e\u043c async fn not_found() -&gt; Result&lt;Response&lt;BoxBody&lt;Bytes, hyper::Error&gt;&gt;, hyper::Error&gt; {       let response = Response::builder()           .status(StatusCode::NOT_FOUND)           .body(empty())           .unwrap();          Ok(response)   }<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0433\u043e\u0432\u043e\u0440\u0438\u043b\u043e\u0441\u044c \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438, <code>hyper<\/code> &#8212; \u044d\u0442\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043d\u0438\u0437\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u0438 \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 <code>axum<\/code> \u0438\u043b\u0438 <code>actix-web<\/code>, \u043d\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0443\u044e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u044e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0435\u0451 \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e:<\/p>\n<pre><code class=\"rust\">async fn router(      req: Request,  ) -&amp;gt; Result&amp;gt;, hyper::Error&amp;gt; {  \/\/ \u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c HTTP-\u043c\u0435\u0442\u043e\u0434 \u0438 \u043f\u0443\u0442\u044c    match (req.method(), req.uri().path()) {          (&amp;amp;Method::POST, \"\/echo\") =&amp;gt; echo(req),          (&amp;amp;Method::POST, \"\/echo\/uppercase\") =&amp;gt; echo_uppercase(req).await,          (&amp;amp;Method::POST, \"\/echo\/reversed\") =&amp;gt; echo_reversed(req).await,          _ =&amp;gt; not_found().await,      }  } <\/code><\/pre>\n<p>\u0412 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>main<\/code> \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c <code>service_fn<\/code> :<\/p>\n<pre><code class=\"rust\">.serve_connection(io, service_fn(router))<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0443:<\/p>\n<pre><code>curl -X POST http:\/\/127.0.0.1:3000\/echo -d \"hello world\" curl -X POST http:\/\/127.0.0.1:3000\/echo\/uppercase -d \"hello world\" curl -X POST http:\/\/127.0.0.1:3000\/echo\/reversed -d \"hello world\"<\/code><\/pre>\n<h2>Middleware<\/h2>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043a \u0442\u0435\u043a\u0443\u0449\u0435\u043c\u0443 \u044d\u0445\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0443 middleware, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 \u0438 \u043f\u0443\u0442\u044c \u043a\u0430\u0436\u0434\u043e\u0433\u043e HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u0430<\/p>\n<p>\u041d\u043e\u0432\u0430\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u0432 <code>Cargo.toml<\/code>:<\/p>\n<pre><code>[dependencies] tower = \"0.5.2\" # \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 \u0434\u043b\u044f middleware<\/code><\/pre>\n<p>\u041d\u043e\u0432\u044b\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u044b:<\/p>\n<pre><code class=\"rust\">use hyper::service::Service; use tower::ServiceBuilder;  <\/code><\/pre>\n<ul>\n<li>\n<p><code>Service<\/code> &#8212; \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u043a \u0441\u0435\u0442\u0435\u0432\u043e\u043c\u0443 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044e (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>service_fn(router)<\/code> \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u044d\u0442\u043e\u0433\u043e \u0442\u0440\u0435\u0439\u0442\u0430)<\/p>\n<\/li>\n<li>\n<p><code>ServiceBuilder<\/code> &#8212; \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c middleware \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0438\u0448\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 middleware \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432:<\/p>\n<pre><code class=\"rust\">\/\/\/ \u041f\u0440\u043e\u0441\u0442\u0430\u044f \u043e\u0431\u0451\u0440\u0442\u043a\u0430, \u043b\u043e\u0433\u0438\u0440\u0443\u044e\u0449\u0430\u044f HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u044b   #[derive(Debug, Clone)]   pub struct Logger&lt;S&gt; {       \/\/\/ \u0421\u0435\u0440\u0432\u0438\u0441, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430       inner: S,   }      impl&lt;S&gt; Logger&lt;S&gt; {       \/\/\/ \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u043b\u043e\u0433\u0435\u0440\u0430, \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u044e\u0449\u0435\u0433\u043e \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0435\u0440\u0432\u0438\u0441       pub fn new(inner: S) -&gt; Self {           Logger { inner }       }   }      type Req = Request&lt;Incoming&gt;;      \/\/\/ \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u0440\u0435\u0439\u0442\u0430 `Service` \u0434\u043b\u044f `Logger`,   \/\/\/ \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043a\u0430\u043a middleware   impl&lt;S&gt; Service&lt;Req&gt; for Logger&lt;S&gt;   where       S: Service&lt;Req&gt;,  \/\/ \u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0442\u0440\u0435\u0439\u0442 `Service`   {       \/\/ \u0422\u0438\u043f \u043e\u0442\u0432\u0435\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u0438\u043c \u0436\u0435, \u043a\u0430\u043a \u0443 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430       type Response = S::Response;       \/\/ \u0422\u0438\u043f \u043e\u0448\u0438\u0431\u043a\u0438 - \u0442\u043e\u0436\u0435 \u0442\u0430\u043a\u043e\u0439 \u0436\u0435       type Error = S::Error;       \/\/ \u0422\u0438\u043f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e future (\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430)       type Future = S::Future;          \/\/\/ \u041c\u0435\u0442\u043e\u0434, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435       fn call(&amp;self, req: Req) -&gt; Self::Future {           \/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043c\u0435\u0442\u043e\u0434 \u0438 \u043f\u0443\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u0430           println!(\"processing request: {} {}\", req.method(), req.uri().path());              \/\/ \u041f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0434\u0430\u043b\u044c\u0448\u0435 \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u0441\u0435\u0440\u0432\u0438\u0441           self.inner.call(req)       }   }<\/code><\/pre>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>main<\/code>:<\/p>\n<pre><code class=\"rust\">tokio::task::spawn(async move {       \/\/ \u041e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432 \u0432 Service                     let svc = service_fn(router);        \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0430\u0448 middleware \u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443       let svc = ServiceBuilder::new().layer_fn(Logger::new).service(svc);       \/\/ \u041e\u0436\u0438\u0434\u0430\u0435\u043c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f (\u0438\u043b\u0438 \u043e\u0448\u0438\u0431\u043a\u0443)      if let Err(err) = http1::Builder::new().serve_connection(io, svc).await {           eprintln!(\"server error: {}\", err);       }   });<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435, \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0432\u0438\u0434\u0430:<\/p>\n<pre><code>processing request: POST \/echo\/reversed processing request: POST \/echo <\/code><\/pre>\n<p>\u0414\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043b\u043e\u0433\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>println!<\/code>. \u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u043b\u043e\u0433\u0435\u0440, \u0442\u043e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 \u043a\u0440\u0435\u0439\u0442\u043e\u043c <a href=\"https:\/\/docs.rs\/tracing\/latest\/tracing\/\" rel=\"noopener noreferrer nofollow\"><code>tracing<\/code><\/a><\/p>\n<h2>Gracefully Shutdown<\/h2>\n<p><strong>Graceful shutdown<\/strong> &#8212; \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440:<\/p>\n<ul>\n<li>\n<p>\u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0451\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0430\u0435\u0442 \u0440\u0435\u0441\u0443\u0440\u0441\u044b (\u0444\u0430\u0439\u043b\u044b, \u0411\u0414, \u0441\u043e\u043a\u0435\u0442\u044b \u0438 \u0442.\u043f.)<\/p>\n<\/li>\n<\/ul>\n<p>\u0427\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<ul>\n<li>\n<p>\u0421\u0438\u0433\u043d\u0430\u043b \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u0426\u0438\u043a\u043b, \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u0435\u043b\u044c, \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 <code>tokio<\/code> \u043d\u043e\u0432\u0443\u044e \u0444\u0438\u0447\u0443 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u0432:<\/p>\n<pre><code>[dependencies] tokio = { version = \"1.44.2\", features = [..., \"signal\"] } # \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0444\u0438\u0447\u0443 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u0432<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u0438\u0433\u043d\u0430\u043b\u0430:<\/p>\n<pre><code class=\"rust\">async fn shutdown_signal() {     \/\/ \u041e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 CTRL+C      tokio::signal::ctrl_c()         .await         .expect(\"failed to install CTRL+C signal handler\"); }<\/code><\/pre>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>main<\/code> \u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u0435 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439:<\/p>\n<pre><code class=\"rust\">#[tokio::main]   async fn main() -&gt; Result&lt;(), Box&lt;dyn std::error::Error + Send + Sync&gt;&gt; {       \/\/ IP-\u0430\u0434\u0440\u0435\u0441 \u0438 \u043f\u043e\u0440\u0442, \u0433\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u0443\u0448\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440   let addr = SocketAddr::from(([0, 0, 0, 0], 3000));        \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 TCP-\u0441\u0435\u0440\u0432\u0435\u0440       let listener = TcpListener::bind(addr).await?;       \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \"graceful shutdown\" (\u043c\u044f\u0433\u043a\u043e\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435)       let graceful = hyper_util::server::graceful::GracefulShutdown::new();     \/\/ \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0441\u0438\u0433\u043d\u0430\u043b \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f       \/\/ \u041f\u043e\u0441\u043b\u0435 \u0435\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043d\u0430\u0447\u043d\u0451\u0442\u0441\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0430         let mut signal = std::pin::pin!(shutdown_signal());          \/\/ \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0446\u0438\u043a\u043b, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f       loop {           tokio::select! {               \/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043d\u043e\u0432\u044b\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439               Ok((stream, _addr)) = listener.accept() =&gt; {                   \/\/ \u0410\u0434\u0430\u043f\u0442\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 `TcpStream` \u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u0435\u0433\u043e \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u043c \u0441 hyper                   let io = TokioIo::new(stream);                   \/\/ \u041e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432 \u0432 Service                                 let svc = service_fn(router);                   \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0430\u0448 middleware \u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443                   let svc = ServiceBuilder::new().layer_fn(Logger::new).service(svc);                   \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 HTTP\/1.1                   let conn = http1::Builder::new().serve_connection(io, svc);                   \/\/ \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u0435 \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f                   let fut = graceful.watch(conn);                     \/\/ \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430                   tokio::task::spawn(async move {                       \/\/ \u041e\u0436\u0438\u0434\u0430\u0435\u043c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f (\u0438\u043b\u0438 \u043e\u0448\u0438\u0431\u043a\u0443)                       if let Err(err) = fut.await {                           eprintln!(\"server error: {}\", err);                       }                   });               },               \/\/ \u041f\u043e\u043b\u0443\u0447\u0435\u043d \u0441\u0438\u0433\u043d\u0430\u043b \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f               _ = &amp;mut signal =&gt; {                   \/\/ \u0417\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c listener, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f                   drop(listener);                   eprintln!(\"graceful shutdown signal received\");                   \/\/ \u041f\u0440\u0435\u0440\u044b\u0432\u0430\u0435\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0446\u0438\u043a\u043b                   break;               }           }       }          \/\/ \u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u0445\u043e\u0434\u0430 \u0438\u0437 \u0446\u0438\u043a\u043b\u0430 \u2014 \u0436\u0434\u0451\u043c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439       tokio::select! {           \/\/ \u0423\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439           _ = graceful.shutdown() =&gt; {               eprintln!(\"all connections gracefully closed\");           },           \/\/ \u0415\u0441\u043b\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043d\u0435 \u0437\u0430\u043a\u0440\u044b\u043b\u0438\u0441\u044c \u0437\u0430 10 \u0441\u0435\u043a\u0443\u043d\u0434 \u2014 \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u043c           _ = tokio::time::sleep(std::time::Duration::from_secs(10)) =&gt; {               eprintln!(\"timed out wait for all connections to close\");           }       }          Ok(())   }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043f\u0440\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0435 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f, \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f:<\/p>\n<pre><code>graceful shutdown signal received all connections gracefully closed<\/code><\/pre>\n<h2>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440 \u0432 docker \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440<\/h2>\n<p><code>Dockerfile<\/code><\/p>\n<pre><code>FROM rust:1.86-slim AS builder   RUN apt-get update &amp;&amp; apt-get install musl-tools -y &amp;&amp; rustup target add x86_64-unknown-linux-musl   WORKDIR \/usr\/src\/app   COPY Cargo.toml Cargo.lock .\/   COPY src src   RUN cargo build --target x86_64-unknown-linux-musl --release      FROM scratch   COPY --from=builder \/usr\/src\/app\/target\/x86_64-unknown-linux-musl\/release\/hyper-server \/usr\/local\/bin\/hyper-server   EXPOSE 3000   CMD [\"hyper-server\"]<\/code><\/pre>\n<p>\u0421\u0431\u043e\u0440\u043a\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430:<\/p>\n<pre><code>docker build -t hyper-server .<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430:<\/p>\n<pre><code>docker run --rm -p 3000:3000 hyper-server<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0430:<\/p>\n<pre><code>curl -X POST http:\/\/127.0.0.1:3000\/echo -d \"hello world\"<\/code><\/pre>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u0435 <code>hyper<\/code>, \u0442\u043e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u0435\u0441\u044c \u0441 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 <a href=\"https:\/\/hyper.rs\/\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439<\/a> \u0438 <a href=\"https:\/\/github.com\/hyperium\/hyper\/tree\/master\/examples\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438<\/a>.<\/p>\n<p>\u042d\u0442\u043e \u043c\u043e\u044f \u043f\u0435\u0440\u0432\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0430 \u0425\u0430\u0431\u0440\u0435, \u0435\u0441\u043b\u0438 \u0432\u044b \u043d\u0430\u0448\u043b\u0438 \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u043e\u0448\u0438\u0431\u043a\u0438 \u0438\u043b\u0438 \u043d\u0435\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0438, \u0431\u0443\u0434\u0443 \u0440\u0430\u0434 \u0443\u0442\u043e\u0447\u043d\u0435\u043d\u0438\u044f\u043c \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/917936\/\"> https:\/\/habr.com\/ru\/articles\/917936\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><code>hyper<\/code> &#8212; \u044d\u0442\u043e \u043d\u0438\u0437\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u0430\u044f HTTP-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043d\u0430 Rust. \u041e\u0431\u044b\u0447\u043d\u043e \u043e\u043d\u0430 \u0441\u043b\u0443\u0436\u0438\u0442 \u0441\u0442\u0440\u043e\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0431\u043b\u043e\u043a\u043e\u043c \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0432\u044b\u0441\u043e\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a <a href=\"https:\/\/crates.io\/crates\/axum\" rel=\"noopener noreferrer nofollow\"><code>axum<\/code><\/a>, <a href=\"https:\/\/crates.io\/crates\/tonic\" rel=\"noopener noreferrer nofollow\"><code>tonic<\/code><\/a>, <a href=\"https:\/\/crates.io\/crates\/reqwest\" rel=\"noopener noreferrer nofollow\"><code>reqwest<\/code><\/a> \u0438 \u0434\u0440\u0443\u0433\u0438\u0445. \u041d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u0437\u043d\u0430\u043d\u0438\u0435 <code>hyper<\/code> \u043c\u043e\u0433\u0443\u0442 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c \u0432 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u044f\u0445.<\/p>\n<p> <code>hyper<\/code> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 api \u043a\u0430\u043a \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u0442\u0430\u043a \u0438 \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043d\u043e \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u043c\u0441\u044f \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438.<\/p>\n<h2>\u041f\u0435\u0440\u0432\u044b\u0439 &#171;Hello, World!&#187;<\/h2>\n<p>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442:<\/p>\n<pre><code>cargo new hyper-server<\/code><\/pre>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 <code>Cargo.toml<\/code>:<\/p>\n<pre><code>[dependencies] hyper = { version = \"1.6.0\", features = [\"server\", \"http1\"] }      hyper-util = { version = \"0.1\", features = [\"full\"] } http-body-util = \"0.1.3\"   tokio = { version = \"1.44.2\", features = [\"rt-multi-thread\", \"macros\"] }<\/code><\/pre>\n<p>\u0427\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043a\u0430\u0436\u0434\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430:<\/p>\n<ul>\n<li>\n<p><code>hyper<\/code> &#8212; \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f HTTP-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0444\u0438\u0447\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 HTTP\/1.1-\u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/p>\n<\/li>\n<li>\n<p><code>hyper-util<\/code> &#8212; \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0443\u0442\u0438\u043b\u0438\u0442\u044b \u0438 \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u044b \u043f\u043e\u0432\u0435\u0440\u0445 <code>hyper<\/code>, \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0449\u0438\u0435 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p><code>http-body-util<\/code> &#8212; \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 HTTP-body <\/p>\n<\/li>\n<li>\n<p><code>tokio<\/code> &#8212; \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u0440\u0430\u043d\u0442\u0430\u0439\u043c. \u0421 \u0432\u0435\u0440\u0441\u0438\u0438 1.0 <code>hyper<\/code> <a href=\"https:\/\/hyper.rs\/guides\/1\/init\/runtime\/\" rel=\"noopener noreferrer nofollow\">\u0431\u044b\u043b<\/a> \u043e\u0442\u0432\u044f\u0437\u0430\u043d \u043e\u0442 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0430 <code>tokio<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0440\u0430\u043d\u0442\u0430\u0439\u043c<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u044b:<\/p>\n<pre><code class=\"rust\">use hyper::{       Request, Response,       body::{Bytes, Incoming},       server::conn::http1,       service::service_fn,   };   use hyper_util::{Full, rt::TokioIo};   use std::{convert::Infallible, net::SocketAddr};   use tokio::net::TcpListener;<\/code><\/pre>\n<p>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p><code>Request<\/code> &#8212; \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441<\/p>\n<\/li>\n<li>\n<p><code>Response<\/code> &#8212; \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 HTTP-\u043e\u0442\u0432\u0435\u0442<\/p>\n<\/li>\n<li>\n<p><code>Bytes<\/code> &#8212; \u0442\u0438\u043f \u0434\u043b\u044f \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0445 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<li>\n<p><code>Incoming<\/code> &#8212; \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0431\u0430\u0439\u0442\u043e\u0432, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0442\u0435\u043b\u043e HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0449\u0435\u0435 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430<\/p>\n<\/li>\n<li>\n<p><code>http1<\/code> &#8212; \u043c\u043e\u0434\u0443\u043b\u044c \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 HTTP\/1.1-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f\u043c\u0438<\/p>\n<\/li>\n<li>\n<p><code>service_fn<\/code> &#8212; \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0430\u0434\u0430\u043f\u0442\u0435\u0440, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0430\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c <code>Service<\/code> \u0438\u0437 \u043e\u0431\u044b\u0447\u043d\u043e\u0439 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><code>Full<\/code> &#8212; \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043e\u0431\u0451\u0440\u0442\u043a\u0430 \u0434\u043b\u044f \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e <code>Body<\/code><\/p>\n<\/li>\n<li>\n<p><code>TokioIo<\/code> &#8212; \u0430\u0434\u0430\u043f\u0442\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 <code>tokio::net::TcpStream<\/code> \u0432 \u0442\u0438\u043f, \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u0441 <code>hyper<\/code><\/p>\n<\/li>\n<li>\n<p><code>Infallible<\/code> &#8212; \u0442\u0438\u043f \u043e\u0448\u0438\u0431\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442<\/p>\n<\/li>\n<li>\n<p><code>SocketAddr<\/code> &#8212; \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0430\u044f IP-\u0430\u0434\u0440\u0435\u0441 \u0438 \u043f\u043e\u0440\u0442<\/p>\n<\/li>\n<li>\n<p><code>TcpListener<\/code>&#8212; \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 TCP-\u0441\u0435\u0440\u0432\u0435\u0440<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u0430:<\/p>\n<pre><code class=\"rust\">async fn hello(_: Request&lt;Incoming&gt;) -&gt; Result&lt;Response&lt;Full&lt;Bytes&gt;&gt;, Infallible&gt; {       Ok(Response::new(Full::new(Bytes::from(\"Hello, World!\"))))   }<\/code><\/pre>\n<p>\u0421 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0432\u0437\u0433\u043b\u044f\u0434\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0433\u0440\u043e\u043c\u043e\u0437\u0434\u043a\u0438\u043c:<\/p>\n<ul>\n<li>\n<p><code>_: Request&lt;Incoming&gt;<\/code><em> &#8212; \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0439 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043d\u0438\u0436\u043d\u0435\u0435 \u043f\u043e\u0434\u0447\u0451\u0440\u043a\u0438\u0432\u0430\u043d\u0438\u0435<\/em>, \u0447\u0442\u043e\u0431\u044b \u044f\u0432\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u0442\u0432\u0435\u0442 \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435<\/p>\n<\/li>\n<li>\n<p><code>Result&lt;Response&lt;Full&lt;Bytes&gt;&gt;, Infallible&gt;<\/code> &#8212; \u0442\u0438\u043f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430: <\/p>\n<ul>\n<li>\n<p><code>Response&lt;Full&lt;Bytes&gt;&gt;<\/code> &#8212; HTTP-\u043e\u0442\u0432\u0435\u0442 \u0441 \u0442\u0435\u043b\u043e\u043c, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u043c \u0431\u043b\u043e\u043a \u0431\u0430\u0439\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p><code>Infallible<\/code> &#8212; \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043d\u0430\u0448 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><code>Response::new(Full::new(Bytes::from(\"Hello, World!\")))<\/code> &#8212; \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443 \u0432 \u0431\u0430\u0439\u0442\u044b \u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0438\u0445 \u0432 \u0442\u0435\u043b\u043e \u043e\u0442\u0432\u0435\u0442\u0430<\/p>\n<\/li>\n<\/ul>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430:<\/p>\n<pre><code class=\"rust\">#[tokio::main]   async fn main() -&gt; Result&lt;(), Box&lt;dyn std::error::Error + Send + Sync&gt;&gt; {       \/\/ IP-\u0430\u0434\u0440\u0435\u0441 \u0438 \u043f\u043e\u0440\u0442, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440    let addr = SocketAddr::from(([0, 0, 0, 0], 3000));        \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 TCP-\u0441\u0435\u0440\u0432\u0435\u0440       let listener = TcpListener::bind(addr).await?;          \/\/ \u0411\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0446\u0438\u043a\u043b: \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u043c \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f       loop {          \/\/ \u0416\u0434\u0451\u043c \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430           let (stream, _) = listener.accept().await?;              \/\/ \u0410\u0434\u0430\u043f\u0442\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 `TcpStream` \u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u0435\u0433\u043e \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u043c \u0441 hyper         let io = TokioIo::new(stream);              \/\/ \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430           tokio::task::spawn(async move {              \/\/ HTTP\/1.1 \u0441\u0435\u0440\u0432\u0435\u0440, \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443 `hello`               if let Err(err) = http1::Builder::new()                   .serve_connection(io, service_fn(hello))                   .await               {               \/\/ \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438                 eprintln!(\"Error serving connection: {:?}\", err);               }           });       }   }<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440:<\/p>\n<pre><code>cargo run<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0430:<\/p>\n<pre><code>curl http:\/\/127.0.0.1:3000<\/code><\/pre>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043c\u043e\u0434\u0443\u043b\u044c <code>http1<\/code>. \u0415\u0441\u043b\u0438 \u0432\u0430\u043d \u043d\u0443\u0436\u0435\u043d <code>http2<\/code>, \u0442\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0432 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u043c <a href=\"https:\/\/github.com\/hyperium\/hyper\/blob\/master\/examples\/hello-http2.rs\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0438\u043c\u0435\u0440\u0435<\/a>.<\/p>\n<h2>\u042d\u0445\u043e \u0441\u0435\u0440\u0432\u0435\u0440<\/h2>\n<p>\u041d\u043e\u0432\u044b\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u044b:<\/p>\n<pre><code class=\"rust\">use hyper::{ body::{Body, Frame}, Method, StatusCode } use http_body_util::{Empty, combinators::BoxBody, BodyExt}; <\/code><\/pre>\n<p>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p><code>Body<\/code> &#8212; \u0442\u0440\u0435\u0439\u0442, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0439 <code>HTTP<\/code> \u0442\u0435\u043b\u043e<\/p>\n<\/li>\n<li>\n<p><code>Frame<\/code> &#8212; \u0435\u0434\u0438\u043d\u0438\u0446\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0442\u0435\u043b\u0435 HTTP-\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043b\u0438\u0431\u043e \u0447\u0430\u0441\u0442\u0438 \u0442\u0435\u043b\u0430 (<code>Bytes<\/code>), \u043b\u0438\u0431\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u043a\u043e\u043d\u0446\u0430 \u043f\u043e\u0442\u043e\u043a\u0430<\/p>\n<\/li>\n<li>\n<p><code>Method<\/code> &#8212; \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 HTTP-\u043c\u0435\u0442\u043e\u0434\u043e\u0432 (<code>GET<\/code>, <code>POST<\/code>, <code>PUT<\/code>, <code>DELETE<\/code> \u0438 \u0442.\u0434.)<\/p>\n<\/li>\n<li>\n<p><code>StatusCode<\/code> &#8212; \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 HTTP-\u0441\u0442\u0430\u0442\u0443\u0441\u043e\u0432 (<code>200 OK<\/code>, <code>404 Not Found<\/code>, <code>500 Internal Server Error<\/code> \u0438 \u0442.\u0434.)<\/p>\n<\/li>\n<li>\n<p><code>Empty<\/code> &#8212;  \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043e\u0431\u0451\u0440\u0442\u043a\u0430 \u0434\u043b\u044f \u043f\u0443\u0441\u0442\u043e\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e <code>Body<\/code><\/p>\n<\/li>\n<li>\n<p><code>BoxBody<\/code> &#8212; \u043e\u0431\u043e\u0431\u0449\u0451\u043d\u043d\u044b\u0439 \u0442\u0438\u043f \u0442\u0435\u043b\u0430 \u043e\u0442\u0432\u0435\u0442\u0430. \u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0438\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0440\u0430\u0437\u043d\u044b\u0435 \u0442\u0438\u043f\u044b <code>Body<\/code><\/p>\n<\/li>\n<li>\n<p><code>BodyExt<\/code> &#8212; \u043d\u0430\u0431\u043e\u0440 \u0443\u0434\u043e\u0431\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0435\u043b\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0430<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u043d\u044b\u0445 \u0438 \u043f\u0443\u0441\u0442\u044b\u0445 \u0442\u0435\u043b \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432:<\/p>\n<pre><code class=\"rust\">\/\/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u0442 \u043f\u0443\u0441\u0442\u043e\u0435 \u0442\u0435\u043b\u043e \u043e\u0442\u0432\u0435\u0442\u0430 fn empty() -&gt; BoxBody&lt;Bytes, hyper::Error&gt; {       Empty::&lt;Bytes&gt;::new()           .map_err(|never| match never {})           .boxed()   }    \/\/\/ \u041e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0439 chunk (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, `&amp;str` \u0438\u043b\u0438 `Vec&lt;u8&gt;`) \u0432 \u0442\u0435\u043b\u043e \u043e\u0442\u0432\u0435\u0442\u0430 fn full&lt;T: Into&lt;Bytes&gt;&gt;(chunk: T) -&gt; BoxBody&lt;Bytes, hyper::Error&gt; {       Full::new(chunk.into())           .map_err(|never| match never {})           .boxed()   } <\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438:<\/p>\n<pre><code class=\"rust\">\/\/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0442\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.    fn echo(req: Request&lt;Incoming&gt;) -&gt; Result&lt;Response&lt;BoxBody&lt;Bytes, hyper::Error&gt;&gt;, hyper::Error&gt; {       Ok(Response::new(req.into_body().boxed()))   }      \/\/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430,   \/\/\/ \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0432 \u0432\u0435\u0440\u0445\u043d\u0438\u0439 ASCII-\u0440\u0435\u0433\u0438\u0441\u0442\u0440   async fn echo_uppercase(req: Request&lt;Incoming&gt;) -&gt; Result&lt;Response&lt;BoxBody&lt;Bytes, hyper::Error&gt;&gt;, hyper::Error&gt; {       \/\/ \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u043f\u043e\u0442\u043e\u043a \u0442\u0435\u043b\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u043e \u0447\u0430\u0441\u0442\u044f\u043c       let frame_stream = req.into_body().map_frame(|frame| {           let frame = if let Ok(data) = frame.into_data() {               \/\/ \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0431\u0430\u0439\u0442 \u0432 \u0432\u0435\u0440\u0445\u043d\u0438\u0439 ASCII-\u0440\u0435\u0433\u0438\u0441\u0442\u0440               data.iter()                   .map(|byte| byte.to_ascii_uppercase())                   .collect::&lt;Bytes&gt;()           } else {               Bytes::new()           };              Frame::data(frame)       });          Ok(Response::new(frame_stream.boxed()))   }      \/\/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u043f\u0435\u0440\u0435\u0432\u0451\u0440\u043d\u0443\u0442\u043e\u043c \u0432\u0438\u0434\u0435   async fn echo_reversed(req: Request&lt;Incoming&gt;) -&gt; Result&lt;Response&lt;BoxBody&lt;Bytes, hyper::Error&gt;&gt;, hyper::Error&gt; {       \/\/ \u0417\u0430\u0449\u0438\u0442\u0430 \u043e\u0442 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0442\u0435\u043b       let upper = req.body().size_hint().upper().unwrap_or(u64::MAX);       \/\/ \u0415\u0441\u043b\u0438 \u0440\u0430\u0437\u043c\u0435\u0440 \u0442\u0435\u043b\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0435\u0442 64 \u041a\u0411, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443 `413 Payload Too Large`       if upper &gt; 1024 * 64 {           let response = Response::builder()               .status(StatusCode::PAYLOAD_TOO_LARGE)               .body(full(\"Body too big\"))               .unwrap();              return Ok(response);       }          \/\/ \u0427\u0438\u0442\u0430\u0435\u043c \u0432\u0441\u0451 \u0442\u0435\u043b\u043e \u0446\u0435\u043b\u0438\u043a\u043e\u043c       let whole_body = req.collect().await?.to_bytes();          \/\/ \u0420\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u0431\u0430\u0439\u0442\u044b \u0432 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435       let reversed_body = whole_body.iter()           .rev()           .cloned()           .collect::&lt;Vec&lt;u8&gt;&gt;();          Ok(Response::new(full(reversed_body)))   }      \/\/\/ \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0442 `404 Not Found` \u0441 \u043f\u0443\u0441\u0442\u044b\u043c \u0442\u0435\u043b\u043e\u043c async fn not_found() -&gt; Result&lt;Response&lt;BoxBody&lt;Bytes, hyper::Error&gt;&gt;, hyper::Error&gt; {       let response = Response::builder()           .status(StatusCode::NOT_FOUND)           .body(empty())           .unwrap();          Ok(response)   }<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0433\u043e\u0432\u043e\u0440\u0438\u043b\u043e\u0441\u044c \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438, <code>hyper<\/code> &#8212; \u044d\u0442\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043d\u0438\u0437\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u0438 \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 <code>axum<\/code> \u0438\u043b\u0438 <code>actix-web<\/code>, \u043d\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0443\u044e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u044e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0435\u0451 \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e:<\/p>\n<pre><code class=\"rust\">async fn router(      req: Request,  ) -&amp;gt; Result&amp;gt;, hyper::Error&amp;gt; {  \/\/ \u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c HTTP-\u043c\u0435\u0442\u043e\u0434 \u0438 \u043f\u0443\u0442\u044c    match (req.method(), req.uri().path()) {          (&amp;amp;Method::POST, \"\/echo\") =&amp;gt; echo(req),          (&amp;amp;Method::POST, \"\/echo\/uppercase\") =&amp;gt; echo_uppercase(req).await,          (&amp;amp;Method::POST, \"\/echo\/reversed\") =&amp;gt; echo_reversed(req).await,          _ =&amp;gt; not_found().await,      }  } <\/code><\/pre>\n<p>\u0412 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>main<\/code> \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c <code>service_fn<\/code> :<\/p>\n<pre><code class=\"rust\">.serve_connection(io, service_fn(router))<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0443:<\/p>\n<pre><code>curl -X POST http:\/\/127.0.0.1:3000\/echo -d \"hello world\" curl -X POST http:\/\/127.0.0.1:3000\/echo\/uppercase -d \"hello world\" curl -X POST http:\/\/127.0.0.1:3000\/echo\/reversed -d \"hello world\"<\/code><\/pre>\n<h2>Middleware<\/h2>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043a \u0442\u0435\u043a\u0443\u0449\u0435\u043c\u0443 \u044d\u0445\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0443 middleware, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 \u0438 \u043f\u0443\u0442\u044c \u043a\u0430\u0436\u0434\u043e\u0433\u043e HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u0430<\/p>\n<p>\u041d\u043e\u0432\u0430\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u0432 <code>Cargo.toml<\/code>:<\/p>\n<pre><code>[dependencies] tower = \"0.5.2\" # \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 \u0434\u043b\u044f middleware<\/code><\/pre>\n<p>\u041d\u043e\u0432\u044b\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u044b:<\/p>\n<pre><code class=\"rust\">use hyper::service::Service; use tower::ServiceBuilder;  <\/code><\/pre>\n<ul>\n<li>\n<p><code>Service<\/code> &#8212; \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u043a \u0441\u0435\u0442\u0435\u0432\u043e\u043c\u0443 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044e (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>service_fn(router)<\/code> \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u044d\u0442\u043e\u0433\u043e \u0442\u0440\u0435\u0439\u0442\u0430)<\/p>\n<\/li>\n<li>\n<p><code>ServiceBuilder<\/code> &#8212; \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c middleware \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0438\u0448\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 middleware \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432:<\/p>\n<pre><code class=\"rust\">\/\/\/ \u041f\u0440\u043e\u0441\u0442\u0430\u044f \u043e\u0431\u0451\u0440\u0442\u043a\u0430, \u043b\u043e\u0433\u0438\u0440\u0443\u044e\u0449\u0430\u044f HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u044b   #[derive(Debug, Clone)]   pub struct Logger&lt;S&gt; {       \/\/\/ \u0421\u0435\u0440\u0432\u0438\u0441, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430       inner: S,   }      impl&lt;S&gt; Logger&lt;S&gt; {       \/\/\/ \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u043b\u043e\u0433\u0435\u0440\u0430, \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u044e\u0449\u0435\u0433\u043e \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0435\u0440\u0432\u0438\u0441       pub fn new(inner: S) -&gt; Self {           Logger { inner }       }   }      type Req = Request&lt;Incoming&gt;;      \/\/\/ \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u0440\u0435\u0439\u0442\u0430 `Service` \u0434\u043b\u044f `Logger`,   \/\/\/ \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043a\u0430\u043a middleware   impl&lt;S&gt; Service&lt;Req&gt; for Logger&lt;S&gt;   where       S: Service&lt;Req&gt;,  \/\/ \u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0442\u0440\u0435\u0439\u0442 `Service`   {       \/\/ \u0422\u0438\u043f \u043e\u0442\u0432\u0435\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u0438\u043c \u0436\u0435, \u043a\u0430\u043a \u0443 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430       type Response = S::Response;       \/\/ \u0422\u0438\u043f \u043e\u0448\u0438\u0431\u043a\u0438 - \u0442\u043e\u0436\u0435 \u0442\u0430\u043a\u043e\u0439 \u0436\u0435       type Error = S::Error;       \/\/ \u0422\u0438\u043f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e future (\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430)       type Future = S::Future;          \/\/\/ \u041c\u0435\u0442\u043e\u0434, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435       fn call(&amp;self, req: Req) -&gt; Self::Future {           \/\/ \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043c\u0435\u0442\u043e\u0434 \u0438 \u043f\u0443\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u0430<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-463069","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/463069","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=463069"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/463069\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=463069"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=463069"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=463069"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}