44 anyhow:: { Error , Result } ,
55 http:: { header:: HeaderName , HeaderValue } ,
66 once_cell:: unsync:: OnceCell ,
7- pyo3:: { FromPyObject , IntoPy , PyErr , PyObject , Python } ,
7+ pyo3:: { types :: PyModule , PyObject , PyResult , Python } ,
88 spin_sdk:: http:: { Request , Response } ,
99 std:: { ops:: Deref , str} ,
1010} ;
1111
1212thread_local ! {
13- static REQUEST : OnceCell <PyObject > = OnceCell :: new( ) ;
1413 static HANDLE_REQUEST : OnceCell <PyObject > = OnceCell :: new( ) ;
1514}
1615
17- struct HttpRequest < ' a > {
18- method : & ' a str ,
19- uri : & ' a str ,
20- headers : Vec < ( & ' a str , & ' a str ) > ,
16+ #[ pyo3:: pyclass]
17+ #[ pyo3( name = "Request" ) ]
18+ struct HttpRequest {
19+ #[ pyo3( get) ]
20+ method : String ,
21+ #[ pyo3( get) ]
22+ uri : String ,
23+ #[ pyo3( get) ]
24+ headers : Vec < ( String , String ) > ,
2125 // todo: this should be a byte slice, but make sure it gets converted to/from Python correctly
22- body : Option < & ' a str > ,
23- }
24-
25- impl IntoPy < PyObject > for HttpRequest < ' _ > {
26- fn into_py ( self , py : Python < ' _ > ) -> PyObject {
27- REQUEST . with ( |cell| {
28- cell. get ( )
29- . unwrap ( )
30- . call1 ( py, ( self . method , self . uri , self . headers , self . body ) )
31- . unwrap ( )
32- } )
33- }
26+ #[ pyo3( get) ]
27+ body : Option < String > ,
3428}
3529
36- #[ derive( FromPyObject ) ]
30+ #[ derive( Clone ) ]
31+ #[ pyo3:: pyclass]
32+ #[ pyo3( name = "Response" ) ]
3733struct HttpResponse {
3834 status : u16 ,
3935 headers : Vec < ( String , String ) > ,
4036 // todo: this should be a byte slice, but make sure it gets converted to/from Python correctly
4137 body : Option < String > ,
4238}
4339
40+ #[ pyo3:: pymethods]
41+ impl HttpResponse {
42+ #[ new]
43+ fn new ( status : u16 , headers : Vec < ( String , String ) > , body : Option < String > ) -> Self {
44+ Self {
45+ status,
46+ headers,
47+ body,
48+ }
49+ }
50+ }
51+
52+ #[ pyo3:: pymodule]
53+ #[ pyo3( name = "spin_http" ) ]
54+ fn spin_http_module ( _py : Python < ' _ > , module : & PyModule ) -> PyResult < ( ) > {
55+ module. add_class :: < HttpRequest > ( ) ?;
56+ module. add_class :: < HttpResponse > ( )
57+ }
58+
4459fn do_init ( ) -> Result < ( ) > {
60+ pyo3:: append_to_inittab!( spin_http_module) ;
61+
4562 pyo3:: prepare_freethreaded_python ( ) ;
4663
4764 Python :: with_gil ( |py| {
48- REQUEST . with ( |cell| {
49- cell. set ( py. import ( "spin_http" ) ?. getattr ( "Request" ) ?. into ( ) )
50- . unwrap ( ) ;
51-
52- Ok :: < _ , PyErr > ( ( ) )
53- } ) ?;
54-
5565 HANDLE_REQUEST . with ( |cell| {
5666 cell. set ( py. import ( "app" ) ?. getattr ( "handle_request" ) ?. into ( ) )
5767 . unwrap ( ) ;
@@ -72,17 +82,22 @@ pub extern "C" fn init() {
7282fn handle ( request : Request ) -> Result < Response > {
7383 let uri = request. uri ( ) . to_string ( ) ;
7484 let request = HttpRequest {
75- method : request. method ( ) . as_str ( ) ,
76- uri : & uri ,
85+ method : request. method ( ) . as_str ( ) . to_owned ( ) ,
86+ uri,
7787 headers : request
7888 . headers ( )
7989 . iter ( )
80- . map ( |( k, v) | Ok ( ( k. as_str ( ) , str:: from_utf8 ( v. as_bytes ( ) ) ?) ) )
90+ . map ( |( k, v) | {
91+ Ok ( (
92+ k. as_str ( ) . to_owned ( ) ,
93+ str:: from_utf8 ( v. as_bytes ( ) ) ?. to_owned ( ) ,
94+ ) )
95+ } )
8196 . collect :: < Result < _ > > ( ) ?,
8297 body : request
8398 . body ( )
8499 . as_ref ( )
85- . map ( |bytes| Ok :: < _ , Error > ( str:: from_utf8 ( bytes) ?) )
100+ . map ( |bytes| Ok :: < _ , Error > ( str:: from_utf8 ( bytes) ?. to_owned ( ) ) )
86101 . transpose ( ) ?,
87102 } ;
88103
0 commit comments