1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-11-25 11:01:14 +00:00

add simple websocket example

This commit is contained in:
Nikolay Kim 2017-10-20 21:08:38 -07:00
parent 9fd84a0aef
commit 71dc9edf8e
7 changed files with 181 additions and 36 deletions

View file

@ -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())

View 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 = "../../" }

View 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();
}

View 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>&nbsp;|&nbsp;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>

View file

@ -148,11 +148,11 @@ pub struct HttpChannel<T: 'static, A: 'static> {
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) {
println!("Drop http channel");
}
}
}*/
impl<T, A> Actor for HttpChannel<T, A>
where T: AsyncRead + AsyncWrite + 'static, A: 'static

View file

@ -129,7 +129,9 @@ impl StaticFiles {
impl<S: 'static> RouteHandler<S> for StaticFiles {
fn set_prefix(&mut self, prefix: String) {
self.prefix += &prefix;
if prefix != "/" {
self.prefix += &prefix;
}
}
fn handle(&self, req: HttpRequest, payload: Payload, state: Rc<S>) -> Task {

View file

@ -49,7 +49,7 @@
//! {
//! match 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),
//! _ => (),
//! }