mirror of
https://github.com/actix/actix-web.git
synced 2024-12-01 14:01:37 +00:00
add simple websocket example
This commit is contained in:
parent
9fd84a0aef
commit
71dc9edf8e
7 changed files with 181 additions and 36 deletions
|
@ -1,32 +0,0 @@
|
||||||
import asyncio
|
|
||||||
import aiohttp
|
|
||||||
|
|
||||||
|
|
||||||
def req1():
|
|
||||||
with aiohttp.MultipartWriter() as writer:
|
|
||||||
writer.append('test')
|
|
||||||
writer.append_json({'passed': True})
|
|
||||||
|
|
||||||
resp = yield from aiohttp.request(
|
|
||||||
"post", 'http://localhost:8080/multipart',
|
|
||||||
data=writer, headers=writer.headers)
|
|
||||||
print(resp)
|
|
||||||
assert 200 == resp.status
|
|
||||||
|
|
||||||
|
|
||||||
def req2():
|
|
||||||
with aiohttp.MultipartWriter() as writer:
|
|
||||||
writer.append('test')
|
|
||||||
writer.append_json({'passed': True})
|
|
||||||
writer.append(open('src/main.rs'))
|
|
||||||
|
|
||||||
resp = yield from aiohttp.request(
|
|
||||||
"post", 'http://localhost:8080/multipart',
|
|
||||||
data=writer, headers=writer.headers)
|
|
||||||
print(resp)
|
|
||||||
assert 200 == resp.status
|
|
||||||
|
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
|
||||||
loop.run_until_complete(req1())
|
|
||||||
loop.run_until_complete(req2())
|
|
12
examples/websocket/Cargo.toml
Normal file
12
examples/websocket/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "websocket-example"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "websocket"
|
||||||
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
actix = { git = "https://github.com/fafhrd91/actix.git" }
|
||||||
|
actix-web = { path = "../../" }
|
73
examples/websocket/src/main.rs
Normal file
73
examples/websocket/src/main.rs
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
#![allow(unused_variables)]
|
||||||
|
extern crate actix;
|
||||||
|
extern crate actix_web;
|
||||||
|
|
||||||
|
use actix::*;
|
||||||
|
use actix_web::*;
|
||||||
|
|
||||||
|
|
||||||
|
struct MyWebSocket;
|
||||||
|
|
||||||
|
impl Actor for MyWebSocket {
|
||||||
|
type Context = HttpContext<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Route for MyWebSocket {
|
||||||
|
type State = ();
|
||||||
|
|
||||||
|
fn request(req: HttpRequest, payload: Payload, ctx: &mut HttpContext<Self>) -> Reply<Self>
|
||||||
|
{
|
||||||
|
match ws::handshake(&req) {
|
||||||
|
Ok(resp) => {
|
||||||
|
ctx.start(resp);
|
||||||
|
ctx.add_stream(ws::WsStream::new(payload));
|
||||||
|
Reply::async(MyWebSocket)
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
Reply::reply(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResponseType<ws::Message> for MyWebSocket {
|
||||||
|
type Item = ();
|
||||||
|
type Error = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StreamHandler<ws::Message> for MyWebSocket {}
|
||||||
|
|
||||||
|
impl Handler<ws::Message> for MyWebSocket {
|
||||||
|
fn handle(&mut self, msg: ws::Message, ctx: &mut HttpContext<Self>)
|
||||||
|
-> Response<Self, ws::Message>
|
||||||
|
{
|
||||||
|
println!("WS: {:?}", msg);
|
||||||
|
match msg {
|
||||||
|
ws::Message::Ping(msg) => ws::WsWriter::pong(ctx, msg),
|
||||||
|
ws::Message::Text(text) => ws::WsWriter::text(ctx, &text),
|
||||||
|
ws::Message::Binary(bin) => ws::WsWriter::binary(ctx, bin),
|
||||||
|
ws::Message::Closed | ws::Message::Error => {
|
||||||
|
ctx.stop();
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
Self::empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let sys = actix::System::new("ws-example");
|
||||||
|
|
||||||
|
HttpServer::new(
|
||||||
|
RoutingMap::default()
|
||||||
|
.resource("/ws/", |r| r.get::<MyWebSocket>())
|
||||||
|
.app("/", Application::default()
|
||||||
|
.route_handler("/", StaticFiles::new("static/", true))
|
||||||
|
.finish())
|
||||||
|
.finish())
|
||||||
|
.serve::<_, ()>("127.0.0.1:8080").unwrap();
|
||||||
|
|
||||||
|
println!("Started http server: 127.0.0.1:8080");
|
||||||
|
let _ = sys.run();
|
||||||
|
}
|
90
examples/websocket/static/index.html
Normal file
90
examples/websocket/static/index.html
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js">
|
||||||
|
</script>
|
||||||
|
<script language="javascript" type="text/javascript">
|
||||||
|
$(function() {
|
||||||
|
var conn = null;
|
||||||
|
function log(msg) {
|
||||||
|
var control = $('#log');
|
||||||
|
control.html(control.html() + msg + '<br/>');
|
||||||
|
control.scrollTop(control.scrollTop() + 1000);
|
||||||
|
}
|
||||||
|
function connect() {
|
||||||
|
disconnect();
|
||||||
|
var wsUri = (window.location.protocol=='https:'&&'wss://'||'ws://')+window.location.host + '/ws/';
|
||||||
|
conn = new WebSocket(wsUri);
|
||||||
|
log('Connecting...');
|
||||||
|
conn.onopen = function() {
|
||||||
|
log('Connected.');
|
||||||
|
update_ui();
|
||||||
|
};
|
||||||
|
conn.onmessage = function(e) {
|
||||||
|
log('Received: ' + e.data);
|
||||||
|
};
|
||||||
|
conn.onclose = function() {
|
||||||
|
log('Disconnected.');
|
||||||
|
conn = null;
|
||||||
|
update_ui();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function disconnect() {
|
||||||
|
if (conn != null) {
|
||||||
|
log('Disconnecting...');
|
||||||
|
conn.close();
|
||||||
|
conn = null;
|
||||||
|
update_ui();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function update_ui() {
|
||||||
|
var msg = '';
|
||||||
|
if (conn == null) {
|
||||||
|
$('#status').text('disconnected');
|
||||||
|
$('#connect').html('Connect');
|
||||||
|
} else {
|
||||||
|
$('#status').text('connected (' + conn.protocol + ')');
|
||||||
|
$('#connect').html('Disconnect');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$('#connect').click(function() {
|
||||||
|
if (conn == null) {
|
||||||
|
connect();
|
||||||
|
} else {
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
update_ui();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
$('#send').click(function() {
|
||||||
|
var text = $('#text').val();
|
||||||
|
log('Sending: ' + text);
|
||||||
|
conn.send(text);
|
||||||
|
$('#text').val('').focus();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
$('#text').keyup(function(e) {
|
||||||
|
if (e.keyCode === 13) {
|
||||||
|
$('#send').click();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h3>Chat!</h3>
|
||||||
|
<div>
|
||||||
|
<button id="connect">Connect</button> | Status:
|
||||||
|
<span id="status">disconnected</span>
|
||||||
|
</div>
|
||||||
|
<div id="log"
|
||||||
|
style="width:20em;height:15em;overflow:auto;border:1px solid black">
|
||||||
|
</div>
|
||||||
|
<form id="chatform" onsubmit="return false;">
|
||||||
|
<input id="text" type="text" />
|
||||||
|
<input id="send" type="button" value="Send" />
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -148,11 +148,11 @@ pub struct HttpChannel<T: 'static, A: 'static> {
|
||||||
keepalive_timer: Option<Timeout>,
|
keepalive_timer: Option<Timeout>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: 'static, A: 'static> Drop for HttpChannel<T, A> {
|
/*impl<T: 'static, A: 'static> Drop for HttpChannel<T, A> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
println!("Drop http channel");
|
println!("Drop http channel");
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
impl<T, A> Actor for HttpChannel<T, A>
|
impl<T, A> Actor for HttpChannel<T, A>
|
||||||
where T: AsyncRead + AsyncWrite + 'static, A: 'static
|
where T: AsyncRead + AsyncWrite + 'static, A: 'static
|
||||||
|
|
|
@ -129,8 +129,10 @@ impl StaticFiles {
|
||||||
impl<S: 'static> RouteHandler<S> for StaticFiles {
|
impl<S: 'static> RouteHandler<S> for StaticFiles {
|
||||||
|
|
||||||
fn set_prefix(&mut self, prefix: String) {
|
fn set_prefix(&mut self, prefix: String) {
|
||||||
|
if prefix != "/" {
|
||||||
self.prefix += &prefix;
|
self.prefix += &prefix;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle(&self, req: HttpRequest, payload: Payload, state: Rc<S>) -> Task {
|
fn handle(&self, req: HttpRequest, payload: Payload, state: Rc<S>) -> Task {
|
||||||
if !self.accessible {
|
if !self.accessible {
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
//! {
|
//! {
|
||||||
//! match msg {
|
//! match msg {
|
||||||
//! ws::Message::Ping(msg) => ws::WsWriter::pong(ctx, msg),
|
//! ws::Message::Ping(msg) => ws::WsWriter::pong(ctx, msg),
|
||||||
//! ws::Message::Text(text) => ws::WsWriter::text(ctx, text),
|
//! ws::Message::Text(text) => ws::WsWriter::text(ctx, &text),
|
||||||
//! ws::Message::Binary(bin) => ws::WsWriter::binary(ctx, bin),
|
//! ws::Message::Binary(bin) => ws::WsWriter::binary(ctx, bin),
|
||||||
//! _ => (),
|
//! _ => (),
|
||||||
//! }
|
//! }
|
||||||
|
|
Loading…
Reference in a new issue