Websocket 问:Rust,您如何使用tokio tungstenite accept_hdr_async函数获取标题?

Websocket 问:Rust,您如何使用tokio tungstenite accept_hdr_async函数获取标题?,websocket,rust,header,tokio,Websocket,Rust,Header,Tokio,我正在试验Rust tokio tungstenite软件包,以创建基于URL的聊天室。例如,我有一个客户端连接到ws://localhost:8080/abcd。我的理解是,我必须使用tokio_tungstenite::accept_hdr_async函数来访问标题以获取路径,但我在使用它时遇到了问题。我的copy\u headers\u callback的第二个参数应该是什么 我不确定我的方法是否合理。我刚开始生锈,它正在踢我的屁股。如果有任何见解,我将不胜感激 我的代码基于以下示例: 使

我正在试验Rust tokio tungstenite软件包,以创建基于URL的聊天室。例如,我有一个客户端连接到
ws://localhost:8080/abcd
。我的理解是,我必须使用tokio_tungstenite::accept_hdr_async函数来访问标题以获取路径,但我在使用它时遇到了问题。我的
copy\u headers\u callback
的第二个参数应该是什么

我不确定我的方法是否合理。我刚开始生锈,它正在踢我的屁股。如果有任何见解,我将不胜感激

我的代码基于以下示例:

使用std::{
集合::HashMap,
环境,
io::错误为IoError,
net::SocketAddr,
sync::{Arc,Mutex},
标记:Unpin,
};
使用futures_channel::mpsc::{unbounded,UnboundedSender};
使用futures_util::{future,pin_mut,stream::trystreamText,streamxt};
使用tokio::net::{TcpListener,TcpStream};
使用钨铅矿:{
协议::消息,
握手::服务器::{Request},
};
类型发送器=无界发送器;
类型PeerMap=弧;
使用serde::{反序列化,序列化};
#[派生(序列化、反序列化)]
结构广播Jsonstruct{
消息:String,
发件人地址:SocketAddress,
}
异步fn句柄连接(对等映射:PeerMap,原始流:TcpStream,客户端地址:SocketAddr){
println!(“来自:{},原始流:{},客户端地址,原始流。本地地址().unwrap())的传入TCP连接);
让复制_头_回调=|请求:&请求|{
对于request.headers().iter()中的(名称、值){
println!((“名称:{},值:”,Name.to_string())
//headers.insert(name.to_string(),value.clone());
}
Ok(无)
};
//接受新的异步WebSocket连接
让ws_stream=tokio_tungstenite::accept_hdr_async(
原始溪流,
复制\u头\u回调,
)
.等待
.expect(“websocket握手时出错”);
println!(“建立的WebSocket连接:{}”,客户端地址);
//将此对等体的写入部分插入对等体映射。
let(发送方,接收方)=无界();
对等映射.锁().展开().插入(客户端地址,发送方);
//设置传入和传出
let(传出、传入)=ws_stream.split();
让广播_incoming=incoming。为每个_尝试_(| msg |{
println!(“收到来自{}:{}的消息,客户机地址,msg.to_text().unwrap());
让peers=peer_map.lock().unwrap();
//创建要序列化的新结构
让广播_data=BroadcastJsonStruct{
消息:msg.to_text().unwrap().to_owned(),
发送者地址:客户端地址到所拥有的(),
};
让新消息=消息::文本(
serde_json::to_字符串(&broadcast_数据)。预期(“序列化广播_数据时出现问题”)
);
println!(“新消息{}”,New_msg.to_text().unwrap());
//我们想把这个信息传播给每个人,除了我们自己。
//筛选器返回的地址不是当前地址
让我们向你的接受者广播=
peers.iter().filter(|(peer_addr,|)peer_addr!=&&client_addr).map(|(|,ws_sink)| ws_sink);
//将邮件发送给所有收件人
对于广播收件人中的recp{
recp.unbounded_send(new_msg.clone()).unwrap();
}
future::ok(())
});
让我们接收来自其他人的消息=receiver.map(确定)。forward(传出);
pin_mut!(广播接收,从其他人接收);
未来::选择(广播接收,从其他人接收)。等待;
println!(“{}已断开连接”&客户端地址);
对等映射.lock().unwrap().remove(&client\u addr);
}
#[tokio::main]
异步fn main()->结果{
//查看命令行参数中是否指定了服务器地址,否则使用默认地址
让server_addr=env::args().nth(1).展开_或_else(||“127.0.0.1:8080.”到_string());
让state=PeerMap::new(Mutex::new(HashMap::new());
//创建我们将接受连接的事件循环和TCP侦听器。
让我们试试\u socket=TcpListener::bind(&server\u addr)。wait;//在地址上创建服务器
let listener=try_socket.expect(“绑定失败”);
println!(“侦听:{}”,服务器地址);
//让我们在单独的任务中生成每个连接的处理。
而让Ok((stream,client_addr))=listener.accept().wait{
tokio::spawn(handle_连接(state.clone(),stream,client_addr));
}
好(())
}
我的错误:

error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument
   --> src/main.rs:45:9
    |
34  |     let copy_headers_callback = |request: &Request| {
    |                                 ------------------- takes 1 argument
...
45  |         copy_headers_callback,
    |         ^^^^^^^^^^^^^^^^^^^^^ expected closure that takes 2 arguments
    | 
   ::: /Users/harryli/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-tungstenite-0.12.0/src/lib.rs:151:8
    |
151 |     C: Callback + Unpin,
    |        -------- required by this bound in `accept_hdr_async`
    |
    = note: required because of the requirements on the impl of `Callback` for `[closure@src/main.rs:34:33: 40:10]`

error: aborting due to previous error; 1 warning emitted

我最终让回调函数打印标题名和值,如下所示

我在标题中找不到路径
/abcd
。我的解决方法是将
window.location.pathname
作为协议传递,然后在服务器中访问该协议

下面的代码显示了一个服务器的工作示例,该服务器仅使用相同的协议向客户端广播消息

JS

constsocket=newwebsocket(“ws://localhost:8080”,window.location.pathname.replace(//\//ig,“-”)
锈回收:

let mut protocol=HeaderValue::from_static(“”);
让copy_headers_callback=|请求:&请求,mut响应:响应|->结果{
对于request.headers().iter()中的(名称、值){
println!(“名称:{},值:{}”,Name.to_string(),value.to_str()。expect(“预期值”);
}
//访问请求中的协议,然后在响应中设置它
protocol=request.headers().get(SEC_WEBSOCKET_protocol).expect(“客户端应指定协议”)。to_owned();//保存协议以在闭包外部使用
让response_protocol=request.headers().get(SEC_WEBSOCKET_protocol).expect(“客户端应指定协议”).to_owned();
response.headers_mut().insert(SEC_WEBSOCKET_协议,response_协议);
Ok(回复)
};
//接受新的异步WebSocket连接
让我们
[package]
name = "server"
version = "0.1.0"
authors = ["harryli0088 <harryli0088@gmail.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tokio-tungstenite = "*"
tokio = { version = "0.3", features = ["full"] }
futures-channel = "0.3"
futures-util = "0.3.8"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
http = "0.2.2"

[dependencies.tungstenite]
version = "0.11.1"
default-features = false