1
0
mirror of https://github.com/actix/examples synced 2025-06-28 09:50:36 +02:00

actix examples in actix release version

This commit is contained in:
krircc
2018-04-13 09:18:42 +08:00
parent ad58e559a0
commit 3ebde8e7c2
88 changed files with 3829 additions and 2 deletions

19
websocket/Cargo.toml Normal file
View File

@ -0,0 +1,19 @@
[package]
name = "websocket"
version = "0.1.0"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
[[bin]]
name = "server"
path = "src/main.rs"
[[bin]]
name = "client"
path = "src/client.rs"
[dependencies]
env_logger = "*"
futures = "0.1"
tokio-core = "0.1"
actix = "0.5"
actix-web = "^0.5"

27
websocket/README.md Normal file
View File

@ -0,0 +1,27 @@
# websocket
Simple echo websocket server.
## Usage
### server
```bash
cd actix-web/examples/websocket
cargo run
# Started http server: 127.0.0.1:8080
```
### web client
- [http://localhost:8080/ws/index.html](http://localhost:8080/ws/index.html)
### python client
- ``pip install aiohttp``
- ``python websocket-client.py``
if ubuntu :
- ``pip3 install aiohttp``
- ``python3 websocket-client.py``

113
websocket/src/client.rs Normal file
View File

@ -0,0 +1,113 @@
//! Simple websocket client.
#![allow(unused_variables)]
extern crate actix;
extern crate actix_web;
extern crate env_logger;
extern crate futures;
extern crate tokio_core;
use std::{io, thread};
use std::time::Duration;
use actix::*;
use futures::Future;
use actix_web::ws::{Message, ProtocolError, Client, ClientWriter};
fn main() {
::std::env::set_var("RUST_LOG", "actix_web=info");
let _ = env_logger::init();
let sys = actix::System::new("ws-example");
Arbiter::handle().spawn(
Client::new("http://127.0.0.1:8080/ws/")
.connect()
.map_err(|e| {
println!("Error: {}", e);
()
})
.map(|(reader, writer)| {
let addr: Addr<Syn, _> = ChatClient::create(|ctx| {
ChatClient::add_stream(reader, ctx);
ChatClient(writer)
});
// start console loop
thread::spawn(move|| {
loop {
let mut cmd = String::new();
if io::stdin().read_line(&mut cmd).is_err() {
println!("error");
return
}
addr.do_send(ClientCommand(cmd));
}
});
()
})
);
let _ = sys.run();
}
struct ChatClient(ClientWriter);
#[derive(Message)]
struct ClientCommand(String);
impl Actor for ChatClient {
type Context = Context<Self>;
fn started(&mut self, ctx: &mut Context<Self>) {
// start heartbeats otherwise server will disconnect after 10 seconds
self.hb(ctx)
}
fn stopped(&mut self, _: &mut Context<Self>) {
println!("Disconnected");
// Stop application on disconnect
Arbiter::system().do_send(actix::msgs::SystemExit(0));
}
}
impl ChatClient {
fn hb(&self, ctx: &mut Context<Self>) {
ctx.run_later(Duration::new(1, 0), |act, ctx| {
act.0.ping("");
act.hb(ctx);
});
}
}
/// Handle stdin commands
impl Handler<ClientCommand> for ChatClient {
type Result = ();
fn handle(&mut self, msg: ClientCommand, ctx: &mut Context<Self>) {
self.0.text(msg.0)
}
}
/// Handle server websocket messages
impl StreamHandler<Message, ProtocolError> for ChatClient {
fn handle(&mut self, msg: Message, ctx: &mut Context<Self>) {
match msg {
Message::Text(txt) => println!("Server: {:?}", txt),
_ => ()
}
}
fn started(&mut self, ctx: &mut Context<Self>) {
println!("Connected");
}
fn finished(&mut self, ctx: &mut Context<Self>) {
println!("Server disconnected");
ctx.stop()
}
}

66
websocket/src/main.rs Normal file
View File

@ -0,0 +1,66 @@
//! Simple echo websocket server.
//! Open `http://localhost:8080/ws/index.html` in browser
//! or [python console client](https://github.com/actix/actix-web/blob/master/examples/websocket-client.py)
//! could be used for testing.
#![allow(unused_variables)]
extern crate actix;
extern crate actix_web;
extern crate env_logger;
use actix::prelude::*;
use actix_web::{
http, middleware, server, fs, ws, App, HttpRequest, HttpResponse, Error};
/// do websocket handshake and start `MyWebSocket` actor
fn ws_index(r: HttpRequest) -> Result<HttpResponse, Error> {
ws::start(r, MyWebSocket)
}
/// websocket connection is long running connection, it easier
/// to handle with an actor
struct MyWebSocket;
impl Actor for MyWebSocket {
type Context = ws::WebsocketContext<Self>;
}
/// Handler for `ws::Message`
impl StreamHandler<ws::Message, ws::ProtocolError> for MyWebSocket {
fn handle(&mut self, msg: ws::Message, ctx: &mut Self::Context) {
// process websocket messages
println!("WS: {:?}", msg);
match msg {
ws::Message::Ping(msg) => ctx.pong(&msg),
ws::Message::Text(text) => ctx.text(text),
ws::Message::Binary(bin) => ctx.binary(bin),
ws::Message::Close(_) => {
ctx.stop();
}
_ => (),
}
}
}
fn main() {
::std::env::set_var("RUST_LOG", "actix_web=info");
env_logger::init();
let sys = actix::System::new("ws-example");
server::new(
|| App::new()
// enable logger
.middleware(middleware::Logger::default())
// websocket route
.resource("/ws/", |r| r.method(http::Method::GET).f(ws_index))
// static files
.handler("/", fs::StaticFiles::new("../static/")
.index_file("index.html")))
// start http server on 127.0.0.1:8080
.bind("127.0.0.1:8080").unwrap()
.start();
println!("Started http server: 127.0.0.1:8080");
let _ = sys.run();
}

72
websocket/websocket-client.py Executable file
View File

@ -0,0 +1,72 @@
#!/usr/bin/env python3
"""websocket cmd client for wssrv.py example."""
import argparse
import asyncio
import signal
import sys
import aiohttp
def start_client(loop, url):
name = input('Please enter your name: ')
# send request
ws = yield from aiohttp.ClientSession().ws_connect(url, autoclose=False, autoping=False)
# input reader
def stdin_callback():
line = sys.stdin.buffer.readline().decode('utf-8')
if not line:
loop.stop()
else:
ws.send_str(name + ': ' + line)
loop.add_reader(sys.stdin.fileno(), stdin_callback)
@asyncio.coroutine
def dispatch():
while True:
msg = yield from ws.receive()
if msg.type == aiohttp.WSMsgType.TEXT:
print('Text: ', msg.data.strip())
elif msg.type == aiohttp.WSMsgType.BINARY:
print('Binary: ', msg.data)
elif msg.type == aiohttp.WSMsgType.PING:
ws.pong()
elif msg.type == aiohttp.WSMsgType.PONG:
print('Pong received')
else:
if msg.type == aiohttp.WSMsgType.CLOSE:
yield from ws.close()
elif msg.type == aiohttp.WSMsgType.ERROR:
print('Error during receive %s' % ws.exception())
elif msg.type == aiohttp.WSMsgType.CLOSED:
pass
break
yield from dispatch()
ARGS = argparse.ArgumentParser(
description="websocket console client for wssrv.py example.")
ARGS.add_argument(
'--host', action="store", dest='host',
default='127.0.0.1', help='Host name')
ARGS.add_argument(
'--port', action="store", dest='port',
default=8080, type=int, help='Port number')
if __name__ == '__main__':
args = ARGS.parse_args()
if ':' in args.host:
args.host, port = args.host.split(':', 1)
args.port = int(port)
url = 'http://{}:{}/ws/'.format(args.host, args.port)
loop = asyncio.get_event_loop()
loop.add_signal_handler(signal.SIGINT, loop.stop)
asyncio.Task(start_client(loop, url))
loop.run_forever()