2个版本
0.1.1 | 2023年2月2日 |
---|---|
0.1.0 | 2022年10月7日 |
#2 in #twisted
每月 28 次下载
用于 pyo3-matrix-synapse-modul…
20KB
291 行
通过tower::Service
处理Twisted请求
这个库帮助将Twisted的IRequest
转换为http::Request
,然后发送http::Response
返回。
用法
通过Service处理Twisted请求
use std::convert::Infallible;
use bytes::Bytes;
use http::{Request, Response};
use http_body::Full;
use pyo3::prelude::*;
use tower::util::BoxCloneService;
use pyo3_twisted_web::handle_twisted_request_through_service;
#[pyclass]
struct Handler {
service: BoxCloneService<Request<Full<Bytes>>, Response<String>, Infallible>,
}
#[pymethods]
impl Handler {
#[new]
fn new() -> Self {
let service = tower::service_fn(|_request: Request<_>| async move {
let response = Response::new(String::from("hello"));
Ok(response)
});
Self {
service: BoxCloneService::new(service),
}
}
fn handle<'a>(&self, twisted_request: &'a PyAny) -> PyResult<&'a PyAny> {
let service = self.service.clone();
handle_twisted_request_through_service(service, twisted_request)
}
}
#[pymodule]
fn my_handler(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<Handler>()?;
Ok(())
}
Python端
from twisted.internet import asyncioreactor
asyncioreactor.install()
import asyncio
from twisted.internet.defer import ensureDeferred, Deferred
from twisted.web.server import NOT_DONE_YET
from twisted.web import server, resource
from twisted.internet import endpoints, reactor
from my_handler import Handler
class MyResource(resource.Resource):
isLeaf = True
def __init__(self) -> None:
super().__init__()
self.handler = Handler()
def render(self, request):
f = self.handler.handle(request)
ensureDeferred(Deferred.fromFuture(f))
return NOT_DONE_YET
endpoints.serverFromString(reactor, "tcp:8888").listen(server.Site(MyResource()))
reactor.run()
在Service外部定义Twisted Resource
use std::convert::Infallible;
use bytes::Bytes;
use http::{Request, Response};
use pyo3::prelude::*;
use pyo3_twisted_web::Resource;
// Via a (sub)class
#[pyclass(extends=Resource)]
struct MyResource;
#[pymethods]
impl MyResource {
#[new]
fn new() -> (Self, Resource) {
let service = tower::service_fn(|_request: Request<_>| async move {
let response = Response::new(String::from("hello"));
Ok(response)
});
let super_ = Resource::from_service::<_, _, Infallible>(service);
(Self, super_)
}
}
// Via a function
#[pyfunction]
fn get_resource(py: Python) -> PyResult<Py<Resource>> {
let service = tower::service_fn(|_request: Request<_>| async move {
let response = Response::new(String::from("hello"));
Ok(response)
});
Py::new(py, Resource::from_service::<_, _, Infallible>(service))
}
#[pymodule]
fn my_handler(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<MyResource>()?;
m.add_function(wrap_pyfunction!(get_resource, m)?)?;
Ok(())
}
Python端
from twisted.internet import asyncioreactor
asyncioreactor.install()
import asyncio
from twisted.web.server import Site
from twisted.internet import endpoints, reactor
from my_handler import MyResource, get_resource
endpoints.serverFromString(reactor, "tcp:8888").listen(Site(MyResource()))
# or
endpoints.serverFromString(reactor, "tcp:8888").listen(Site(get_resource()))
reactor.run()
限制
应安装Twisted asyncioreactor
。通过pyo3-asyncio
使用tokio
运行时执行Future,这需要一个正在运行的asyncio事件循环。
Service必须接受一个http::Request<bytes::Bytes>
,并返回一个http::Request<impl bytes::Buf>
。必须将Service::Error
转换为pyo3::PyErr
(如果你不希望你的处理程序抛出Python异常,则std::convert::Infallible
是一个很好的选择)。
依赖关系
~7–14MB
~154K SLoC