2008-05-23 23:21:07 +04:00
/*
Unix SMB / CIFS implementation .
Samba utility functions
Copyright © Jelmer Vernooij < jelmer @ samba . org > 2008
Implementation of the WSGI interface described in PEP0333
( http : //www.python.org/dev/peps/pep-0333)
2010-11-14 19:36:51 +03:00
2008-05-23 23:21:07 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
2010-11-14 19:36:51 +03:00
2008-05-23 23:21:07 +04:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2010-11-14 19:36:51 +03:00
2008-05-23 23:21:07 +04:00
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2009-10-23 09:23:01 +04:00
# include <Python.h>
2008-05-23 23:21:07 +04:00
# include "includes.h"
2008-05-24 20:13:30 +04:00
# include "web_server/web_server.h"
2008-10-11 23:31:42 +04:00
# include "../lib/util/dlinklist.h"
2008-09-21 22:01:00 +04:00
# include "lib/tls/tls.h"
2010-04-28 16:52:40 +04:00
# include "lib/tsocket/tsocket.h"
2012-12-28 18:37:14 +04:00
# include "python/modules.h"
2009-01-08 14:20:20 +03:00
2008-09-21 20:45:09 +04:00
typedef struct {
PyObject_HEAD
struct websrv_context * web ;
} web_request_Object ;
2008-05-24 20:13:30 +04:00
static PyObject * start_response ( PyObject * self , PyObject * args , PyObject * kwargs )
2008-05-23 23:21:07 +04:00
{
2008-09-21 20:45:09 +04:00
PyObject * response_header , * exc_info = NULL ;
2008-05-23 23:21:07 +04:00
char * status ;
2010-12-12 19:27:36 +03:00
Py_ssize_t i ;
2008-05-23 23:21:07 +04:00
const char * kwnames [ ] = {
" status " , " response_header " , " exc_info " , NULL
} ;
2008-09-21 20:45:09 +04:00
web_request_Object * py_web = ( web_request_Object * ) self ;
struct websrv_context * web = py_web - > web ;
struct http_header * headers = NULL ;
2008-05-23 23:21:07 +04:00
2008-09-21 20:45:09 +04:00
if ( ! PyArg_ParseTupleAndKeywords ( args , kwargs , " sO|O:start_response " , discard_const_p ( char * , kwnames ) , & status , & response_header , & exc_info ) ) {
2008-05-23 23:21:07 +04:00
return NULL ;
}
2008-09-21 20:45:09 +04:00
/* FIXME: exc_info */
2008-05-23 23:21:07 +04:00
2008-09-21 20:45:09 +04:00
if ( ! PyList_Check ( response_header ) ) {
PyErr_SetString ( PyExc_TypeError , " response_header should be list " ) ;
return NULL ;
}
for ( i = 0 ; i < PyList_Size ( response_header ) ; i + + ) {
struct http_header * hdr = talloc_zero ( web , struct http_header ) ;
PyObject * item = PyList_GetItem ( response_header , i ) ;
PyObject * py_name , * py_value ;
if ( ! PyTuple_Check ( item ) ) {
PyErr_SetString ( PyExc_TypeError , " Expected tuple " ) ;
return NULL ;
}
if ( PyTuple_Size ( item ) ! = 2 ) {
PyErr_SetString ( PyExc_TypeError , " header tuple has invalid size, expected 2 " ) ;
return NULL ;
}
py_name = PyTuple_GetItem ( item , 0 ) ;
if ( ! PyString_Check ( py_name ) ) {
PyErr_SetString ( PyExc_TypeError , " header name should be string " ) ;
return NULL ;
}
py_value = PyTuple_GetItem ( item , 1 ) ;
if ( ! PyString_Check ( py_value ) ) {
PyErr_SetString ( PyExc_TypeError , " header value should be string " ) ;
return NULL ;
}
hdr - > name = talloc_strdup ( hdr , PyString_AsString ( py_name ) ) ;
hdr - > value = talloc_strdup ( hdr , PyString_AsString ( py_value ) ) ;
DLIST_ADD ( headers , hdr ) ;
}
websrv_output_headers ( web , status , headers ) ;
2009-01-06 06:13:57 +03:00
Py_RETURN_NONE ;
2008-05-23 23:21:07 +04:00
}
2008-09-21 20:45:09 +04:00
static PyMethodDef web_request_methods [ ] = {
{ " start_response " , ( PyCFunction ) start_response , METH_VARARGS | METH_KEYWORDS , NULL } ,
{ NULL }
} ;
PyTypeObject web_request_Type = {
PyObject_HEAD_INIT ( NULL ) 0 ,
. tp_name = " wsgi.Request " ,
. tp_methods = web_request_methods ,
. tp_basicsize = sizeof ( web_request_Object ) ,
2010-12-29 20:56:13 +03:00
. tp_flags = Py_TPFLAGS_DEFAULT ,
2008-09-21 20:45:09 +04:00
} ;
2008-05-24 17:43:37 +04:00
typedef struct {
PyObject_HEAD
} error_Stream_Object ;
2008-05-24 05:54:47 +04:00
2008-05-24 17:43:37 +04:00
static PyObject * py_error_flush ( PyObject * self , PyObject * args , PyObject * kwargs )
{
/* Nothing to do here */
2009-01-06 06:13:57 +03:00
Py_RETURN_NONE ;
2008-05-24 17:43:37 +04:00
}
static PyObject * py_error_write ( PyObject * self , PyObject * args , PyObject * kwargs )
{
const char * kwnames [ ] = { " str " , NULL } ;
char * str = NULL ;
2008-09-21 18:53:29 +04:00
if ( ! PyArg_ParseTupleAndKeywords ( args , kwargs , " s:write " , discard_const_p ( char * , kwnames ) , & str ) ) {
2008-05-24 17:43:37 +04:00
return NULL ;
}
2012-11-24 22:35:33 +04:00
DEBUG ( 0 , ( " %s " , str ) ) ;
2008-05-24 17:43:37 +04:00
2009-01-06 06:13:57 +03:00
Py_RETURN_NONE ;
2008-05-24 17:43:37 +04:00
}
static PyObject * py_error_writelines ( PyObject * self , PyObject * args , PyObject * kwargs )
{
const char * kwnames [ ] = { " seq " , NULL } ;
PyObject * seq = NULL , * item ;
2008-09-21 18:53:29 +04:00
if ( ! PyArg_ParseTupleAndKeywords ( args , kwargs , " O:writelines " , discard_const_p ( char * , kwnames ) , & seq ) ) {
2008-05-24 17:43:37 +04:00
return NULL ;
}
2012-11-24 22:35:33 +04:00
2008-05-24 17:43:37 +04:00
while ( ( item = PyIter_Next ( seq ) ) ) {
char * str = PyString_AsString ( item ) ;
2012-11-24 22:35:33 +04:00
DEBUG ( 0 , ( " %s " , str ) ) ;
2008-05-24 17:43:37 +04:00
}
2009-01-06 06:13:57 +03:00
Py_RETURN_NONE ;
2008-05-24 17:43:37 +04:00
}
static PyMethodDef error_Stream_methods [ ] = {
2008-09-21 20:45:09 +04:00
{ " flush " , ( PyCFunction ) py_error_flush , METH_VARARGS | METH_KEYWORDS , NULL } ,
{ " write " , ( PyCFunction ) py_error_write , METH_VARARGS | METH_KEYWORDS , NULL } ,
{ " writelines " , ( PyCFunction ) py_error_writelines , METH_VARARGS | METH_KEYWORDS , NULL } ,
2008-05-24 17:43:37 +04:00
{ NULL , NULL , 0 , NULL }
} ;
PyTypeObject error_Stream_Type = {
PyObject_HEAD_INIT ( NULL ) 0 ,
. tp_name = " wsgi.ErrorStream " ,
. tp_basicsize = sizeof ( error_Stream_Object ) ,
. tp_methods = error_Stream_methods ,
2010-12-29 20:56:13 +03:00
. tp_flags = Py_TPFLAGS_DEFAULT ,
2008-05-24 17:43:37 +04:00
} ;
typedef struct {
PyObject_HEAD
2008-09-21 22:01:00 +04:00
struct websrv_context * web ;
size_t offset ;
2008-05-24 17:43:37 +04:00
} input_Stream_Object ;
2008-09-21 22:01:00 +04:00
static PyObject * py_input_read ( PyObject * _self , PyObject * args , PyObject * kwargs )
2008-05-24 05:54:47 +04:00
{
2008-09-21 22:01:00 +04:00
const char * kwnames [ ] = { " size " , NULL } ;
PyObject * ret ;
input_Stream_Object * self = ( input_Stream_Object * ) _self ;
int size = - 1 ;
if ( ! PyArg_ParseTupleAndKeywords ( args , kwargs , " |i " , discard_const_p ( char * , kwnames ) , & size ) )
return NULL ;
/* Don't read beyond buffer boundaries */
if ( size = = - 1 )
size = self - > web - > input . partial . length - self - > offset ;
else
size = MIN ( size , self - > web - > input . partial . length - self - > offset ) ;
ret = PyString_FromStringAndSize ( ( char * ) self - > web - > input . partial . data + self - > offset , size ) ;
self - > offset + = size ;
2010-11-14 19:36:51 +03:00
2008-09-21 22:01:00 +04:00
return ret ;
2008-05-24 05:54:47 +04:00
}
2008-09-21 22:01:00 +04:00
static PyObject * py_input_readline ( PyObject * _self )
2008-05-24 17:43:37 +04:00
{
2008-09-21 20:45:09 +04:00
/* FIXME */
2008-09-21 22:01:00 +04:00
PyErr_SetString ( PyExc_NotImplementedError ,
" readline() not yet implemented " ) ;
2008-05-24 17:43:37 +04:00
return NULL ;
}
2008-09-21 22:01:00 +04:00
static PyObject * py_input_readlines ( PyObject * _self , PyObject * args , PyObject * kwargs )
2008-05-24 17:43:37 +04:00
{
2008-09-21 22:01:00 +04:00
const char * kwnames [ ] = { " hint " , NULL } ;
int hint ;
if ( ! PyArg_ParseTupleAndKeywords ( args , kwargs , " |i " , discard_const_p ( char * , kwnames ) , & hint ) )
return NULL ;
2008-09-21 20:45:09 +04:00
/* FIXME */
2008-09-21 22:01:00 +04:00
PyErr_SetString ( PyExc_NotImplementedError ,
" readlines() not yet implemented " ) ;
2008-05-24 17:43:37 +04:00
return NULL ;
}
2008-09-21 22:01:00 +04:00
static PyObject * py_input___iter__ ( PyObject * _self )
2008-05-24 05:54:47 +04:00
{
2008-09-21 20:45:09 +04:00
/* FIXME */
2008-09-21 22:01:00 +04:00
PyErr_SetString ( PyExc_NotImplementedError ,
" __iter__() not yet implemented " ) ;
2008-05-24 05:54:47 +04:00
return NULL ;
}
2008-05-24 17:43:37 +04:00
static PyMethodDef input_Stream_methods [ ] = {
2008-09-21 20:45:09 +04:00
{ " read " , ( PyCFunction ) py_input_read , METH_VARARGS | METH_KEYWORDS , NULL } ,
2008-09-21 22:01:00 +04:00
{ " readline " , ( PyCFunction ) py_input_readline , METH_NOARGS , NULL } ,
2008-09-21 20:45:09 +04:00
{ " readlines " , ( PyCFunction ) py_input_readlines , METH_VARARGS | METH_KEYWORDS , NULL } ,
2008-09-21 22:01:00 +04:00
{ " __iter__ " , ( PyCFunction ) py_input___iter__ , METH_NOARGS , NULL } ,
2008-05-24 17:43:37 +04:00
{ NULL , NULL , 0 , NULL }
} ;
PyTypeObject input_Stream_Type = {
PyObject_HEAD_INIT ( NULL ) 0 ,
. tp_name = " wsgi.InputStream " ,
. tp_basicsize = sizeof ( input_Stream_Object ) ,
. tp_methods = input_Stream_methods ,
2010-12-29 20:56:13 +03:00
. tp_flags = Py_TPFLAGS_DEFAULT ,
2008-05-24 17:43:37 +04:00
} ;
2008-09-21 22:01:00 +04:00
static PyObject * Py_InputHttpStream ( struct websrv_context * web )
2008-05-24 17:43:37 +04:00
{
2008-09-21 18:53:29 +04:00
input_Stream_Object * ret = PyObject_New ( input_Stream_Object , & input_Stream_Type ) ;
2008-09-21 22:01:00 +04:00
ret - > web = web ;
ret - > offset = 0 ;
2008-09-21 18:53:29 +04:00
return ( PyObject * ) ret ;
2008-05-24 17:43:37 +04:00
}
static PyObject * Py_ErrorHttpStream ( void )
{
2008-09-21 18:53:29 +04:00
error_Stream_Object * ret = PyObject_New ( error_Stream_Object , & error_Stream_Type ) ;
return ( PyObject * ) ret ;
2008-05-24 17:43:37 +04:00
}
2012-11-24 22:35:33 +04:00
static void DEBUG_Print_PyError ( int level , const char * message )
{
PyObject * old_stderr , * new_stderr ;
PyObject * sys_module ;
PyObject * ptype , * pvalue , * ptb ;
PyErr_Fetch ( & ptype , & pvalue , & ptb ) ;
DEBUG ( 0 , ( " WSGI: Server exception occurred: %s \n " , message ) ) ;
sys_module = PyImport_ImportModule ( " sys " ) ;
if ( sys_module = = NULL ) {
DEBUG ( 0 , ( " Unable to obtain sys module while printing error " ) ) ;
return ;
}
old_stderr = PyObject_GetAttrString ( sys_module , " stderr " ) ;
if ( old_stderr = = NULL ) {
DEBUG ( 0 , ( " Unable to obtain old stderr " ) ) ;
Py_DECREF ( sys_module ) ;
return ;
}
new_stderr = Py_ErrorHttpStream ( ) ;
if ( new_stderr = = NULL ) {
DEBUG ( 0 , ( " Unable to create error stream " ) ) ;
Py_DECREF ( sys_module ) ;
Py_DECREF ( old_stderr ) ;
return ;
}
PyObject_SetAttrString ( sys_module , " stderr " , new_stderr ) ;
Py_DECREF ( new_stderr ) ;
PyErr_Restore ( ptype , pvalue , ptb ) ;
PyErr_Print ( ) ;
PyObject_SetAttrString ( sys_module , " stderr " , old_stderr ) ;
Py_DECREF ( old_stderr ) ;
Py_DECREF ( sys_module ) ;
}
2008-09-21 22:01:00 +04:00
static PyObject * create_environ ( bool tls , int content_length , struct http_header * headers , const char * request_method , const char * servername , int serverport , PyObject * inputstream , const char * request_string )
2008-05-23 23:21:07 +04:00
{
2008-09-21 20:45:09 +04:00
PyObject * env ;
PyObject * py_scheme ;
2012-11-22 04:46:58 +04:00
PyObject * py_val ;
2008-09-21 20:45:09 +04:00
struct http_header * hdr ;
2008-09-21 22:01:00 +04:00
char * questionmark ;
2012-11-22 04:46:58 +04:00
2008-09-21 20:45:09 +04:00
env = PyDict_New ( ) ;
if ( env = = NULL ) {
2008-05-23 23:21:07 +04:00
return NULL ;
2008-09-21 20:45:09 +04:00
}
2008-05-24 05:54:47 +04:00
PyDict_SetItemString ( env , " wsgi.input " , inputstream ) ;
2012-11-22 04:46:58 +04:00
py_val = Py_ErrorHttpStream ( ) ;
if ( py_val = = NULL ) goto error ;
PyDict_SetItemString ( env , " wsgi.errors " , py_val ) ;
Py_DECREF ( py_val ) ;
py_val = Py_BuildValue ( " (i,i) " , 1 , 0 ) ;
if ( py_val = = NULL ) goto error ;
PyDict_SetItemString ( env , " wsgi.version " , py_val ) ;
Py_DECREF ( py_val ) ;
2008-05-23 23:21:07 +04:00
PyDict_SetItemString ( env , " wsgi.multithread " , Py_False ) ;
2012-11-22 04:46:59 +04:00
PyDict_SetItemString ( env , " wsgi.multiprocess " , Py_False ) ;
2008-05-23 23:21:07 +04:00
PyDict_SetItemString ( env , " wsgi.run_once " , Py_False ) ;
2012-11-22 04:46:58 +04:00
py_val = PyString_FromString ( " HTTP/1.0 " ) ;
if ( py_val = = NULL ) goto error ;
PyDict_SetItemString ( env , " SERVER_PROTOCOL " , py_val ) ;
Py_DECREF ( py_val ) ;
2008-09-21 20:45:09 +04:00
if ( content_length > 0 ) {
2012-11-22 04:46:58 +04:00
py_val = PyLong_FromLong ( content_length ) ;
if ( py_val = = NULL ) goto error ;
PyDict_SetItemString ( env , " CONTENT_LENGTH " , py_val ) ;
Py_DECREF ( py_val ) ;
2008-09-21 20:45:09 +04:00
}
2012-11-22 04:46:58 +04:00
py_val = PyString_FromString ( request_method ) ;
if ( py_val = = NULL ) goto error ;
PyDict_SetItemString ( env , " REQUEST_METHOD " , py_val ) ;
Py_DECREF ( py_val ) ;
2008-09-21 20:45:09 +04:00
2012-11-22 04:46:57 +04:00
/* There is always a single wsgi app to which all requests are redirected,
* so SCRIPT_NAME will be / */
2012-11-22 04:46:58 +04:00
py_val = PyString_FromString ( " / " ) ;
if ( py_val = = NULL ) goto error ;
PyDict_SetItemString ( env , " SCRIPT_NAME " , py_val ) ;
Py_DECREF ( py_val ) ;
2008-09-21 22:01:00 +04:00
questionmark = strchr ( request_string , ' ? ' ) ;
if ( questionmark = = NULL ) {
2012-11-22 04:46:58 +04:00
py_val = PyString_FromString ( request_string ) ;
if ( py_val = = NULL ) goto error ;
PyDict_SetItemString ( env , " PATH_INFO " , py_val ) ;
Py_DECREF ( py_val ) ;
2008-09-21 22:01:00 +04:00
} else {
2012-11-22 04:46:58 +04:00
py_val = PyString_FromString ( questionmark + 1 ) ;
if ( py_val = = NULL ) goto error ;
PyDict_SetItemString ( env , " QUERY_STRING " , py_val ) ;
Py_DECREF ( py_val ) ;
py_val = PyString_FromStringAndSize ( request_string , questionmark - request_string ) ;
if ( py_val = = NULL ) goto error ;
PyDict_SetItemString ( env , " PATH_INFO " , py_val ) ;
Py_DECREF ( py_val ) ;
2008-09-21 22:01:00 +04:00
}
2012-11-22 04:46:58 +04:00
py_val = PyString_FromString ( servername ) ;
if ( py_val = = NULL ) goto error ;
PyDict_SetItemString ( env , " SERVER_NAME " , py_val ) ;
Py_DECREF ( py_val ) ;
py_val = PyString_FromFormat ( " %d " , serverport ) ;
if ( py_val = = NULL ) goto error ;
PyDict_SetItemString ( env , " SERVER_PORT " , py_val ) ;
Py_DECREF ( py_val ) ;
2008-09-21 20:45:09 +04:00
for ( hdr = headers ; hdr ; hdr = hdr - > next ) {
char * name ;
2008-09-21 22:01:00 +04:00
if ( ! strcasecmp ( hdr - > name , " Content-Type " ) ) {
2012-11-22 04:46:58 +04:00
py_val = PyString_FromString ( hdr - > value ) ;
PyDict_SetItemString ( env , " CONTENT_TYPE " , py_val ) ;
Py_DECREF ( py_val ) ;
} else {
2010-05-27 19:45:19 +04:00
if ( asprintf ( & name , " HTTP_%s " , hdr - > name ) < 0 ) {
2010-05-28 20:58:45 +04:00
PyErr_NoMemory ( ) ;
2012-11-22 04:46:58 +04:00
goto error ;
2010-05-27 19:45:19 +04:00
}
2012-11-22 04:46:58 +04:00
py_val = PyString_FromString ( hdr - > value ) ;
PyDict_SetItemString ( env , name , py_val ) ;
Py_DECREF ( py_val ) ;
2008-09-21 22:01:00 +04:00
free ( name ) ;
}
2008-09-21 20:45:09 +04:00
}
2008-05-23 23:21:07 +04:00
2008-09-21 20:45:09 +04:00
if ( tls ) {
py_scheme = PyString_FromString ( " https " ) ;
} else {
py_scheme = PyString_FromString ( " http " ) ;
}
2012-11-22 04:46:58 +04:00
if ( py_scheme = = NULL ) goto error ;
2008-09-21 20:45:09 +04:00
PyDict_SetItemString ( env , " wsgi.url_scheme " , py_scheme ) ;
2012-11-22 04:46:58 +04:00
Py_DECREF ( py_scheme ) ;
2008-05-23 23:21:07 +04:00
return env ;
2012-11-22 04:46:58 +04:00
error :
Py_DECREF ( env ) ;
return NULL ;
2008-05-23 23:21:07 +04:00
}
2008-05-24 20:13:30 +04:00
2012-11-24 23:44:23 +04:00
static void wsgi_serve_500 ( struct websrv_context * web )
{
struct http_header * headers = NULL ;
const char * contents [ ] = {
" An internal server error occurred while handling this request. " ,
" Please refer to the server logs for more details. " ,
NULL
} ;
int i ;
websrv_output_headers ( web , " 500 Internal Server Error " , headers ) ;
for ( i = 0 ; contents [ i ] ; i + + ) {
websrv_output ( web , contents [ i ] , strlen ( contents [ i ] ) ) ;
}
}
2008-09-21 20:45:09 +04:00
static void wsgi_process_http_input ( struct web_server_data * wdata ,
struct websrv_context * web )
{
PyObject * py_environ , * result , * item , * iter ;
2009-02-02 12:13:43 +03:00
PyObject * request_handler = ( PyObject * ) wdata - > private_data ;
2010-04-28 16:52:40 +04:00
struct tsocket_address * my_address = web - > conn - > local_address ;
const char * addr = " 0.0.0.0 " ;
uint16_t port = 0 ;
2012-11-22 04:46:58 +04:00
web_request_Object * py_web ;
PyObject * py_input_stream ;
py_web = PyObject_New ( web_request_Object , & web_request_Type ) ;
if ( py_web = = NULL ) {
2012-11-24 22:35:33 +04:00
DEBUG_Print_PyError ( 0 , " Unable to allocate web request " ) ;
2012-11-22 04:46:58 +04:00
return ;
}
2008-09-21 20:45:09 +04:00
py_web - > web = web ;
2010-04-28 16:52:40 +04:00
if ( tsocket_address_is_inet ( my_address , " ip " ) ) {
addr = tsocket_address_inet_addr_string ( my_address , wdata ) ;
port = tsocket_address_inet_port ( my_address ) ;
}
2012-11-22 04:46:58 +04:00
py_input_stream = Py_InputHttpStream ( web ) ;
if ( py_input_stream = = NULL ) {
2012-11-24 22:35:33 +04:00
DEBUG_Print_PyError ( 0 , " unable to create python input stream " ) ;
2012-11-22 04:46:58 +04:00
return ;
}
2008-09-21 22:01:00 +04:00
py_environ = create_environ ( tls_enabled ( web - > conn - > socket ) ,
2008-09-21 20:45:09 +04:00
web - > input . content_length ,
web - > input . headers ,
2008-09-21 22:01:00 +04:00
web - > input . post_request ? " POST " : " GET " ,
2010-04-28 16:52:40 +04:00
addr ,
port ,
2012-11-22 04:46:58 +04:00
py_input_stream ,
2008-09-21 22:01:00 +04:00
web - > input . url
) ;
2012-11-22 04:46:58 +04:00
Py_DECREF ( py_input_stream ) ;
2008-09-21 20:45:09 +04:00
if ( py_environ = = NULL ) {
2012-11-24 22:35:33 +04:00
DEBUG_Print_PyError ( 0 , " Unable to create WSGI environment object " ) ;
2012-11-24 23:44:23 +04:00
wsgi_serve_500 ( web ) ;
2008-09-21 20:45:09 +04:00
return ;
}
result = PyObject_CallMethod ( request_handler , discard_const_p ( char , " __call__ " ) , discard_const_p ( char , " OO " ) ,
py_environ , PyObject_GetAttrString ( ( PyObject * ) py_web , " start_response " ) ) ;
if ( result = = NULL ) {
2012-11-24 22:35:33 +04:00
DEBUG_Print_PyError ( 0 , " error while handling request " ) ;
2012-11-24 23:44:23 +04:00
wsgi_serve_500 ( web ) ;
2008-09-21 20:45:09 +04:00
return ;
}
iter = PyObject_GetIter ( result ) ;
Py_DECREF ( result ) ;
2012-11-22 04:46:55 +04:00
if ( iter = = NULL ) {
2012-11-24 22:35:33 +04:00
DEBUG_Print_PyError ( 0 , " application did not return iterable " ) ;
2012-11-24 23:44:23 +04:00
wsgi_serve_500 ( web ) ;
2012-11-22 04:46:55 +04:00
return ;
}
2008-09-21 20:45:09 +04:00
/* Now, iter over all the data returned */
while ( ( item = PyIter_Next ( iter ) ) ) {
2008-09-21 21:03:12 +04:00
websrv_output ( web , PyString_AsString ( item ) , PyString_Size ( item ) ) ;
2008-09-21 20:45:09 +04:00
Py_DECREF ( item ) ;
}
Py_DECREF ( iter ) ;
}
bool wsgi_initialize ( struct web_server_data * wdata )
2008-05-24 20:13:30 +04:00
{
2011-01-17 02:25:42 +03:00
PyObject * py_web_server ;
2008-05-24 20:13:30 +04:00
2008-09-21 20:45:09 +04:00
Py_Initialize ( ) ;
2011-02-05 10:00:45 +03:00
py_update_path ( ) ; /* Ensure that we have the Samba paths at
* the start of the sys . path ( ) */
2011-01-17 02:25:42 +03:00
2008-09-21 20:45:09 +04:00
if ( PyType_Ready ( & web_request_Type ) < 0 )
return false ;
if ( PyType_Ready ( & input_Stream_Type ) < 0 )
return false ;
if ( PyType_Ready ( & error_Stream_Type ) < 0 )
return false ;
wdata - > http_process_input = wsgi_process_http_input ;
2011-01-17 02:25:42 +03:00
py_web_server = PyImport_ImportModule ( " samba.web_server " ) ;
if ( py_web_server = = NULL ) {
2012-11-24 22:35:33 +04:00
DEBUG_Print_PyError ( 0 , " Unable to find web server " ) ;
2008-09-21 20:45:09 +04:00
return false ;
}
2011-01-17 02:25:42 +03:00
wdata - > private_data = py_web_server ;
2008-09-21 20:45:09 +04:00
return true ;
2008-05-24 20:13:30 +04:00
}