mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-05-14 10:43:51 +00:00
preliminary api for language-independent body read another step completed body read language independent implementation ported gevent to the new read/write api ported websockets to the new read/write api removed channels subsystem removed channels subsystem ported lua to the new read/write api fixed post-buffering readline is still broken improved request body readline very difficult test for readline()/read() combo passed other improvements in postbuffering/read/readline ported --http-socket to the new api added X-Forwarded-SSL management removed old api more refactoring ported the RACK plugin to the new api ported psgi plugin to the new api defintely removed clustering simpified ifdel hell simpified ifdef hell removed useless configuration options
747 lines
20 KiB
C
747 lines
20 KiB
C
#include "uwsgi_python.h"
|
|
|
|
/* notes
|
|
|
|
exit(1) on every malloc error: apps can be dinamically loaded so on memory problem
|
|
it is better to let the master process manager respawn the worker.
|
|
|
|
TODO dynamic loading on prefork+thread looks flaky... NEED TO FIX IT
|
|
*/
|
|
|
|
extern struct uwsgi_server uwsgi;
|
|
extern struct uwsgi_python up;
|
|
|
|
extern char **environ;
|
|
|
|
PyMethodDef uwsgi_sendfile_method[] = {{"uwsgi_sendfile", py_uwsgi_sendfile, METH_VARARGS, ""}};
|
|
|
|
PyMethodDef uwsgi_eventfd_read_method[] = { {"uwsgi_eventfd_read", py_eventfd_read, METH_VARARGS, ""}};
|
|
PyMethodDef uwsgi_eventfd_write_method[] = { {"uwsgi_eventfd_write", py_eventfd_write, METH_VARARGS, ""}};
|
|
|
|
void set_dyn_pyhome(char *home, uint16_t pyhome_len) {
|
|
|
|
|
|
char venv_version[15];
|
|
PyObject *site_module;
|
|
|
|
PyObject *pysys_dict = get_uwsgi_pydict("sys");
|
|
|
|
PyObject *pypath = PyDict_GetItemString(pysys_dict, "path");
|
|
if (!pypath) {
|
|
PyErr_Print();
|
|
exit(1);
|
|
}
|
|
|
|
// simulate a pythonhome directive
|
|
if (uwsgi.wsgi_req->pyhome_len > 0) {
|
|
|
|
PyObject *venv_path = UWSGI_PYFROMSTRINGSIZE(uwsgi.wsgi_req->pyhome, uwsgi.wsgi_req->pyhome_len);
|
|
|
|
#ifdef UWSGI_DEBUG
|
|
uwsgi_debug("setting dynamic virtualenv to %.*s\n", uwsgi.wsgi_req->pyhome_len, uwsgi.wsgi_req->pyhome);
|
|
#endif
|
|
|
|
PyDict_SetItemString(pysys_dict, "prefix", venv_path);
|
|
PyDict_SetItemString(pysys_dict, "exec_prefix", venv_path);
|
|
|
|
venv_version[14] = 0;
|
|
if (snprintf(venv_version, 15, "/lib/python%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION) == -1) {
|
|
return;
|
|
}
|
|
|
|
// check here
|
|
PyString_Concat(&venv_path, PyString_FromString(venv_version));
|
|
|
|
if (PyList_Insert(pypath, 0, venv_path)) {
|
|
PyErr_Print();
|
|
}
|
|
|
|
site_module = PyImport_ImportModule("site");
|
|
if (site_module) {
|
|
PyImport_ReloadModule(site_module);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThreadState *interpreter, int app_type) {
|
|
|
|
PyObject *app_list = NULL, *applications = NULL;
|
|
|
|
|
|
if (uwsgi_apps_cnt >= uwsgi.max_apps) {
|
|
uwsgi_log("ERROR: you cannot load more than %d apps in a worker\n", uwsgi.max_apps);
|
|
return -1;
|
|
}
|
|
|
|
|
|
int id = uwsgi_apps_cnt;
|
|
|
|
int multiapp = 0;
|
|
|
|
int i;
|
|
|
|
struct uwsgi_app *wi;
|
|
|
|
time_t now = uwsgi_now();
|
|
|
|
if (uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, -1) != -1) {
|
|
uwsgi_log( "mountpoint %.*s already configured. skip.\n", wsgi_req->appid_len, wsgi_req->appid);
|
|
return -1;
|
|
}
|
|
|
|
wi = &uwsgi_apps[id];
|
|
|
|
memset(wi, 0, sizeof(struct uwsgi_app));
|
|
wi->mountpoint_len = wsgi_req->appid_len < 0xff ? wsgi_req->appid_len : (0xff-1);
|
|
strncpy(wi->mountpoint, wsgi_req->appid, wi->mountpoint_len);
|
|
|
|
// dynamic chdir ?
|
|
if (wsgi_req->chdir_len > 0) {
|
|
strncpy(wi->chdir, wsgi_req->chdir, wsgi_req->chdir_len < 0xff ? wsgi_req->chdir_len : (0xff-1));
|
|
#ifdef UWSGI_DEBUG
|
|
uwsgi_debug("chdir to %s\n", wi->chdir);
|
|
#endif
|
|
if (chdir(wi->chdir)) {
|
|
uwsgi_error("chdir()");
|
|
}
|
|
}
|
|
|
|
// Initialize a new environment for the new interpreter
|
|
|
|
// reload "os" environ to allow dynamic setenv()
|
|
if (up.reload_os_env) {
|
|
|
|
char **e, *p;
|
|
PyObject *k, *env_value;
|
|
|
|
PyObject *os_module = PyImport_ImportModule("os");
|
|
if (os_module) {
|
|
PyObject *os_module_dict = PyModule_GetDict(os_module);
|
|
PyObject *py_environ = PyDict_GetItemString(os_module_dict, "environ");
|
|
if (py_environ) {
|
|
for (e = environ; *e != NULL; e++) {
|
|
p = strchr(*e, '=');
|
|
if (p == NULL) continue;
|
|
|
|
k = PyString_FromStringAndSize(*e, (int)(p-*e));
|
|
if (k == NULL) {
|
|
PyErr_Print();
|
|
continue;
|
|
}
|
|
|
|
env_value = PyString_FromString(p+1);
|
|
if (env_value == NULL) {
|
|
PyErr_Print();
|
|
Py_DECREF(k);
|
|
continue;
|
|
}
|
|
|
|
#ifdef UWSGI_DEBUG
|
|
uwsgi_log("%s = %s\n", PyString_AsString(k), PyString_AsString(env_value));
|
|
#endif
|
|
|
|
if (PyObject_SetItem(py_environ, k, env_value)) {
|
|
PyErr_Print();
|
|
}
|
|
|
|
Py_DECREF(k);
|
|
Py_DECREF(env_value);
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
if (interpreter == NULL && id) {
|
|
|
|
wi->interpreter = Py_NewInterpreter();
|
|
if (!wi->interpreter) {
|
|
uwsgi_log( "unable to initialize the new python interpreter\n");
|
|
exit(1);
|
|
}
|
|
PyThreadState_Swap(wi->interpreter);
|
|
init_pyargv();
|
|
|
|
// we need to inizialize an embedded module for every interpreter
|
|
init_uwsgi_embedded_module();
|
|
init_uwsgi_vars();
|
|
|
|
}
|
|
else if (interpreter) {
|
|
wi->interpreter = interpreter;
|
|
}
|
|
else {
|
|
wi->interpreter = up.main_thread;
|
|
}
|
|
|
|
if (wsgi_req->pyhome_len) {
|
|
set_dyn_pyhome(wsgi_req->pyhome, wsgi_req->pyhome_len);
|
|
}
|
|
|
|
if (wsgi_req->touch_reload_len > 0 && wsgi_req->touch_reload_len < 0xff) {
|
|
struct stat trst;
|
|
strncpy(wi->touch_reload, wsgi_req->touch_reload, wsgi_req->touch_reload_len);
|
|
if (!stat(wi->touch_reload, &trst)) {
|
|
wi->touch_reload_mtime = trst.st_mtime;
|
|
}
|
|
}
|
|
|
|
wi->callable = up.loaders[loader](arg1);
|
|
|
|
if (!wi->callable) {
|
|
uwsgi_log("unable to load app %d (mountpoint='%s') (callable not found or import error)\n", id, wi->mountpoint);
|
|
goto doh;
|
|
}
|
|
|
|
|
|
|
|
// the module contains multiple apps
|
|
if (PyDict_Check((PyObject *)wi->callable)) {
|
|
applications = wi->callable;
|
|
uwsgi_log("found a multiapp module...\n");
|
|
app_list = PyDict_Keys(applications);
|
|
multiapp = PyList_Size(app_list);
|
|
if (multiapp < 1) {
|
|
uwsgi_log("you have to define at least one app in the apllications dictionary\n");
|
|
goto doh;
|
|
}
|
|
|
|
PyObject *app_mnt = PyList_GetItem(app_list, 0);
|
|
if (!PyString_Check(app_mnt)) {
|
|
uwsgi_log("the app mountpoint must be a string\n");
|
|
goto doh;
|
|
}
|
|
char *tmp_mountpoint = PyString_AsString(app_mnt);
|
|
wi->mountpoint_len = strlen(wi->mountpoint) < 0xff ? strlen(wi->mountpoint) : (0xff-1);
|
|
strncpy(wi->mountpoint, tmp_mountpoint, wi->mountpoint_len);
|
|
wsgi_req->appid = wi->mountpoint;
|
|
wsgi_req->appid_len = wi->mountpoint_len;
|
|
#ifdef UWSGI_DEBUG
|
|
uwsgi_log("main mountpoint = %s\n", wi->mountpoint);
|
|
#endif
|
|
wi->callable = PyDict_GetItem(applications, app_mnt);
|
|
if (PyString_Check((PyObject *) wi->callable)) {
|
|
PyObject *callables_dict = get_uwsgi_pydict((char *)arg1);
|
|
if (callables_dict) {
|
|
wi->callable = PyDict_GetItem(callables_dict, (PyObject *)wi->callable);
|
|
}
|
|
}
|
|
}
|
|
|
|
Py_INCREF((PyObject *)wi->callable);
|
|
|
|
wi->environ = malloc(sizeof(PyObject*)*uwsgi.cores);
|
|
if (!wi->environ) {
|
|
uwsgi_error("malloc()");
|
|
exit(1);
|
|
}
|
|
|
|
for(i=0;i<uwsgi.cores;i++) {
|
|
wi->environ[i] = PyDict_New();
|
|
if (!wi->environ[i]) {
|
|
uwsgi_log("unable to allocate new env dictionary for app\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
wi->argc = 1;
|
|
|
|
if (app_type == PYTHON_APP_TYPE_WSGI) {
|
|
#ifdef UWSGI_DEBUG
|
|
uwsgi_log("-- WSGI callable selected --\n");
|
|
#endif
|
|
wi->request_subhandler = uwsgi_request_subhandler_wsgi;
|
|
wi->response_subhandler = uwsgi_response_subhandler_wsgi;
|
|
wi->argc = 2;
|
|
}
|
|
else if (app_type == PYTHON_APP_TYPE_WEB3) {
|
|
#ifdef UWSGI_DEBUG
|
|
uwsgi_log("-- Web3 callable selected --\n");
|
|
#endif
|
|
wi->request_subhandler = uwsgi_request_subhandler_web3;
|
|
wi->response_subhandler = uwsgi_response_subhandler_web3;
|
|
}
|
|
else if (app_type == PYTHON_APP_TYPE_PUMP) {
|
|
#ifdef UWSGI_DEBUG
|
|
uwsgi_log("-- Pump callable selected --\n");
|
|
#endif
|
|
wi->request_subhandler = uwsgi_request_subhandler_pump;
|
|
wi->response_subhandler = uwsgi_response_subhandler_pump;
|
|
}
|
|
|
|
wi->args = malloc(sizeof(PyObject*)*uwsgi.cores);
|
|
if (!wi->args) {
|
|
uwsgi_error("malloc()");
|
|
exit(1);
|
|
}
|
|
|
|
for(i=0;i<uwsgi.cores;i++) {
|
|
wi->args[i] = PyTuple_New(wi->argc);
|
|
if (!wi->args[i]) {
|
|
uwsgi_log("unable to allocate new tuple for app args\n");
|
|
exit(1);
|
|
}
|
|
|
|
// add start_response on WSGI app
|
|
Py_INCREF((PyObject *)up.wsgi_spitout);
|
|
if (app_type == PYTHON_APP_TYPE_WSGI) {
|
|
if (PyTuple_SetItem(wi->args[i], 1, up.wsgi_spitout)) {
|
|
uwsgi_log("unable to set start_response in args tuple\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (app_type == PYTHON_APP_TYPE_WSGI) {
|
|
// prepare sendfile() for WSGI app
|
|
wi->sendfile = PyCFunction_New(uwsgi_sendfile_method, NULL);
|
|
|
|
wi->eventfd_read = PyCFunction_New(uwsgi_eventfd_read_method, NULL);
|
|
wi->eventfd_write = PyCFunction_New(uwsgi_eventfd_write_method, NULL);
|
|
}
|
|
|
|
// cache most used values
|
|
wi->error = PyFile_FromFile(stderr, "wsgi_errors", "w", NULL);
|
|
Py_INCREF(wi->error);
|
|
|
|
wi->gateway_version = PyTuple_New(2);
|
|
PyTuple_SetItem(wi->gateway_version, 0, PyInt_FromLong(1));
|
|
PyTuple_SetItem(wi->gateway_version, 1, PyInt_FromLong(0));
|
|
Py_INCREF((PyObject *)wi->gateway_version);
|
|
|
|
wi->uwsgi_version = PyString_FromString(UWSGI_VERSION);
|
|
Py_INCREF((PyObject *)wi->uwsgi_version);
|
|
|
|
wi->uwsgi_node = PyString_FromString(uwsgi.hostname);
|
|
Py_INCREF((PyObject *)wi->uwsgi_node);
|
|
|
|
if (uwsgi.threads > 1 && id) {
|
|
// if we have multiple threads we need to initialize a PyThreadState for each one
|
|
for(i=0;i<uwsgi.threads;i++) {
|
|
//uwsgi_log("%p\n", uwsgi.core[i]->ts[id]);
|
|
uwsgi.workers[uwsgi.mywid].cores[i].ts[id] = PyThreadState_New( ((PyThreadState *)wi->interpreter)->interp);
|
|
if (!uwsgi.workers[uwsgi.mywid].cores[i].ts[id]) {
|
|
uwsgi_log("unable to allocate new PyThreadState structure for app %s", wi->mountpoint);
|
|
goto doh;
|
|
}
|
|
}
|
|
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_save_key) );
|
|
}
|
|
else if (interpreter == NULL && id) {
|
|
PyThreadState_Swap(up.main_thread);
|
|
}
|
|
|
|
const char *default_app = "";
|
|
|
|
if ((wsgi_req->appid_len == 0 || (wsgi_req->appid_len = 1 && wsgi_req->appid[0] == '/')) && uwsgi.default_app == -1) {
|
|
default_app = " (default app)" ;
|
|
uwsgi.default_app = id;
|
|
}
|
|
|
|
wi->started_at = now;
|
|
wi->startup_time = uwsgi_now() - now;
|
|
|
|
if (app_type == PYTHON_APP_TYPE_WSGI) {
|
|
uwsgi_log( "WSGI app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app);
|
|
}
|
|
else if (app_type == PYTHON_APP_TYPE_WEB3) {
|
|
uwsgi_log( "Web3 app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app);
|
|
}
|
|
else if (app_type == PYTHON_APP_TYPE_PUMP) {
|
|
uwsgi_log( "Pump app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app);
|
|
}
|
|
|
|
|
|
uwsgi_apps_cnt++;
|
|
|
|
if (multiapp > 1) {
|
|
for(i=1;i<multiapp;i++) {
|
|
PyObject *app_mnt = PyList_GetItem(app_list, i);
|
|
if (!PyString_Check(app_mnt)) {
|
|
uwsgi_log("applications dictionary key must be a string, skipping.\n");
|
|
continue;
|
|
}
|
|
|
|
wsgi_req->appid = PyString_AsString(app_mnt);
|
|
wsgi_req->appid_len = strlen(wsgi_req->appid);
|
|
PyObject *a_callable = PyDict_GetItem(applications, app_mnt);
|
|
if (PyString_Check(a_callable)) {
|
|
|
|
PyObject *callables_dict = get_uwsgi_pydict((char *)arg1);
|
|
if (callables_dict) {
|
|
a_callable = PyDict_GetItem(callables_dict, a_callable);
|
|
}
|
|
}
|
|
if (!a_callable) {
|
|
uwsgi_log("skipping broken app %s\n", wsgi_req->appid);
|
|
continue;
|
|
}
|
|
init_uwsgi_app(LOADER_CALLABLE, a_callable, wsgi_req, wi->interpreter, app_type);
|
|
}
|
|
}
|
|
|
|
// emulate COW
|
|
uwsgi_emulate_cow_for_apps(id);
|
|
|
|
return id;
|
|
|
|
doh:
|
|
if (PyErr_Occurred())
|
|
PyErr_Print();
|
|
if (interpreter == NULL && id) {
|
|
Py_EndInterpreter(wi->interpreter);
|
|
if (uwsgi.threads > 1) {
|
|
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_save_key));
|
|
}
|
|
else {
|
|
PyThreadState_Swap(up.main_thread);
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
char *get_uwsgi_pymodule(char *module) {
|
|
|
|
char *quick_callable;
|
|
|
|
if ( (quick_callable = strchr(module, ':')) ) {
|
|
quick_callable[0] = 0;
|
|
quick_callable++;
|
|
return quick_callable;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
PyObject *get_uwsgi_pydict(char *module) {
|
|
|
|
PyObject *wsgi_module, *wsgi_dict;
|
|
|
|
wsgi_module = PyImport_ImportModule(module);
|
|
if (!wsgi_module) {
|
|
PyErr_Print();
|
|
return NULL;
|
|
}
|
|
|
|
wsgi_dict = PyModule_GetDict(wsgi_module);
|
|
if (!wsgi_dict) {
|
|
PyErr_Print();
|
|
return NULL;
|
|
}
|
|
|
|
return wsgi_dict;
|
|
|
|
}
|
|
|
|
PyObject *uwsgi_uwsgi_loader(void *arg1) {
|
|
|
|
PyObject *wsgi_dict;
|
|
|
|
char *quick_callable;
|
|
|
|
PyObject *tmp_callable;
|
|
PyObject *applications;
|
|
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
|
|
|
|
char *module = (char *) arg1;
|
|
|
|
quick_callable = get_uwsgi_pymodule(module);
|
|
if (quick_callable == NULL) {
|
|
if (up.callable) {
|
|
quick_callable = up.callable;
|
|
}
|
|
else {
|
|
quick_callable = "application";
|
|
}
|
|
wsgi_dict = get_uwsgi_pydict(module);
|
|
}
|
|
else {
|
|
wsgi_dict = get_uwsgi_pydict(module);
|
|
module[strlen(module)] = ':';
|
|
}
|
|
|
|
if (!wsgi_dict) {
|
|
return NULL;
|
|
}
|
|
|
|
applications = PyDict_GetItemString(uwsgi_dict, "applications");
|
|
if (applications && PyDict_Check(applications)) return applications;
|
|
|
|
applications = PyDict_GetItemString(wsgi_dict, "applications");
|
|
if (applications && PyDict_Check(applications)) return applications;
|
|
|
|
// quick callable -> thanks gunicorn for the idea
|
|
// we have extended the concept a bit...
|
|
if (quick_callable[strlen(quick_callable) -2 ] == '(' && quick_callable[strlen(quick_callable) -1] ==')') {
|
|
quick_callable[strlen(quick_callable) -2 ] = 0;
|
|
tmp_callable = PyDict_GetItemString(wsgi_dict, quick_callable);
|
|
quick_callable[strlen(quick_callable)] = '(';
|
|
if (tmp_callable) {
|
|
return python_call(tmp_callable, PyTuple_New(0), 0, NULL);
|
|
}
|
|
}
|
|
|
|
return PyDict_GetItemString(wsgi_dict, quick_callable);
|
|
|
|
}
|
|
|
|
/* this is the mount loader, it loads app on mountpoint automagically */
|
|
PyObject *uwsgi_mount_loader(void *arg1) {
|
|
|
|
PyObject *callable = NULL;
|
|
char *what = (char *) arg1;
|
|
|
|
if ( !strcmp(what+strlen(what)-3, ".py") || !strcmp(what+strlen(what)-5, ".wsgi")) {
|
|
callable = uwsgi_file_loader((void *)what);
|
|
if (!callable) exit(UWSGI_FAILED_APP_CODE);
|
|
}
|
|
else if (!strcmp(what+strlen(what)-4, ".ini")) {
|
|
callable = uwsgi_paste_loader((void *)what);
|
|
}
|
|
else if (strchr(what, ':')) {
|
|
callable = uwsgi_uwsgi_loader((void *)what);
|
|
}
|
|
|
|
return callable;
|
|
}
|
|
|
|
|
|
/* this is the dynamic loader, it loads app reading information from a wsgi_request */
|
|
PyObject *uwsgi_dyn_loader(void *arg1) {
|
|
|
|
PyObject *callable = NULL;
|
|
char *tmpstr;
|
|
|
|
struct wsgi_request *wsgi_req = (struct wsgi_request *) arg1;
|
|
|
|
// MANAGE UWSGI_SCRIPT
|
|
if (wsgi_req->script_len > 0) {
|
|
tmpstr = uwsgi_strncopy(wsgi_req->script, wsgi_req->script_len);
|
|
callable = uwsgi_uwsgi_loader((void *)tmpstr);
|
|
free(tmpstr);
|
|
}
|
|
// MANAGE UWSGI_MODULE
|
|
else if (wsgi_req->module_len > 0) {
|
|
if (wsgi_req->callable_len > 0) {
|
|
tmpstr = uwsgi_concat3n(wsgi_req->module, wsgi_req->module_len, ":", 1, wsgi_req->callable, wsgi_req->callable_len);
|
|
}
|
|
else {
|
|
tmpstr = uwsgi_strncopy(wsgi_req->module, wsgi_req->module_len);
|
|
}
|
|
callable = uwsgi_uwsgi_loader((void *)tmpstr);
|
|
free(tmpstr);
|
|
}
|
|
// MANAGE UWSGI_FILE
|
|
else if (wsgi_req->file_len > 0) {
|
|
tmpstr = uwsgi_strncopy(wsgi_req->file, wsgi_req->file_len);
|
|
callable = uwsgi_file_loader((void *)tmpstr);
|
|
free(tmpstr);
|
|
}
|
|
// TODO MANAGE UWSGI_PASTE
|
|
/*
|
|
else if (wsgi_req->wsgi_paste_len > 0) {
|
|
tmpstr = uwsgi_strncopy(wsgi_req->paste, wsgi_req->paste_len);
|
|
callable = uwsgi_paste_loader((void *)tmpstr);
|
|
free(tmpstr);
|
|
}
|
|
*/
|
|
|
|
return callable;
|
|
}
|
|
|
|
|
|
/* trying to emulate Graham's mod_wsgi, this will allows easy and fast migrations */
|
|
PyObject *uwsgi_file_loader(void *arg1) {
|
|
|
|
char *filename = (char *) arg1;
|
|
PyObject *wsgi_file_module, *wsgi_file_dict;
|
|
PyObject *wsgi_file_callable;
|
|
|
|
char *callable = up.callable;
|
|
if (!callable) callable = "application";
|
|
|
|
char *py_filename = uwsgi_concat2("uwsgi_file_", uwsgi_pythonize(filename));
|
|
|
|
wsgi_file_module = uwsgi_pyimport_by_filename(py_filename, filename);
|
|
if (!wsgi_file_module) {
|
|
PyErr_Print();
|
|
free(py_filename);
|
|
return NULL;
|
|
}
|
|
|
|
wsgi_file_dict = PyModule_GetDict(wsgi_file_module);
|
|
if (!wsgi_file_dict) {
|
|
PyErr_Print();
|
|
Py_DECREF(wsgi_file_module);
|
|
free(py_filename);
|
|
return NULL;
|
|
}
|
|
|
|
wsgi_file_callable = PyDict_GetItemString(wsgi_file_dict, callable);
|
|
if (!wsgi_file_callable) {
|
|
PyErr_Print();
|
|
Py_DECREF(wsgi_file_dict);
|
|
Py_DECREF(wsgi_file_module);
|
|
free(py_filename);
|
|
uwsgi_log( "unable to find \"application\" callable in file %s\n", filename);
|
|
return NULL;
|
|
}
|
|
|
|
if (!PyFunction_Check(wsgi_file_callable) && !PyCallable_Check(wsgi_file_callable)) {
|
|
uwsgi_log( "\"application\" must be a callable object in file %s\n", filename);
|
|
Py_DECREF(wsgi_file_callable);
|
|
Py_DECREF(wsgi_file_dict);
|
|
Py_DECREF(wsgi_file_module);
|
|
free(py_filename);
|
|
return NULL;
|
|
}
|
|
|
|
free(py_filename);
|
|
|
|
return wsgi_file_callable;
|
|
|
|
}
|
|
|
|
PyObject *uwsgi_paste_loader(void *arg1) {
|
|
|
|
char *paste = (char *) arg1;
|
|
PyObject *paste_module, *paste_dict, *paste_loadapp;
|
|
PyObject *paste_arg, *paste_app;
|
|
|
|
uwsgi_log( "Loading paste environment: %s\n", paste);
|
|
|
|
if (up.paste_logger) {
|
|
PyObject *paste_logger_dict = get_uwsgi_pydict("paste.script.util.logging_config");
|
|
if (paste_logger_dict) {
|
|
PyObject *paste_logger_fileConfig = PyDict_GetItemString(paste_logger_dict, "fileConfig");
|
|
if (paste_logger_fileConfig) {
|
|
PyObject *paste_logger_arg = PyTuple_New(1);
|
|
if (!paste_logger_arg) {
|
|
PyErr_Print();
|
|
exit(UWSGI_FAILED_APP_CODE);
|
|
}
|
|
PyTuple_SetItem(paste_logger_arg, 0, UWSGI_PYFROMSTRING(paste+7));
|
|
if (python_call(paste_logger_fileConfig, paste_logger_arg, 0, NULL)) {
|
|
PyErr_Print();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
paste_module = PyImport_ImportModule("paste.deploy");
|
|
if (!paste_module) {
|
|
PyErr_Print();
|
|
exit(UWSGI_FAILED_APP_CODE);
|
|
}
|
|
|
|
paste_dict = PyModule_GetDict(paste_module);
|
|
if (!paste_dict) {
|
|
PyErr_Print();
|
|
exit(UWSGI_FAILED_APP_CODE);
|
|
}
|
|
|
|
paste_loadapp = PyDict_GetItemString(paste_dict, "loadapp");
|
|
if (!paste_loadapp) {
|
|
PyErr_Print();
|
|
exit(UWSGI_FAILED_APP_CODE);
|
|
}
|
|
|
|
paste_arg = PyTuple_New(1);
|
|
if (!paste_arg) {
|
|
PyErr_Print();
|
|
exit(UWSGI_FAILED_APP_CODE);
|
|
}
|
|
|
|
if (PyTuple_SetItem(paste_arg, 0, UWSGI_PYFROMSTRING(paste))) {
|
|
PyErr_Print();
|
|
exit(UWSGI_FAILED_APP_CODE);
|
|
}
|
|
|
|
paste_app = PyEval_CallObject(paste_loadapp, paste_arg);
|
|
if (!paste_app) {
|
|
PyErr_Print();
|
|
exit(UWSGI_FAILED_APP_CODE);
|
|
}
|
|
|
|
|
|
return paste_app;
|
|
}
|
|
|
|
PyObject *uwsgi_eval_loader(void *arg1) {
|
|
|
|
#ifdef UWSGI_PYPY
|
|
uwsgi_log("the eval loader is currently not supported under PyPy !!!\n");
|
|
return NULL;
|
|
#else
|
|
char *code = (char *) arg1;
|
|
|
|
PyObject *wsgi_eval_module, *wsgi_eval_callable = NULL;
|
|
|
|
struct _node *wsgi_eval_node = NULL;
|
|
PyObject *wsgi_compiled_node;
|
|
|
|
wsgi_eval_node = PyParser_SimpleParseString(code, Py_file_input);
|
|
if (!wsgi_eval_node) {
|
|
PyErr_Print();
|
|
uwsgi_log( "failed to parse <eval> code\n");
|
|
exit(UWSGI_FAILED_APP_CODE);
|
|
}
|
|
|
|
wsgi_compiled_node = (PyObject *) PyNode_Compile(wsgi_eval_node, "uwsgi_eval_config");
|
|
|
|
if (!wsgi_compiled_node) {
|
|
PyErr_Print();
|
|
uwsgi_log( "failed to compile eval code\n");
|
|
exit(UWSGI_FAILED_APP_CODE);
|
|
}
|
|
|
|
|
|
wsgi_eval_module = PyImport_ExecCodeModule("uwsgi_eval_config", wsgi_compiled_node);
|
|
if (!wsgi_eval_module) {
|
|
PyErr_Print();
|
|
exit(UWSGI_FAILED_APP_CODE);
|
|
}
|
|
|
|
|
|
Py_DECREF(wsgi_compiled_node);
|
|
|
|
up.loader_dict = PyModule_GetDict(wsgi_eval_module);
|
|
if (!up.loader_dict) {
|
|
PyErr_Print();
|
|
exit(UWSGI_FAILED_APP_CODE);
|
|
}
|
|
|
|
|
|
if (up.callable) {
|
|
wsgi_eval_callable = PyDict_GetItemString(up.loader_dict, up.callable);
|
|
}
|
|
else {
|
|
|
|
wsgi_eval_callable = PyDict_GetItemString(up.loader_dict, "application");
|
|
}
|
|
|
|
if (wsgi_eval_callable) {
|
|
if (!PyFunction_Check(wsgi_eval_callable) && !PyCallable_Check(wsgi_eval_callable)) {
|
|
uwsgi_log( "you must define a callable object in your code\n");
|
|
exit(UWSGI_FAILED_APP_CODE);
|
|
}
|
|
}
|
|
|
|
return wsgi_eval_callable;
|
|
#endif
|
|
|
|
}
|
|
|
|
PyObject *uwsgi_callable_loader(void *arg1) {
|
|
return (PyObject *) arg1;
|
|
}
|
|
|
|
PyObject *uwsgi_string_callable_loader(void *arg1) {
|
|
char *callable = (char *) arg1;
|
|
|
|
return PyDict_GetItem(up.loader_dict, UWSGI_PYFROMSTRING(callable));
|
|
}
|