mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
89158b0509 | ||
|
|
86b90b8b16 | ||
|
|
fe4c88c1c5 | ||
|
|
f0f08728ab | ||
|
|
5259c803e8 | ||
|
|
c6e5e533fa | ||
|
|
21e4cc19c8 | ||
|
|
045001fd6c | ||
|
|
eadaf3407a | ||
|
|
7434d3113c | ||
|
|
ab9fade14d | ||
|
|
5be63b02e8 | ||
|
|
7694c38021 | ||
|
|
d13f7a45b9 | ||
|
|
44e8f01671 | ||
|
|
09a8104256 | ||
|
|
09d8ac2656 | ||
|
|
c5877df60c | ||
|
|
0f2fff31ee | ||
|
|
ebcdd294aa | ||
|
|
d663e10584 | ||
|
|
048299e1d3 | ||
|
|
96aaa9fa3f | ||
|
|
015f17192c | ||
|
|
f0ac801ecd | ||
|
|
f3b207c024 | ||
|
|
0379e200b6 | ||
|
|
abe6168bc3 | ||
|
|
a6aa2c31c6 | ||
|
|
f35ad319cf | ||
|
|
527ad44463 | ||
|
|
b245307f55 | ||
|
|
9285b403d9 | ||
|
|
58b72a4c80 | ||
|
|
73f706723e | ||
|
|
4d22f7171f | ||
|
|
b60e22b4e5 | ||
|
|
7310b73289 | ||
|
|
4fa61c225a | ||
|
|
63b41856e5 | ||
|
|
ed1e668240 | ||
|
|
e3a7e70180 | ||
|
|
9f0b20c8d2 | ||
|
|
68aff372ce | ||
|
|
38cfa72318 | ||
|
|
31047e1e10 | ||
|
|
bbb90296bb | ||
|
|
00c6aa2f65 | ||
|
|
720da09631 | ||
|
|
47f7c09b97 | ||
|
|
cb5704da10 | ||
|
|
c64356b231 | ||
|
|
2acd2f5224 | ||
|
|
ba251f8e3d | ||
|
|
48019f9044 | ||
|
|
d9a1f2448c | ||
|
|
553a947c2d | ||
|
|
736aedfa89 | ||
|
|
6184acc727 | ||
|
|
f0d96b03fa | ||
|
|
14bf840eef | ||
|
|
7ea08093c7 | ||
|
|
8eb8d07151 | ||
|
|
cdd95b434e | ||
|
|
82cbcea886 | ||
|
|
ea54a05fc3 | ||
|
|
eba39dcd67 | ||
|
|
d71ea1404d | ||
|
|
0f0d5b2a5f | ||
|
|
10a75ef848 | ||
|
|
4bd9bf8917 | ||
|
|
323da1299e | ||
|
|
75d08898b4 | ||
|
|
5e47796a02 | ||
|
|
0ade5aba0a | ||
|
|
f7b1ad8cb0 | ||
|
|
3bd147e687 | ||
|
|
66c99e257f | ||
|
|
8407a5921b | ||
|
|
5f36987827 | ||
|
|
ede1622368 | ||
|
|
a28dfb790e | ||
|
|
3711cbbd61 | ||
|
|
c9ef6281ff | ||
|
|
604ea6fd57 | ||
|
|
41dfcaa705 | ||
|
|
daa41d4a51 | ||
|
|
ded4450a70 | ||
|
|
cd0be56bbe | ||
|
|
0bf7b64b46 | ||
|
|
215d2e7055 | ||
|
|
2b5b0cf1bc | ||
|
|
67231da4a9 | ||
|
|
8c25b38470 | ||
|
|
08bbe0cd30 | ||
|
|
9f9f63fe2f | ||
|
|
997bd63cc3 | ||
|
|
6a566d9dca | ||
|
|
d2e743a800 | ||
|
|
2fedb175b4 | ||
|
|
6c5e25dbfe | ||
|
|
94fd3f0bfd | ||
|
|
ca169b05fb | ||
|
|
10ea1fee6e | ||
|
|
d7b8704165 | ||
|
|
0f774b840c | ||
|
|
81521a314b | ||
|
|
37ee7f8908 | ||
|
|
309648f68b | ||
|
|
5cfa65d04e | ||
|
|
e73c8194a0 | ||
|
|
00a3f6ae7f | ||
|
|
b7edaa68c8 | ||
|
|
2877ba54de | ||
|
|
f74a19a71a | ||
|
|
3da5238ee5 | ||
|
|
567dd36592 | ||
|
|
b48062a026 | ||
|
|
b039cb713f | ||
|
|
8e987ffa18 | ||
|
|
52502342e0 | ||
|
|
cb9e3c22f9 | ||
|
|
0c465775ad | ||
|
|
a5417f4963 | ||
|
|
b48076f6e4 | ||
|
|
c472eae332 | ||
|
|
918fc654f4 | ||
|
|
9097cbe10d | ||
|
|
e260873338 | ||
|
|
a7822742c0 | ||
|
|
f1316ef4bb | ||
|
|
4106931175 | ||
|
|
fb5ba40f0c | ||
|
|
854e51f0ad | ||
|
|
676b43f17d | ||
|
|
48b68e6a92 | ||
|
|
61f33721e1 | ||
|
|
5c3c46598f | ||
|
|
4358036f9e | ||
|
|
54d75d92ef | ||
|
|
b1ae57c932 | ||
|
|
2636baa33f | ||
|
|
926c739517 |
@@ -2,3 +2,9 @@ d3850b52334a91d005b0fe45e1e38ba0997a1fb8 no_server mode
|
||||
2d8a617299153ed2efa6ecee7920e9d36c29e0f5 0.9.5beta1
|
||||
04722a2d0121080d14a64df097c278860db5ce8a 0.9.5rc1
|
||||
820cc64ab296dc4589ef72a33a6b804c22a0430c 0.9.5rc2
|
||||
b0db39cfad5ac6d4f00bbb3f9c57cf73206e2afb 0.9.5
|
||||
9f8b98ad1dfa51b86b13fa624c65f73523075fc4 0.9.5.1
|
||||
a83e7a482e65befcfbb0e24af8cd5d15190acdd7 0.9.6-rc1
|
||||
b8f67c6cd0d62f864db9b2b265b4e260ad7d873c 0.9.6-rc2
|
||||
35918dd4b3771158b2b57410613ef029e08bbd60 0.9.6
|
||||
5f25d1f97f9dde3e391a668c1c610a52a5db8244 0.9.6.1
|
||||
|
||||
@@ -1,5 +1,87 @@
|
||||
*** september 2010 ***
|
||||
|
||||
* 0.9.6.1 [20100912]
|
||||
|
||||
- print the request uri during SIGPIPE or HARAKIRI
|
||||
- added SIGUSR2 support (it will print the current running request, if available)
|
||||
- protocol parsing optimization
|
||||
- fixed --logto support
|
||||
- new --eval option allows inline definition of WSGI script
|
||||
- support for defining WSGI script in xml using CDATA
|
||||
- allow --pp as --pythonpath shortcut
|
||||
- various spooler optimizations and fixes
|
||||
- added -O2 optimization by default
|
||||
- added uwsgi.is_a_reload commodity function
|
||||
- .ini file support fix
|
||||
- SNMP agent fix
|
||||
- support for subprocesses generated by master
|
||||
- fix a regression in SCRIPT_NAME handling
|
||||
- Haiku official support
|
||||
- gcc 2.95 support
|
||||
- dynamic app management optimizations
|
||||
- export x-wsgiorg.uwsgi.version in WSGI env
|
||||
|
||||
*** august 2010 ***
|
||||
|
||||
* 0.9.6 [20100829]
|
||||
|
||||
- better handling of SCRIPT_NAME
|
||||
- vacuum option for deleting unix sockets and pidfiles after usage
|
||||
- advanced XML configuration
|
||||
- new configuration systems: INI files and LDAP
|
||||
- embedded HTTP server for development/testing
|
||||
- better signal handling
|
||||
- PSGI plugin improved
|
||||
- usability fixes and new commodities options for root startup
|
||||
- grunt processes (detached workers)
|
||||
- preliminary integrated virtualhosting mode
|
||||
- new option catch-exceptions can redirect python exceptions to your browser
|
||||
- logging improvements (--logto and --logdate options)
|
||||
- Full PEP 333 compliant usage of wsgi.file_wrapper
|
||||
- re-initialize random seed after every fork() [security fix]
|
||||
- fix Spooler's usage of stdin
|
||||
- export WSGI environment in uwsgi.env (for doing evil things)
|
||||
- logsize tracking (uwsgi.logsize) for future embedded log rotation
|
||||
|
||||
*** july 2010 ***
|
||||
|
||||
* 0.9.5.4 [20100706]
|
||||
|
||||
*** june 2010 ***
|
||||
|
||||
* 0.9.5.3 [20100628]
|
||||
|
||||
- fixed linux x86_64 compilation (sorry)
|
||||
|
||||
* 0.9.5.2 [20100626] *
|
||||
|
||||
- fixed a request parsing bug
|
||||
- applied debian fixes
|
||||
- fixed multiple interpreter sys.argv
|
||||
- improved --chmod-socket
|
||||
- fixed uid 0 SIGHUP
|
||||
- updated nginx and apache modules
|
||||
- updated PSGI, lua and example plugin
|
||||
- fixed --pyargv with python 3.x
|
||||
- improved plugin build system
|
||||
|
||||
*** may 2010 ***
|
||||
|
||||
* 0.9.5.1 [20100519] *
|
||||
|
||||
- fixed paste support
|
||||
- added a new modifier (22)
|
||||
- full support for configuration via environment variables
|
||||
- nginx_string option in nginx module
|
||||
- fix for harakiri without master
|
||||
- backported unladen swallow support for 0.9.6-dev
|
||||
- fixed address space limit detection via getrlimit()
|
||||
- http body buffering implementation
|
||||
- added --prio option (to set priority)
|
||||
- added --post-limit to limit the size of uploads
|
||||
- added --logto option to allow udp logging without daemonizing
|
||||
- applied Gentoo's packagers fixes for build system
|
||||
|
||||
* 0.9.5 [20100501] *
|
||||
|
||||
- hook based request/modifier management
|
||||
@@ -9,7 +91,7 @@
|
||||
- logging via udp
|
||||
- improved spooler for cron-like apps
|
||||
- async support
|
||||
- green thread platform (uGreen) on top of teh async mode
|
||||
- green thread platform (uGreen) on top of the async mode
|
||||
- transparent Erlang integration
|
||||
- embedded snmp agent
|
||||
- nagios mode
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
all:
|
||||
python2.7 uwsgiconfig.py --build
|
||||
@@ -0,0 +1,923 @@
|
||||
/*
|
||||
|
||||
*** uWSGI/mod_Ruwsgi ***
|
||||
|
||||
Copyright 2009-2010 Roger Florkowski <rflorkowski@mypublisher.com>
|
||||
Copyright 2009-2010 Unbit S.a.s. <info@unbit.it>
|
||||
|
||||
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 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#define MOD_UWSGI_VERSION "1.0"
|
||||
|
||||
#include "ap_config.h"
|
||||
#include "apr_version.h"
|
||||
#include "apr_lib.h"
|
||||
#include "apr_strings.h"
|
||||
#include "httpd.h"
|
||||
#include "http_core.h"
|
||||
#include "http_request.h"
|
||||
#include "http_config.h"
|
||||
#include "http_log.h"
|
||||
#include "http_protocol.h"
|
||||
#include "util_script.h"
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/uio.h>
|
||||
#include <time.h>
|
||||
#include <poll.h>
|
||||
|
||||
#define DEFAULT_TIMEOUT 60 /* default socket timeout */
|
||||
#define DEFAULT_CGIMODE 0 /* not enabled */
|
||||
|
||||
#define UNSET 0
|
||||
#define ENABLED 1
|
||||
#define DISABLED 2
|
||||
|
||||
#if APR_MAJOR_VERSION == 0
|
||||
#define apr_socket_send apr_send
|
||||
#define GET_PORT(port, addr) apr_sockaddr_port_get(&(port), addr)
|
||||
#define CREATE_SOCKET(sock, family, pool) \
|
||||
apr_socket_create(sock, family, SOCK_STREAM, pool)
|
||||
#else
|
||||
#define GET_PORT(port, addr) ((port) = (addr)->port)
|
||||
#define CREATE_SOCKET(sock, family, pool) \
|
||||
apr_socket_create(sock, family, SOCK_STREAM, APR_PROTO_TCP, pool)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
char *path;
|
||||
char *addr;
|
||||
apr_port_t port;
|
||||
} mount_entry;
|
||||
|
||||
/*
|
||||
* Configuration record. Used per-directory configuration data.
|
||||
*/
|
||||
typedef struct {
|
||||
mount_entry mount;
|
||||
int enabled; /* mod_uwsgi is enabled from this directory */
|
||||
int timeout;
|
||||
int cgi_mode;
|
||||
uint8_t modifier1;
|
||||
uint8_t modifier2;
|
||||
} uwsgi_cfg;
|
||||
|
||||
/* Server level configuration */
|
||||
typedef struct {
|
||||
apr_array_header_t *mounts;
|
||||
int timeout;
|
||||
int cgi_mode;
|
||||
} uwsgi_server_cfg;
|
||||
|
||||
module AP_MODULE_DECLARE_DATA uwsgi_module;
|
||||
|
||||
/*
|
||||
* Locate our directory configuration record for the current request.
|
||||
*/
|
||||
static uwsgi_cfg *
|
||||
our_dconfig(request_rec *r)
|
||||
{
|
||||
return (uwsgi_cfg *) ap_get_module_config(r->per_dir_config, &uwsgi_module);
|
||||
}
|
||||
|
||||
static uwsgi_server_cfg *our_sconfig(server_rec *s)
|
||||
{
|
||||
return (uwsgi_server_cfg *) ap_get_module_config(s->module_config,
|
||||
&uwsgi_module);
|
||||
}
|
||||
|
||||
static int
|
||||
mount_entry_matches(const char *url, const char *prefix,
|
||||
const char **path_info)
|
||||
{
|
||||
int i;
|
||||
for (i=0; prefix[i] != '\0'; i++) {
|
||||
if (url[i] == '\0' || url[i] != prefix[i])
|
||||
return 0;
|
||||
}
|
||||
if (url[i] == '\0' || url[i] == '/') {
|
||||
*path_info = url + i;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_translate(request_rec *r)
|
||||
{
|
||||
uwsgi_cfg *cfg = our_dconfig(r);
|
||||
|
||||
if (cfg->enabled == DISABLED) {
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
if (cfg->mount.addr != UNSET) {
|
||||
ap_assert(cfg->mount.port != UNSET);
|
||||
r->handler = "uwsgi-handler";
|
||||
r->filename = r->uri;
|
||||
return OK;
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
uwsgi_server_cfg *scfg = our_sconfig(r->server);
|
||||
mount_entry *entries = (mount_entry *) scfg->mounts->elts;
|
||||
for (i = 0; i < scfg->mounts->nelts; ++i) {
|
||||
const char *path_info;
|
||||
mount_entry *mount = &entries[i];
|
||||
if (mount_entry_matches(r->uri, mount->path, &path_info)) {
|
||||
r->handler = "uwsgi-handler";
|
||||
r->path_info = apr_pstrdup(r->pool, path_info);
|
||||
r->filename = r->uri;
|
||||
ap_set_module_config(r->request_config, &uwsgi_module, mount);
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
static int uwsgi_map_location(request_rec *r)
|
||||
{
|
||||
if (r->handler && strcmp(r->handler, "uwsgi-handler") == 0) {
|
||||
return OK; /* We don't want directory walk. */
|
||||
}
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
static void log_err(const char *file, int line, request_rec *r,
|
||||
apr_status_t status, const char *msg)
|
||||
{
|
||||
ap_log_rerror(file, line, APLOG_ERR, status, r, "uwsgi: %s", msg);
|
||||
}
|
||||
|
||||
static void log_debug(const char *file, int line, request_rec *r, const
|
||||
char *msg)
|
||||
{
|
||||
/*
|
||||
ap_log_rerror(file, line, APLOG_DEBUG, APR_SUCCESS, r, msg);
|
||||
ap_log_rerror(file, line, APLOG_WARNING, APR_SUCCESS, r, "uwsgi: %s", msg);
|
||||
*/
|
||||
ap_log_rerror(file, line, APLOG_DEBUG, APR_SUCCESS, r, "uwsgi: %s", msg);
|
||||
}
|
||||
|
||||
/* buffered socket implementation (buckets are overkill) */
|
||||
|
||||
#define BUFFER_SIZE 8000
|
||||
|
||||
struct sockbuff {
|
||||
apr_socket_t *sock;
|
||||
char buf[BUFFER_SIZE];
|
||||
int used;
|
||||
};
|
||||
|
||||
static void binit(struct sockbuff *s, apr_socket_t *sock)
|
||||
{
|
||||
s->sock = sock;
|
||||
s->used = 0;
|
||||
}
|
||||
|
||||
static apr_status_t sendall(apr_socket_t *sock, char *buf, apr_size_t len)
|
||||
{
|
||||
apr_status_t rv;
|
||||
apr_size_t n;
|
||||
while (len > 0) {
|
||||
n = len;
|
||||
if ((rv = apr_socket_send(sock, buf, &n))) return rv;
|
||||
buf += n;
|
||||
len -= n;
|
||||
}
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
static apr_status_t bflush(struct sockbuff *s)
|
||||
{
|
||||
apr_status_t rv;
|
||||
ap_assert(s->used >= 0 && s->used <= BUFFER_SIZE);
|
||||
if (s->used) {
|
||||
if ((rv = sendall(s->sock, s->buf, s->used))) return rv;
|
||||
s->used = 0;
|
||||
}
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
static apr_status_t bwrite(struct sockbuff *s, char *buf, apr_size_t len)
|
||||
{
|
||||
apr_status_t rv;
|
||||
if (len >= BUFFER_SIZE - s->used) {
|
||||
if ((rv = bflush(s))) return rv;
|
||||
while (len >= BUFFER_SIZE) {
|
||||
if ((rv = sendall(s->sock, buf, BUFFER_SIZE))) return rv;
|
||||
buf += BUFFER_SIZE;
|
||||
len -= BUFFER_SIZE;
|
||||
}
|
||||
}
|
||||
if (len > 0) {
|
||||
ap_assert(len < BUFFER_SIZE - s->used);
|
||||
memcpy(s->buf + s->used, buf, len);
|
||||
s->used += len;
|
||||
}
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
static apr_status_t bputs(struct sockbuff *s, char *buf)
|
||||
{
|
||||
return bwrite(s, buf, strlen(buf));
|
||||
}
|
||||
|
||||
static apr_status_t bputc(struct sockbuff *s, char c)
|
||||
{
|
||||
char buf[1];
|
||||
buf[0] = c;
|
||||
return bwrite(s, buf, 1);
|
||||
}
|
||||
|
||||
static apr_status_t bputh(struct sockbuff *s, unsigned short h)
|
||||
{
|
||||
return bwrite(s, (char *)&h, 2);
|
||||
}
|
||||
|
||||
#define CONFIG_VALUE(value, fallback) ((value) != UNSET ? (value) : (fallback))
|
||||
|
||||
static apr_status_t
|
||||
open_socket(apr_socket_t **sock, request_rec *r)
|
||||
{
|
||||
int timeout;
|
||||
int retries = 4;
|
||||
int sleeptime = 1;
|
||||
apr_status_t rv;
|
||||
apr_sockaddr_t *sockaddr;
|
||||
uwsgi_server_cfg *scfg = our_sconfig(r->server);
|
||||
uwsgi_cfg *cfg = our_dconfig(r);
|
||||
mount_entry *m = (mount_entry *) ap_get_module_config(r->request_config,
|
||||
&uwsgi_module);
|
||||
if (!m) {
|
||||
m = &cfg->mount;
|
||||
}
|
||||
|
||||
timeout = CONFIG_VALUE(cfg->timeout, CONFIG_VALUE(scfg->timeout,
|
||||
DEFAULT_TIMEOUT));
|
||||
rv = apr_sockaddr_info_get(&sockaddr,
|
||||
CONFIG_VALUE(m->addr, "localhost"),
|
||||
APR_UNSPEC,
|
||||
CONFIG_VALUE(m->port, 5000),
|
||||
0,
|
||||
r->pool);
|
||||
if (rv) {
|
||||
log_err(APLOG_MARK, r, rv, "apr_sockaddr_info_get() error");
|
||||
return rv;
|
||||
}
|
||||
|
||||
restart:
|
||||
*sock = NULL;
|
||||
rv = CREATE_SOCKET(sock, sockaddr->family, r->pool);
|
||||
if (rv) {
|
||||
log_err(APLOG_MARK, r, rv, "apr_socket_create() error");
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = apr_socket_timeout_set(*sock, apr_time_from_sec(timeout));
|
||||
if (rv) {
|
||||
log_err(APLOG_MARK, r, rv, "apr_socket_timeout_set() error");
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = apr_socket_connect(*sock, sockaddr);
|
||||
if (rv) {
|
||||
apr_socket_close(*sock);
|
||||
if ((APR_STATUS_IS_ECONNREFUSED(rv) |
|
||||
APR_STATUS_IS_EINPROGRESS(rv)) && retries > 0) {
|
||||
/* server may be temporarily down, retry */
|
||||
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, rv, r,
|
||||
"uwsgi: connection failed, retrying");
|
||||
apr_sleep(apr_time_from_sec(sleeptime));
|
||||
--retries;
|
||||
sleeptime *= 2;
|
||||
goto restart;
|
||||
}
|
||||
log_err(APLOG_MARK, r, rv, "uwsgi: can't connect to server");
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef APR_TCP_NODELAY
|
||||
/* disable Nagle, we don't send small packets */
|
||||
apr_socket_opt_set(*sock, APR_TCP_NODELAY, 1);
|
||||
#endif
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
/* This code is a duplicate of what's in util_script.c. We can't use
|
||||
* r->unparsed_uri because it gets changed if there was a redirect. */
|
||||
static char *original_uri(request_rec *r)
|
||||
{
|
||||
char *first, *last;
|
||||
|
||||
if (r->the_request == NULL) {
|
||||
return (char *) apr_pcalloc(r->pool, 1);
|
||||
}
|
||||
|
||||
first = r->the_request; /* use the request-line */
|
||||
|
||||
while (*first && !apr_isspace(*first)) {
|
||||
++first; /* skip over the method */
|
||||
}
|
||||
while (apr_isspace(*first)) {
|
||||
++first; /* and the space(s) */
|
||||
}
|
||||
|
||||
last = first;
|
||||
while (*last && !apr_isspace(*last)) {
|
||||
++last; /* end at next whitespace */
|
||||
}
|
||||
|
||||
return apr_pstrmemdup(r->pool, first, last - first);
|
||||
}
|
||||
|
||||
static char *lookup_name(apr_table_t *t, const char *name)
|
||||
{
|
||||
const apr_array_header_t *hdrs_arr = apr_table_elts(t);
|
||||
apr_table_entry_t *hdrs = (apr_table_entry_t *) hdrs_arr->elts;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < hdrs_arr->nelts; ++i) {
|
||||
if (hdrs[i].key == NULL)
|
||||
continue;
|
||||
|
||||
if (strcasecmp(hdrs[i].key, name) == 0)
|
||||
return hdrs[i].val;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *lookup_header(request_rec *r, const char *name)
|
||||
{
|
||||
return lookup_name(r->headers_in, name);
|
||||
}
|
||||
|
||||
static void add_header(apr_table_t *t, const char *name, const char *value)
|
||||
{
|
||||
if (name != NULL && value != NULL)
|
||||
apr_table_addn(t, name, value);
|
||||
}
|
||||
|
||||
static int find_path_info(const char *uri, const char *path_info)
|
||||
{
|
||||
int n;
|
||||
n = strlen(uri) - strlen(path_info);
|
||||
ap_assert(n >= 0);
|
||||
return n;
|
||||
}
|
||||
|
||||
static char *http2env(apr_pool_t *p, const char *name)
|
||||
{
|
||||
char *env_name = apr_pstrcat(p, "HTTP_", name, NULL);
|
||||
char *cp;
|
||||
|
||||
for (cp = env_name + 5; *cp != 0; cp++) {
|
||||
if (*cp == '-') {
|
||||
*cp = '_';
|
||||
}
|
||||
else {
|
||||
*cp = apr_toupper(*cp);
|
||||
}
|
||||
}
|
||||
|
||||
return env_name;
|
||||
}
|
||||
|
||||
static apr_status_t
|
||||
send_headers(request_rec *r, struct sockbuff *s)
|
||||
{
|
||||
int i;
|
||||
const apr_array_header_t *hdrs_arr, *env_arr;
|
||||
apr_table_entry_t *hdrs, *env;
|
||||
char *buf;
|
||||
unsigned short int n = 0;
|
||||
apr_table_t *t;
|
||||
apr_status_t rv = 0;
|
||||
apr_port_t port = 0;
|
||||
GET_PORT(port, r->connection->remote_addr);
|
||||
uwsgi_cfg *cfg = our_dconfig(r);
|
||||
|
||||
log_debug(APLOG_MARK,r, "sending headers");
|
||||
t = apr_table_make(r->pool, 40);
|
||||
if (!t)
|
||||
return APR_ENOMEM;
|
||||
|
||||
/* headers to send */
|
||||
|
||||
/* CONTENT_LENGTH must come first and always be present */
|
||||
buf = lookup_header(r, "Content-Length");
|
||||
if (buf == NULL)
|
||||
buf = "0";
|
||||
add_header(t, "CONTENT_LENGTH", buf);
|
||||
|
||||
add_header(t, "REQUEST_METHOD", (char *) r->method) ;
|
||||
add_header(t, "QUERY_STRING", r->args ? r->args : "") ;
|
||||
add_header(t, "SERVER_SOFTWARE", ap_get_server_version());
|
||||
add_header(t, "SERVER_ADMIN", r->server->server_admin);
|
||||
add_header(t, "SERVER_NAME", (char *) ap_get_server_name(r)) ;
|
||||
add_header(t, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r))) ;
|
||||
add_header(t, "SERVER_ADDR", r->connection->local_ip);
|
||||
add_header(t, "SERVER_PROTOCOL", r->protocol) ;
|
||||
|
||||
add_header(t, "REQUEST_URI", original_uri(r)) ;
|
||||
add_header(t, "REMOTE_ADDR", r->connection->remote_ip) ;
|
||||
add_header(t, "REMOTE_PORT", apr_psprintf(r->pool, "%d", port));
|
||||
add_header(t, "REMOTE_USER", r->user) ;
|
||||
add_header(t, "DOCUMENT_ROOT", (char *) ap_document_root(r)) ;
|
||||
|
||||
if (r->path_info) {
|
||||
int path_info_start = find_path_info(r->uri, r->path_info);
|
||||
add_header(t, "SCRIPT_NAME", apr_pstrndup(r->pool, r->uri,
|
||||
path_info_start));
|
||||
add_header(t, "PATH_INFO", r->path_info);
|
||||
}
|
||||
else {
|
||||
/* skip PATH_INFO, don't know it */
|
||||
add_header(t, "SCRIPT_NAME", r->uri) ;
|
||||
}
|
||||
|
||||
add_header(t, "CONTENT_TYPE", lookup_header(r, "Content-type"));
|
||||
|
||||
/* HTTP headers */
|
||||
hdrs_arr = apr_table_elts(r->headers_in);
|
||||
hdrs = (apr_table_entry_t *) hdrs_arr->elts;
|
||||
for (i = 0; i < hdrs_arr->nelts; ++i) {
|
||||
if (hdrs[i].key) {
|
||||
add_header(t, http2env(r->pool, hdrs[i].key), hdrs[i].val);
|
||||
}
|
||||
}
|
||||
|
||||
/* environment variables */
|
||||
env_arr = apr_table_elts(r->subprocess_env);
|
||||
env = (apr_table_entry_t*) env_arr->elts;
|
||||
for (i = 0; i < env_arr->nelts; ++i) {
|
||||
add_header(t, env[i].key, env[i].val);
|
||||
}
|
||||
|
||||
hdrs_arr = apr_table_elts(t);
|
||||
hdrs = (apr_table_entry_t*) hdrs_arr->elts;
|
||||
|
||||
/* calculate length of header data */
|
||||
for (i = 0; i < hdrs_arr->nelts; ++i) {
|
||||
n += strlen(hdrs[i].key);
|
||||
n += strlen(hdrs[i].val);
|
||||
n += 4 ; /* XXX */
|
||||
}
|
||||
log_debug(APLOG_MARK,r, apr_psprintf(r->pool, "pktheader size is %u", n)) ;
|
||||
log_debug(APLOG_MARK,r, apr_psprintf(r->pool, "num headers %u", hdrs_arr->nelts)) ;
|
||||
|
||||
/* write pkt header */
|
||||
rv = bputc(s, cfg->modifier1); /* marker */
|
||||
if (rv) return rv;
|
||||
rv = bputh(s, n); /* length of header data */
|
||||
if (rv) return rv;
|
||||
rv = bputc(s, cfg->modifier2); /* marker */
|
||||
if (rv) return rv;
|
||||
|
||||
/* write out headers */
|
||||
for (i = 0; i < hdrs_arr->nelts; ++i) {
|
||||
rv = bputh(s, strlen(hdrs[i].key)); /* length */
|
||||
if (rv) return rv;
|
||||
rv = bputs(s, hdrs[i].key); /* key */
|
||||
if (rv) return rv;
|
||||
rv = bputh(s, strlen(hdrs[i].val)); /* length */
|
||||
if (rv) return rv;
|
||||
rv = bputs(s, hdrs[i].val); /* data */
|
||||
if (rv) return rv;
|
||||
}
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
static apr_status_t send_request_body(request_rec *r, struct sockbuff *s)
|
||||
{
|
||||
if (ap_should_client_block(r)) {
|
||||
char buf[BUFFER_SIZE];
|
||||
apr_status_t rv;
|
||||
apr_off_t len;
|
||||
|
||||
while ((len = ap_get_client_block(r, buf, sizeof buf)) > 0) {
|
||||
if ((rv = bwrite(s, buf, len))) return rv;
|
||||
}
|
||||
if (len == -1)
|
||||
return HTTP_INTERNAL_SERVER_ERROR; /* what to return? */
|
||||
}
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
static int uwsgi_handler(request_rec *r)
|
||||
{
|
||||
apr_status_t rv = 0;
|
||||
int cgi_mode, http_status = 0;
|
||||
struct sockbuff s;
|
||||
apr_socket_t *sock;
|
||||
apr_bucket_brigade *bb = NULL;
|
||||
apr_bucket *b = NULL;
|
||||
const char *location;
|
||||
uwsgi_cfg *cfg = our_dconfig(r);
|
||||
uwsgi_server_cfg *scfg = our_sconfig(r->server);
|
||||
|
||||
if (strcmp(r->handler, "uwsgi-handler"))
|
||||
return DECLINED;
|
||||
|
||||
http_status = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
|
||||
if (http_status != OK)
|
||||
return http_status;
|
||||
|
||||
log_debug(APLOG_MARK, r, "connecting to server");
|
||||
|
||||
rv = open_socket(&sock, r);
|
||||
if (rv) {
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
binit(&s, sock);
|
||||
|
||||
rv = send_headers(r, &s);
|
||||
if (rv) {
|
||||
log_err(APLOG_MARK, r, rv, "error sending request headers");
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
rv = send_request_body(r, &s);
|
||||
if (rv) {
|
||||
log_err(APLOG_MARK, r, rv, "error sending request body");
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
rv = bflush(&s);
|
||||
if (rv) {
|
||||
log_err(APLOG_MARK, r, rv, "error sending request");
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
|
||||
log_debug(APLOG_MARK, r, "reading response headers");
|
||||
bb = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc);
|
||||
|
||||
cgi_mode = CONFIG_VALUE(cfg->cgi_mode, CONFIG_VALUE(scfg->cgi_mode, DEFAULT_CGIMODE));
|
||||
if (!cgi_mode) {
|
||||
|
||||
/* receive implemented with http-0.9 based protocol */
|
||||
apr_interval_time_t timeout;
|
||||
char buf[4096] ;
|
||||
apr_pollfd_t pollfd = {r->pool, APR_POLL_SOCKET, APR_POLLIN, 0, { NULL }, NULL };
|
||||
pollfd.desc.s = sock;
|
||||
timeout = CONFIG_VALUE(cfg->timeout, CONFIG_VALUE(scfg->timeout,
|
||||
DEFAULT_TIMEOUT)) * 1000 * 1000;
|
||||
r->assbackwards = 1 ; /* XXX */
|
||||
|
||||
for(;;) {
|
||||
apr_int32_t nsds;
|
||||
apr_size_t len;
|
||||
|
||||
if ((rv = apr_poll(&pollfd, 1, &nsds, timeout)) == APR_TIMEUP) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() timeout");
|
||||
break;
|
||||
}
|
||||
if (rv != APR_SUCCESS) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: poll() %s", strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
len = 4096;
|
||||
rv = apr_socket_recv(sock, buf, &len);
|
||||
if (rv == APR_SUCCESS) {
|
||||
apr_brigade_write(bb, NULL, NULL, buf, len);
|
||||
}
|
||||
else if (rv == APR_EOF) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
|
||||
}
|
||||
|
||||
}
|
||||
log_debug(APLOG_MARK,r, "recv finished") ;
|
||||
b = apr_bucket_flush_create(r->connection->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(bb, b);
|
||||
b = apr_bucket_eos_create(r->connection->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(bb, b);
|
||||
|
||||
} else {
|
||||
|
||||
/* receive implemented with http-1.x based protocol */
|
||||
b = apr_bucket_socket_create(sock, r->connection->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(bb, b);
|
||||
b = apr_bucket_eos_create(r->connection->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(bb, b);
|
||||
|
||||
rv = ap_scan_script_header_err_brigade(r, bb, NULL);
|
||||
if (rv) {
|
||||
if (rv == HTTP_INTERNAL_SERVER_ERROR) {
|
||||
log_err(APLOG_MARK, r, rv, "error reading response headers");
|
||||
}
|
||||
else {
|
||||
/* Work around an Apache bug whereby the returned status is
|
||||
* ignored and status_line is used instead. This bug is
|
||||
* present at least in 2.0.54.
|
||||
*/
|
||||
r->status_line = NULL;
|
||||
}
|
||||
apr_brigade_destroy(bb);
|
||||
return rv;
|
||||
}
|
||||
|
||||
location = apr_table_get(r->headers_out, "Location");
|
||||
|
||||
if (location && location[0] == '/' &&
|
||||
((r->status == HTTP_OK) || ap_is_HTTP_REDIRECT(r->status))) {
|
||||
|
||||
apr_brigade_destroy(bb);
|
||||
|
||||
/* Internal redirect -- fake-up a pseudo-request */
|
||||
r->status = HTTP_OK;
|
||||
|
||||
/* This redirect needs to be a GET no matter what the original
|
||||
* method was.
|
||||
*/
|
||||
r->method = apr_pstrdup(r->pool, "GET");
|
||||
r->method_number = M_GET;
|
||||
|
||||
ap_internal_redirect_handler(location, r);
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
rv = ap_pass_brigade(r->output_filters, bb);
|
||||
if (rv) {
|
||||
log_err(APLOG_MARK, r, rv, "ap_pass_brigade()");
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
|
||||
server_rec *base_server)
|
||||
{
|
||||
ap_add_version_component(p, "mod_uwsgi/" MOD_UWSGI_VERSION);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static void *
|
||||
uwsgi_create_dir_config(apr_pool_t *p, char *dirspec)
|
||||
{
|
||||
uwsgi_cfg *cfg = apr_pcalloc(p, sizeof(uwsgi_cfg));
|
||||
|
||||
cfg->enabled = UNSET;
|
||||
cfg->mount.addr = UNSET;
|
||||
cfg->mount.port = UNSET;
|
||||
cfg->timeout = UNSET;
|
||||
cfg->cgi_mode = UNSET;
|
||||
cfg->modifier1 = UNSET;
|
||||
cfg->modifier2 = UNSET;
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
#define MERGE(b, n, a) (n->a == UNSET ? b->a : n->a)
|
||||
|
||||
static void *
|
||||
uwsgi_merge_dir_config(apr_pool_t *p, void *basev, void *newv)
|
||||
{
|
||||
uwsgi_cfg* cfg = apr_pcalloc(p, sizeof(uwsgi_cfg));
|
||||
uwsgi_cfg* base = basev;
|
||||
uwsgi_cfg* new = newv;
|
||||
|
||||
cfg->enabled = MERGE(base, new, enabled);
|
||||
cfg->mount.addr = MERGE(base, new, mount.addr);
|
||||
cfg->mount.port = MERGE(base, new, mount.port);
|
||||
cfg->timeout = MERGE(base, new, timeout);
|
||||
cfg->cgi_mode = MERGE(base, new, cgi_mode);
|
||||
cfg->modifier1 = MERGE(base, new, modifier1);
|
||||
cfg->modifier2 = MERGE(base, new, modifier2);
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
static void *
|
||||
uwsgi_create_server_config(apr_pool_t *p, server_rec *s)
|
||||
{
|
||||
uwsgi_server_cfg *c =
|
||||
(uwsgi_server_cfg *) apr_pcalloc(p, sizeof(uwsgi_server_cfg));
|
||||
|
||||
c->mounts = apr_array_make(p, 20, sizeof(mount_entry));
|
||||
c->timeout = UNSET;
|
||||
c->cgi_mode = UNSET;
|
||||
return c;
|
||||
}
|
||||
|
||||
static void *
|
||||
uwsgi_merge_server_config(apr_pool_t *p, void *basev, void *overridesv)
|
||||
{
|
||||
uwsgi_server_cfg *c = (uwsgi_server_cfg *)
|
||||
apr_pcalloc(p, sizeof(uwsgi_server_cfg));
|
||||
uwsgi_server_cfg *base = (uwsgi_server_cfg *) basev;
|
||||
uwsgi_server_cfg *overrides = (uwsgi_server_cfg *) overridesv;
|
||||
|
||||
c->mounts = apr_array_append(p, overrides->mounts, base->mounts);
|
||||
c->timeout = MERGE(base, overrides, timeout);
|
||||
c->cgi_mode = MERGE(base, overrides, cgi_mode);
|
||||
return c;
|
||||
}
|
||||
|
||||
static const char *
|
||||
cmd_uwsgi_mount(cmd_parms *cmd, void *dummy, const char *path, const char *addr)
|
||||
{
|
||||
int n;
|
||||
apr_status_t rv;
|
||||
char *scope_id = NULL; /* A ip6 parameter - not used here. */
|
||||
uwsgi_server_cfg *scfg = our_sconfig(cmd->server);
|
||||
mount_entry *new = apr_array_push(scfg->mounts);
|
||||
n = strlen(path);
|
||||
while (n > 0 && path[n-1] == '/') {
|
||||
n--; /* strip trailing slashes */
|
||||
}
|
||||
new->path = apr_pstrndup(cmd->pool, path, n);
|
||||
rv = apr_parse_addr_port(&new->addr, &scope_id, &new->port, addr,
|
||||
cmd->pool);
|
||||
if (rv)
|
||||
return "error parsing address:port string";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *
|
||||
cmd_uwsgi_server(cmd_parms *cmd, void *pcfg, const char *addr_and_port)
|
||||
{
|
||||
apr_status_t rv;
|
||||
uwsgi_cfg *cfg = pcfg;
|
||||
char *scope_id = NULL; /* A ip6 parameter - not used here. */
|
||||
|
||||
if (cmd->path == NULL)
|
||||
return "not a server command";
|
||||
|
||||
rv = apr_parse_addr_port(&cfg->mount.addr, &scope_id, &cfg->mount.port,
|
||||
addr_and_port, cmd->pool);
|
||||
if (rv)
|
||||
return "error parsing address:port string";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *
|
||||
cmd_uwsgi_handler(cmd_parms* cmd, void* pcfg, int flag)
|
||||
{
|
||||
uwsgi_cfg *cfg = pcfg;
|
||||
|
||||
if (cmd->path == NULL) /* server command */
|
||||
return "not a server command";
|
||||
|
||||
if (flag)
|
||||
cfg->enabled = ENABLED;
|
||||
else
|
||||
cfg->enabled = DISABLED;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *
|
||||
cmd_uwsgi_timeout(cmd_parms *cmd, void* pcfg, const char *strtimeout)
|
||||
{
|
||||
uwsgi_cfg *dcfg = pcfg;
|
||||
int timeout = atoi(strtimeout);
|
||||
|
||||
if (cmd->path == NULL) {
|
||||
uwsgi_server_cfg *scfg = our_sconfig(cmd->server);
|
||||
scfg->timeout = timeout;
|
||||
}
|
||||
else {
|
||||
dcfg->timeout = timeout;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *
|
||||
cmd_uwsgi_force_cgi_mode(cmd_parms *cmd, void *pcfg, const char *value)
|
||||
{
|
||||
int cgi_mode;
|
||||
|
||||
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value)) {
|
||||
cgi_mode = 1;
|
||||
}
|
||||
else {
|
||||
cgi_mode = 0;
|
||||
}
|
||||
|
||||
if (cmd->path == NULL) {
|
||||
uwsgi_server_cfg *scfg = our_sconfig(cmd->server);
|
||||
scfg->cgi_mode = cgi_mode;
|
||||
}
|
||||
else {
|
||||
uwsgi_cfg *dcfg = pcfg;
|
||||
dcfg->cgi_mode = cgi_mode;
|
||||
}
|
||||
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
static const char *
|
||||
cmd_uwsgi_modifier1(cmd_parms *cmd, void *pcfg, const char *value)
|
||||
{
|
||||
uwsgi_cfg *cfg = pcfg;
|
||||
int val ;
|
||||
|
||||
if (cmd->path == NULL) /* server command */
|
||||
return "not a server command";
|
||||
|
||||
val = atoi(value);
|
||||
if (val < 0 || val > 255) {
|
||||
return "ignored uWSGImodifier1. Value must be between 0 and 255" ;
|
||||
}
|
||||
else {
|
||||
cfg->modifier1 = (uint8_t) val;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *
|
||||
cmd_uwsgi_modifier2(cmd_parms *cmd, void *pcfg, const char *value)
|
||||
{
|
||||
uwsgi_cfg *cfg = pcfg;
|
||||
int val ;
|
||||
|
||||
if (cmd->path == NULL) /* server command */
|
||||
return "not a server command";
|
||||
|
||||
val = atoi(value);
|
||||
if (val < 0 || val > 255) {
|
||||
return "ignored uWSGImodifier2. Value must be between 0 and 255" ;
|
||||
}
|
||||
else {
|
||||
cfg->modifier2 = (uint8_t) val;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const command_rec uwsgi_cmds[] = {
|
||||
AP_INIT_TAKE2("uWSGImount", cmd_uwsgi_mount, NULL, RSRC_CONF,
|
||||
"path prefix and address of UWSGI server"),
|
||||
AP_INIT_TAKE1("uWSGIserver", cmd_uwsgi_server, NULL, ACCESS_CONF,
|
||||
"Address and port of an UWSGI server (e.g. localhost:4000)"),
|
||||
AP_INIT_FLAG( "uWSGIhandler", cmd_uwsgi_handler, NULL, ACCESS_CONF,
|
||||
"On or Off to enable or disable the UWSGI handler"),
|
||||
AP_INIT_TAKE1("uWSGIserverTimeout", cmd_uwsgi_timeout, NULL, ACCESS_CONF|RSRC_CONF,
|
||||
"Timeout (in seconds) for communication with the UWSGI server."),
|
||||
AP_INIT_TAKE1("uWSGIforceCGImode", cmd_uwsgi_force_cgi_mode, NULL, ACCESS_CONF|RSRC_CONF,
|
||||
"Force uWSGI CGI mode for perfect integration with apache filter"),
|
||||
AP_INIT_TAKE1("uWSGImodifier1", cmd_uwsgi_modifier1, NULL, ACCESS_CONF,
|
||||
"Set uWSGI modifier1"),
|
||||
AP_INIT_TAKE1("uWSGImodifier2", cmd_uwsgi_modifier2, NULL, ACCESS_CONF,
|
||||
"Set uWSGI modifier2"),
|
||||
/*
|
||||
AP_INIT_TAKE12("uWSGIsocket", cmd_uwsgi_socket, NULL, RSRC_CONF|ACCESS_CONF,
|
||||
"Absolute path and optional timeout in seconds of uwsgi server socket"),
|
||||
AP_INIT_TAKE1("uWSGIsocket2", cmd_uwsgi_socket2, NULL, RSRC_CONF|ACCESS_CONF,
|
||||
"Absolute path of failover uwsgi server socket"),
|
||||
AP_INIT_TAKE1("uWSGIforceScriptName", cmd_uwsgi_force_script_name, NULL, ACCESS_CONF,
|
||||
"Fix for PATH_INFO/SCRIPT_NAME when the location has filesystem correspondence"),
|
||||
*/
|
||||
{NULL}
|
||||
};
|
||||
|
||||
static void uwsgi_register_hooks(apr_pool_t *p)
|
||||
{
|
||||
ap_hook_post_config(uwsgi_init, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
ap_hook_handler(uwsgi_handler, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
ap_hook_translate_name(uwsgi_translate, NULL, NULL, APR_HOOK_LAST);
|
||||
ap_hook_map_to_storage(uwsgi_map_location, NULL, NULL, APR_HOOK_FIRST);
|
||||
}
|
||||
|
||||
/* Dispatch list for API hooks */
|
||||
module AP_MODULE_DECLARE_DATA uwsgi_module = {
|
||||
STANDARD20_MODULE_STUFF,
|
||||
uwsgi_create_dir_config, /* create per-dir config structs */
|
||||
uwsgi_merge_dir_config, /* merge per-dir config structs */
|
||||
uwsgi_create_server_config, /* create per-server config structs */
|
||||
uwsgi_merge_server_config, /* merge per-server config structs */
|
||||
uwsgi_cmds, /* table of config file commands */
|
||||
uwsgi_register_hooks, /* register hooks */
|
||||
};
|
||||
|
||||
+40
-22
@@ -2,7 +2,7 @@
|
||||
|
||||
*** uWSGI/mod_uwsgi ***
|
||||
|
||||
Copyright 2009 Unbit S.a.s. <info@unbit.it>
|
||||
Copyright 2009-2010 Unbit S.a.s. <info@unbit.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
@@ -456,33 +456,51 @@ static int uwsgi_handler(request_rec *r) {
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
else if (cnt > 0) {
|
||||
cnt = recv(uwsgi_poll.fd, buf, 4096, 0) ;
|
||||
if (cnt < 0) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
|
||||
apr_brigade_destroy(bb);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
if (uwsgi_poll.revents & POLLIN) {
|
||||
cnt = recv(uwsgi_poll.fd, buf, 4096, 0) ;
|
||||
if (cnt < 0) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: recv() %s", strerror(errno));
|
||||
apr_brigade_destroy(bb);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
else if (cnt > 0) {
|
||||
if (!c->cgi_mode && uwsgi_http_status_read < 12) {
|
||||
if (uwsgi_http_status_read + cnt >= 12) {
|
||||
memcpy(uwsgi_http_status+uwsgi_http_status_read, buf, 12-uwsgi_http_status_read);
|
||||
r->status = atoi(uwsgi_http_status+8);
|
||||
uwsgi_http_status_read+=cnt;
|
||||
}
|
||||
else {
|
||||
memcpy(uwsgi_http_status+uwsgi_http_status_read, buf, cnt);
|
||||
uwsgi_http_status_read+=cnt;
|
||||
}
|
||||
}
|
||||
// check for client disconnect
|
||||
if (r->connection->aborted) {
|
||||
close(uwsgi_poll.fd);
|
||||
apr_brigade_destroy(bb);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
apr_brigade_write(bb, NULL, NULL, buf, cnt);
|
||||
hret = ap_fflush(r->output_filters, bb) ;
|
||||
if (hret != APR_SUCCESS) {
|
||||
close(uwsgi_poll.fd);
|
||||
apr_brigade_destroy(bb);
|
||||
return hret;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (cnt > 0) {
|
||||
if (!c->cgi_mode && uwsgi_http_status_read < 12) {
|
||||
if (uwsgi_http_status_read + cnt >= 12) {
|
||||
memcpy(uwsgi_http_status+uwsgi_http_status_read, buf, 12-uwsgi_http_status_read);
|
||||
r->status = atoi(uwsgi_http_status+8);
|
||||
uwsgi_http_status_read+=cnt;
|
||||
}
|
||||
else {
|
||||
memcpy(uwsgi_http_status+uwsgi_http_status_read, buf, cnt);
|
||||
uwsgi_http_status_read+=cnt;
|
||||
}
|
||||
}
|
||||
apr_brigade_write(bb, NULL, NULL, buf, cnt);
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
if (uwsgi_poll.revents & POLLHUP || uwsgi_poll.revents & POLLERR || uwsgi_poll.revents & POLLNVAL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "uwsgi: poll() %s", strerror(errno));
|
||||
close(uwsgi_poll.fd);
|
||||
apr_brigade_destroy(bb);
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# uWSGI - manage uWSGI application server
|
||||
#
|
||||
|
||||
description "uWSGI"
|
||||
|
||||
start on runlevel [2345]
|
||||
stop on runlevel [!2345]
|
||||
|
||||
respawn
|
||||
|
||||
env LOGTO=/tmp/uwsgi.log
|
||||
env BINPATH=/home/foo/uwsgi/uwsgi
|
||||
|
||||
# --no-orphans avoid workers without master
|
||||
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -m simple_app --logto $LOGTO -M -p 4
|
||||
@@ -191,6 +191,10 @@ module Rack
|
||||
buf, sender = client.recvfrom(remains)
|
||||
end
|
||||
|
||||
if buf.length == 0
|
||||
break
|
||||
end
|
||||
|
||||
rack_input.write( buf )
|
||||
remains -= buf.length
|
||||
end
|
||||
|
||||
Vendored
-6
@@ -1,6 +0,0 @@
|
||||
Package: uwsgi
|
||||
Version: 0.9.5
|
||||
Maintainer: Unbit
|
||||
Description: Fast, developer-friendly wsgi server
|
||||
Architecture: all
|
||||
Depends: python, libxml2
|
||||
@@ -59,6 +59,7 @@
|
||||
{% if masterpid %}
|
||||
<br/>
|
||||
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="reload/" method="post">
|
||||
{% csrf_token %}
|
||||
<input type="submit" value="gracefully reload uWSGI" name="_reload"/>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifdef UWSGI_EVDIS
|
||||
|
||||
#include "uwsgi.h"
|
||||
|
||||
void evdis_loop(struct uwsgi_server *uwsgi) {
|
||||
|
||||
// populate event list
|
||||
|
||||
int kfd = kqueue();
|
||||
if (kfd < 0) {
|
||||
uwsgi_error("kqueue()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#else
|
||||
#warning "*** Event Dispatcher support is disabled ***"
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifdef __linux__
|
||||
|
||||
#include <sys/inotify.h>
|
||||
|
||||
int uwsgi_file_monitor_new() {
|
||||
|
||||
int inotify_fd ;
|
||||
|
||||
|
||||
inotify_fd = inotify_init();
|
||||
|
||||
if (inotify_fd < 0) {
|
||||
uwsgi_error("inotify_init()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return inotify_fd ;
|
||||
}
|
||||
|
||||
int uwsgi_file_monitor_add(int fd, char *what) {
|
||||
|
||||
int inotify_watch_fd ;
|
||||
|
||||
inotify_watch_fd = inotify_add_watch(fd, what, IN_ALL_EVENTS);
|
||||
|
||||
if (inotify_watch_fd < 0) {
|
||||
uwsgi_error("inotify_add_watch()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return inotify_watch_fd;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,397 @@
|
||||
#include "uwsgi.h"
|
||||
|
||||
struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_http_req {
|
||||
|
||||
pthread_t a_new_thread;
|
||||
int fd;
|
||||
struct sockaddr_in c_addr;
|
||||
socklen_t c_len;
|
||||
};
|
||||
|
||||
enum {
|
||||
uwsgi_http_method,
|
||||
uwsgi_http_uri,
|
||||
uwsgi_http_protocol,
|
||||
uwsgi_http_protocol_r,
|
||||
|
||||
uwsgi_http_header_key,
|
||||
uwsgi_http_header_key_colon,
|
||||
|
||||
uwsgi_http_header_val,
|
||||
uwsgi_http_header_val_r,
|
||||
|
||||
uwsgi_http_end
|
||||
};
|
||||
|
||||
void http_end() {
|
||||
uwsgi_log("closing uWSGI embedded HTTP server.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void http_wait_end() {
|
||||
pid_t wp_p;
|
||||
int wp_c;
|
||||
wp_p = waitpid(-1, &wp_c, 0);
|
||||
uwsgi_log("closing uWSGI embedded HTTP server.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static char *add_uwsgi_var(char *up, char *key, uint16_t keylen, char *val, uint16_t vallen, int header, char *watermark)
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
if (!header) {
|
||||
|
||||
if ( (up + 2 + keylen + 2 + vallen) > watermark ) return up ;
|
||||
|
||||
*up++ = (unsigned char) (keylen & 0xff);
|
||||
*up++ = (unsigned char) ((keylen >> 8) & 0xff);
|
||||
|
||||
memcpy(up, key, keylen);
|
||||
up += keylen;
|
||||
} else {
|
||||
|
||||
|
||||
for (i = 0; i < keylen; i++) {
|
||||
if (key[i] == '-') {
|
||||
key[i] = '_';
|
||||
} else {
|
||||
key[i] = toupper( (int) key[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp("CONTENT_TYPE", key, keylen) && strncmp("CONTENT_LENGTH", key, keylen)) {
|
||||
if ( (up + 2 + keylen + 5 + 2 + vallen) > watermark ) return up ;
|
||||
*up++ = (unsigned char) (((uint16_t) keylen + 5) & 0xff);
|
||||
*up++ = (unsigned char) ((((uint16_t) keylen + 5) >> 8) & 0xff);
|
||||
memcpy(up, "HTTP_", 5);
|
||||
up += 5;
|
||||
} else {
|
||||
if ( (up + 2 + keylen + 2 + vallen) > watermark ) return up ;
|
||||
*up++ = (unsigned char) (keylen & 0xff);
|
||||
*up++ = (unsigned char) ((keylen >> 8) & 0xff);
|
||||
}
|
||||
|
||||
|
||||
memcpy(up, key, keylen);
|
||||
up += keylen;
|
||||
}
|
||||
|
||||
*up++ = (unsigned char) (vallen & 0xff);
|
||||
*up++ = (unsigned char) ((vallen >> 8) & 0xff);
|
||||
memcpy(up, val, vallen);
|
||||
up += vallen;
|
||||
|
||||
return up;
|
||||
}
|
||||
|
||||
static void *http_request(void *);
|
||||
|
||||
void http_loop(struct uwsgi_server * uwsgi)
|
||||
{
|
||||
|
||||
|
||||
struct uwsgi_http_req *ur;
|
||||
int ret;
|
||||
pthread_attr_t pa;
|
||||
int stat_loc ;
|
||||
|
||||
ret = pthread_attr_init(&pa);
|
||||
if (ret) {
|
||||
uwsgi_log("pthread_attr_init() = %d\n", ret);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = pthread_attr_setdetachstate(&pa, PTHREAD_CREATE_DETACHED);
|
||||
if (ret) {
|
||||
uwsgi_log("pthread_attr_setdetachstate() = %d\n", ret);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// ignore broken pipes;
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
if (!uwsgi->http_only) {
|
||||
signal(SIGCHLD, &http_end);
|
||||
signal(SIGINT, &http_wait_end);
|
||||
}
|
||||
else {
|
||||
signal(SIGINT, &http_end);
|
||||
}
|
||||
|
||||
uwsgi->http_server_name = malloc(256);
|
||||
if (!uwsgi->http_server_name) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(uwsgi->http_server_name, 0, 256);
|
||||
if (gethostname(uwsgi->http_server_name, 255)) {
|
||||
uwsgi_error("gethostname()");
|
||||
memcpy(uwsgi->http_server_name, "localhost", 9);
|
||||
}
|
||||
|
||||
uwsgi_log("starting HTTP loop on %s (pid: %d)\n", uwsgi->http_server_name, (int) getpid());
|
||||
for(;;) {
|
||||
|
||||
if (!uwsgi->http_only) {
|
||||
if (waitpid(-1, &stat_loc, WNOHANG) != 0) {
|
||||
http_end();
|
||||
}
|
||||
}
|
||||
ur = malloc(sizeof(struct uwsgi_http_req));
|
||||
if (!ur) {
|
||||
uwsgi_error("malloc()");
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
ur->c_len = sizeof(struct sockaddr_in) ;
|
||||
ur->fd = accept(uwsgi->http_fd, (struct sockaddr *) &ur->c_addr, &ur->c_len);
|
||||
|
||||
if (ur->fd < 0) {
|
||||
uwsgi_error("accept()");
|
||||
free(ur);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = pthread_create(&ur->a_new_thread, &pa, http_request, (void *) ur);
|
||||
if (ret) {
|
||||
uwsgi_log("pthread_create() = %d\n", ret);
|
||||
free(ur);
|
||||
// sleep a bit to allow some resource gaining
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void *http_request(void *u_h_r)
|
||||
{
|
||||
|
||||
char buf[4096];
|
||||
|
||||
char tmp_buf[4096];
|
||||
|
||||
char uwsgipkt[4096];
|
||||
|
||||
struct uwsgi_http_req *ur = (struct uwsgi_http_req *) u_h_r ;
|
||||
|
||||
int clientfd = ur->fd;
|
||||
int uwsgi_fd = -1;
|
||||
|
||||
int need_to_read = 1;
|
||||
int state = uwsgi_http_method;
|
||||
|
||||
int http_body_len = 0;
|
||||
|
||||
size_t len;
|
||||
|
||||
int i, j;
|
||||
|
||||
char HTTP_header_key[1024];
|
||||
|
||||
uint16_t ulen;
|
||||
|
||||
char *ptr = tmp_buf;
|
||||
|
||||
int qs = 0;
|
||||
|
||||
char *up = uwsgipkt;
|
||||
|
||||
char *watermark = up + 4096 ;
|
||||
char *watermark2 = tmp_buf + 4096 ;
|
||||
|
||||
int path_info_len;
|
||||
char *ip;
|
||||
|
||||
up[0] = 0;
|
||||
up[3] = 0;
|
||||
up += 4;
|
||||
|
||||
while (need_to_read) {
|
||||
len = read(clientfd, buf, 4096);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("read()");
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < (int) len; i++) {
|
||||
|
||||
if (buf[i] == ' ') {
|
||||
|
||||
if (state == uwsgi_http_method) {
|
||||
|
||||
up = add_uwsgi_var(up, "REQUEST_METHOD", 14, tmp_buf, ptr - tmp_buf, 0, watermark);
|
||||
ptr = tmp_buf;
|
||||
state = uwsgi_http_uri;
|
||||
|
||||
} else if (state == uwsgi_http_uri) {
|
||||
|
||||
up = add_uwsgi_var(up, "REQUEST_URI", 11, tmp_buf, ptr - tmp_buf, 0, watermark);
|
||||
|
||||
path_info_len = ptr - tmp_buf;
|
||||
for (j = 0; j < ptr - tmp_buf; j++) {
|
||||
if (tmp_buf[j] == '?') {
|
||||
path_info_len = j;
|
||||
if (j + 1 < (ptr - tmp_buf)) {
|
||||
up = add_uwsgi_var(up, "QUERY_STRING", 12, tmp_buf + j + 1, (ptr - tmp_buf) - (j + 1), 0, watermark);
|
||||
qs = 1 ;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!qs) {
|
||||
up = add_uwsgi_var(up, "QUERY_STRING", 12, NULL, 0, 0, watermark);
|
||||
}
|
||||
up = add_uwsgi_var(up, "PATH_INFO", 9, tmp_buf, path_info_len, 0, watermark);
|
||||
|
||||
ptr = tmp_buf;
|
||||
state = uwsgi_http_protocol;
|
||||
|
||||
} else if (state == uwsgi_http_header_key_colon) {
|
||||
|
||||
if (ptr+1 > watermark2) { close(uwsgi_fd); goto clear;}
|
||||
*ptr++ = 0;
|
||||
|
||||
memset(HTTP_header_key, 0, sizeof(HTTP_header_key));
|
||||
memcpy(HTTP_header_key, tmp_buf, strlen(tmp_buf));
|
||||
ptr = tmp_buf;
|
||||
state = uwsgi_http_header_val;
|
||||
} else {
|
||||
//check for overflow
|
||||
if (ptr+1 > watermark2) { close(uwsgi_fd); goto clear;}
|
||||
*ptr++ = buf[i];
|
||||
}
|
||||
|
||||
} else if (buf[i] == '\r') {
|
||||
|
||||
if (state == uwsgi_http_protocol) {
|
||||
state = uwsgi_http_protocol_r;
|
||||
}
|
||||
if (state == uwsgi_http_header_val) {
|
||||
state = uwsgi_http_header_val_r;
|
||||
} else if (state == uwsgi_http_header_key) {
|
||||
state = uwsgi_http_end;
|
||||
}
|
||||
} else if (buf[i] == '\n') {
|
||||
|
||||
if (state == uwsgi_http_header_val_r) {
|
||||
|
||||
up = add_uwsgi_var(up, HTTP_header_key, strlen(HTTP_header_key), tmp_buf, ptr - tmp_buf, 1, watermark);
|
||||
if (!strcmp("CONTENT_LENGTH", HTTP_header_key)) {
|
||||
if (ptr+1 > watermark2) { close(uwsgi_fd); goto clear;}
|
||||
*ptr++ = 0;
|
||||
http_body_len = atoi(tmp_buf);
|
||||
}
|
||||
ptr = tmp_buf;
|
||||
state = uwsgi_http_header_key;
|
||||
} else if (state == uwsgi_http_protocol_r) {
|
||||
|
||||
up = add_uwsgi_var(up, "SERVER_PROTOCOL", 15, tmp_buf, ptr - tmp_buf, 0, watermark);
|
||||
ptr = tmp_buf;
|
||||
state = uwsgi_http_header_key;
|
||||
} else if (state == uwsgi_http_end) {
|
||||
need_to_read = 0;
|
||||
|
||||
|
||||
up = add_uwsgi_var(up, "SERVER_NAME", 11, uwsgi.http_server_name, strlen(uwsgi.http_server_name), 0, watermark);
|
||||
up = add_uwsgi_var(up, "SERVER_PORT", 11, uwsgi.http_server_port, strlen(uwsgi.http_server_port), 0, watermark);
|
||||
|
||||
up = add_uwsgi_var(up, "SCRIPT_NAME", 11, "", 0, 0, watermark);
|
||||
|
||||
ip = inet_ntoa(ur->c_addr.sin_addr);
|
||||
up = add_uwsgi_var(up, "REMOTE_ADDR", 11, ip, strlen(ip), 0, watermark);
|
||||
|
||||
//up = add_uwsgi_var(up, "REMOTE_ADDR", 11, "127.0.0.1", 9, 0, watermark);
|
||||
//up = add_uwsgi_var(up, "REMOTE_USER", 11, "unknown", 7, 0);
|
||||
|
||||
for(j=0;j<uwsgi.http_vars_cnt;j++) {
|
||||
char *separator;
|
||||
|
||||
separator = strchr(uwsgi.http_vars[j], '=');
|
||||
if (separator) {
|
||||
up = add_uwsgi_var(up, uwsgi.http_vars[j], separator - uwsgi.http_vars[j], separator + 1, strlen(separator + 1), 0, watermark);
|
||||
}
|
||||
else {
|
||||
up = add_uwsgi_var(up, uwsgi.http_vars[j], strlen(uwsgi.http_vars[j]), NULL, 0, 0, watermark);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_fd = uwsgi_connect(uwsgi.socket_name, 10);
|
||||
if (uwsgi_fd >= 0) {
|
||||
ulen = (up - uwsgipkt) - 4;
|
||||
uwsgipkt[1] = (unsigned char) (ulen & 0xff);
|
||||
uwsgipkt[2] = (unsigned char) ((ulen >> 8) & 0xff);
|
||||
|
||||
if (write(uwsgi_fd, uwsgipkt, ulen + 4) < 0) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
|
||||
if (http_body_len > 0) {
|
||||
if (http_body_len >= (int) len - (i + 1)) {
|
||||
if (write(uwsgi_fd, buf + i + 1, len - (i + 1)) < 0) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
http_body_len -= len - (i + 1);
|
||||
} else {
|
||||
if (write(uwsgi_fd, buf + i, http_body_len) < 0) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
http_body_len = 0;
|
||||
}
|
||||
|
||||
while (http_body_len > 0) {
|
||||
int to_read = 4096;
|
||||
if (http_body_len < to_read) {
|
||||
to_read = http_body_len;
|
||||
}
|
||||
len = read(clientfd, uwsgipkt, to_read);
|
||||
if (write(uwsgi_fd, uwsgipkt, len) < 0) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
http_body_len -= len;
|
||||
}
|
||||
}
|
||||
while ((len = read(uwsgi_fd, uwsgipkt, 4096)) > 0) {
|
||||
if (write(clientfd, uwsgipkt, len) < 0) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
close(uwsgi_fd);
|
||||
}
|
||||
else {
|
||||
close(uwsgi_fd);
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
} else if (buf[i] == ':') {
|
||||
|
||||
if (state == uwsgi_http_header_key) {
|
||||
state = uwsgi_http_header_key_colon;
|
||||
} else {
|
||||
//check for overflow
|
||||
if (ptr+1 > watermark2) { close(uwsgi_fd); goto clear;}
|
||||
*ptr++ = buf[i];
|
||||
}
|
||||
} else {
|
||||
|
||||
//check for overflow
|
||||
if (ptr+1 > watermark2) { close(uwsgi_fd); goto clear;}
|
||||
*ptr++ = buf[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
clear:
|
||||
close(clientfd);
|
||||
|
||||
free(ur);
|
||||
pthread_exit(NULL);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
#ifdef UWSGI_INI
|
||||
|
||||
#include "uwsgi.h"
|
||||
|
||||
/*
|
||||
ini file must be read ALL into memory.
|
||||
This memory must not be freed for all the server lifecycle
|
||||
*/
|
||||
|
||||
enum {
|
||||
ini_key_start,
|
||||
ini_val_start,
|
||||
};
|
||||
|
||||
void ini_rstrip(char *line) {
|
||||
|
||||
off_t i ;
|
||||
|
||||
for(i = strlen(line)-1;i>=0; i--) {
|
||||
if (line[i] == ' ' || line[i] == '\t') {
|
||||
line[i] = 0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char *ini_lstrip(char *line) {
|
||||
|
||||
off_t i ;
|
||||
char *ptr = line;
|
||||
|
||||
for(i=0;i< (int) strlen(line);i++) {
|
||||
if (line[i] == ' ' || line[i] == '\t') {
|
||||
ptr++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
char *ini_get_key(char *key) {
|
||||
|
||||
off_t i;
|
||||
char *ptr = key ;
|
||||
|
||||
for(i=0;i< (int) strlen(key);i++) {
|
||||
ptr++ ;
|
||||
if (key[i] == '=') {
|
||||
key[i] = 0;
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
char *ini_get_line(char *ini, off_t size) {
|
||||
|
||||
off_t i ;
|
||||
char *ptr = ini;
|
||||
|
||||
for(i=0;i<size;i++) {
|
||||
ptr++;
|
||||
if (ini[i] == '\n') {
|
||||
ini[i] = 0;
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_ini_config(char *file, struct option *long_options) {
|
||||
|
||||
int fd;
|
||||
ssize_t len;
|
||||
char *ini;
|
||||
struct stat sb;
|
||||
|
||||
char *ini_line;
|
||||
|
||||
char *section = "";
|
||||
char *key;
|
||||
char *val;
|
||||
|
||||
int lines = 1 ;
|
||||
|
||||
struct option *lopt, *aopt;
|
||||
char *section_asked = "uwsgi";
|
||||
char *colon ;
|
||||
|
||||
colon = strchr(file, ':');
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
if (colon[1] != 0) {
|
||||
section_asked = colon+1 ;
|
||||
}
|
||||
}
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("open()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (fstat(fd, &sb)) {
|
||||
uwsgi_error("fstat()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ini = malloc(sb.st_size+1);
|
||||
|
||||
if (!ini) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
len = read(fd, ini, sb.st_size);
|
||||
if (len != sb.st_size) {
|
||||
uwsgi_error("read()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ini[sb.st_size+1] = 0 ;
|
||||
|
||||
while(sb.st_size) {
|
||||
ini_line = ini_get_line(ini, sb.st_size);
|
||||
if (ini_line == NULL) {
|
||||
break;
|
||||
}
|
||||
lines++;
|
||||
|
||||
// skip empty line
|
||||
key = ini_lstrip(ini);
|
||||
ini_rstrip(key);
|
||||
if (key[0] != 0) {
|
||||
if (key[0] == '[') {
|
||||
section = key+1;
|
||||
section[strlen(section)-1] = 0;
|
||||
}
|
||||
else if (key[0] == ';' || key[0] == '#') {
|
||||
// this is a comment
|
||||
}
|
||||
else {
|
||||
// val is always valid, but (obviously) can be ignored
|
||||
val = ini_get_key(key);
|
||||
|
||||
if (!strcmp(section, section_asked)) {
|
||||
ini_rstrip(key);
|
||||
val = ini_lstrip(val);
|
||||
ini_rstrip(val);
|
||||
lopt = long_options;
|
||||
while ((aopt = lopt)) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
if (!strcmp(key, aopt->name)) {
|
||||
if (aopt->flag) {
|
||||
*aopt->flag = aopt->val;
|
||||
}
|
||||
else {
|
||||
manage_opt(aopt->val, val);
|
||||
}
|
||||
}
|
||||
lopt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sb.st_size -= (ini_line - ini);
|
||||
ini += (ini_line - ini);
|
||||
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,352 @@
|
||||
#ifdef UWSGI_LDAP
|
||||
|
||||
#include "uwsgi.h"
|
||||
|
||||
#include <ldap.h>
|
||||
|
||||
void ldap2uwsgi(char *ldapname, char *uwsginame) {
|
||||
|
||||
char *ptr = uwsginame ;
|
||||
|
||||
int i;
|
||||
|
||||
for(i=0;i< (int) strlen(ldapname);i++) {
|
||||
if (isupper( (int)ldapname[i])) {
|
||||
*ptr++= '-';
|
||||
*ptr++= tolower( (int) ldapname[i]);
|
||||
}
|
||||
else {
|
||||
*ptr++= ldapname[i] ;
|
||||
}
|
||||
}
|
||||
|
||||
*ptr++= 0;
|
||||
}
|
||||
|
||||
int calc_ldap_name(char *name) {
|
||||
|
||||
int i;
|
||||
int counter = 0;
|
||||
|
||||
for(i=0;i< (int)strlen(name);i++) {
|
||||
if (isupper( (int) name[i])) {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
return strlen(name) + counter ;
|
||||
}
|
||||
|
||||
void uwsgi_ldap_schema_dump_ldif(struct option *lo) {
|
||||
|
||||
struct option *aopt, *lopt ;
|
||||
|
||||
lopt = lo;
|
||||
int i;
|
||||
int counter = 30000;
|
||||
|
||||
int pythonpath_found = 0 ;
|
||||
|
||||
uwsgi_log("\n");
|
||||
uwsgi_log("dn: cn=uwsgi,cn=schema,cn=config\n");
|
||||
uwsgi_log("objectClass: olcSchemaConfig\n");
|
||||
uwsgi_log("cn: uwsgi\n");
|
||||
|
||||
while( (aopt = lopt) ) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
|
||||
if (aopt->val == LONG_ARGS_PYTHONPATH) {
|
||||
if (pythonpath_found) {
|
||||
goto next;
|
||||
}
|
||||
pythonpath_found = 1;
|
||||
}
|
||||
|
||||
if (aopt->flag) {
|
||||
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", counter) ;
|
||||
counter++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", aopt->val) ;
|
||||
}
|
||||
for(i=0;i< (int)strlen(aopt->name);i++) {
|
||||
if (aopt->name[i] == '-') {
|
||||
i++;
|
||||
uwsgi_log("%c", toupper( (int) aopt->name[i]));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("%c", aopt->name[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (aopt->has_arg) {
|
||||
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
|
||||
}
|
||||
next:
|
||||
lopt++;
|
||||
}
|
||||
|
||||
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n") ;
|
||||
|
||||
lopt = lo;
|
||||
|
||||
uwsgi_log("olcObjectClasses: ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
|
||||
|
||||
pythonpath_found = 0;
|
||||
while( (aopt = lopt) ) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
|
||||
if (aopt->val == LONG_ARGS_PYTHONPATH) {
|
||||
if (pythonpath_found) {
|
||||
goto next2;
|
||||
}
|
||||
pythonpath_found = 1;
|
||||
}
|
||||
|
||||
uwsgi_log("uWSGI");
|
||||
|
||||
for(i=0;i< (int)strlen(aopt->name);i++) {
|
||||
if (aopt->name[i] == '-') {
|
||||
i++;
|
||||
uwsgi_log("%c", toupper( (int) aopt->name[i]));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("%c", aopt->name[i]);
|
||||
}
|
||||
}
|
||||
uwsgi_log(" $ ");
|
||||
next2:
|
||||
lopt++;
|
||||
}
|
||||
|
||||
uwsgi_log("uWSGInull ))\n");
|
||||
|
||||
uwsgi_log("\n");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_ldap_schema_dump(struct option *lo) {
|
||||
|
||||
struct option *aopt, *lopt ;
|
||||
|
||||
lopt = lo;
|
||||
int i;
|
||||
int counter = 30000;
|
||||
int pythonpath_found = 0;
|
||||
|
||||
while( (aopt = lopt) ) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
|
||||
|
||||
if (aopt->val == LONG_ARGS_PYTHONPATH) {
|
||||
if (pythonpath_found) {
|
||||
goto next;
|
||||
}
|
||||
pythonpath_found = 1;
|
||||
}
|
||||
|
||||
if (aopt->flag) {
|
||||
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", counter) ;
|
||||
counter++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME 'uWSGI", aopt->val) ;
|
||||
}
|
||||
for(i=0;i< (int)strlen(aopt->name);i++) {
|
||||
if (aopt->name[i] == '-') {
|
||||
i++;
|
||||
uwsgi_log("%c", toupper( (int) aopt->name[i]));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("%c", aopt->name[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (aopt->has_arg) {
|
||||
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
|
||||
}
|
||||
next:
|
||||
lopt++;
|
||||
}
|
||||
|
||||
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n") ;
|
||||
|
||||
lopt = lo;
|
||||
|
||||
uwsgi_log("objectclass ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
|
||||
|
||||
pythonpath_found = 0;
|
||||
while( (aopt = lopt) ) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
|
||||
if (aopt->val == LONG_ARGS_PYTHONPATH) {
|
||||
if (pythonpath_found) {
|
||||
goto next2;
|
||||
}
|
||||
pythonpath_found = 1;
|
||||
}
|
||||
|
||||
uwsgi_log("uWSGI");
|
||||
|
||||
for(i=0;i< (int)strlen(aopt->name);i++) {
|
||||
if (aopt->name[i] == '-') {
|
||||
i++;
|
||||
uwsgi_log("%c", toupper( (int) aopt->name[i]));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("%c", aopt->name[i]);
|
||||
}
|
||||
}
|
||||
uwsgi_log(" $ ");
|
||||
next2:
|
||||
lopt++;
|
||||
}
|
||||
|
||||
uwsgi_log("uWSGInull ))\n");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void uwsgi_ldap_config(struct uwsgi_server *uwsgi, struct option *long_options) {
|
||||
|
||||
LDAP *ldp;
|
||||
LDAPMessage *results, *entry;
|
||||
BerElement *ber;
|
||||
struct berval **bervalues;
|
||||
char *attr;
|
||||
char *uwsgi_attr;
|
||||
|
||||
char *url = "ldap:///";
|
||||
char *url_slash;
|
||||
|
||||
int desired_version = LDAP_VERSION3;
|
||||
int ret;
|
||||
|
||||
struct option *aopt, *lopt;
|
||||
|
||||
LDAPURLDesc *ldap_url;
|
||||
|
||||
if (uwsgi->ldap) {
|
||||
url = uwsgi->ldap;
|
||||
}
|
||||
|
||||
if (!ldap_is_ldap_url(url)) {
|
||||
uwsgi_log("invalid LDAP url.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ldap_url_parse(url, &ldap_url) != LDAP_SUCCESS) {
|
||||
uwsgi_log("unable to parse LDAP url.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
url_slash = strchr(url, '/');
|
||||
url_slash = strchr(url_slash + 1, '/');
|
||||
|
||||
url_slash = strchr(url_slash + 1, '/');
|
||||
if (url_slash) {
|
||||
url_slash[0] = 0;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("LDAP URL: %s\n", url);
|
||||
uwsgi_debug("LDAP BASE DN: %s\n", ldap_url->lud_dn);
|
||||
#endif
|
||||
|
||||
if ( (ret = ldap_initialize( &ldp, url)) != LDAP_SUCCESS) {
|
||||
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if ( (ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
|
||||
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if ( (ret = ldap_search_ext_s(ldp, ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter, NULL, 0, NULL, NULL, NULL, 1, &results)) != LDAP_SUCCESS) {
|
||||
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("LDAP connection initialized %p\n", ldp);
|
||||
#endif
|
||||
|
||||
free(ldap_url);
|
||||
|
||||
if (ldap_count_entries(ldp, results) < 1) {
|
||||
uwsgi_log("no LDAP entry found\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
entry = ldap_first_entry(ldp, results);
|
||||
|
||||
for( attr = ldap_first_attribute(ldp, entry, &ber); attr != NULL; attr = ldap_next_attribute(ldp, entry, ber)) {
|
||||
if (!strncmp(attr,"uWSGI",5)) {
|
||||
|
||||
uwsgi_attr = malloc( calc_ldap_name(attr) + 1 );
|
||||
if (!uwsgi_attr) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ldap2uwsgi(attr+5, uwsgi_attr);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("LDAP attribute: %s = --%s\n", attr, uwsgi_attr);
|
||||
#endif
|
||||
bervalues = ldap_get_values_len(ldp, entry, attr);
|
||||
if (bervalues) {
|
||||
// do not free uwsgi_val;
|
||||
char *uwsgi_val = malloc( bervalues[0]->bv_len + 1 );
|
||||
if (!uwsgi_val) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memcpy(uwsgi_val, bervalues[0]->bv_val, bervalues[0]->bv_len);
|
||||
uwsgi_val[bervalues[0]->bv_len] = 0;
|
||||
|
||||
lopt = long_options;
|
||||
while ((aopt = lopt)) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
if (!strcmp(uwsgi_attr, aopt->name)) {
|
||||
if (aopt->flag) {
|
||||
*aopt->flag = aopt->val;
|
||||
}
|
||||
else {
|
||||
manage_opt(aopt->val, uwsgi_val);
|
||||
}
|
||||
}
|
||||
lopt++;
|
||||
}
|
||||
}
|
||||
|
||||
free(bervalues);
|
||||
free(uwsgi_attr);
|
||||
}
|
||||
free(attr);
|
||||
}
|
||||
|
||||
free(ber);
|
||||
free(results);
|
||||
|
||||
ldap_unbind_ext_s(ldp, NULL, NULL);
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -38,7 +38,7 @@
|
||||
#ifdef __linux__
|
||||
#include <endian.h>
|
||||
#elif __sun__
|
||||
#elif __apple__
|
||||
#elif __APPLE__
|
||||
#include <libkern/OSByteOrder.h>
|
||||
#else
|
||||
#include <machine/endian.h>
|
||||
@@ -483,6 +483,12 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
|
||||
);
|
||||
uwsgi_add_var(b, "REMOTE_PORT", 11, buf, strlen(buf));
|
||||
|
||||
if (!buffer_is_empty(con->authed_user)) {
|
||||
uwsgi_add_var(b, "REMOTE_USER", 11,
|
||||
CONST_BUF_LEN(con->authed_user));
|
||||
}
|
||||
|
||||
|
||||
|
||||
s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
|
||||
uwsgi_add_var(b, "REMOTE_ADDR", 11, (char *)s, strlen(s));
|
||||
@@ -490,7 +496,7 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
|
||||
if (hctx->path_info_offset > 1) {
|
||||
uwsgi_add_var(b, "SCRIPT_NAME", 11, con->uri.path->ptr, hctx->path_info_offset);
|
||||
if (strlen(con->uri.path->ptr + hctx->path_info_offset) > 0) {
|
||||
uwsgi_add_var(b, "PATH_INFO", 9, con->request.orig_uri->ptr + hctx->path_info_offset, strlen(con->request.orig_uri->ptr + hctx->path_info_offset));
|
||||
uwsgi_add_var(b, "PATH_INFO", 9, con->uri.path->ptr + hctx->path_info_offset, strlen(con->uri.path->ptr + hctx->path_info_offset));
|
||||
}
|
||||
else {
|
||||
uwsgi_add_var(b, "PATH_INFO", 9, "/", 1);
|
||||
@@ -498,7 +504,7 @@ static int uwsgi_create_env(server *srv, handler_ctx *hctx) {
|
||||
}
|
||||
else {
|
||||
uwsgi_add_var(b, "SCRIPT_NAME", 11, "", 0) ;
|
||||
uwsgi_add_var(b, "PATH_INFO", 9, con->request.orig_uri->ptr, con->request.orig_uri->used-1) ;
|
||||
uwsgi_add_var(b, "PATH_INFO", 9, con->uri.path->ptr, strlen(con->uri.path->ptr)) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
char mempkt[4096];
|
||||
char logpkt[4096];
|
||||
|
||||
struct iovec logvec[2] ;
|
||||
struct iovec logvec[4] ;
|
||||
int logvecpos = 0 ;
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
@@ -45,9 +45,8 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
app_req = wi->requests;
|
||||
}
|
||||
}
|
||||
via = msg2;
|
||||
|
||||
if (wsgi_req->sendfile_fd > -1) {
|
||||
if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { //wsgi_req->sendfile_fd_size > 0 ) {
|
||||
via = msg1;
|
||||
}
|
||||
#endif
|
||||
@@ -56,15 +55,24 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
microseconds = wsgi_req->end_of_request.tv_sec * 1000000 + wsgi_req->end_of_request.tv_usec;
|
||||
microseconds2 = wsgi_req->start_of_request.tv_sec * 1000000 + wsgi_req->start_of_request.tv_usec;
|
||||
|
||||
if (uwsgi.vhost) {
|
||||
logvec[logvecpos].iov_base = wsgi_req->host ;
|
||||
logvec[logvecpos].iov_len = wsgi_req->host_len ;
|
||||
logvecpos++;
|
||||
|
||||
logvec[logvecpos].iov_base = " " ;
|
||||
logvec[logvecpos].iov_len = 1 ;
|
||||
logvecpos++;
|
||||
}
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1) {
|
||||
#ifndef UNBIT
|
||||
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ",
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size, uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024,
|
||||
uwsgi.workers[uwsgi.mywid].rss_size, uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
|
||||
(unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long ) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024,
|
||||
(unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long ) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
|
||||
#else
|
||||
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} ",
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size, uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
|
||||
(unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -76,10 +84,10 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld msecs%s(%.*s %d) %d headers in %d bytes (%d async switches on async core %d)\n",
|
||||
uwsgi.mypid,
|
||||
(int) uwsgi.mypid,
|
||||
wsgi_req->app_id,
|
||||
app_req,
|
||||
uwsgi.workers[0].requests,
|
||||
(unsigned long long ) uwsgi.workers[0].requests,
|
||||
wsgi_req->remote_addr_len, wsgi_req->remote_addr,
|
||||
wsgi_req->remote_user_len, wsgi_req->remote_user,
|
||||
wsgi_req->var_cnt,
|
||||
@@ -87,7 +95,7 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
24, time_request,
|
||||
wsgi_req->method_len, wsgi_req->method,
|
||||
wsgi_req->uri_len, wsgi_req->uri,
|
||||
(uint64_t) wsgi_req->response_size,
|
||||
(unsigned long long) wsgi_req->response_size,
|
||||
(long int) (microseconds - microseconds2) / 1000,
|
||||
via,
|
||||
wsgi_req->protocol_len, wsgi_req->protocol,
|
||||
@@ -113,7 +121,7 @@ void get_memusage() {
|
||||
int i;
|
||||
procfile = fopen("/proc/self/stat", "r");
|
||||
if (procfile) {
|
||||
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", &uwsgi.workers[uwsgi.mywid].vsz_size, &uwsgi.workers[uwsgi.mywid].rss_size);
|
||||
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) &uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long *) &uwsgi.workers[uwsgi.mywid].rss_size);
|
||||
if (i != 2) {
|
||||
uwsgi_log( "warning: invalid record in /proc/self/stat\n");
|
||||
}
|
||||
@@ -172,6 +180,17 @@ void get_memusage() {
|
||||
|
||||
kvm_close(kv);
|
||||
}
|
||||
|
||||
#elif defined(__HAIKU__)
|
||||
area_info ai;
|
||||
int32 cookie;
|
||||
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size = 0 ;
|
||||
uwsgi.workers[uwsgi.mywid].rss_size = 0 ;
|
||||
while(get_next_area_info(0, &cookie, &ai) == B_OK) {
|
||||
uwsgi.workers[uwsgi.mywid].vsz_size += ai.ram_size;
|
||||
if ( (ai.protection & B_WRITE_AREA) != 0) {
|
||||
uwsgi.workers[uwsgi.mywid].rss_size += ai.ram_size;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<unbit>
|
||||
<pippo/>
|
||||
|
||||
<pluto>
|
||||
ciao
|
||||
ciao
|
||||
</pluto>
|
||||
|
||||
|
||||
<uwsgi id="unbit.it">
|
||||
<http>:3333</http>
|
||||
<module>trac.web.main:dispatch_request</module>
|
||||
<pluto>ciao</pluto>
|
||||
<env>TRAC_ENV=/root/uwsgi/utrac</env>
|
||||
</uwsgi>
|
||||
|
||||
<uwsgi id="projects.unbit.it">
|
||||
<http>:4444</http>
|
||||
<module>trac.web.main:dispatch_request</module>
|
||||
</uwsgi>
|
||||
|
||||
</unbit>
|
||||
@@ -0,0 +1,26 @@
|
||||
import uwsgi
|
||||
|
||||
import os
|
||||
|
||||
def application(env, start_response):
|
||||
|
||||
boundary = 'uwsgi_mjpeg_frame'
|
||||
|
||||
start_response('200 Ok', [
|
||||
|
||||
('Cache-Control', 'no-cache'),
|
||||
('Cache-Control', 'private'),
|
||||
('Pragma', 'no-cache'),
|
||||
('Content-Type', 'multipart/x-mixed-replace; boundary=' + boundary),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
yield "--%s\n" % boundary
|
||||
|
||||
while 1:
|
||||
yield "Content-Type: image/jpeg\r\n\r\n"
|
||||
uwsgi.sendfile('screenshot.jpg')
|
||||
yield "--%s\n" % boundary
|
||||
#os.system('./isightcapture -w 640 -h 480 screenshot.jpg')
|
||||
#os.system('screencapture -m -T 1 screenshot.jpg')
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
use Mojolicious::Lite;
|
||||
|
||||
# /
|
||||
get '/' => 'index';
|
||||
|
||||
# /*
|
||||
get '/:groovy' => sub {
|
||||
my $self = shift;
|
||||
$self->render_text($self->param('groovy'), layout => 'funky');
|
||||
};
|
||||
|
||||
app->start('psgi');
|
||||
__DATA__
|
||||
|
||||
@@ index.html.ep
|
||||
% layout 'funky';
|
||||
Yea baby!
|
||||
|
||||
@@ layouts/funky.html.ep
|
||||
<!doctype html><html>
|
||||
<head><title>Funky!</title></head>
|
||||
<body><%= content %></body>
|
||||
</html>
|
||||
@@ -2,13 +2,14 @@
|
||||
|
||||
void nagios(struct uwsgi_server *uwsgi) {
|
||||
|
||||
char *tcp_port;
|
||||
struct pollfd nagios_poll;
|
||||
// connect and send
|
||||
if (uwsgi->socket_name == NULL) {
|
||||
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
|
||||
exit(3);
|
||||
}
|
||||
char *tcp_port = strchr(uwsgi->socket_name, ':');
|
||||
tcp_port = strchr(uwsgi->socket_name, ':');
|
||||
if (tcp_port == NULL) {
|
||||
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
|
||||
exit(3);
|
||||
|
||||
@@ -35,7 +35,9 @@
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
#define NGX_HTTP_UWSGI_TEMP_PATH "uwsgi_temp"
|
||||
#ifndef NGX_HTTP_UWSGI_TEMP_PATH
|
||||
#define NGX_HTTP_UWSGI_TEMP_PATH "uwsgi_temp"
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
ngx_http_upstream_conf_t upstream;
|
||||
@@ -48,6 +50,8 @@ typedef struct {
|
||||
ngx_array_t *uwsgi_lengths;
|
||||
ngx_array_t *uwsgi_values;
|
||||
|
||||
ngx_str_t uwsgi_string ;
|
||||
|
||||
u_char modifier1;
|
||||
u_char modifier2;
|
||||
|
||||
@@ -106,7 +110,9 @@ static ngx_conf_bitmask_t ngx_http_uwsgi_next_upstream_masks[] = {
|
||||
{ngx_string ("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT},
|
||||
{ngx_string ("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER},
|
||||
{ngx_string ("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500},
|
||||
{ngx_string ("http_502"), NGX_HTTP_UPSTREAM_FT_HTTP_502},
|
||||
{ngx_string ("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503},
|
||||
{ngx_string ("http_504"), NGX_HTTP_UPSTREAM_FT_HTTP_504},
|
||||
{ngx_string ("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404},
|
||||
{ngx_string ("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING},
|
||||
{ngx_string ("off"), NGX_HTTP_UPSTREAM_FT_OFF},
|
||||
@@ -271,6 +277,14 @@ static ngx_command_t ngx_http_uwsgi_commands[] = {
|
||||
offsetof (ngx_http_uwsgi_loc_conf_t, params_source),
|
||||
NULL},
|
||||
|
||||
{ ngx_string("uwsgi_string"),
|
||||
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
|
||||
NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_uwsgi_loc_conf_t, uwsgi_string),
|
||||
NULL },
|
||||
|
||||
{ngx_string ("uwsgi_pass_header"),
|
||||
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
|
||||
NGX_CONF_FLAG,
|
||||
@@ -538,13 +552,18 @@ ngx_http_uwsgi_create_request (ngx_http_request_t * r)
|
||||
}
|
||||
}
|
||||
|
||||
if (uwcf->uwsgi_string.data && uwcf->uwsgi_string.len) {
|
||||
uwsgi_pkt_size += uwcf->uwsgi_string.len ;
|
||||
}
|
||||
|
||||
// check here
|
||||
|
||||
/* allow custom uwsgi packet
|
||||
if (uwsgi_pkt_size > 0 && uwsgi_pkt_size < 2) {
|
||||
ngx_log_error (NGX_LOG_ALERT, r->connection->log, 0,
|
||||
"uwsgi request is too little: %uz", uwsgi_pkt_size);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
*/
|
||||
|
||||
b = ngx_create_temp_buf (r->pool, uwsgi_pkt_size + 4);
|
||||
if (b == NULL) {
|
||||
@@ -676,6 +695,11 @@ ngx_http_uwsgi_create_request (ngx_http_request_t * r)
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (uwcf->uwsgi_string.data && uwcf->uwsgi_string.len) {
|
||||
b->last = ngx_copy(b->last, uwcf->uwsgi_string.data, uwcf->uwsgi_string.len);
|
||||
}
|
||||
|
||||
if (uwcf->upstream.pass_request_body) {
|
||||
body = r->upstream->request_bufs;
|
||||
r->upstream->request_bufs = cl;
|
||||
@@ -1381,6 +1405,8 @@ ngx_http_uwsgi_merge_loc_conf (ngx_conf_t * cf, void *parent, void *child)
|
||||
ngx_conf_merge_value (conf->upstream.intercept_errors,
|
||||
prev->upstream.intercept_errors, 0);
|
||||
|
||||
ngx_conf_merge_str_value(conf->uwsgi_string, prev->uwsgi_string, "");
|
||||
|
||||
hash.max_size = 512;
|
||||
hash.bucket_size = ngx_align (64, ngx_cacheline_size);
|
||||
hash.name = "uwsgi_hide_headers_hash";
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
#include "uwsgi.h"
|
||||
|
||||
void embed_plugins(struct uwsgi_server *uwsgi) {
|
||||
|
||||
#ifdef UWSGI_EMBED_PLUGIN_PSGI
|
||||
if (uwsgi->plugin_arg_psgi)
|
||||
ret = uwsgi_load_plugin(uwsgi, 5, "psgi_plugin.so", uwsgi->plugin_arg_psgi, 0);
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EMBED_PLUGIN_LUA
|
||||
if (uwsgi->plugin_arg_lua)
|
||||
ret = uwsgi_load_plugin(uwsgi, 6, "lua_plugin.so", uwsgi->plugin_arg_lua, 0);
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EMBED_PLUGIN_RACK
|
||||
if (uwsgi->plugin_arg_rack)
|
||||
ret = uwsgi_load_plugin(uwsgi, 7, "rack_plugin.so", uwsgi->plugin_arg_rack, 0);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_load_plugin(struct uwsgi_server *uwsgi, int modifier, char *plugin, char *pargs, int absolute) {
|
||||
|
||||
char *plugin_name ;
|
||||
|
||||
void *plugin_handle;
|
||||
int (*plugin_init) (struct uwsgi_server *, char *);
|
||||
int (*plugin_request) (struct uwsgi_server *, struct wsgi_request *);
|
||||
void (*plugin_after_request) (struct uwsgi_server *, struct wsgi_request *);
|
||||
|
||||
if (absolute) {
|
||||
plugin_name = malloc(strlen(plugin) + 1);
|
||||
memcpy(plugin_name, plugin, strlen(plugin) + 1);
|
||||
}
|
||||
else {
|
||||
plugin_name = malloc(strlen(UWSGI_PLUGIN_DIR) + 1 + strlen(plugin) + 1);
|
||||
if (!plugin_name) {
|
||||
uwsgi_error("malloc()");
|
||||
return -1 ;
|
||||
}
|
||||
memcpy(plugin_name, UWSGI_PLUGIN_DIR, strlen(UWSGI_PLUGIN_DIR));
|
||||
memcpy(plugin_name + strlen(UWSGI_PLUGIN_DIR) , "/", 1);
|
||||
memcpy(plugin_name + strlen(UWSGI_PLUGIN_DIR) + 1, plugin, strlen(plugin) + 1);
|
||||
}
|
||||
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
|
||||
free(plugin_name);
|
||||
|
||||
if (!plugin_handle) {
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
}
|
||||
else {
|
||||
plugin_init = dlsym(plugin_handle, "uwsgi_init");
|
||||
if (plugin_init) {
|
||||
if ((*plugin_init) (uwsgi, pargs)) {
|
||||
uwsgi_log( "plugin initialization returned error\n");
|
||||
if (dlclose(plugin_handle)) {
|
||||
uwsgi_log( "unable to unload plugin\n");
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
plugin_request = dlsym(plugin_handle, "uwsgi_request");
|
||||
if (plugin_request) {
|
||||
uwsgi->shared->hooks[modifier] = plugin_request;
|
||||
plugin_after_request = dlsym(plugin_handle, "uwsgi_after_request");
|
||||
if (plugin_after_request) {
|
||||
uwsgi->shared->after_hooks[modifier] = plugin_after_request;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
|
||||
fprintf(stderr,"i am the example plugin initialization function with arg: %s\n", args);
|
||||
uwsgi_log("i am the example plugin initialization function with arg: %s\n", args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -16,5 +16,5 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
void uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
fprintf(stderr,"i am the example plugin after request function\n");
|
||||
uwsgi_log("i am the example plugin after request function\n");
|
||||
}
|
||||
|
||||
@@ -104,8 +104,7 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
// put function in the stack
|
||||
lua_pushvalue(ulua.L, -1);
|
||||
lua_getfield(ulua.L, -1, "run");
|
||||
lua_getfield(ulua.L, LUA_GLOBALSINDEX, "run");
|
||||
|
||||
// put cgi vars in the stack
|
||||
lua_newtable(ulua.L);
|
||||
|
||||
+24
-20
@@ -6,6 +6,8 @@
|
||||
static PerlInterpreter *my_perl;
|
||||
static SV *psgi_func ;
|
||||
|
||||
extern char **environ;
|
||||
|
||||
/* statistically ordered */
|
||||
static struct http_status_codes hsc[] = {
|
||||
|
||||
@@ -76,7 +78,6 @@ xs_init(pTHX)
|
||||
|
||||
int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
|
||||
|
||||
char *pargs[2] ;
|
||||
char *psgibuffer ;
|
||||
int fd ;
|
||||
|
||||
@@ -84,20 +85,20 @@ int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
|
||||
|
||||
struct http_status_codes *http_sc ;
|
||||
|
||||
char *embedding[] = { "", "-e", "0" };
|
||||
int argc = 4 ;
|
||||
char *embedding[] = { "", args, "-e", "0" };
|
||||
char **argv = embedding ;
|
||||
|
||||
uwsgi_log("initializing Perl environment: %s\n", args);
|
||||
|
||||
fprintf(stderr,"initializing Perl environment: %s\n", args);
|
||||
|
||||
PERL_SYS_INIT3(&argc, &argv, &environ);
|
||||
my_perl = perl_alloc();
|
||||
if (!my_perl) {
|
||||
fprintf(stderr,"unable to allocate perl interpreter\n");
|
||||
uwsgi_log("unable to allocate perl interpreter\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pargs[0] = "" ;
|
||||
pargs[1] = args ;
|
||||
|
||||
PL_perl_destruct_level = 1;
|
||||
perl_construct(my_perl);
|
||||
|
||||
// filling http status codes
|
||||
@@ -106,31 +107,32 @@ int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
|
||||
}
|
||||
|
||||
|
||||
perl_parse(my_perl, xs_init, 3, embedding, NULL);
|
||||
PL_origalen = 1;
|
||||
perl_parse(my_perl, xs_init, 4, embedding, NULL);
|
||||
|
||||
perl_eval_pv("use IO::Handle;", 0);
|
||||
|
||||
fd = open(args, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
perror("open()");
|
||||
uwsgi_error("open()");
|
||||
goto clear ;
|
||||
}
|
||||
|
||||
if (fstat(fd, &stat_psgi)) {
|
||||
perror("fstat()");
|
||||
uwsgi_error("fstat()");
|
||||
close(fd);
|
||||
goto clear;
|
||||
}
|
||||
|
||||
psgibuffer = malloc(stat_psgi.st_size);
|
||||
if (!psgibuffer) {
|
||||
perror("malloc()");
|
||||
uwsgi_error("malloc()");
|
||||
close(fd);
|
||||
goto clear;
|
||||
}
|
||||
|
||||
if (read(fd, psgibuffer, stat_psgi.st_size) != stat_psgi.st_size) {
|
||||
perror("read()");
|
||||
uwsgi_error("read()");
|
||||
close(fd);
|
||||
free(psgibuffer);
|
||||
goto clear;
|
||||
@@ -139,8 +141,9 @@ int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
|
||||
psgibuffer[stat_psgi.st_size] = 0 ;
|
||||
|
||||
psgi_func = perl_eval_pv(psgibuffer, 0);
|
||||
|
||||
if (!psgi_func) {
|
||||
fprintf(stderr,"unable to find PSGI function entry point.\n");
|
||||
uwsgi_log("unable to find PSGI function entry point.\n");
|
||||
close(fd);
|
||||
free(psgibuffer);
|
||||
goto clear;
|
||||
@@ -175,13 +178,13 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
|
||||
/* Standard PSGI request */
|
||||
if (!wsgi_req->uh.pktsize) {
|
||||
fprintf (stderr, "Invalid PSGI request. skip.\n");
|
||||
uwsgi_log("Invalid PSGI request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi_parse_vars(uwsgi, wsgi_req)) {
|
||||
fprintf(stderr,"Invalid PSGI request. skip.\n");
|
||||
uwsgi_log("Invalid PSGI request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -259,7 +262,6 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
// dereference output
|
||||
response = (AV *) SvRV( sv_2mortal(newSVsv(POPs)) ) ;
|
||||
|
||||
|
||||
status_code = av_fetch(response, 0, 0);
|
||||
|
||||
wsgi_req->hvec[0].iov_base = "HTTP/1.1 ";
|
||||
@@ -320,7 +322,7 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
if ( (wsgi_req->response_size = writev(wsgi_req->poll.fd, wsgi_req->hvec, vi+1)) < 0) {
|
||||
perror("writev()");
|
||||
uwsgi_error("writev()");
|
||||
}
|
||||
|
||||
|
||||
@@ -328,8 +330,7 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
|
||||
io = *hitem;
|
||||
|
||||
|
||||
if (SvTYPE(SvRV(io)) == SVt_PVGV) {
|
||||
if (SvTYPE(SvRV(io)) == SVt_PVGV || SvTYPE(SvRV(io)) == SVt_PVHV) {
|
||||
|
||||
for(;;) {
|
||||
|
||||
@@ -360,6 +361,9 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
uwsgi_log("unsupported response body type: %d\n", SvTYPE(SvRV(io)));
|
||||
}
|
||||
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
|
||||
@@ -0,0 +1,382 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
#include <ruby.h>
|
||||
|
||||
extern char **environ;
|
||||
|
||||
/* statistically ordered */
|
||||
static struct http_status_codes hsc[] = {
|
||||
|
||||
{"200", "OK"},
|
||||
{"302", "Found"},
|
||||
{"404", "Not Found"},
|
||||
{"500", "Internal Server Error"},
|
||||
{"301", "Moved Permanently"},
|
||||
{"304", "Not Modified"},
|
||||
{"303", "See Other"},
|
||||
{"403", "Forbidden"},
|
||||
{"307", "Temporary Redirect"},
|
||||
{"401", "Unauthorized"},
|
||||
{"400", "Bad Request"},
|
||||
{"405", "Method Not Allowed"},
|
||||
{"408", "Request Timeout"},
|
||||
|
||||
{"100", "Continue"},
|
||||
{"101", "Switching Protocols"},
|
||||
{"201", "Created"},
|
||||
{"202", "Accepted"},
|
||||
{"203", "Non-Authoritative Information"},
|
||||
{"204", "No Content"},
|
||||
{"205", "Reset Content"},
|
||||
{"206", "Partial Content"},
|
||||
{"300", "Multiple Choices"},
|
||||
{"305", "Use Proxy"},
|
||||
{"402", "Payment Required"},
|
||||
{"406", "Not Acceptable"},
|
||||
{"407", "Proxy Authentication Required"},
|
||||
{"409", "Conflict"},
|
||||
{"410", "Gone"},
|
||||
{"411", "Length Required"},
|
||||
{"412", "Precondition Failed"},
|
||||
{"413", "Request Entity Too Large"},
|
||||
{"414", "Request-URI Too Long"},
|
||||
{"415", "Unsupported Media Type"},
|
||||
{"416", "Requested Range Not Satisfiable"},
|
||||
{"417", "Expectation Failed"},
|
||||
{"501", "Not Implemented"},
|
||||
{"502", "Bad Gateway"},
|
||||
{"503", "Service Unavailable"},
|
||||
{"504", "Gateway Timeout"},
|
||||
{"505", "HTTP Version Not Supported"},
|
||||
{ "", NULL },
|
||||
};
|
||||
|
||||
|
||||
VALUE dispatcher;
|
||||
VALUE rb_uwsgi_io_class;
|
||||
ID call;
|
||||
|
||||
VALUE rb_uwsgi_io_new(VALUE class, VALUE wr) {
|
||||
|
||||
struct wsgi_request *wsgi_req;
|
||||
|
||||
Data_Get_Struct(wr, struct wsgi_request, wsgi_req);
|
||||
uwsgi_log("INITIALIZING UWSGI IO FOR FD: %d\n", wsgi_req->poll.fd);
|
||||
|
||||
VALUE self = Data_Wrap_Struct(class , 0, 0, wsgi_req);
|
||||
|
||||
rb_obj_call_init(self, 0, NULL);
|
||||
|
||||
return self;
|
||||
|
||||
}
|
||||
|
||||
VALUE rb_uwsgi_io_init(int argc, VALUE *argv, VALUE self) {
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
VALUE rb_uwsgi_io_gets(VALUE obj, VALUE args) {
|
||||
|
||||
struct wsgi_request *wsgi_req;
|
||||
Data_Get_Struct(obj, struct wsgi_request, wsgi_req);
|
||||
|
||||
uwsgi_log("CALLING gets !!!\n");
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE rb_uwsgi_io_each(VALUE obj, VALUE args) {
|
||||
|
||||
struct wsgi_request *wsgi_req;
|
||||
Data_Get_Struct(obj, struct wsgi_request, wsgi_req);
|
||||
|
||||
uwsgi_log("CALLING each !!!\n");
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE rb_uwsgi_io_read(VALUE obj, VALUE args) {
|
||||
|
||||
struct wsgi_request *wsgi_req;
|
||||
Data_Get_Struct(obj, struct wsgi_request, wsgi_req);
|
||||
|
||||
size_t len;
|
||||
|
||||
uwsgi_log("CALLING read on %d !!!\n", wsgi_req->poll.fd);
|
||||
|
||||
if (RARRAY(args)->len == 0) {
|
||||
uwsgi_log("READ ALL THE BODY (%d bytes)\n", wsgi_req->post_cl);
|
||||
char *post_body = malloc(wsgi_req->post_cl);
|
||||
if (post_body) {
|
||||
len = read( wsgi_req->poll.fd, post_body, wsgi_req->post_cl);
|
||||
VALUE chunk = rb_str_new(post_body, wsgi_req->post_cl);
|
||||
free(post_body);
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
else if (RARRAY(args)->len > 0) {
|
||||
|
||||
uwsgi_log("CHUNK SIZE: %d\n", NUM2INT( RARRAY(args)->ptr[0] ) );
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE rb_uwsgi_io_rewind(VALUE obj, VALUE args) {
|
||||
|
||||
struct wsgi_request *wsgi_req;
|
||||
Data_Get_Struct(obj, struct wsgi_request, wsgi_req);
|
||||
|
||||
uwsgi_log("CALLING rewind !!!\n");
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
|
||||
|
||||
struct http_status_codes *http_sc;
|
||||
|
||||
// filling http status codes
|
||||
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
|
||||
http_sc->message_size = strlen(http_sc->message);
|
||||
}
|
||||
|
||||
ruby_init();
|
||||
ruby_init_loadpath();
|
||||
ruby_script("uwsgi");
|
||||
|
||||
if (chdir("mytipo")) {
|
||||
uwsgi_error("chdir()");
|
||||
}
|
||||
|
||||
rb_require("config/environment");
|
||||
|
||||
uwsgi_log("ruby ready\n");
|
||||
|
||||
VALUE ac = rb_const_get(rb_cObject, rb_intern("ActionController")) ;
|
||||
|
||||
dispatcher = rb_funcall( rb_const_get(ac, rb_intern("Dispatcher")), rb_intern("new"), 0);
|
||||
|
||||
if (dispatcher == Qnil) {
|
||||
uwsgi_log("OOOPS\n");
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("OK %p\n", dispatcher);
|
||||
}
|
||||
|
||||
rb_gc_register_address(&dispatcher);
|
||||
|
||||
call = rb_intern("call");
|
||||
rb_gc_register_address(&call);
|
||||
|
||||
|
||||
rb_uwsgi_io_class = rb_define_class("Uwsgi_IO", rb_cObject);
|
||||
|
||||
rb_gc_register_address(&rb_uwsgi_io_class);
|
||||
|
||||
rb_define_singleton_method(rb_uwsgi_io_class, "new", rb_uwsgi_io_new, 1);
|
||||
rb_define_method(rb_uwsgi_io_class, "initialize", rb_uwsgi_io_init, -1);
|
||||
rb_define_method(rb_uwsgi_io_class, "gets", rb_uwsgi_io_gets, 0);
|
||||
rb_define_method(rb_uwsgi_io_class, "each", rb_uwsgi_io_each, 0);
|
||||
rb_define_method(rb_uwsgi_io_class, "read", rb_uwsgi_io_read, -2);
|
||||
rb_define_method(rb_uwsgi_io_class, "rewind", rb_uwsgi_io_rewind, 0);
|
||||
|
||||
rb_gc_disable();
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
VALUE call_dispatch(VALUE env) {
|
||||
|
||||
return rb_funcall(dispatcher, call, 1, env);
|
||||
|
||||
}
|
||||
|
||||
VALUE send_body(VALUE obj, VALUE fd) {
|
||||
|
||||
size_t len;
|
||||
|
||||
uwsgi_log("sending body\n");
|
||||
if (TYPE(obj) == T_STRING) {
|
||||
uwsgi_log("chunk is a string\n");
|
||||
len = write( NUM2INT(fd), RSTRING(obj)->ptr, RSTRING(obj)->len);
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE send_header(VALUE obj, VALUE fd) {
|
||||
|
||||
size_t len;
|
||||
|
||||
uwsgi_log("SENDING HEADER: %d\n", TYPE(obj));
|
||||
|
||||
if (TYPE(obj) == T_ARRAY) {
|
||||
|
||||
if (RARRAY(obj)->len == 2) {
|
||||
VALUE hkey = rb_obj_as_string( RARRAY(obj)->ptr[0]);
|
||||
VALUE hval = rb_obj_as_string( RARRAY(obj)->ptr[1]);
|
||||
|
||||
len = write( NUM2INT(fd), RSTRING(hkey)->ptr, RSTRING(hkey)->len);
|
||||
len = write( NUM2INT(fd), ": ", 2);
|
||||
|
||||
len = write( NUM2INT(fd), RSTRING(hval)->ptr, RSTRING(hval)->len);
|
||||
len = write( NUM2INT(fd), "\r\n", 2);
|
||||
}
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static void uwsgi_ruby_exception(void) {
|
||||
|
||||
VALUE lasterr = rb_gv_get("$!");
|
||||
VALUE message = rb_obj_as_string(lasterr);
|
||||
|
||||
uwsgi_log("%s\n", RSTRING(message)->ptr);
|
||||
if(!NIL_P(ruby_errinfo)) {
|
||||
VALUE ary = rb_funcall(ruby_errinfo, rb_intern("backtrace"), 0);
|
||||
int i;
|
||||
for (i=0; i<RARRAY(ary)->len; i++) {
|
||||
uwsgi_log("%s\n", RSTRING(RARRAY(ary)->ptr[i])->ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
|
||||
int error;
|
||||
int i;
|
||||
|
||||
struct http_status_codes *http_sc;
|
||||
|
||||
/* Standard RACK request */
|
||||
if (!wsgi_req->uh.pktsize) {
|
||||
uwsgi_log("Invalid RACK request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi_parse_vars(uwsgi, wsgi_req)) {
|
||||
uwsgi_log("Invalid RACK request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
VALUE env = rb_hash_new();
|
||||
|
||||
// fill ruby hash
|
||||
for(i=0;i<wsgi_req->var_cnt;i++) {
|
||||
|
||||
rb_hash_aset(env, rb_str_new(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len),
|
||||
rb_str_new(wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len));
|
||||
i++;
|
||||
}
|
||||
|
||||
VALUE rbv = rb_ary_new();
|
||||
rb_ary_store(rbv, 0, INT2NUM(1));
|
||||
rb_ary_store(rbv, 1, INT2NUM(1));
|
||||
rb_hash_aset(env, rb_str_new2("rack.version"), rbv);
|
||||
|
||||
rb_hash_aset(env, rb_str_new2("rack.url_scheme"), rb_str_new2("http"));
|
||||
|
||||
rb_hash_aset(env, rb_str_new2("rack.multithread"), Qfalse);
|
||||
rb_hash_aset(env, rb_str_new2("rack.multiprocess"), Qtrue);
|
||||
rb_hash_aset(env, rb_str_new2("rack.run_once"), Qfalse);
|
||||
|
||||
VALUE dws_wr = Data_Wrap_Struct(rb_uwsgi_io_class, 0, 0, wsgi_req);
|
||||
rb_hash_aset(env, rb_str_new2("rack.input"), rb_funcall(rb_uwsgi_io_class, rb_intern("new"), 1, dws_wr ));
|
||||
|
||||
|
||||
VALUE ret = rb_protect( call_dispatch, env, &error);
|
||||
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (TYPE(ret) == T_ARRAY) {
|
||||
if (RARRAY(ret)->len != 3) {
|
||||
uwsgi_log("Invalid RACK response size: %d\n", RARRAY(ret)->len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// manage Status
|
||||
|
||||
|
||||
VALUE status = rb_obj_as_string(RARRAY(ret)->ptr[0]);
|
||||
uwsgi_log("Status: %.*s\n", RSTRING(status)->len, RSTRING(status)->ptr);
|
||||
// get the status code
|
||||
|
||||
wsgi_req->hvec[0].iov_base = "HTTP/1.1 ";
|
||||
wsgi_req->hvec[0].iov_len = 9 ;
|
||||
|
||||
wsgi_req->hvec[1].iov_base = RSTRING(status)->ptr;
|
||||
wsgi_req->hvec[1].iov_len = 3 ;
|
||||
|
||||
wsgi_req->hvec[2].iov_base = " ";
|
||||
wsgi_req->hvec[2].iov_len = 1 ;
|
||||
|
||||
wsgi_req->hvec[3].iov_len = 0 ;
|
||||
|
||||
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
|
||||
if (!strncmp(http_sc->key, RSTRING(status)->ptr, 3)) {
|
||||
wsgi_req->hvec[3].iov_base = http_sc->message ;
|
||||
wsgi_req->hvec[3].iov_len = http_sc->message_size ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wsgi_req->hvec[4].iov_base = "\r\n";
|
||||
wsgi_req->hvec[4].iov_len = 2 ;
|
||||
|
||||
if ( (wsgi_req->response_size = writev(wsgi_req->poll.fd, wsgi_req->hvec, 5)) < 0) {
|
||||
uwsgi_error("writev()");
|
||||
}
|
||||
|
||||
VALUE headers = RARRAY(ret)->ptr[1] ;
|
||||
if (rb_respond_to( headers, rb_intern("each") )) {
|
||||
|
||||
uwsgi_log("headers respond_to each\n");
|
||||
rb_iterate( rb_each, headers, send_header, INT2NUM(wsgi_req->poll.fd));
|
||||
|
||||
}
|
||||
|
||||
uwsgi_log("wsgi_req ptr: %p\n", wsgi_req);
|
||||
|
||||
write(wsgi_req->poll.fd, "\r\n", 2);
|
||||
|
||||
uwsgi_log("PTR: %p\n", RARRAY(ret)->ptr[2]);
|
||||
|
||||
VALUE body = RARRAY(ret)->ptr[2] ;
|
||||
|
||||
//rb_gc_register_address(&body);
|
||||
|
||||
if (rb_respond_to( body, rb_intern("to_path") )) {
|
||||
uwsgi_log("BODY respond_to 'to_path'\n");
|
||||
}
|
||||
else if (rb_respond_to( body, rb_intern("each") )) {
|
||||
rb_iterate( rb_each, body, send_body, INT2NUM(wsgi_req->poll.fd));
|
||||
}
|
||||
|
||||
uwsgi_log("Fatto %p\n", body);
|
||||
|
||||
if (rb_respond_to( body, rb_intern("close") )) {
|
||||
uwsgi_log("BODY respond_to 'close'\n");
|
||||
}
|
||||
|
||||
uwsgi_log("Fatto 2 %p\n", wsgi_req);
|
||||
}
|
||||
|
||||
rb_gc_disable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (uwsgi->shared->options[UWSGI_OPTION_LOGGING])
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import os,sys
|
||||
|
||||
NAME='rack'
|
||||
CFLAGS = '-I' + os.popen("ruby -e \"require 'mkmf';print Config::CONFIG['archdir']\"").read().rstrip()
|
||||
LDFLAGS = '-l' + os.popen("ruby -e \"require 'mkmf';print CONFIG['RUBY_SO_NAME']\"").read().rstrip()
|
||||
+61
-17
@@ -2,6 +2,20 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static size_t get_content_length(char *buf, uint16_t size) {
|
||||
int i;
|
||||
size_t val = 0 ;
|
||||
for(i=0;i<size;i++) {
|
||||
if (buf[i] >= '0' && buf[i] <= '9') {
|
||||
val = (val*10) + (buf[i] - '0') ;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
ssize_t send_udp_message(uint8_t modifier1, char *host, char *message, uint16_t message_size) {
|
||||
|
||||
@@ -252,6 +266,10 @@ int uwsgi_parse_response(struct pollfd *upoll, int timeout, struct uwsgi_header
|
||||
uh->pktsize = uwsgi_swap16(uh->pktsize);
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("uwsgi payload size: %d (0x%X) modifier1: %d modifier2: %d\n", uh->pktsize, uh->pktsize, uh->modifier1, uh->modifier2);
|
||||
#endif
|
||||
|
||||
/* check for max buffer size */
|
||||
if (uh->pktsize > uwsgi.buffer_size) {
|
||||
uwsgi_log( "invalid request block size: %d...skip\n", uh->pktsize);
|
||||
@@ -322,66 +340,92 @@ int uwsgi_parse_vars(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req)
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
|
||||
ptrbuf += strsize;
|
||||
if (ptrbuf + 2 < bufferend) {
|
||||
// value can be null (even at the end) so use <=
|
||||
if (ptrbuf + 2 <= bufferend) {
|
||||
memcpy(&strsize, ptrbuf, 2);
|
||||
#ifdef __BIG_ENDIAN__
|
||||
strsize = uwsgi_swap16(strsize);
|
||||
#endif
|
||||
ptrbuf += 2;
|
||||
if (ptrbuf + strsize <= bufferend) {
|
||||
if (!strncmp("SCRIPT_NAME", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
//uwsgi_log("uwsgi %.*s = %.*s\n", wsgi_req->hvec[wsgi_req->var_cnt].iov_len, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, strsize, ptrbuf);
|
||||
if (!uwsgi_strncmp("SCRIPT_NAME", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->script_name = ptrbuf;
|
||||
wsgi_req->script_name_len = strsize;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("SCRIPT_NAME=%.*s\n", wsgi_req->script_name_len, wsgi_req->script_name);
|
||||
#endif
|
||||
}
|
||||
else if (!strncmp("SERVER_PROTOCOL", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
else if (!uwsgi_strncmp("PATH_INFO", 9, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->path_info = ptrbuf;
|
||||
wsgi_req->path_info_len = strsize;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("PATH_INFO=%.*s\n", wsgi_req->path_info_len, wsgi_req->path_info);
|
||||
#endif
|
||||
}
|
||||
else if (!uwsgi_strncmp("SERVER_PROTOCOL", 15, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->protocol = ptrbuf;
|
||||
wsgi_req->protocol_len = strsize;
|
||||
}
|
||||
else if (!strncmp("REQUEST_URI", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
else if (!uwsgi_strncmp("REQUEST_URI", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->uri = ptrbuf;
|
||||
wsgi_req->uri_len = strsize;
|
||||
}
|
||||
else if (!strncmp("QUERY_STRING", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
else if (!uwsgi_strncmp("QUERY_STRING", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->query_string = ptrbuf;
|
||||
wsgi_req->query_string_len = strsize;
|
||||
}
|
||||
else if (!strncmp("REQUEST_METHOD", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
else if (!uwsgi_strncmp("REQUEST_METHOD", 14, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->method = ptrbuf;
|
||||
wsgi_req->method_len = strsize;
|
||||
}
|
||||
else if (!strncmp("REMOTE_ADDR", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
else if (!uwsgi_strncmp("REMOTE_ADDR", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->remote_addr = ptrbuf;
|
||||
wsgi_req->remote_addr_len = strsize;
|
||||
}
|
||||
else if (!strncmp("REMOTE_USER", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
else if (!uwsgi_strncmp("REMOTE_USER", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->remote_user = ptrbuf;
|
||||
wsgi_req->remote_user_len = strsize;
|
||||
}
|
||||
else if (!strncmp("UWSGI_SCHEME", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
else if (!uwsgi_strncmp("UWSGI_SCHEME", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->scheme = ptrbuf;
|
||||
wsgi_req->scheme_len = strsize;
|
||||
}
|
||||
else if (!strncmp("UWSGI_SCRIPT",wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len )) {
|
||||
else if (!uwsgi_strncmp("UWSGI_SCRIPT", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len )) {
|
||||
wsgi_req->wsgi_script = ptrbuf;
|
||||
wsgi_req->wsgi_script_len = strsize;
|
||||
}
|
||||
else if (!strncmp("UWSGI_MODULE", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
else if (!uwsgi_strncmp("UWSGI_MODULE", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->wsgi_module = ptrbuf;
|
||||
wsgi_req->wsgi_module_len = strsize;
|
||||
}
|
||||
else if (!strncmp("UWSGI_CALLABLE", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
else if (!uwsgi_strncmp("UWSGI_CALLABLE", 14, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->wsgi_callable = ptrbuf;
|
||||
wsgi_req->wsgi_callable_len = strsize;
|
||||
}
|
||||
else if (!strncmp("HTTPS", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
else if (!uwsgi_strncmp("UWSGI_PYHOME", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->pyhome = ptrbuf;
|
||||
wsgi_req->pyhome_len = strsize;
|
||||
}
|
||||
else if (!uwsgi_strncmp("UWSGI_CHDIR", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->chdir = ptrbuf;
|
||||
wsgi_req->chdir_len = strsize;
|
||||
}
|
||||
else if (!uwsgi_strncmp("SERVER_NAME", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->host = ptrbuf;
|
||||
wsgi_req->host_len = strsize;
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("SERVER_NAME=%.*s\n", wsgi_req->host_len, wsgi_req->host);
|
||||
#endif
|
||||
}
|
||||
else if (!uwsgi_strncmp("HTTPS", 5, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->https = ptrbuf;
|
||||
wsgi_req->https_len = strsize;
|
||||
}
|
||||
#ifdef UNBIT
|
||||
else if (!strncmp("UNBIT_FLAGS", wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->unbit_flags = *(unsigned long long *) ptrbuf;
|
||||
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
|
||||
wsgi_req->post_cl = get_content_length(ptrbuf, strsize);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (wsgi_req->var_cnt < uwsgi->vec_size - (4 + 1)) {
|
||||
wsgi_req->var_cnt++;
|
||||
}
|
||||
|
||||
@@ -189,12 +189,12 @@ void uwsgi_proxy(int proxyfd) {
|
||||
for (i = 0; i < nevents; i++) {
|
||||
|
||||
|
||||
if (eevents[i].ASYNC_FD == proxyfd) {
|
||||
if ( (int)eevents[i].ASYNC_FD == proxyfd) {
|
||||
|
||||
if (eevents[i].ASYNC_IS_IN) {
|
||||
// new connection, accept it
|
||||
ev.ASYNC_FD = accept(proxyfd, (struct sockaddr *) &upc_addr, &upc_len);
|
||||
if (ev.ASYNC_FD < 0) {
|
||||
if ( (int) ev.ASYNC_FD < 0) {
|
||||
uwsgi_error("accept()");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
import uwsgi
|
||||
import sys
|
||||
|
||||
uwsgi.load_plugin(0, "plugins/psgi/psgi_plugin.so", "test.psgi")
|
||||
if uwsgi.load_plugin(0, "plugins/psgi/psgi_plugin.so", "mojoapp.pl"):
|
||||
print "PSGI plugin loaded"
|
||||
else:
|
||||
print "unable to load PSGI plugin"
|
||||
sys.exit(1)
|
||||
|
||||
@@ -30,7 +30,7 @@ int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
if (wsgi_req->sendfile_fd != -1) {
|
||||
if (wsgi_req->sendfile_obj == wsgi_req->async_result && wsgi_req->sendfile_fd != -1) {
|
||||
sf_len = uwsgi_sendfile(uwsgi, wsgi_req);
|
||||
if (sf_len < 1) goto clear;
|
||||
wsgi_req->response_size += sf_len ;
|
||||
@@ -45,6 +45,32 @@ int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_WSGI2
|
||||
// is it a tuple (WSGI2.0) ?
|
||||
// move it to another hook !!!
|
||||
if (PyTuple_Check((PyObject *)wsgi_req->async_result)) {
|
||||
if (PyTuple_Size((PyObject *)wsgi_req->async_result) != 3) {
|
||||
uwsgi_log("invalid WSGI2.0 response size: %d.\n", PyTuple_Size((PyObject *)wsgi_req->async_result));
|
||||
goto clear;
|
||||
}
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("wsgi_req->async_result = %d\n", ((PyObject *)wsgi_req->async_result)->ob_refcnt);
|
||||
#endif
|
||||
if (py_uwsgi_spit(NULL, (PyObject *)wsgi_req->async_result) == Py_None) {
|
||||
goto clear;
|
||||
}
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("wsgi_req->async_result = %d\n", ((PyObject *)wsgi_req->async_result)->ob_refcnt);
|
||||
#endif
|
||||
wsgi_req->async_orig_result = wsgi_req->async_result ;
|
||||
wsgi_req->async_result = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 2);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("wsgi_req->async_orig_result = %d\n", ((PyObject *)wsgi_req->async_orig_result)->ob_refcnt);
|
||||
uwsgi_debug("wsgi_req->async_result = %d\n", ((PyObject *)wsgi_req->async_result)->ob_refcnt);
|
||||
#endif
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ok its a yield
|
||||
if (!wsgi_req->async_placeholder) {
|
||||
@@ -61,7 +87,6 @@ int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi
|
||||
|
||||
|
||||
|
||||
|
||||
pychunk = PyIter_Next(wsgi_req->async_placeholder) ;
|
||||
|
||||
if (!pychunk) {
|
||||
@@ -81,7 +106,7 @@ int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
if (PyBytes_Check(pychunk)) {
|
||||
else if (PyBytes_Check(pychunk)) {
|
||||
if ((wsize = write(wsgi_req->poll.fd, PyBytes_AsString(pychunk), PyBytes_Size(pychunk))) < 0) {
|
||||
uwsgi_error("write()");
|
||||
Py_DECREF(pychunk);
|
||||
@@ -90,6 +115,14 @@ int manage_python_response(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi
|
||||
wsgi_req->response_size += wsize;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
else if (wsgi_req->sendfile_obj == pychunk && wsgi_req->sendfile_fd != -1) {
|
||||
sf_len = uwsgi_sendfile(uwsgi, wsgi_req);
|
||||
if (sf_len < 1) goto clear;
|
||||
wsgi_req->response_size += sf_len ;
|
||||
}
|
||||
#endif
|
||||
|
||||
Py_DECREF(pychunk);
|
||||
return UWSGI_AGAIN ;
|
||||
@@ -103,25 +136,57 @@ clear:
|
||||
}
|
||||
if (wsgi_req->async_post && !wsgi_req->fd_closed) {
|
||||
fclose(wsgi_req->async_post);
|
||||
wsgi_req->fd_closed = 1 ;
|
||||
if (!uwsgi->post_buffering || wsgi_req->post_cl <= (size_t) uwsgi->post_buffering) {
|
||||
wsgi_req->fd_closed = 1 ;
|
||||
|
||||
}
|
||||
}
|
||||
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
|
||||
#ifdef UWSGI_WSGI2
|
||||
Py_XDECREF((PyObject *)wsgi_req->async_orig_result);
|
||||
#endif
|
||||
clear2:
|
||||
Py_DECREF((PyObject *)wsgi_req->async_result);
|
||||
PyErr_Clear();
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
if (wsgi_req->async_placeholder) {
|
||||
uwsgi_debug("wsgi_req->async_placeholder: %d\n", ((PyObject *)wsgi_req->async_placeholder)->ob_refcnt);
|
||||
}
|
||||
#ifdef UWSGI_WSGI2
|
||||
if (wsgi_req->async_orig_result) {
|
||||
uwsgi_debug("wsgi_req->async_orig_result: %d\n", ((PyObject *)wsgi_req->async_orig_result)->ob_refcnt);
|
||||
}
|
||||
#endif
|
||||
if (wsgi_req->async_result) {
|
||||
uwsgi_debug("wsgi_req->async_result: %d\n", ((PyObject *)wsgi_req->async_result)->ob_refcnt);
|
||||
}
|
||||
if (wsgi_req->async_app) {
|
||||
uwsgi_debug("wsgi_req->async_app: %d\n", ((PyObject *)wsgi_req->async_app)->ob_refcnt);
|
||||
}
|
||||
#endif
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
PyObject *python_call(PyObject *callable, PyObject *args) {
|
||||
PyObject *python_call(PyObject *callable, PyObject *args, int catch) {
|
||||
|
||||
PyObject *pyret;
|
||||
|
||||
pyret = PyEval_CallObject(callable, args);
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
if (!catch) {
|
||||
PyErr_Print();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
if (pyret) {
|
||||
uwsgi_debug("called %p %p %d\n", callable, args, pyret->ob_refcnt);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return pyret;
|
||||
}
|
||||
|
||||
@@ -129,7 +194,7 @@ PyObject *python_call(PyObject *callable, PyObject *args) {
|
||||
|
||||
int uwsgi_python_call(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, PyObject *callable, PyObject *args) {
|
||||
|
||||
wsgi_req->async_result = python_call(callable, args);
|
||||
wsgi_req->async_result = python_call(callable, args, 0);
|
||||
|
||||
if (wsgi_req->async_result) {
|
||||
while ( manage_python_response(uwsgi, wsgi_req) != UWSGI_OK) {
|
||||
@@ -143,3 +208,50 @@ int uwsgi_python_call(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req,
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
void init_pyargv(struct uwsgi_server *uwsgi) {
|
||||
|
||||
char *ap;
|
||||
|
||||
#ifdef PYTHREE
|
||||
wchar_t pname[6];
|
||||
mbstowcs(pname, "uwsgi", 6);
|
||||
uwsgi->py_argv[0] = pname;
|
||||
#else
|
||||
uwsgi->py_argv[0] = "uwsgi";
|
||||
#endif
|
||||
|
||||
if (uwsgi->pyargv != NULL && !uwsgi->pyargc) {
|
||||
uwsgi->pyargc++;
|
||||
#ifdef PYTHREE
|
||||
wchar_t *wcargv = malloc( sizeof( wchar_t ) * (strlen(uwsgi->pyargv)+1));
|
||||
if (!wcargv) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
memset(wcargv, 0, sizeof( wchar_t ) * (strlen(uwsgi->pyargv)+1));
|
||||
#endif
|
||||
|
||||
#ifdef __sun__
|
||||
// FIX THIS !!!
|
||||
ap = strtok(uwsgi->pyargv, " ");
|
||||
while ((ap = strtok(NULL, " ")) != NULL) {
|
||||
#else
|
||||
while ((ap = strsep(&uwsgi->pyargv, " \t")) != NULL) {
|
||||
#endif
|
||||
if (*ap != '\0') {
|
||||
#ifdef PYTHREE
|
||||
mbstowcs( wcargv + strlen(ap), ap, strlen(ap));
|
||||
uwsgi->py_argv[uwsgi->pyargc] = wcargv + strlen(ap);
|
||||
#else
|
||||
uwsgi->py_argv[uwsgi->pyargc] = ap;
|
||||
#endif
|
||||
uwsgi->pyargc++;
|
||||
}
|
||||
if (uwsgi->pyargc + 1 > MAX_PYARGV)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PySys_SetArgv(uwsgi->pyargc, uwsgi->py_argv);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
#ifdef UWSGI_ROUTING
|
||||
#include "uwsgi.h"
|
||||
|
||||
void routing_setup(struct uwsgi_server *uwsgi) {
|
||||
|
||||
int i;
|
||||
struct uwsgi_route *ur;
|
||||
int max_ovec = 0 ;
|
||||
|
||||
for(i=0;i<uwsgi->nroutes;i++) {
|
||||
uwsgi_log("%d = %p\n", i, uwsgi->routes[i].pattern);
|
||||
ur = &uwsgi->routes[i];
|
||||
if (ur->args > max_ovec) {
|
||||
max_ovec = ur->args;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi->async_ovector = malloc( sizeof(int *) * uwsgi->async);
|
||||
if (!uwsgi->async_ovector) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_log("max_ovec = %d\n", max_ovec);
|
||||
for(i=0;i<uwsgi->async;i++) {
|
||||
uwsgi->async_ovector[i] = malloc(sizeof(int) * ((max_ovec+1)*3));
|
||||
if (!uwsgi->async_ovector[i]) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void check_route(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
|
||||
int ret,i ;
|
||||
struct uwsgi_route *ur;
|
||||
|
||||
for(i=0;i<uwsgi->nroutes;i++) {
|
||||
|
||||
//uwsgi_log("checking route %d\n", i);
|
||||
ur = &uwsgi->routes[i];
|
||||
ret = pcre_exec(ur->pattern, ur->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len, 0, 0, wsgi_req->ovector, (ur->args+1)*3 );
|
||||
|
||||
if (ret >= 0) {
|
||||
uwsgi_log("found route %d for PATH_INFO=%.*s\n", i, wsgi_req->path_info_len, wsgi_req->path_info);
|
||||
if (ur->action) {
|
||||
ur->action(uwsgi, wsgi_req, ur);
|
||||
}
|
||||
else {
|
||||
uwsgi_route_action_wsgi(uwsgi, wsgi_req, ur);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO check for errors if < 0 && != NO_MATCH */
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
void uwsgi_route_action_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
|
||||
int i;
|
||||
PyObject *route_py_callbase, *route_py_dict = NULL;
|
||||
|
||||
uwsgi_log("managing WSGI route...\n");
|
||||
if (ur->callable == NULL) {
|
||||
if (ur->callbase) {
|
||||
route_py_callbase = PyImport_ImportModule(ur->callbase);
|
||||
if (route_py_callbase == NULL) {
|
||||
PyErr_Print();
|
||||
}
|
||||
else {
|
||||
uwsgi_log("callbase dict ok for %s\n", ur->call);
|
||||
route_py_dict = PyModule_GetDict(route_py_callbase);
|
||||
}
|
||||
}
|
||||
|
||||
ur->callable = PyDict_GetItemString(route_py_dict, ur->call);
|
||||
if (ur->callable == NULL) {
|
||||
uwsgi_log("route_py_dict: %p call: %s\n", route_py_dict, ur->call);
|
||||
PyErr_Print();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO put regex captured groups in WSGI env
|
||||
|
||||
|
||||
PyObject *ra = PyTuple_New(ur->args);
|
||||
for (i=1;i<=ur->args;i++) {
|
||||
PyTuple_SetItem(ra, i-1, PyString_FromStringAndSize(
|
||||
wsgi_req->path_info + wsgi_req->ovector[i*2],
|
||||
wsgi_req->ovector[(i*2)+1] - wsgi_req->ovector[i*2]
|
||||
));
|
||||
}
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.uwsgi.route_args", ra);
|
||||
|
||||
if (ur->callable) {
|
||||
wsgi_req->async_app = ur->callable;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_route_action_uwsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
|
||||
PyObject *route_py_callbase, *route_py_dict = NULL ;
|
||||
int i;
|
||||
|
||||
uwsgi_log("managing uwsgi route...\n");
|
||||
if (ur->callable == NULL) {
|
||||
if (ur->callbase) {
|
||||
route_py_callbase = PyImport_ImportModule(ur->callbase);
|
||||
if (route_py_callbase == NULL) {
|
||||
PyErr_Print();
|
||||
}
|
||||
else {
|
||||
uwsgi_log("callbase dict ok for %s\n", ur->call);
|
||||
route_py_dict = PyModule_GetDict(route_py_callbase);
|
||||
}
|
||||
}
|
||||
|
||||
ur->callable = PyDict_GetItemString(route_py_dict, ur->call);
|
||||
if (ur->callable == NULL) {
|
||||
uwsgi_log("route_py_dict: %p call: %s\n", route_py_dict, ur->call);
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
ur->callable_args = PyTuple_New(ur->args+1);
|
||||
}
|
||||
|
||||
|
||||
if (ur->callable) {
|
||||
uwsgi_log("route callable dict ok: %d\n", ur->args);
|
||||
wsgi_req->async_app = ur->callable;
|
||||
wsgi_req->async_args = ur->callable_args;
|
||||
|
||||
for (i=1;i<=ur->args;i++) {
|
||||
uwsgi_log("%d\n", i);
|
||||
uwsgi_log("%d / %d\n", wsgi_req->ovector[i*2], wsgi_req->ovector[(i*2)+1]);
|
||||
uwsgi_log("%d = %.*s\n", i,wsgi_req->ovector[(i*2)+1] - wsgi_req->ovector[i*2],
|
||||
wsgi_req->path_info + wsgi_req->ovector[i*2]);
|
||||
PyTuple_SetItem(wsgi_req->async_args, i, PyString_FromStringAndSize(
|
||||
wsgi_req->path_info + wsgi_req->ovector[i*2],
|
||||
wsgi_req->ovector[(i*2)+1] - wsgi_req->ovector[i*2]
|
||||
));
|
||||
}
|
||||
|
||||
uwsgi_log("route callable built\n");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+49
-32
@@ -8,7 +8,7 @@ PyObject *py_uwsgi_sendfile(PyObject * self, PyObject * args) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
|
||||
|
||||
if (!PyArg_ParseTuple(args, "Oi:uwsgi_sendfile", &wsgi_req->async_sendfile, &wsgi_req->sendfile_fd_chunk)) {
|
||||
if (!PyArg_ParseTuple(args, "O|i:uwsgi_sendfile", &wsgi_req->async_sendfile, &wsgi_req->sendfile_fd_chunk)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,12 @@ PyObject *py_uwsgi_sendfile(PyObject * self, PyObject * args) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// PEP 333 hack
|
||||
wsgi_req->sendfile_obj = wsgi_req->async_sendfile;
|
||||
//wsgi_req->sendfile_obj = (void *) PyTuple_New(0);
|
||||
|
||||
return PyTuple_New(0);
|
||||
Py_INCREF((PyObject *) wsgi_req->sendfile_obj);
|
||||
return (PyObject *) wsgi_req->sendfile_obj;
|
||||
}
|
||||
|
||||
ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
@@ -30,7 +34,6 @@ ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
|
||||
int fd = wsgi_req->sendfile_fd ;
|
||||
int sockfd = wsgi_req->poll.fd ;
|
||||
struct stat stat_buf;
|
||||
int sf_ret;
|
||||
|
||||
if (!wsgi_req->sendfile_fd_size) {
|
||||
|
||||
@@ -45,19 +48,32 @@ ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
|
||||
|
||||
if (wsgi_req->sendfile_fd_size) {
|
||||
|
||||
if (!wsgi_req->sendfile_fd_chunk) wsgi_req->sendfile_fd_chunk = 4096 ;
|
||||
if (!wsgi_req->sendfile_fd_chunk) wsgi_req->sendfile_fd_chunk = 4096 ;
|
||||
|
||||
return uwsgi_do_sendfile(sockfd, wsgi_req->sendfile_fd, wsgi_req->sendfile_fd_size, wsgi_req->sendfile_fd_chunk, &wsgi_req->sendfile_fd_pos, uwsgi->async);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk, off_t *pos, int async) {
|
||||
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
|
||||
off_t sf_len = wsgi_req->sendfile_fd_size ;
|
||||
int sf_ret;
|
||||
|
||||
if (uwsgi->async > 1) {
|
||||
sf_len = wsgi_req->sendfile_fd_chunk;
|
||||
sf_ret = sendfile(fd, sockfd, wsgi_req->sendfile_fd_pos, 0, NULL, &sf_len, 0);
|
||||
wsgi_req->sendfile_fd_pos += sf_len ;
|
||||
off_t sf_len = filesize ;
|
||||
|
||||
if (async > 1) {
|
||||
sf_len = chunk;
|
||||
sf_ret = sendfile(filefd, sockfd, *pos, 0, NULL, &sf_len, 0);
|
||||
*pos += sf_len ;
|
||||
}
|
||||
else {
|
||||
sf_ret = sendfile(fd, sockfd, 0, 0, NULL, &sf_len, 0);
|
||||
sf_ret = sendfile(filefd, sockfd, 0, 0, NULL, &sf_len, 0);
|
||||
}
|
||||
|
||||
if (sf_ret) {
|
||||
@@ -66,16 +82,17 @@ ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
|
||||
}
|
||||
|
||||
return sf_len;
|
||||
#elif __APPLE__
|
||||
off_t sf_len = wsgi_req->sendfile_fd_size ;
|
||||
#elif defined(__APPLE__)
|
||||
int sf_ret;
|
||||
off_t sf_len = filesize ;
|
||||
|
||||
if (uwsgi->async > 1) {
|
||||
sf_len = wsgi_req->sendfile_fd_chunk;
|
||||
sf_ret = sendfile(fd, sockfd, wsgi_req->sendfile_fd_pos, &sf_len, NULL, 0);
|
||||
wsgi_req->sendfile_fd_pos += sf_len ;
|
||||
if (async > 1) {
|
||||
sf_len = chunk;
|
||||
sf_ret = sendfile(filefd, sockfd, *pos, &sf_len, NULL, 0);
|
||||
*pos += sf_len ;
|
||||
}
|
||||
else {
|
||||
sf_ret = sendfile(fd, sockfd, 0, &sf_len, NULL, 0);
|
||||
sf_ret = sendfile(filefd, sockfd, 0, &sf_len, NULL, 0);
|
||||
}
|
||||
|
||||
if (sf_ret) {
|
||||
@@ -86,11 +103,13 @@ ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
|
||||
return sf_len;
|
||||
|
||||
#elif defined(__linux__) || defined(__sun__)
|
||||
if (uwsgi->async > 1) {
|
||||
sf_ret = sendfile(sockfd, fd, &wsgi_req->sendfile_fd_pos, wsgi_req->sendfile_fd_chunk);
|
||||
int sf_ret;
|
||||
|
||||
if (async > 1) {
|
||||
sf_ret = sendfile(sockfd, filefd, pos, chunk);
|
||||
}
|
||||
else {
|
||||
sf_ret = sendfile(sockfd, fd, &wsgi_req->sendfile_fd_pos, wsgi_req->sendfile_fd_size);
|
||||
sf_ret = sendfile(sockfd, filefd, pos, filesize);
|
||||
}
|
||||
|
||||
if (sf_ret < 0) {
|
||||
@@ -100,7 +119,7 @@ ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
|
||||
|
||||
return sf_ret ;
|
||||
#else
|
||||
static nosf_buf_size = 0 ;
|
||||
static size_t nosf_buf_size = 0 ;
|
||||
static char *nosf_buf ;
|
||||
|
||||
ssize_t jlen = 0;
|
||||
@@ -108,16 +127,16 @@ ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
|
||||
ssize_t i = 0;
|
||||
|
||||
if (!nosf_buf) {
|
||||
nosf_buf = malloc(wsgi_req->sendfile_fd_chunk);
|
||||
nosf_buf = malloc(chunk);
|
||||
}
|
||||
else if (wsgi_req->sendfile_fd_chunk != nosf_buf_size) {
|
||||
nosf_buf = realloc(nosf_buf, wsgi_req->sendfile_fd_chunk);
|
||||
else if (chunk != nosf_buf_size) {
|
||||
nosf_buf = realloc(nosf_buf, chunk);
|
||||
}
|
||||
|
||||
nosf_buf_size = wsgi_req->sendfile_fd_chunk ;
|
||||
nosf_buf_size = chunk ;
|
||||
|
||||
if (uwsgi->async > 1) {
|
||||
jlen = read(fd, nosf_buf, wsgi_req->sendfile_fd_chunk);
|
||||
if (async > 1) {
|
||||
jlen = read(filefd, nosf_buf, chunk);
|
||||
if (jlen <= 0) {
|
||||
uwsgi_error("read()");
|
||||
return 0;
|
||||
@@ -130,8 +149,8 @@ ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
|
||||
return jlen ;
|
||||
}
|
||||
|
||||
while (i < wsgi_req->sendfile_fd_size) {
|
||||
jlen = read(fd, nosf_buf, wsgi_req->sendfile_fd_chunk);
|
||||
while (i < (int) filesize) {
|
||||
jlen = read(filefd, nosf_buf, chunk);
|
||||
if (jlen <= 0) {
|
||||
uwsgi_error("read()");
|
||||
break;
|
||||
@@ -148,13 +167,11 @@ ssize_t uwsgi_sendfile(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
|
||||
return rlen;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,7 +34,7 @@ class uWSGIDistribution(Distribution):
|
||||
|
||||
|
||||
setup(name='uWSGI',
|
||||
version='0.9.5',
|
||||
version='0.9.6.1',
|
||||
description='The uWSGI server',
|
||||
author='Unbit',
|
||||
author_email='info@unbit.it',
|
||||
|
||||
+30
-1
@@ -1,8 +1,37 @@
|
||||
import uwsgi
|
||||
|
||||
print "!!! uWSGI version:", uwsgi.version
|
||||
|
||||
def ciao():
|
||||
print "modifica su /tmp"
|
||||
|
||||
def ciao2():
|
||||
print "nuovo uwsgi_server"
|
||||
|
||||
counter = 0
|
||||
|
||||
#if uwsgi.load_plugin(0, 'plugins/example/example_plugin.so', 'ciao'):
|
||||
# print "example plugin loaded"
|
||||
#else:
|
||||
# print "unable to load example plugin"
|
||||
|
||||
#uwsgi.event_add(uwsgi.EVENT_FILE, "/tmp", ciao)
|
||||
#uwsgi.event_add(uwsgi.EVENT_DNSSD, "_uwsgi._tcp", ciao2)
|
||||
#uwsgi.event_add(uwsgi.EVENT_TIMER, 1000, ciao2)
|
||||
|
||||
def application(env, start_response):
|
||||
#print env
|
||||
|
||||
global counter
|
||||
|
||||
print env
|
||||
start_response('200 Ok', [('Content-type', 'text/plain')])
|
||||
yield "hello world"
|
||||
yield "hello world2"
|
||||
|
||||
for i in xrange(1,1000):
|
||||
yield str(i)
|
||||
|
||||
yield "\n"
|
||||
|
||||
yield str(counter)
|
||||
counter += 1
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
def mygen(uri):
|
||||
for i in xrange(1,100):
|
||||
yield "ciao %s<br/>" % uri
|
||||
|
||||
|
||||
def application(env, start_response = None):
|
||||
return '200 OK', [('Content-Type', 'text/html')], "<h1>This is the fastest homepage of the world !!!</h1>"
|
||||
#return '200 OK', [('Content-Type', 'text/html')], mygen(env['PATH_INFO'])
|
||||
@@ -39,9 +39,9 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
|
||||
uint8_t community_len;
|
||||
|
||||
uint64_t snmp_int;
|
||||
uint64_t request_id;
|
||||
uint64_t version;
|
||||
uint64_t snmp_int = 0;
|
||||
uint64_t request_id = 0;
|
||||
uint64_t version = 0;
|
||||
|
||||
|
||||
// KISS for memory management
|
||||
@@ -55,6 +55,9 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("SNMP packet size: %d\n", size);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -68,6 +71,9 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
return;
|
||||
ptr += ptrdelta;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("SNMP version: %d\n", version);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -90,11 +96,16 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
if (memcmp(ptr, uwsgi.shared->snmp_community, community_len))
|
||||
return;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("SNMP community: %.*s\n", community_len, ptr);
|
||||
#endif
|
||||
|
||||
ptr += community_len;
|
||||
|
||||
// check for get request
|
||||
if (*ptr != SNMP_GET)
|
||||
return;
|
||||
|
||||
*ptr = SNMP_RES;
|
||||
ptr++;
|
||||
seq1 = ptr;
|
||||
@@ -110,34 +121,45 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
if (*ptr != SNMP_INTEGER)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
ptrdelta = get_snmp_integer(ptr, &request_id);
|
||||
|
||||
|
||||
if (ptrdelta <= 0)
|
||||
return;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("SNMP request id: %d %p\n", request_id, ptr);
|
||||
#endif
|
||||
|
||||
// check here
|
||||
if (ptr + ptrdelta >= buffer + size)
|
||||
return;
|
||||
ptr += ptrdelta;
|
||||
|
||||
|
||||
// get error
|
||||
if (*ptr != SNMP_INTEGER)
|
||||
return;
|
||||
|
||||
ptr++;
|
||||
snmp_int = 0;
|
||||
ptrdelta = get_snmp_integer(ptr, &snmp_int);
|
||||
|
||||
if (ptrdelta <= 0)
|
||||
return;
|
||||
if (ptr + ptrdelta >= buffer + size)
|
||||
return;
|
||||
if (snmp_int != 0)
|
||||
return;
|
||||
|
||||
ptr += ptrdelta;
|
||||
|
||||
// get index
|
||||
if (*ptr != SNMP_INTEGER)
|
||||
return;
|
||||
ptr++;
|
||||
snmp_int = 0;
|
||||
ptrdelta = get_snmp_integer(ptr, &snmp_int);
|
||||
if (ptrdelta <= 0)
|
||||
return;
|
||||
@@ -148,6 +170,10 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
return;
|
||||
ptr += ptrdelta;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("SNMP int [1]: %d\n", snmp_int);
|
||||
#endif
|
||||
|
||||
// check for sequence
|
||||
if (*ptr != SNMP_SEQUENCE)
|
||||
return;
|
||||
@@ -173,6 +199,10 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
seq3 = ptr;
|
||||
ptr++;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("SNMP ASN len: %d\n", asnlen);
|
||||
#endif
|
||||
|
||||
// is it an OID ?
|
||||
if (*ptr != SNMP_OID)
|
||||
return;
|
||||
@@ -248,11 +278,16 @@ static int get_snmp_integer(uint8_t * ptr, uint64_t * val) {
|
||||
uint16_t tlen;
|
||||
int i, j;
|
||||
|
||||
uint8_t *cval = (uint8_t *) val;
|
||||
|
||||
tlen = *ptr;
|
||||
|
||||
if (tlen > 4)
|
||||
return -1;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("SNMP get integer TLEN %d %p\n", tlen, ptr);
|
||||
#endif
|
||||
|
||||
j = 0;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
@@ -260,7 +295,7 @@ static int get_snmp_integer(uint8_t * ptr, uint64_t * val) {
|
||||
#else
|
||||
for (i = tlen - 1; i >= 0; i--) {
|
||||
#endif
|
||||
val[j] = ptr[1 + i];
|
||||
cval[j] = ptr[1 + i];
|
||||
j++;
|
||||
}
|
||||
|
||||
@@ -419,7 +454,7 @@ PyObject *py_snmp_community(PyObject * self, PyObject * args) {
|
||||
memcpy(uwsgi.shared->snmp_community, snmp_community, 72);
|
||||
}
|
||||
else {
|
||||
strlcpy(uwsgi.shared->snmp_community, snmp_community, 73);
|
||||
memcpy(uwsgi.shared->snmp_community, snmp_community, strlen(snmp_community) + 1);
|
||||
}
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
|
||||
@@ -38,12 +38,17 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
}
|
||||
|
||||
uws_addr->sun_family = AF_UNIX;
|
||||
strlcpy(uws_addr->sun_path + abstract_socket, socket_name, 102+1);
|
||||
|
||||
memcpy(uws_addr->sun_path + abstract_socket, socket_name, 102);
|
||||
|
||||
#ifdef __HAIKU__
|
||||
if (bind(serverfd, (struct sockaddr *) uws_addr, sizeof(struct sockaddr_un))) {
|
||||
#else
|
||||
if (bind(serverfd, (struct sockaddr *) uws_addr, strlen(socket_name) + abstract_socket + ((void *) uws_addr->sun_path - (void *) uws_addr)) != 0) {
|
||||
#endif
|
||||
uwsgi_error("bind()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
uwsgi_error("listen()");
|
||||
@@ -52,12 +57,21 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
|
||||
// chmod unix socket for lazy users
|
||||
if (chmod_socket == 1 && abstract_socket == 0) {
|
||||
uwsgi_log( "chmod() socket to 666 for lazy and brave users\n");
|
||||
if (chmod(socket_name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) != 0) {
|
||||
uwsgi_error("chmod()");
|
||||
if (uwsgi.chmod_socket_value) {
|
||||
if (chmod(socket_name, uwsgi.chmod_socket_value) != 0) {
|
||||
uwsgi_error("chmod()");
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "chmod() socket to 666 for lazy and brave users\n");
|
||||
if (chmod(socket_name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) != 0) {
|
||||
uwsgi_error("chmod()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(uws_addr);
|
||||
|
||||
return serverfd;
|
||||
}
|
||||
|
||||
@@ -190,6 +204,47 @@ int bind_to_udp(char *socket_name) {
|
||||
}
|
||||
#endif
|
||||
|
||||
int uwsgi_connect(char *socket_name, int timeout) {
|
||||
|
||||
char *tcp_port = strchr(socket_name, ':');
|
||||
|
||||
if (tcp_port) {
|
||||
tcp_port[0] = 0;
|
||||
tcp_port++;
|
||||
return connect_to_tcp(socket_name, atoi(tcp_port), timeout);
|
||||
}
|
||||
|
||||
return connect_to_unix(socket_name, timeout);
|
||||
}
|
||||
|
||||
int connect_to_unix(char *socket_name, int timeout) {
|
||||
|
||||
struct pollfd uwsgi_poll;
|
||||
struct sockaddr_un uws_addr;
|
||||
|
||||
memset(&uws_addr, 0, sizeof(struct sockaddr_un));
|
||||
|
||||
uws_addr.sun_family = AF_UNIX;
|
||||
memcpy(uws_addr.sun_path, socket_name, 102);
|
||||
|
||||
uwsgi_poll.fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (uwsgi_poll.fd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uwsgi_poll.events = POLLIN;
|
||||
|
||||
if (timed_connect(&uwsgi_poll, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_un), timeout)) {
|
||||
uwsgi_error("connect()");
|
||||
close(uwsgi_poll.fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return uwsgi_poll.fd;
|
||||
|
||||
}
|
||||
|
||||
int connect_to_tcp(char *socket_name, int port, int timeout) {
|
||||
|
||||
struct pollfd uwsgi_poll;
|
||||
@@ -207,6 +262,8 @@ int connect_to_tcp(char *socket_name, int port, int timeout) {
|
||||
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
|
||||
}
|
||||
|
||||
socket_name[strlen(socket_name)] = ':' ;
|
||||
|
||||
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (uwsgi_poll.fd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
@@ -262,7 +319,8 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (setsockopt(serverfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], sizeof(int))) {
|
||||
uwsgi_error("setsockopt()");
|
||||
}
|
||||
#elif defined(__apple__) || defined(__freebsd__)
|
||||
// OSX has no SO_ACCEPTFILTER !!!
|
||||
#elif defined(__freebsd__)
|
||||
struct accept_filter_arg afa;
|
||||
strcpy(afa.af_name, "dataready");
|
||||
afa.af_arg[0] = 0;
|
||||
@@ -277,6 +335,9 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
uwsgi_log( "binding on TCP port: %d\n", ntohs(uws_addr.sin_port));
|
||||
|
||||
if (bind(serverfd, (struct sockaddr *) &uws_addr, sizeof(uws_addr)) != 0) {
|
||||
if (errno == EADDRINUSE) {
|
||||
uwsgi_log("probably another instance of uWSGI is running on the same address.\n");
|
||||
}
|
||||
uwsgi_error("bind()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
#ifdef UWSGI_SPOOLER
|
||||
#include "uwsgi.h"
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
|
||||
|
||||
int spool_request(struct uwsgi_server *uwsgi, char *filename, int rn, char *buffer, int size) {
|
||||
|
||||
@@ -21,7 +18,7 @@ int spool_request(struct uwsgi_server *uwsgi, char *filename, int rn, char *buff
|
||||
|
||||
hostname[256] = 0;
|
||||
|
||||
if (snprintf(filename, 1024, "%s/uwsgi_spoolfile_on_%s_%d_%d_%llu_%llu", uwsgi->spool_dir, hostname, getpid(), rn, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
|
||||
if (snprintf(filename, 1024, "%s/uwsgi_spoolfile_on_%s_%d_%d_%llu_%llu", uwsgi->spool_dir, hostname, (int) getpid(), rn, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -59,7 +56,7 @@ int spool_request(struct uwsgi_server *uwsgi, char *filename, int rn, char *buff
|
||||
|
||||
close(fd);
|
||||
|
||||
uwsgi_log( "written %d bytes to spool file %s.\n", size + 4, filename);
|
||||
uwsgi_log( "written %d bytes to spool file %s\n", size + 4, filename);
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -81,14 +78,14 @@ void spooler(struct uwsgi_server *uwsgi, PyObject * uwsgi_module_dict) {
|
||||
int rlen = 0;
|
||||
int datasize;
|
||||
|
||||
// prevent process blindly reading stdin to make mess
|
||||
int nullfd;
|
||||
|
||||
struct uwsgi_header uh;
|
||||
|
||||
char *key;
|
||||
char *val;
|
||||
|
||||
// spool every 30 seconds by default
|
||||
uwsgi->shared->spooler_frequency = 30 ;
|
||||
|
||||
spool_tuple = PyTuple_New(1);
|
||||
|
||||
if (!spool_tuple) {
|
||||
@@ -114,8 +111,25 @@ void spooler(struct uwsgi_server *uwsgi, PyObject * uwsgi_module_dict) {
|
||||
}
|
||||
|
||||
// asked by Marco Beri
|
||||
|
||||
#ifdef __HAIKU__
|
||||
uwsgi_log( "lowering spooler priority to %d\n", B_LOW_PRIORITY);
|
||||
set_thread_priority(find_thread(NULL), B_LOW_PRIORITY);
|
||||
#else
|
||||
uwsgi_log( "lowering spooler priority to %d\n", PRIO_MAX);
|
||||
setpriority(PRIO_PROCESS, getpid(), PRIO_MAX);
|
||||
#endif
|
||||
|
||||
nullfd = open("/dev/null", O_RDONLY);
|
||||
if (nullfd < 0) {
|
||||
uwsgi_error("open()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (nullfd != 0) {
|
||||
dup2(nullfd, 0);
|
||||
close(nullfd);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
|
||||
@@ -133,7 +147,7 @@ void spooler(struct uwsgi_server *uwsgi, PyObject * uwsgi_module_dict) {
|
||||
continue;
|
||||
}
|
||||
if (!access(dp->d_name, R_OK | W_OK)) {
|
||||
uwsgi_log( "managing spool request %s...\n", dp->d_name);
|
||||
uwsgi_log( "managing spool request %s ...\n", dp->d_name);
|
||||
|
||||
spooler_callable = PyDict_GetItemString(uwsgi_module_dict, "spooler");
|
||||
if (!spooler_callable) {
|
||||
@@ -238,7 +252,7 @@ void spooler(struct uwsgi_server *uwsgi, PyObject * uwsgi_module_dict) {
|
||||
}
|
||||
|
||||
|
||||
spool_result = python_call(spooler_callable, spool_tuple);
|
||||
spool_result = python_call(spooler_callable, spool_tuple, 0);
|
||||
if (!spool_result) {
|
||||
PyErr_Print();
|
||||
uwsgi_log( "error detected. spool request canceled.\n");
|
||||
|
||||
@@ -9,4 +9,3 @@ my $app = sub {
|
||||
[ "Hello World\r\n", $env->{'REQUEST_URI'} ],
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import uwsgi
|
||||
import time
|
||||
|
||||
def application(env, start_response):
|
||||
|
||||
start_response('200 Ok', [ ('Content-Type','text/html') ] )
|
||||
|
||||
yield "I am the worker %d<br/>" % uwsgi.worker_id()
|
||||
|
||||
grunt = uwsgi.grunt()
|
||||
|
||||
if grunt is None:
|
||||
print "worker %d detached" % uwsgi.worker_id()
|
||||
else:
|
||||
yield "And now i am the grunt with a fix worker id of %d<br/>" % uwsgi.worker_id()
|
||||
time.sleep(2)
|
||||
yield "Now, i will start a very slow task...<br/>"
|
||||
for i in xrange(1,10):
|
||||
yield "waiting for %d seconds<br/>" % i
|
||||
time.sleep(i)
|
||||
|
||||
|
||||
@@ -414,7 +414,7 @@ void u_green_loop(struct uwsgi_server *uwsgi) {
|
||||
|
||||
for(i=0; i<uwsgi->async_nevents;i++) {
|
||||
|
||||
if (uwsgi->async_events[i].ASYNC_FD == uwsgi->serverfd) {
|
||||
if ( (int) uwsgi->async_events[i].ASYNC_FD == uwsgi->serverfd) {
|
||||
wsgi_req = find_first_accepting_wsgi_req(uwsgi);
|
||||
if (!wsgi_req) goto cycle;
|
||||
u_green_schedule_to_req(uwsgi, wsgi_req);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import uwsgi
|
||||
|
||||
def ciao():
|
||||
uwsgi.start_response('200 OK', [ ('Content-type', 'text/plain') ])
|
||||
uwsgi.send(str(22+30))
|
||||
|
||||
def application(env, start_response):
|
||||
|
||||
start_response('200 Ok', [('Content-type', 'text/html')])
|
||||
|
||||
if env['REQUEST_METHOD'] == 'POST':
|
||||
print "getting file..."
|
||||
remains = int(env['CONTENT_LENGTH'])
|
||||
print remains
|
||||
buf = ''
|
||||
while remains > 0:
|
||||
if remains < 8192:
|
||||
buf = env['wsgi.input'].read(remains)
|
||||
else:
|
||||
buf = env['wsgi.input'].read(8192)
|
||||
#print len(buf)
|
||||
remains = remains - len(buf)
|
||||
#print "remains",remains
|
||||
print "upload ready"
|
||||
yield env['CONTENT_LENGTH']
|
||||
else:
|
||||
yield """
|
||||
<form method="POST" enctype="multipart/form-data">
|
||||
<input type="file" name="file" />
|
||||
<input type="submit" value="invia" />
|
||||
</form>
|
||||
"""
|
||||
|
||||
@@ -27,6 +27,15 @@ uint64_t uwsgi_swap64(uint64_t x) {
|
||||
|
||||
#endif
|
||||
|
||||
void inc_harakiri(int sec) {
|
||||
if (uwsgi.master_process) {
|
||||
uwsgi.workers[uwsgi.mywid].harakiri += sec;
|
||||
}
|
||||
else {
|
||||
alarm(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] + sec);
|
||||
}
|
||||
}
|
||||
|
||||
void set_harakiri(int sec) {
|
||||
if (uwsgi.master_process) {
|
||||
if (sec == 0) {
|
||||
@@ -41,16 +50,10 @@ void set_harakiri(int sec) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef UNBIT
|
||||
|
||||
void daemonize(char *logfile) {
|
||||
pid_t pid;
|
||||
int fd, fdin;
|
||||
int fdin;
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
char *udp_port;
|
||||
struct sockaddr_in udp_addr;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -94,8 +97,25 @@ void daemonize(char *logfile) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* stdin */
|
||||
if (dup2(fdin, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
logto(logfile);
|
||||
|
||||
}
|
||||
|
||||
void logto(char *logfile) {
|
||||
|
||||
int fd ;
|
||||
|
||||
#ifdef UWSGI_UDP
|
||||
char *udp_port;
|
||||
struct sockaddr_in udp_addr;
|
||||
|
||||
udp_port = strchr(logfile, ':');
|
||||
if (udp_port) {
|
||||
udp_port[0] = 0 ;
|
||||
@@ -129,35 +149,29 @@ void daemonize(char *logfile) {
|
||||
exit(1);
|
||||
}
|
||||
#ifdef UWSGI_UDP
|
||||
uwsgi.logfile = logfile;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* stdin */
|
||||
if (dup2(fdin, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* stdout */
|
||||
if (dup2(fd, 1) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
if (fd != 1) {
|
||||
if (dup2(fd, 1) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* stderr */
|
||||
if (dup2(fd, 2) < 0) {
|
||||
if (dup2(1, 2) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
char *uwsgi_get_cwd() {
|
||||
|
||||
@@ -190,17 +204,14 @@ char *uwsgi_get_cwd() {
|
||||
}
|
||||
|
||||
void internal_server_error(int fd, char *message) {
|
||||
#ifndef UNBIT
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] == 0) {
|
||||
#endif
|
||||
uwsgi.wsgi_req->headers_size = write(fd, "HTTP/1.1 500 Internal Server Error\r\nContent-type: text/html\r\n\r\n", 63);
|
||||
#ifndef UNBIT
|
||||
}
|
||||
else {
|
||||
uwsgi.wsgi_req->headers_size = write(fd, "Status: 500 Internal Server Error\r\nContent-type: text/html\r\n\r\n", 62);
|
||||
}
|
||||
uwsgi.wsgi_req->header_cnt = 2;
|
||||
#endif
|
||||
|
||||
uwsgi.wsgi_req->response_size = write(fd, "<h1>uWSGI Error</h1>", 20);
|
||||
uwsgi.wsgi_req->response_size += write(fd, message, strlen(message));
|
||||
}
|
||||
@@ -241,15 +252,15 @@ void uwsgi_as_root() {
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi.chroot) {
|
||||
if (uwsgi.chroot && !uwsgi.is_a_reload) {
|
||||
uwsgi_log("cannot chroot() as non-root user\n");
|
||||
exit(1);
|
||||
}
|
||||
if (uwsgi.gid) {
|
||||
if (uwsgi.gid && getgid() != uwsgi.gid) {
|
||||
uwsgi_log("cannot setgid() as non-root user\n");
|
||||
exit(1);
|
||||
}
|
||||
if (uwsgi.uid) {
|
||||
if (uwsgi.uid && getuid() != uwsgi.uid) {
|
||||
uwsgi_log("cannot setuid() as non-root user\n");
|
||||
exit(1);
|
||||
}
|
||||
@@ -271,6 +282,7 @@ void uwsgi_close_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_r
|
||||
|
||||
// close the connection with the webserver
|
||||
if (!wsgi_req->fd_closed) {
|
||||
// TODO find a way to discard pending data
|
||||
close(wsgi_req->poll.fd);
|
||||
}
|
||||
uwsgi->workers[0].requests++;
|
||||
@@ -281,13 +293,13 @@ void uwsgi_close_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_r
|
||||
(*uwsgi->shared->after_hooks[wsgi_req->uh.modifier1]) (uwsgi, wsgi_req);
|
||||
|
||||
// leave harakiri mode
|
||||
if (uwsgi->workers[uwsgi->mywid].harakiri > 0) {
|
||||
if (uwsgi->shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
set_harakiri(0);
|
||||
}
|
||||
|
||||
// defunct process reaper
|
||||
if (uwsgi->shared->options[UWSGI_OPTION_REAPER] == 1) {
|
||||
waitpid(-1, &waitpid_status, WNOHANG);
|
||||
if (uwsgi->shared->options[UWSGI_OPTION_REAPER] == 1 || uwsgi->grunt) {
|
||||
while( waitpid(WAIT_ANY, &waitpid_status, WNOHANG) > 0) ;
|
||||
}
|
||||
// reset request
|
||||
memset(wsgi_req, 0, sizeof(struct wsgi_request));
|
||||
@@ -314,6 +326,14 @@ void wsgi_req_setup(struct wsgi_request *wsgi_req, int async_id) {
|
||||
wsgi_req->hvec = &uwsgi.async_hvec[wsgi_req->async_id];
|
||||
wsgi_req->buffer = uwsgi.async_buf[wsgi_req->async_id];
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
wsgi_req->ovector = uwsgi.async_ovector[wsgi_req->async_id];
|
||||
#endif
|
||||
|
||||
if (uwsgi.post_buffering > 0) {
|
||||
wsgi_req->post_buffering_buf = uwsgi.async_post_buf[wsgi_req->async_id];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int wsgi_req_recv(struct wsgi_request *wsgi_req) {
|
||||
@@ -381,16 +401,53 @@ void sanitize_args(struct uwsgi_server *uwsgi) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (uwsgi->wsgi_config) {
|
||||
uwsgi->single_interpreter = 1 ;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_INI
|
||||
if (uwsgi->ini) {
|
||||
uwsgi->single_interpreter = 1 ;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_PASTE
|
||||
if (uwsgi->paste) {
|
||||
uwsgi->single_interpreter = 1 ;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi->shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
if (!uwsgi->post_buffering) {
|
||||
uwsgi_log(" *** WARNING: you have enabled harakiri without post buffering. Slow upload could be rejected on post-unbuffered webservers *** \n");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_HTTP
|
||||
if (uwsgi->http && !uwsgi->http_only) {
|
||||
uwsgi->vacuum = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void env_to_arg(char *src, char *dst) {
|
||||
int i;
|
||||
int val = 0 ;
|
||||
|
||||
for(i=0;i<strlen(src);i++) {
|
||||
dst[i] = tolower(src[i]);
|
||||
if (dst[i] == '_') {
|
||||
dst[i] = '-';
|
||||
for(i=0;i< (int) strlen(src);i++) {
|
||||
if (src[i] == '=') {
|
||||
val = 1 ;
|
||||
}
|
||||
if (val) {
|
||||
dst[i] = src[i];
|
||||
}
|
||||
else {
|
||||
dst[i] = tolower( (int) src[i]);
|
||||
if (dst[i] == '_') {
|
||||
dst[i] = '-';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,12 +506,32 @@ void parse_sys_envs(char **envs, struct option *long_options) {
|
||||
void uwsgi_log(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
char logpkt[4096];
|
||||
int rlen;
|
||||
int rlen = 0;
|
||||
|
||||
struct timeval tv;
|
||||
|
||||
if (uwsgi.logdate) {
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
memcpy( logpkt, ctime( (const time_t *) &tv.tv_sec), 24);
|
||||
memcpy( logpkt + 24, " - ", 3);
|
||||
|
||||
rlen = 24 + 3 ;
|
||||
|
||||
}
|
||||
|
||||
va_start (ap, fmt);
|
||||
rlen = vsnprintf(logpkt, 4096, fmt, ap );
|
||||
rlen += vsnprintf(logpkt + rlen, 4096 - rlen, fmt, ap );
|
||||
va_end(ap);
|
||||
|
||||
// do not check for errors
|
||||
rlen = write(2, logpkt, rlen);
|
||||
}
|
||||
|
||||
inline int uwsgi_strncmp(char *src, int slen, char *dst, int dlen) {
|
||||
|
||||
if (slen != dlen) return 1;
|
||||
|
||||
return memcmp(src, dst, dlen);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
/* uWSGI */
|
||||
|
||||
/* indent -i8 -br -brs -brf -l0 -npsl -nip -npcs */
|
||||
/* indent -i8 -br -brs -brf -l0 -npsl -nip -npcs -npsl -di1 */
|
||||
|
||||
#define UWSGI_VERSION "0.9.5-dev"
|
||||
#define UWSGI_VERSION "0.9.6.1"
|
||||
|
||||
#define uwsgi_error(x) uwsgi_log("%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
|
||||
#define uwsgi_debug(x, ...) uwsgi_log("[uWSGI DEBUG] " x, __VA_ARGS__);
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -16,9 +17,16 @@
|
||||
#include <netinet/tcp.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
// linux has not strlcpy
|
||||
#include <dirent.h>
|
||||
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#ifdef __linux
|
||||
#define strlcpy(x, y, z) strcpy(x, y)
|
||||
#include <sys/prctl.h>
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_SCTP
|
||||
@@ -29,6 +37,14 @@
|
||||
#include <ucontext.h>
|
||||
#endif
|
||||
|
||||
#ifndef UWSGI_PLUGIN_BASE
|
||||
#define UWSGI_PLUGIN_BASE ""
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
#include <pcre.h>
|
||||
#endif
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/file.h>
|
||||
@@ -37,6 +53,10 @@
|
||||
|
||||
#include <sys/wait.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_4
|
||||
#endif
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include <poll.h>
|
||||
@@ -49,9 +69,7 @@
|
||||
|
||||
#include <sys/resource.h>
|
||||
|
||||
#ifndef UNBIT
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <libkern/OSAtomic.h>
|
||||
@@ -72,6 +90,10 @@
|
||||
#define PRIO_MAX 20
|
||||
#endif
|
||||
|
||||
#ifdef __HAIKU__
|
||||
#define WAIT_ANY (-1)
|
||||
#endif
|
||||
|
||||
#define MAX_PYARGV 10
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
@@ -80,11 +102,17 @@
|
||||
#include <sys/sendfile.h>
|
||||
#include <sys/epoll.h>
|
||||
#elif defined(__sun__)
|
||||
#include <sys/sendfile.h>
|
||||
#include <sys/devpoll.h>
|
||||
#elif defined(__HAIKU__)
|
||||
#else
|
||||
#include <sys/event.h>
|
||||
#endif
|
||||
|
||||
#ifdef __HAIKU__
|
||||
#include <kernel/OS.h>
|
||||
#endif
|
||||
|
||||
#undef _XOPEN_SOURCE
|
||||
#include <Python.h>
|
||||
|
||||
@@ -101,7 +129,7 @@
|
||||
#endif
|
||||
|
||||
/* this value are taken from nginx */
|
||||
#if defined(__apple__) || defined(__freebsd__)
|
||||
#if defined(__APPLE__) || defined(__freebsd__)
|
||||
#define UWSGI_LISTEN_QUEUE -1
|
||||
#else
|
||||
#define UWSGI_LISTEN_QUEUE 511
|
||||
@@ -139,6 +167,29 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
|
||||
#define LONG_ARGS_UGREEN_PAGES 17022
|
||||
#define LONG_ARGS_FILE_CONFIG 17023
|
||||
#define LONG_ARGS_MULTICAST 17024
|
||||
#define LONG_ARGS_LOGTO 17025
|
||||
#define LONG_ARGS_PRIO 17026
|
||||
#define LONG_ARGS_POST_BUFFERING 17027
|
||||
#define LONG_ARGS_POST_BUFFERING_SIZE 17028
|
||||
#define LONG_ARGS_LIMIT_POST 17029
|
||||
#define LONG_ARGS_HTTP 17030
|
||||
#define LONG_ARGS_MODE 17031
|
||||
#define LONG_ARGS_CHDIR 17032
|
||||
#define LONG_ARGS_ENV 17033
|
||||
#define LONG_ARGS_CHDIR2 17034
|
||||
#define LONG_ARGS_INI 17035
|
||||
#define LONG_ARGS_LDAP_SCHEMA 17036
|
||||
#define LONG_ARGS_LDAP 17037
|
||||
#define LONG_ARGS_LDAP_SCHEMA_LDIF 17038
|
||||
#define LONG_ARGS_PING 17039
|
||||
#define LONG_ARGS_PING_TIMEOUT 17040
|
||||
#define LONG_ARGS_INI_PASTE 17041
|
||||
#define LONG_ARGS_CALLABLE 17042
|
||||
#define LONG_ARGS_HTTP_VAR 17043
|
||||
#define LONG_ARGS_NO_DEFAULT_APP 17044
|
||||
#define LONG_ARGS_EVAL_CONFIG 17045
|
||||
|
||||
|
||||
|
||||
#define UWSGI_OK 0
|
||||
#define UWSGI_AGAIN 1
|
||||
@@ -174,8 +225,9 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
|
||||
#ifdef _BIG_ENDIAN
|
||||
#define __BIG_ENDIAN__ 1
|
||||
#endif
|
||||
#elif __apple__
|
||||
#elif __APPLE__
|
||||
#include <libkern/OSByteOrder.h>
|
||||
#elif defined(__HAIKU__)
|
||||
#else
|
||||
#include <machine/endian.h>
|
||||
#endif
|
||||
@@ -190,14 +242,9 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
|
||||
#define UWSGI_OPTION_THREADS 7
|
||||
#define UWSGI_OPTION_REAPER 8
|
||||
|
||||
#ifdef UNBIT
|
||||
#define UWSGI_MODIFIER_HT_S 1
|
||||
#define UWSGI_MODIFIER_HT_M 2
|
||||
#define UWSGI_MODIFIER_HT_H 3
|
||||
#endif
|
||||
|
||||
#define UWSGI_MODIFIER_ADMIN_REQUEST 10
|
||||
#define UWSGI_MODIFIER_SPOOL_REQUEST 17
|
||||
#define UWSGI_MODIFIER_EVAL 22
|
||||
#define UWSGI_MODIFIER_FASTFUNC 26
|
||||
#define UWSGI_MODIFIER_MANAGE_PATH_INFO 30
|
||||
#define UWSGI_MODIFIER_MESSAGE 31
|
||||
@@ -218,6 +265,7 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
|
||||
#define PyString_FromFormat PyUnicode_FromFormat
|
||||
#define PyString_FromString PyUnicode_FromString
|
||||
#define PyString_Size PyUnicode_GET_DATA_SIZE
|
||||
#define PyString_Concat PyUnicode_Concat
|
||||
#define PyString_AsString (char *) PyUnicode_AS_UNICODE
|
||||
#define PyFile_FromFile(A,B,C,D) PyFile_FromFd(fileno((A)), (B), (C), -1, NULL, NULL, NULL, 0)
|
||||
#endif
|
||||
@@ -230,10 +278,14 @@ PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
|
||||
|
||||
#define MAX_VARS 64
|
||||
|
||||
struct wsgi_request;
|
||||
struct uwsgi_server;
|
||||
|
||||
struct uwsgi_app {
|
||||
|
||||
PyThreadState *interpreter;
|
||||
PyObject *pymain_dict;
|
||||
PyObject *wsgi_dict;
|
||||
PyObject *wsgi_callable;
|
||||
|
||||
|
||||
@@ -255,9 +307,35 @@ struct uwsgi_app {
|
||||
#endif
|
||||
|
||||
int requests;
|
||||
char *chdir;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
struct uwsgi_route {
|
||||
|
||||
const char *mountpoint;
|
||||
const char *callbase;
|
||||
|
||||
pcre *pattern;
|
||||
pcre_extra *pattern_extra;
|
||||
pcre *method;
|
||||
pcre_extra *method_extra;
|
||||
|
||||
const char *call;
|
||||
|
||||
int modifier1;
|
||||
int modifier2;
|
||||
|
||||
void *callable;
|
||||
void *callable_args;
|
||||
int args;
|
||||
|
||||
void (*action)(struct uwsgi_server *, struct wsgi_request *, struct uwsgi_route *);
|
||||
};
|
||||
#endif
|
||||
|
||||
struct __attribute__ ((packed)) uwsgi_header {
|
||||
uint8_t modifier1;
|
||||
uint16_t pktsize;
|
||||
@@ -302,16 +380,23 @@ struct wsgi_request {
|
||||
char *script_name;
|
||||
uint16_t script_name_len;
|
||||
|
||||
char *host;
|
||||
uint16_t host_len;
|
||||
|
||||
char *path_info;
|
||||
uint16_t path_info_len;
|
||||
|
||||
char *wsgi_script;
|
||||
uint16_t wsgi_script_len;
|
||||
char *wsgi_module;
|
||||
uint16_t wsgi_module_len;
|
||||
char *wsgi_callable;
|
||||
uint16_t wsgi_callable_len;
|
||||
char *pyhome;
|
||||
uint16_t pyhome_len;
|
||||
|
||||
#ifdef UNBIT
|
||||
unsigned long long unbit_flags;
|
||||
#endif
|
||||
char *chdir;
|
||||
uint16_t chdir_len;
|
||||
|
||||
int fd_closed;
|
||||
|
||||
@@ -319,6 +404,7 @@ struct wsgi_request {
|
||||
size_t sendfile_fd_chunk;
|
||||
size_t sendfile_fd_size;
|
||||
off_t sendfile_fd_pos;
|
||||
void *sendfile_obj;
|
||||
|
||||
uint16_t var_cnt;
|
||||
uint16_t header_cnt;
|
||||
@@ -339,6 +425,9 @@ struct wsgi_request {
|
||||
|
||||
void *async_app;
|
||||
void *async_result;
|
||||
#ifdef UWSGI_WSGI2
|
||||
void *async_orig_result;
|
||||
#endif
|
||||
void *async_placeholder;
|
||||
void *async_args;
|
||||
void *async_environ;
|
||||
@@ -347,6 +436,11 @@ struct wsgi_request {
|
||||
|
||||
int async_plagued;
|
||||
|
||||
int *ovector;
|
||||
size_t post_cl;
|
||||
char *post_buffering_buf;
|
||||
uint64_t post_buffering_read;
|
||||
|
||||
#ifdef UWSGI_STACKLESS
|
||||
PyTaskletObject* tasklet;
|
||||
#endif
|
||||
@@ -368,12 +462,25 @@ struct uwsgi_server {
|
||||
struct wsgi_request *wsgi_req ;
|
||||
|
||||
PyThreadState *_save;
|
||||
#ifndef UNBIT
|
||||
char *chroot;
|
||||
gid_t gid;
|
||||
uid_t uid;
|
||||
|
||||
char *mode;
|
||||
|
||||
#ifdef UWSGI_HTTP
|
||||
char *http;
|
||||
char *http_server_name;
|
||||
char *http_server_port;
|
||||
int http_only;
|
||||
int http_fd;
|
||||
char *http_vars[64];
|
||||
int http_vars_cnt;
|
||||
#endif
|
||||
|
||||
int ignore_script_name;
|
||||
int no_default_app;
|
||||
int logdate;
|
||||
|
||||
int serverfd;
|
||||
#ifdef UWSGI_PROXY
|
||||
@@ -381,10 +488,23 @@ struct uwsgi_server {
|
||||
char *proxy_socket_name;
|
||||
#endif
|
||||
|
||||
char *logfile;
|
||||
|
||||
int vhost;
|
||||
|
||||
struct iovec *async_hvec;
|
||||
char **async_buf;
|
||||
char **async_post_buf;
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
int **async_ovector;
|
||||
#endif
|
||||
|
||||
struct rlimit rl;
|
||||
size_t limit_post;
|
||||
int prio;
|
||||
|
||||
int grunt;
|
||||
|
||||
char *binary_path;
|
||||
|
||||
@@ -424,6 +544,10 @@ struct uwsgi_server {
|
||||
|
||||
int buffer_size;
|
||||
|
||||
int post_buffering;
|
||||
int post_buffering_harakiri;
|
||||
int post_buffering_bufsize;
|
||||
|
||||
int master_process;
|
||||
|
||||
int no_defer_accept;
|
||||
@@ -472,9 +596,9 @@ struct uwsgi_server {
|
||||
|
||||
struct timeval start_tv;
|
||||
|
||||
#ifndef UNBIT
|
||||
int abstract_socket;
|
||||
int chmod_socket;
|
||||
mode_t chmod_socket_value;
|
||||
int listen_queue;
|
||||
|
||||
#ifdef UWSGI_XML
|
||||
@@ -486,10 +610,31 @@ struct uwsgi_server {
|
||||
char *python_path[64];
|
||||
int python_path_cnt;
|
||||
char *pyargv;
|
||||
|
||||
int pyargc;
|
||||
#ifdef PYTHREE
|
||||
wchar_t *py_argv[MAX_PYARGV];
|
||||
#else
|
||||
char *py_argv[MAX_PYARGV];
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
#ifndef MAX_UWSGI_ROUTES
|
||||
#define MAX_UWSGI_ROUTES 64
|
||||
#endif
|
||||
int routing;
|
||||
int nroutes;
|
||||
struct uwsgi_route routes[MAX_UWSGI_ROUTES];
|
||||
#endif
|
||||
|
||||
char *wsgi_config;
|
||||
|
||||
#ifdef UWSGI_INI
|
||||
char *ini;
|
||||
#endif
|
||||
#ifdef UWSGI_PASTE
|
||||
char *paste;
|
||||
#endif
|
||||
char *wsgi_file;
|
||||
|
||||
int single_interpreter;
|
||||
@@ -521,6 +666,51 @@ struct uwsgi_server {
|
||||
int erlang_nodes;
|
||||
int erlangfd;
|
||||
#endif
|
||||
|
||||
int no_orphans;
|
||||
|
||||
#ifdef UWSGI_EMBED_PLUGINS
|
||||
|
||||
#ifdef UWSGI_EMBED_PLUGIN_PSGI
|
||||
char *plugin_arg_psgi;
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EMBED_PLUGIN_LUA
|
||||
char *plugin_arg_lua;
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EMBED_PLUGIN_RACK
|
||||
char *plugin_arg_rack;
|
||||
char *plugin_arg_rails;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
char *chdir2;
|
||||
int catch_exceptions;
|
||||
|
||||
int vacuum;
|
||||
int no_server;
|
||||
|
||||
#ifdef UWSGI_LDAP
|
||||
char *ldap;
|
||||
#endif
|
||||
|
||||
char *ping;
|
||||
int ping_timeout;
|
||||
|
||||
char *callable;
|
||||
|
||||
int xml_round2;
|
||||
|
||||
char *cwd;
|
||||
|
||||
char *eval;
|
||||
|
||||
int log_slow_requests;
|
||||
int log_zero_headers;
|
||||
int log_empty_body;
|
||||
int log_high_memory;
|
||||
};
|
||||
|
||||
struct uwsgi_cluster_node {
|
||||
@@ -559,6 +749,8 @@ struct uwsgi_shared {
|
||||
|
||||
struct uwsgi_cluster_node nodes[MAX_CLUSTER_NODES];
|
||||
|
||||
off_t logsize;
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
pid_t spooler_pid;
|
||||
int spooler_frequency;
|
||||
@@ -609,6 +801,7 @@ struct uwsgi_worker {
|
||||
char *uwsgi_get_cwd(void);
|
||||
|
||||
void warn_pipe(void);
|
||||
void what_i_am_doing(void);
|
||||
void goodbye_cruel_world(void);
|
||||
void gracefully_kill(void);
|
||||
void reap_them_all(void);
|
||||
@@ -620,19 +813,22 @@ int bind_to_unix(char *, int, int, int);
|
||||
int bind_to_tcp(char *, int, char *);
|
||||
int bind_to_udp(char *);
|
||||
int timed_connect(struct pollfd *, const struct sockaddr *, int, int);
|
||||
int uwsgi_connect(char *, int);
|
||||
int connect_to_tcp(char *, int, int);
|
||||
int connect_to_unix(char *, int);
|
||||
#ifdef UWSGI_SCTP
|
||||
int bind_to_sctp(char *, int, char *);
|
||||
#endif
|
||||
#ifndef UNBIT
|
||||
|
||||
void daemonize(char *);
|
||||
#endif
|
||||
void logto(char *);
|
||||
|
||||
void log_request(struct wsgi_request *);
|
||||
void get_memusage(void);
|
||||
void harakiri(void);
|
||||
#ifndef UNBIT
|
||||
|
||||
void stats(void);
|
||||
#endif
|
||||
|
||||
void init_uwsgi_vars(void);
|
||||
void init_uwsgi_embedded_module(void);
|
||||
|
||||
@@ -641,8 +837,11 @@ void uwsgi_xml_config(struct wsgi_request *, struct option *);
|
||||
#endif
|
||||
|
||||
void uwsgi_wsgi_config(char *);
|
||||
#ifdef UWSGI_PASTE
|
||||
void uwsgi_paste_config(void);
|
||||
#endif
|
||||
void uwsgi_wsgi_file_config(void);
|
||||
void uwsgi_eval_config(char *);
|
||||
|
||||
void internal_server_error(int, char *);
|
||||
|
||||
@@ -664,6 +863,7 @@ pid_t spooler_start(int, PyObject *);
|
||||
#endif
|
||||
|
||||
void set_harakiri(int);
|
||||
void inc_harakiri(int);
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uint16_t uwsgi_swap16(uint16_t);
|
||||
@@ -692,6 +892,7 @@ int uwsgi_request_admin(struct uwsgi_server *, struct wsgi_request *);
|
||||
#ifdef UWSGI_SPOOLER
|
||||
int uwsgi_request_spooler(struct uwsgi_server *, struct wsgi_request *);
|
||||
#endif
|
||||
int uwsgi_request_eval(struct uwsgi_server *, struct wsgi_request *);
|
||||
int uwsgi_request_fastfunc(struct uwsgi_server *, struct wsgi_request *);
|
||||
int uwsgi_request_marshal(struct uwsgi_server *, struct wsgi_request *);
|
||||
int uwsgi_request_ping(struct uwsgi_server *, struct wsgi_request *);
|
||||
@@ -730,7 +931,12 @@ struct wsgi_request *find_first_available_wsgi_req(struct uwsgi_server *);
|
||||
struct wsgi_request *find_wsgi_req_by_fd(struct uwsgi_server *, int, int);
|
||||
struct wsgi_request *find_wsgi_req_by_id(struct uwsgi_server *, int);
|
||||
|
||||
#ifdef __clang__
|
||||
struct wsgi_request *next_wsgi_req(struct uwsgi_server *, struct wsgi_request *);
|
||||
#else
|
||||
inline struct wsgi_request *next_wsgi_req(struct uwsgi_server *, struct wsgi_request *);
|
||||
#endif
|
||||
|
||||
|
||||
int async_add(int, int , int) ;
|
||||
int async_mod(int, int , int) ;
|
||||
@@ -779,11 +985,12 @@ PyObject *py_uwsgi_stackless(PyObject *, PyObject *) ;
|
||||
|
||||
int manage_python_response(struct uwsgi_server *, struct wsgi_request *);
|
||||
int uwsgi_python_call(struct uwsgi_server *, struct wsgi_request *, PyObject *, PyObject *);
|
||||
PyObject *python_call(PyObject *, PyObject *);
|
||||
PyObject *python_call(PyObject *, PyObject *, int);
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
PyObject *py_uwsgi_sendfile(PyObject *, PyObject *) ;
|
||||
ssize_t uwsgi_sendfile(struct uwsgi_server *, struct wsgi_request *);
|
||||
ssize_t uwsgi_do_sendfile(int, int, size_t, size_t, off_t*, int);
|
||||
#endif
|
||||
|
||||
PyObject *py_uwsgi_write(PyObject *, PyObject *) ;
|
||||
@@ -819,7 +1026,11 @@ void u_green_init(struct uwsgi_server *);
|
||||
void u_green_loop(struct uwsgi_server *);
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
struct wsgi_request *current_wsgi_req(struct uwsgi_server *);
|
||||
#else
|
||||
inline struct wsgi_request *current_wsgi_req(struct uwsgi_server *);
|
||||
#endif
|
||||
|
||||
void sanitize_args(struct uwsgi_server *);
|
||||
|
||||
@@ -827,3 +1038,97 @@ void env_to_arg(char *, char *);
|
||||
void parse_sys_envs(char **, struct option *);
|
||||
|
||||
void uwsgi_log(const char *, ...);
|
||||
|
||||
|
||||
#ifdef UWSGI_EVDIS
|
||||
#define EVDIS_TYPE_FILE
|
||||
#define EVDIS_TYPE_DNSSD
|
||||
#endif
|
||||
|
||||
int uwsgi_load_plugin(struct uwsgi_server *, int, char *, char *, int);
|
||||
void embed_plugins(struct uwsgi_server *);
|
||||
|
||||
|
||||
// PLUGINS
|
||||
|
||||
#define UWSGI_PLUGIN_LONGOPT_PSGI
|
||||
#define UWSGI_PLUGIN_LONGOPT_LUA
|
||||
#define UWSGI_PLUGIN_LONGOPT_RACK
|
||||
#define LONG_ARGS_PLUGIN_EMBED_PSGI
|
||||
#define LONG_ARGS_PLUGIN_EMBED_LUA
|
||||
#define LONG_ARGS_PLUGIN_EMBED_RACK
|
||||
|
||||
|
||||
|
||||
#ifdef UWSGI_EMBED_PLUGINS
|
||||
|
||||
|
||||
#ifdef UWSGI_EMBED_PLUGIN_PSGI
|
||||
|
||||
#undef UWSGI_PLUGIN_LONGOPT_PSGI
|
||||
#define UWSGI_PLUGIN_LONGOPT_PSGI {"psgi", required_argument, 0, 30005},
|
||||
|
||||
#undef LONG_ARGS_PLUGIN_EMBED_PSGI
|
||||
#define LONG_ARGS_PLUGIN_EMBED_PSGI case 30005:\
|
||||
uwsgi.plugin_arg_psgi = optarg;\
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EMBED_PLUGIN_LUA
|
||||
|
||||
#undef UWSGI_PLUGIN_LONGOPT_LUA
|
||||
#define UWSGI_PLUGIN_LONGOPT_LUA {"lua", required_argument, 0, 30006},
|
||||
|
||||
#undef LONG_ARGS_PLUGIN_EMBED_LUA
|
||||
#define LONG_ARGS_PLUGIN_EMBED_LUA case 30006:\
|
||||
uwsgi.plugin_arg_lua = optarg;\
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EMBED_PLUGIN_RACK
|
||||
|
||||
#undef UWSGI_PLUGIN_LONGOPT_RACK
|
||||
#define UWSGI_PLUGIN_LONGOPT_RACK {"rack", required_argument, 0, 30007},\
|
||||
{"rails", required_argument, 0, 30008},
|
||||
|
||||
#undef LONG_ARGS_PLUGIN_EMBED_RACK
|
||||
#define LONG_ARGS_PLUGIN_EMBED_RACK case 30007:\
|
||||
uwsgi.plugin_arg_rack = optarg;\
|
||||
break;\
|
||||
case 30008:\
|
||||
uwsgi.plugin_arg_rails = optarg;\
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
void routing_setup(struct uwsgi_server *);
|
||||
void check_route(struct uwsgi_server *, struct wsgi_request *);
|
||||
void uwsgi_route_action_uwsgi(struct uwsgi_server *, struct wsgi_request *, struct uwsgi_route *);
|
||||
void uwsgi_route_action_wsgi(struct uwsgi_server *, struct wsgi_request *, struct uwsgi_route *);
|
||||
#endif
|
||||
|
||||
void init_pyargv(struct uwsgi_server *);
|
||||
|
||||
void http_loop(struct uwsgi_server *);
|
||||
|
||||
int unconfigured_hook(struct uwsgi_server *, struct wsgi_request *);
|
||||
|
||||
#ifdef UWSGI_INI
|
||||
void uwsgi_ini_config(char *, struct option*);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef UWSGI_LDAP
|
||||
void uwsgi_ldap_schema_dump(struct option*);
|
||||
void uwsgi_ldap_schema_dump_ldif(struct option*);
|
||||
void uwsgi_ldap_config(struct uwsgi_server *, struct option*);
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
int uwsgi_strncmp(char *, int , char *, int );
|
||||
#else
|
||||
inline int uwsgi_strncmp(char *, int , char *, int );
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
<uwsgi>
|
||||
<app mountpoint="/test">
|
||||
<script>myapp_wsgi</script>
|
||||
</app>
|
||||
<module>rtmpt</module>
|
||||
<socket mode="dev">:3031</socket>
|
||||
<socket mode="pippo">:3031</socket>
|
||||
|
||||
|
||||
<routing base="rtmpt" modifier1="0" modifier2="0">
|
||||
<route method="GET" pattern="^/pippo/(\d+)$" requires="REMOTE_USER">homepage</route>
|
||||
<route method="GET|POST" pattern="^/ciccia/(\d+)/(\w+)$">view1</route>
|
||||
<route action="wsgi" pattern="^/amf">amfapp</route>
|
||||
<route pattern="^/open/">rtmpt_open</route>
|
||||
<route pattern="^/idle/(\d+)/(\d+)$">rtmpt_idle</route>
|
||||
<route pattern="^/send/(\d+)/(\d+)$">rtmpt_send</route>
|
||||
<route pattern="^/$">index</route>
|
||||
</routing>
|
||||
</uwsgi>
|
||||
|
||||
@@ -55,6 +55,34 @@ int uwsgi_request_admin(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_re
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
int uwsgi_request_eval(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
|
||||
PyObject *code, *py_dict;
|
||||
|
||||
PyObject *m = PyImport_AddModule("__main__");
|
||||
if (m == NULL) {
|
||||
PyErr_Print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
py_dict = PyModule_GetDict(m);
|
||||
// make it a valid c string
|
||||
wsgi_req->buffer[wsgi_req->uh.pktsize] = 0 ;
|
||||
// need to find a way to cache compilations...
|
||||
code = Py_CompileString(wsgi_req->buffer, "uWSGI", Py_file_input);
|
||||
if (code == NULL) {
|
||||
PyErr_Print();
|
||||
return -1;
|
||||
}
|
||||
PyEval_EvalCode((PyCodeObject *)code, py_dict, py_dict );
|
||||
Py_DECREF(code);
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
return -1;
|
||||
}
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
/* uwsgi FASTFUNC|26 */
|
||||
int uwsgi_request_fastfunc(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
+346
-44
@@ -19,6 +19,92 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
#define UWSGI_LOGBASE "[- uWSGI -"
|
||||
|
||||
PyObject *py_uwsgi_send(PyObject * self, PyObject * args) {
|
||||
|
||||
char *data;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s:send", &data)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (write(uwsgi.wsgi_req->poll.fd, data, strlen(data)) < 0) {
|
||||
uwsgi_error("write()");
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
PyObject *py_uwsgi_advanced_sendfile(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *what;
|
||||
char *filename;
|
||||
size_t chunk;
|
||||
off_t pos = 0;
|
||||
size_t filesize = 0;
|
||||
struct stat stat_buf;
|
||||
|
||||
int fd = -1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O|iii:sendfile", &what, &chunk, &pos, &filesize)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PyString_Check(what)) {
|
||||
|
||||
filename = PyString_AsString(what);
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("open");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
fd = PyObject_AsFileDescriptor(what);
|
||||
if (fd < 0) goto clear;
|
||||
|
||||
// check for mixing file_wrapper and sendfile
|
||||
if (fd == uwsgi.wsgi_req->sendfile_fd) {
|
||||
Py_INCREF(what);
|
||||
}
|
||||
}
|
||||
|
||||
if (!filesize) {
|
||||
if (fstat(fd, &stat_buf)) {
|
||||
uwsgi_error("fstat()");
|
||||
goto clear2;
|
||||
}
|
||||
else {
|
||||
filesize = stat_buf.st_size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!filesize) goto clear2;
|
||||
|
||||
if (!chunk) chunk = 4096;
|
||||
|
||||
uwsgi.wsgi_req->response_size += uwsgi_do_sendfile(uwsgi.wsgi_req->poll.fd, fd, filesize, chunk, &pos, 0);
|
||||
|
||||
close(fd);
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
clear2:
|
||||
close(fd);
|
||||
clear:
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
|
||||
|
||||
@@ -172,7 +258,7 @@ PyObject *py_uwsgi_sharedarea_write(PyObject * self, PyObject * args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pos + strlen(value) >= uwsgi.page_size * uwsgi.sharedareasize) {
|
||||
if (pos + (int) strlen(value) >= uwsgi.page_size * uwsgi.sharedareasize) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
@@ -287,6 +373,58 @@ PyObject *py_uwsgi_spooler_freq(PyObject * self, PyObject * args) {
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_spooler_jobs(PyObject * self, PyObject * args) {
|
||||
|
||||
DIR *sdir;
|
||||
struct dirent *dp;
|
||||
char *abs_path;
|
||||
struct stat sf_lstat;
|
||||
|
||||
PyObject *jobslist = PyList_New(0);
|
||||
|
||||
sdir = opendir(uwsgi.spool_dir);
|
||||
|
||||
if (sdir) {
|
||||
while ((dp = readdir(sdir)) != NULL) {
|
||||
if (!strncmp("uwsgi_spoolfile_on_", dp->d_name, 19)) {
|
||||
abs_path = malloc(strlen(uwsgi.spool_dir) + 1 + strlen(dp->d_name) + 1);
|
||||
if (!abs_path) {
|
||||
uwsgi_error("malloc()");
|
||||
closedir(sdir);
|
||||
goto clear;
|
||||
}
|
||||
|
||||
memset(abs_path, 0 , strlen(uwsgi.spool_dir) + 1 + strlen(dp->d_name) + 1);
|
||||
|
||||
memcpy(abs_path, uwsgi.spool_dir, strlen(uwsgi.spool_dir));
|
||||
memcpy(abs_path + strlen(uwsgi.spool_dir) , "/", 1);
|
||||
memcpy(abs_path + strlen(uwsgi.spool_dir) + 1, dp->d_name, strlen(dp->d_name) );
|
||||
|
||||
|
||||
if (lstat(abs_path, &sf_lstat)) {
|
||||
free(abs_path);
|
||||
continue;
|
||||
}
|
||||
if (!S_ISREG(sf_lstat.st_mode)) {
|
||||
free(abs_path);
|
||||
continue;
|
||||
}
|
||||
if (!access(abs_path, R_OK | W_OK)) {
|
||||
if (PyList_Append(jobslist, PyString_FromString(abs_path))) {
|
||||
PyErr_Print();
|
||||
}
|
||||
}
|
||||
free(abs_path);
|
||||
}
|
||||
}
|
||||
closedir(sdir);
|
||||
}
|
||||
|
||||
clear:
|
||||
return jobslist;
|
||||
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args) {
|
||||
PyObject *spool_dict, *spool_vars;
|
||||
@@ -298,6 +436,7 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args) {
|
||||
|
||||
spool_dict = PyTuple_GetItem(args, 0);
|
||||
if (!PyDict_Check(spool_dict)) {
|
||||
uwsgi_log("The argument of spooler callable must be a dictionary.\n");
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
@@ -352,6 +491,7 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("spooler callable dictionary must contains only strings.\n");
|
||||
Py_DECREF(zero);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
@@ -391,6 +531,8 @@ PyObject *py_uwsgi_send_multi_message(PyObject * self, PyObject * args) {
|
||||
char *buffer;
|
||||
struct uwsgi_header uh;
|
||||
PyObject *arg_cluster;
|
||||
|
||||
PyObject *cluster_node;
|
||||
|
||||
PyObject *arg_host, *arg_port, *arg_message;
|
||||
|
||||
@@ -448,7 +590,7 @@ PyObject *py_uwsgi_send_multi_message(PyObject * self, PyObject * args) {
|
||||
for (i = 0; i < clen; i++) {
|
||||
multipoll[i].events = POLLIN;
|
||||
|
||||
PyObject *cluster_node = PyTuple_GetItem(arg_cluster, i);
|
||||
cluster_node = PyTuple_GetItem(arg_cluster, i);
|
||||
arg_host = PyTuple_GetItem(cluster_node, 0);
|
||||
if (!PyString_Check(arg_host)) {
|
||||
goto clear;
|
||||
@@ -564,55 +706,21 @@ PyObject *py_uwsgi_set_option(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_load_plugin(PyObject * self, PyObject * args) {
|
||||
uint8_t modifier;
|
||||
int modifier;
|
||||
char *plugin_name = NULL;
|
||||
char *pargs = NULL;
|
||||
|
||||
void *plugin_handle;
|
||||
int (*plugin_init) (struct uwsgi_server *, char *);
|
||||
int (*plugin_request) (struct uwsgi_server *, struct wsgi_request *);
|
||||
void (*plugin_after_request) (struct uwsgi_server *, struct wsgi_request *);
|
||||
|
||||
if (!PyArg_ParseTuple(args, "is|s:load_plugin", &modifier, &plugin_name, &pargs)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
|
||||
if (!plugin_handle) {
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
}
|
||||
else {
|
||||
plugin_init = dlsym(plugin_handle, "uwsgi_init");
|
||||
if (plugin_init) {
|
||||
if ((*plugin_init) (&uwsgi, pargs)) {
|
||||
uwsgi_log( "plugin initialization returned error\n");
|
||||
if (dlclose(plugin_handle)) {
|
||||
uwsgi_log( "unable to unload plugin\n");
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
}
|
||||
|
||||
plugin_request = dlsym(plugin_handle, "uwsgi_request");
|
||||
if (plugin_request) {
|
||||
uwsgi.shared->hooks[modifier] = plugin_request;
|
||||
plugin_after_request = dlsym(plugin_handle, "uwsgi_after_request");
|
||||
if (plugin_after_request) {
|
||||
uwsgi.shared->after_hooks[modifier] = plugin_after_request;
|
||||
}
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
}
|
||||
if (uwsgi_load_plugin(&uwsgi, modifier, plugin_name, pargs, 1)) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_MULTICAST
|
||||
@@ -638,6 +746,22 @@ PyObject *py_uwsgi_multicast(PyObject * self, PyObject * args) {
|
||||
}
|
||||
#endif
|
||||
|
||||
PyObject *py_uwsgi_has_hook(PyObject * self, PyObject * args) {
|
||||
int modifier1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i:has_hook", &modifier1)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uwsgi.shared->hooks[modifier1] != unconfigured_hook) {
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_send_message(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *arg_message = NULL;
|
||||
@@ -829,10 +953,28 @@ PyObject *py_uwsgi_worker_id(PyObject * self, PyObject * args) {
|
||||
return PyInt_FromLong(uwsgi.mywid);
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_disconnect(PyObject * self, PyObject * args) {
|
||||
uwsgi_log( "detaching uWSGI from current connection...\n");
|
||||
PyObject *py_uwsgi_logsize(PyObject * self, PyObject * args) {
|
||||
return PyInt_FromLong(uwsgi.shared->logsize);
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_mem(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *ml = PyTuple_New(2);
|
||||
|
||||
get_memusage();
|
||||
|
||||
PyTuple_SetItem(ml, 0, PyLong_FromLong(uwsgi.workers[uwsgi.mywid].rss_size));
|
||||
PyTuple_SetItem(ml, 1, PyLong_FromLong(uwsgi.workers[uwsgi.mywid].vsz_size));
|
||||
|
||||
return ml;
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_disconnect(PyObject * self, PyObject * args) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
|
||||
|
||||
uwsgi_log( "disconnecting worker %d (pid :%d) from session...\n", uwsgi.mywid, uwsgi.mypid);
|
||||
|
||||
fclose(wsgi_req->async_post);
|
||||
wsgi_req->fd_closed = 1 ;
|
||||
@@ -841,10 +983,161 @@ PyObject *py_uwsgi_disconnect(PyObject * self, PyObject * args) {
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_parse_file(PyObject * self, PyObject * args) {
|
||||
|
||||
char *filename;
|
||||
int fd;
|
||||
ssize_t len;
|
||||
char *buffer, *ptrbuf, *bufferend, *keybuf;
|
||||
uint16_t strsize = 0, keysize = 0;
|
||||
|
||||
struct uwsgi_header uh;
|
||||
PyObject *zero;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s:parsefile", &filename)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error("open()");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
len = read(fd, &uh, 4);
|
||||
if (len != 4) {
|
||||
uwsgi_error("read()");
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
buffer = malloc(uh.pktsize);
|
||||
if (!buffer) {
|
||||
uwsgi_error("malloc()");
|
||||
goto clear2;
|
||||
}
|
||||
len = read(fd, buffer, uh.pktsize);
|
||||
if (len != uh.pktsize) {
|
||||
uwsgi_error("read()");
|
||||
free(buffer);
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
ptrbuf = buffer ;
|
||||
bufferend = ptrbuf + uh.pktsize ;
|
||||
|
||||
if (!uh.modifier1 || uh.modifier1 == UWSGI_MODIFIER_SPOOL_REQUEST) {
|
||||
zero = PyDict_New();
|
||||
|
||||
while (ptrbuf < bufferend) {
|
||||
if (ptrbuf + 2 < bufferend) {
|
||||
memcpy(&strsize, ptrbuf, 2);
|
||||
#ifdef __BIG_ENDIAN__
|
||||
strsize = uwsgi_swap16(strsize);
|
||||
#endif
|
||||
/* key cannot be null */
|
||||
if (!strsize) {
|
||||
uwsgi_log( "uwsgi key cannot be null.\n");
|
||||
goto clear3;
|
||||
}
|
||||
|
||||
ptrbuf += 2;
|
||||
if (ptrbuf + strsize < bufferend) {
|
||||
// var key
|
||||
keybuf = ptrbuf;
|
||||
keysize = strsize;
|
||||
ptrbuf += strsize;
|
||||
// value can be null (even at the end) so use <=
|
||||
if (ptrbuf + 2 <= bufferend) {
|
||||
memcpy(&strsize, ptrbuf, 2);
|
||||
#ifdef __BIG_ENDIAN__
|
||||
strsize = uwsgi_swap16(strsize);
|
||||
#endif
|
||||
ptrbuf += 2;
|
||||
if (ptrbuf + strsize <= bufferend) {
|
||||
PyDict_SetItem(zero, PyString_FromStringAndSize( keybuf, keysize ), PyString_FromStringAndSize( ptrbuf, strsize ));
|
||||
ptrbuf += strsize;
|
||||
}
|
||||
else {
|
||||
goto clear3;
|
||||
}
|
||||
}
|
||||
else {
|
||||
goto clear3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
goto clear3;
|
||||
}
|
||||
}
|
||||
|
||||
return zero;
|
||||
|
||||
}
|
||||
|
||||
goto clear;
|
||||
|
||||
clear3:
|
||||
Py_DECREF(zero);
|
||||
clear2:
|
||||
close(fd);
|
||||
clear:
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_grunt(PyObject * self, PyObject * args) {
|
||||
|
||||
pid_t grunt_pid ;
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
|
||||
|
||||
if (uwsgi.grunt) {
|
||||
uwsgi_log( "spawning a grunt from worker %d (pid :%d)...\n", uwsgi.mywid, uwsgi.mypid);
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "grunt support is disabled !!!\n" );
|
||||
goto clear;
|
||||
}
|
||||
|
||||
grunt_pid = fork();
|
||||
if (grunt_pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
goto clear;
|
||||
}
|
||||
else if (grunt_pid == 0) {
|
||||
close(uwsgi.serverfd);
|
||||
// create a new session
|
||||
setsid();
|
||||
// exit on SIGPIPE
|
||||
signal(SIGPIPE, (void *) &end_me);
|
||||
uwsgi.mywid = uwsgi.numproc + 1;
|
||||
uwsgi.mypid = getpid();
|
||||
memset(&uwsgi.workers[uwsgi.mywid], 0, sizeof(struct uwsgi_worker));
|
||||
// this is pratically useless...
|
||||
uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
|
||||
// this field will be overwrite after each call
|
||||
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
|
||||
// take the gil to support threads in grunt (is this useful ?)
|
||||
uwsgi.workers[uwsgi.mywid].i_have_gil = 1;
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
// close connection on the worker
|
||||
fclose(wsgi_req->async_post);
|
||||
wsgi_req->fd_closed = 1 ;
|
||||
|
||||
clear:
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
static PyMethodDef uwsgi_spooler_methods[] = {
|
||||
{"send_to_spooler", py_uwsgi_send_spool, METH_VARARGS, ""},
|
||||
{"set_spooler_frequency", py_uwsgi_spooler_freq, METH_VARARGS, ""},
|
||||
{"spooler_jobs", py_uwsgi_spooler_jobs, METH_VARARGS, ""},
|
||||
{NULL, NULL},
|
||||
};
|
||||
#endif
|
||||
@@ -865,16 +1158,25 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
{"worker_id", py_uwsgi_worker_id, METH_VARARGS, ""},
|
||||
{"log", py_uwsgi_log, METH_VARARGS, ""},
|
||||
{"disconnect", py_uwsgi_disconnect, METH_VARARGS, ""},
|
||||
{"grunt", py_uwsgi_grunt, METH_VARARGS, ""},
|
||||
{"load_plugin", py_uwsgi_load_plugin, METH_VARARGS, ""},
|
||||
{"lock", py_uwsgi_lock, METH_VARARGS, ""},
|
||||
{"unlock", py_uwsgi_unlock, METH_VARARGS, ""},
|
||||
{"send", py_uwsgi_send, METH_VARARGS, ""},
|
||||
#ifdef UWSGI_SENDFILE
|
||||
{"sendfile", py_uwsgi_advanced_sendfile, METH_VARARGS, ""},
|
||||
#endif
|
||||
{"set_warning_message", py_uwsgi_warning, METH_VARARGS, ""},
|
||||
{"mem", py_uwsgi_mem, METH_VARARGS, ""},
|
||||
{"has_hook", py_uwsgi_has_hook, METH_VARARGS, ""},
|
||||
{"logsize", py_uwsgi_logsize, METH_VARARGS, ""},
|
||||
#ifdef UWSGI_MULTICAST
|
||||
{"send_multicast_message", py_uwsgi_multicast, METH_VARARGS, ""},
|
||||
#endif
|
||||
#ifdef UWSGI_ASYNC
|
||||
{"async_sleep", py_uwsgi_async_sleep, METH_VARARGS, ""},
|
||||
#endif
|
||||
{"parsefile", py_uwsgi_parse_file, METH_VARARGS, ""},
|
||||
//{"call_hook", py_uwsgi_call_hook, METH_VARARGS, ""},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
+251
-52
@@ -1,6 +1,7 @@
|
||||
# uWSGI configuration
|
||||
|
||||
XML=True
|
||||
INI=True
|
||||
SNMP=True
|
||||
SCTP=False
|
||||
ERLANG=False
|
||||
@@ -10,17 +11,28 @@ UDP=True
|
||||
MULTICAST=True
|
||||
THREADING=True
|
||||
SENDFILE=True
|
||||
PROFILER=True
|
||||
PROFILER=False
|
||||
NAGIOS=True
|
||||
PROXY=True
|
||||
PASTE=True
|
||||
MINTERPRETERS=True
|
||||
ASYNC=True
|
||||
UGREEN=True
|
||||
UGREEN=False
|
||||
HTTP=True
|
||||
EVDIS=False
|
||||
LDAP=False
|
||||
WSGI2=False
|
||||
ROUTING=False
|
||||
STACKLESS=False
|
||||
#PLUGINS = ['psgi']
|
||||
PLUGINS = []
|
||||
USWALLOW=False
|
||||
UNBIT=False
|
||||
DEBUG=False
|
||||
EMBED_PLUGINS=True
|
||||
UWSGI_BIN_NAME = 'uwsgi'
|
||||
GCC='gcc'
|
||||
UWSGI_PLUGIN_DIR = '.'
|
||||
|
||||
|
||||
# specific compilation flags
|
||||
# libxml2 or expat
|
||||
@@ -40,23 +52,67 @@ ERLANG_LDFLAGS = '-lerl_interface -lei'
|
||||
|
||||
import os
|
||||
uwsgi_os = os.uname()[0]
|
||||
uwsgi_cpu = os.uname()[4]
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
from distutils import sysconfig
|
||||
|
||||
gcc_list = ['utils', 'pyutils', 'protocol', 'socket', 'logging', 'wsgi_handlers', 'wsgi_headers', 'uwsgi_handlers', 'uwsgi']
|
||||
GCC = os.environ.get('CC', sysconfig.get_config_var('CC'))
|
||||
if not GCC:
|
||||
GCC = 'gcc'
|
||||
|
||||
# large file support
|
||||
try:
|
||||
cflags = ['-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + sysconfig.get_config_var('CFLAGS').split()
|
||||
except:
|
||||
print("You need python headers to build uWSGI.")
|
||||
sys.exit(1)
|
||||
|
||||
def spcall(cmd):
|
||||
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
|
||||
|
||||
if p.wait() == 0:
|
||||
if sys.version_info[0] > 2:
|
||||
return p.stdout.read().rstrip().decode()
|
||||
return p.stdout.read().rstrip()
|
||||
else:
|
||||
return None
|
||||
|
||||
def spcall2(cmd):
|
||||
p = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)
|
||||
|
||||
if p.wait() == 0:
|
||||
if sys.version_info[0] > 2:
|
||||
return p.stderr.read().rstrip().decode()
|
||||
return p.stderr.read().rstrip()
|
||||
else:
|
||||
return None
|
||||
|
||||
gcc_version = str(spcall2("%s -v" % GCC)).split('\n')[-1].split()[2]
|
||||
|
||||
gcc_major = int(gcc_version.split('.')[0])
|
||||
gcc_minor = int(gcc_version.split('.')[1])
|
||||
|
||||
|
||||
gcc_list = ['utils', 'pyutils', 'protocol', 'socket', 'logging', 'wsgi_handlers', 'wsgi_headers', 'uwsgi_handlers', 'plugins', 'uwsgi']
|
||||
|
||||
cflags = ['-O2', '-Wall', '-Werror', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + os.environ.get("CFLAGS", "").split()
|
||||
|
||||
# add -fno-strict-aliasing only on python2 and gcc < 4.3
|
||||
if (sys.version_info[0] == 2) or (gcc_major < 4) or (gcc_major == 4 and gcc_minor < 3):
|
||||
cflags = cflags + ['-fno-strict-aliasing']
|
||||
|
||||
if gcc_major >= 4:
|
||||
cflags = cflags + [ '-Wextra', '-Wno-unused-parameter', '-Wno-missing-field-initializers' ]
|
||||
|
||||
cflags = cflags + ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ]
|
||||
ldflags = ['-lpthread', '-rdynamic'] + sysconfig.get_config_var('LIBS').split() + sysconfig.get_config_var('SYSLIBS').split()
|
||||
|
||||
ldflags = os.environ.get("LDFLAGS", "").split()
|
||||
libs = ['-lpthread', '-rdynamic'] + sysconfig.get_config_var('LIBS').split() + sysconfig.get_config_var('SYSLIBS').split()
|
||||
if not sysconfig.get_config_var('Py_ENABLE_SHARED'):
|
||||
libs.append('-L' + sysconfig.get_config_var('LIBPL'))
|
||||
|
||||
|
||||
if USWALLOW:
|
||||
cflags = cflags + sysconfig.get_config_var('LLVM_CXXFLAGS').split()
|
||||
ldflags = ldflags + sysconfig.get_config_var('LLVM_LDFLAGS').split() + sysconfig.get_config_var('LINKFORSHARED').split()
|
||||
GCC = 'clang'
|
||||
|
||||
def depends_on(what, dep):
|
||||
for d in dep:
|
||||
@@ -64,13 +120,6 @@ def depends_on(what, dep):
|
||||
print("%s needs %s support." % (what, d))
|
||||
sys.exit(1)
|
||||
|
||||
def spcall(cmd):
|
||||
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
|
||||
|
||||
if p.wait() == 0:
|
||||
return p.stdout.read().rstrip().decode()
|
||||
else:
|
||||
return None
|
||||
|
||||
def add_o(x):
|
||||
if x == 'uwsgi':
|
||||
@@ -92,12 +141,13 @@ def build_uwsgi(bin_name):
|
||||
sys.exit(1)
|
||||
|
||||
if len(PLUGINS) > 0:
|
||||
print("*** uWSGI embedding plugin ***")
|
||||
print("*** uWSGI building plugins ***")
|
||||
for plugin in PLUGINS:
|
||||
print(plugin)
|
||||
print("*** building plugin: %s ***" % plugin)
|
||||
build_plugin("plugins/%s" % plugin)
|
||||
|
||||
print("*** uWSGI linking ***")
|
||||
ldline = "%s -o %s %s %s" % (GCC, bin_name, ' '.join(map(add_o, gcc_list)), ' '.join(ldflags))
|
||||
ldline = "%s -o %s %s %s %s" % (GCC, bin_name, ' '.join(ldflags), ' '.join(map(add_o, gcc_list)), ' '.join(libs))
|
||||
print(ldline)
|
||||
ret = os.system(ldline)
|
||||
if ret != 0:
|
||||
@@ -109,55 +159,136 @@ def build_uwsgi(bin_name):
|
||||
print("*** uWSGI is ready, launch it with %s ***" % bin_name)
|
||||
|
||||
def unbit_setup():
|
||||
global XML, SNMP, SCTP, ERLANG, SPOOLER
|
||||
global EMBEDDED, UDP, MULTICAST, THREADING
|
||||
global SENDFILE, PROFILER, NAGIOS, PROXY
|
||||
|
||||
global UWSGI_BIN_NAME
|
||||
global XML
|
||||
XML=True
|
||||
|
||||
XML=False
|
||||
global INI
|
||||
INI=False
|
||||
|
||||
global SNMP
|
||||
SNMP=False
|
||||
|
||||
global SCTP
|
||||
SCTP=False
|
||||
|
||||
global ERLANG
|
||||
ERLANG=False
|
||||
|
||||
global SPOOLER
|
||||
SPOOLER=True
|
||||
|
||||
global EMBEDDED
|
||||
EMBEDDED=True
|
||||
|
||||
global UDP
|
||||
UDP=False
|
||||
|
||||
global MULTICAST
|
||||
MULTICAST=False
|
||||
|
||||
global THREADING
|
||||
THREADING=False
|
||||
|
||||
global SENDFILE
|
||||
SENDFILE=True
|
||||
|
||||
global PROFILER
|
||||
PROFILER=False
|
||||
|
||||
global NAGIOS
|
||||
NAGIOS=False
|
||||
|
||||
global PROXY
|
||||
PROXY=False
|
||||
|
||||
EMBEDDED=True
|
||||
SPOOLER=True
|
||||
THREADING=True
|
||||
SENDFILE=True
|
||||
PROFILER=True
|
||||
global PASTE
|
||||
PASTE=False
|
||||
|
||||
global MINTERPRETERS
|
||||
MINTERPRETERS=False
|
||||
|
||||
global ASYNC
|
||||
ASYNC=False
|
||||
|
||||
global UGREEN
|
||||
UGREEN=False
|
||||
|
||||
global HTTP
|
||||
HTTP=False
|
||||
|
||||
global EVDIS
|
||||
EVDIS=False
|
||||
|
||||
global WSGI2
|
||||
WSGI2=False
|
||||
|
||||
global LDAP
|
||||
LDAP=False
|
||||
|
||||
global ROUTING
|
||||
ROUTING=False
|
||||
|
||||
global STACKLESS
|
||||
STACKLESS=False
|
||||
|
||||
global PLUGINS
|
||||
#PLUGINS = ['psgi']
|
||||
PLUGINS = []
|
||||
|
||||
global USWALLOW
|
||||
USWALLOW=False
|
||||
|
||||
global UNBIT
|
||||
UNBIT=True
|
||||
UWSGI_BIN_NAME='/usr/share/unbit/uwsgi26'
|
||||
|
||||
global DEBUG
|
||||
DEBUG=False
|
||||
|
||||
global EMBED_PLUGINS
|
||||
EMBED_PLUGINS=True
|
||||
|
||||
global UWSGI_BIN_NAME
|
||||
UWSGI_BIN_NAME = '../bin/uwsgi'
|
||||
|
||||
global UWSGI_PLUGIN_DIR
|
||||
UWSGI_PLUGIN_DIR = '../bin'
|
||||
|
||||
global PYLIB_PATH
|
||||
PYLIB_PATH = '/proc/unbit/opt/python26/lib'
|
||||
|
||||
def parse_vars():
|
||||
|
||||
global UGREEN
|
||||
global UGREEN, ASYNC, PROXY
|
||||
|
||||
version = sys.version_info
|
||||
uver = "%d.%d" % (version[0], version[1])
|
||||
|
||||
ldflags.append('-lpython' + uver)
|
||||
libs.append('-lpython' + uver)
|
||||
|
||||
if str(PYLIB_PATH) != '':
|
||||
ldflags.insert(0,'-L' + PYLIB_PATH)
|
||||
libs.insert(0,'-L' + PYLIB_PATH)
|
||||
os.environ['LD_RUN_PATH'] = PYLIB_PATH
|
||||
|
||||
kvm_list = ['FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly']
|
||||
|
||||
if uwsgi_os == 'SunOS':
|
||||
ldflags.append('-lsendfile')
|
||||
ldflags.remove('-rdynamic')
|
||||
libs.append('-lsendfile')
|
||||
libs.remove('-rdynamic')
|
||||
|
||||
if uwsgi_os in kvm_list:
|
||||
ldflags.append('-lkvm')
|
||||
libs.append('-lkvm')
|
||||
|
||||
if uwsgi_os == 'OpenBSD':
|
||||
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm' or uwsgi_os == 'Haiku':
|
||||
UGREEN = False
|
||||
|
||||
if uwsgi_os == 'Haiku':
|
||||
ASYNC = False
|
||||
PROXY = False
|
||||
libs.remove('-rdynamic')
|
||||
libs.remove('-lpthread')
|
||||
libs.append('-lroot')
|
||||
|
||||
if EMBEDDED:
|
||||
cflags.append('-DUWSGI_EMBEDDED')
|
||||
gcc_list.append('uwsgi_pymodule')
|
||||
@@ -187,11 +318,50 @@ def parse_vars():
|
||||
cflags.append("-DUWSGI_NAGIOS")
|
||||
gcc_list.append('nagios')
|
||||
|
||||
if INI:
|
||||
cflags.append("-DUWSGI_INI")
|
||||
gcc_list.append('ini')
|
||||
|
||||
if DEBUG:
|
||||
cflags.append("-DUWSGI_DEBUG")
|
||||
|
||||
if PROXY:
|
||||
depends_on("PROXY", ['ASYNC'])
|
||||
cflags.append("-DUWSGI_PROXY")
|
||||
gcc_list.append('proxy')
|
||||
|
||||
if LDAP:
|
||||
cflags.append("-DUWSGI_LDAP")
|
||||
gcc_list.append('ldap')
|
||||
libs.append('-lldap')
|
||||
|
||||
if ROUTING:
|
||||
depends_on("ROUTING", ['WSGI2', 'XML'])
|
||||
cflags.append("-DUWSGI_ROUTING")
|
||||
gcc_list.append('routing')
|
||||
pcreconf = spcall("pcre-config --cflags")
|
||||
if pcreconf is None:
|
||||
print ("*** Unable to locate pcre-config. The uWSGI build has been interrupted. You have to install pcre.")
|
||||
sys.exit(1)
|
||||
else:
|
||||
cflags.append(pcreconf)
|
||||
|
||||
pcreconf = spcall("pcre-config --libs")
|
||||
if pcreconf is None:
|
||||
print ("*** Unable to locate pcre-config. The uWSGI build has been interrupted. You have to install pcre.")
|
||||
sys.exit(1)
|
||||
else:
|
||||
libs.append(pcreconf)
|
||||
|
||||
if HTTP:
|
||||
cflags.append("-DUWSGI_HTTP")
|
||||
gcc_list.append('http')
|
||||
|
||||
if EVDIS:
|
||||
cflags.append("-DUWSGI_EVDIS")
|
||||
gcc_list.append('evdis')
|
||||
|
||||
|
||||
if UGREEN:
|
||||
if uwsgi_os == 'Darwin':
|
||||
cflags.append("-D_XOPEN_SOURCE")
|
||||
@@ -210,6 +380,9 @@ def parse_vars():
|
||||
if PROFILER:
|
||||
cflags.append("-DUWSGI_PROFILER")
|
||||
|
||||
if PASTE:
|
||||
cflags.append('-DUWSGI_PASTE')
|
||||
|
||||
if SENDFILE:
|
||||
cflags.append("-DUWSGI_SENDFILE")
|
||||
gcc_list.append('sendfile')
|
||||
@@ -221,7 +394,7 @@ def parse_vars():
|
||||
print("*** libxml2 headers unavailable. uWSGI build is interrupted. You have to install libxml2 development package or use libexpat or disable XML")
|
||||
sys.exit(1)
|
||||
else:
|
||||
ldflags.append(xmlconf)
|
||||
libs.append(xmlconf)
|
||||
xmlconf = spcall("xml2-config --cflags")
|
||||
if xmlconf is None:
|
||||
print("*** libxml2 headers unavailable. uWSGI build is interrupted. You have to install libxml2 development package or use libexpat or disable XML")
|
||||
@@ -232,29 +405,44 @@ def parse_vars():
|
||||
gcc_list.append('xmlconf')
|
||||
elif XML_IMPLEMENTATION == 'expat':
|
||||
cflags.append("-DUWSGI_XML -DUWSGI_XML_EXPAT")
|
||||
ldflags.append('-lexpat')
|
||||
libs.append('-lexpat')
|
||||
gcc_list.append('xmlconf')
|
||||
|
||||
|
||||
if ERLANG:
|
||||
depends_on("ERLANG", ['EMBEDDED'])
|
||||
cflags.append("-DUWSGI_ERLANG")
|
||||
ldflags.append(ERLANG_LDFLAGS)
|
||||
libs.append(ERLANG_LDFLAGS)
|
||||
if str(ERLANG_CFLAGS) != '':
|
||||
cflags.append(ERLANG_CFLAGS)
|
||||
gcc_list.append('erlang')
|
||||
|
||||
if UWSGI_PLUGIN_DIR is not None:
|
||||
cflags.append("-DUWSGI_PLUGIN_DIR=\\\"%s\\\"" % UWSGI_PLUGIN_DIR)
|
||||
|
||||
if len(PLUGINS) > 0 and EMBED_PLUGINS:
|
||||
cflags.append("-DUWSGI_EMBED_PLUGINS")
|
||||
for plugin in PLUGINS:
|
||||
cflags.append("-DUWSGI_EMBED_PLUGIN_%s" % plugin.upper())
|
||||
|
||||
if SCTP:
|
||||
ldflags.append("-lsctp")
|
||||
cflags.append("-DUWSGI_SCTP")
|
||||
libs.append("-lsctp")
|
||||
cflags.append("-DUWSGI_SCTP")
|
||||
|
||||
if SPOOLER:
|
||||
depends_on("SPOOLER", ['EMBEDDED'])
|
||||
cflags.append("-DUWSGI_SPOOLER")
|
||||
gcc_list.append('spooler')
|
||||
|
||||
if WSGI2:
|
||||
cflags.append("-DUWSGI_WSGI2")
|
||||
|
||||
if DEBUG:
|
||||
cflags.append("-DUWSGI_DEBUG")
|
||||
cflags.append("-g")
|
||||
|
||||
if UNBIT:
|
||||
cflags.append("-DUWSGI_UNBIT")
|
||||
cflags.append("-DUNBIT")
|
||||
|
||||
def build_plugin(path):
|
||||
path = path.rstrip('/')
|
||||
@@ -262,14 +450,23 @@ def build_plugin(path):
|
||||
sys.path.insert(0, path)
|
||||
import uwsgiplugin as up
|
||||
|
||||
cflags.append(up.CFLAGS)
|
||||
ldflags.append(up.LDFLAGS)
|
||||
p_cflags = cflags[:]
|
||||
p_ldflags = ldflags[:]
|
||||
|
||||
cflags.insert(0, '-I.')
|
||||
p_cflags.append(up.CFLAGS)
|
||||
p_ldflags.append(up.LDFLAGS)
|
||||
|
||||
p_cflags.insert(0, '-I.')
|
||||
|
||||
plugin_base = path + '/' + up.NAME + '_plugin'
|
||||
plugin_dest = UWSGI_PLUGIN_DIR + '/' + up.NAME + '_plugin'
|
||||
|
||||
gccline = "%s -fPIC -shared -o %s.so %s %s.c %s" % (GCC, plugin_base, ' '.join(cflags), plugin_base, ' '.join(ldflags))
|
||||
shared_flag = '-shared'
|
||||
|
||||
if uwsgi_os == 'Darwin':
|
||||
shared_flag = '-dynamiclib -undefined dynamic_lookup'
|
||||
|
||||
gccline = "%s -fPIC %s -o %s.so %s %s %s.c" % (GCC, shared_flag, plugin_dest, ' '.join(p_cflags), ' '.join(p_ldflags), plugin_base )
|
||||
print(gccline)
|
||||
|
||||
ret = os.system(gccline)
|
||||
@@ -277,7 +474,7 @@ def build_plugin(path):
|
||||
print("*** unable to build %s plugin ***" % up.NAME)
|
||||
sys.exit(1)
|
||||
|
||||
print("*** %s plugin built and available in %s ***" % (up.NAME, plugin_base + '.so'))
|
||||
print("*** %s plugin built and available in %s ***" % (up.NAME, plugin_dest + '.so'))
|
||||
|
||||
|
||||
|
||||
@@ -294,9 +491,11 @@ if __name__ == "__main__":
|
||||
sys.exit(1)
|
||||
|
||||
if cmd == '--cflags':
|
||||
print(' '.join(cflags))
|
||||
print(' '.join(cflags))
|
||||
if cmd == '--ldflags':
|
||||
print(' '.join(ldflags))
|
||||
print(' '.join(ldflags))
|
||||
if cmd == '--libs':
|
||||
print(' '.join(libs))
|
||||
elif cmd == '--build':
|
||||
parse_vars()
|
||||
build_uwsgi(UWSGI_BIN_NAME)
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import uwsgi
|
||||
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
def application(env, start_response):
|
||||
print env
|
||||
start_response('200 OK', [('Content-Type', 'text/html')])
|
||||
|
||||
yield '<h1>uWSGI %s status</h1>' % uwsgi.version
|
||||
yield 'masterpid: <b>' + str(uwsgi.masterpid()) + '</b><br/>'
|
||||
|
||||
yield 'started on: <b>' + time.ctime(uwsgi.started_on) + '</b><br/>'
|
||||
|
||||
yield 'buffer size: <b>' + str(uwsgi.buffer_size) + '</b><br/>'
|
||||
|
||||
yield 'total_requests: <b>' + str(uwsgi.total_requests()) + '</b><br/>'
|
||||
|
||||
yield 'log size: <b>' + str(uwsgi.logsize()) + '</b><br/>'
|
||||
|
||||
yield 'workers: <b>' + str(uwsgi.numproc) + '</b><br/>'
|
||||
|
||||
yield "cwd: <b>%s</b><br/>" % os.getcwd()
|
||||
|
||||
try:
|
||||
yield "mode: <b>%s</b><br/>" % uwsgi.mode
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
yield "pidfile: <b>%s</b><br/>" % uwsgi.pidfile
|
||||
except:
|
||||
pass
|
||||
|
||||
yield "<h2>Hooks</h2>"
|
||||
|
||||
for h in range(0,255):
|
||||
if uwsgi.has_hook(h):
|
||||
yield "%d<br/>" % h
|
||||
|
||||
yield '<h2>dynamic options</h2>'
|
||||
|
||||
yield '<b>logging</b>: ' + str(uwsgi.get_option(0)) + '<br/>'
|
||||
yield '<b>max_requests</b>: ' + str(uwsgi.getoption(1)) + '<br/>'
|
||||
yield '<b>socket_timeout</b>: ' + str(uwsgi.getoption(2)) + '<br/>'
|
||||
yield '<b>memory_debug</b>: ' + str(uwsgi.getoption(3)) + '<br/>'
|
||||
yield '<b>master_interval</b>: ' + str(uwsgi.getoption(4)) + '<br/>'
|
||||
yield '<b>harakiri</b>: ' + str(uwsgi.getoption(5)) + '<br/>'
|
||||
yield '<b>cgi_mode</b>: ' + str(uwsgi.get_option(6)) + '<br/>'
|
||||
yield '<b>threads</b>: ' + str(uwsgi.get_option(7)) + '<br/>'
|
||||
yield '<b>process_reaper</b>: ' + str(uwsgi.get_option(8)) + '<br/>'
|
||||
|
||||
yield '<table border="1">'
|
||||
yield '<th>worker id</th><th>pid</th><th>in request</th><th>requests</th><th>running time</th><th>address space</th><th>rss</th>'
|
||||
|
||||
workers = uwsgi.workers();
|
||||
|
||||
yield '<h2>workers</h2>'
|
||||
|
||||
for w in workers:
|
||||
#print w
|
||||
#print w['running_time']
|
||||
if w is not None:
|
||||
yield '<tr><td>'+ str(w['id']) +'</td><td>' + str(w['pid']) + '</td><td>' + str(w['pid']) + '</td><td>' + str(w['requests']) + '</td><td>' + str(w['running_time']) + '</td><td>' + str(w['vsz']) + '</td><td>' + str(w['rss']) + '</td></tr>'
|
||||
print w
|
||||
|
||||
yield '</table>'
|
||||
|
||||
yield "<h2>PYTHONPATH</h2>"
|
||||
|
||||
yield "<ul>"
|
||||
for p in sys.path:
|
||||
yield "<li>%s</li>" % p
|
||||
|
||||
yield "</ul>"
|
||||
|
||||
yield "<i>%s</i>" % str(os.uname())
|
||||
+158
-23
@@ -73,14 +73,24 @@ PyObject *py_eventfd_write(PyObject * self, PyObject * args) {
|
||||
int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
|
||||
|
||||
int i;
|
||||
|
||||
size_t post_remains = wsgi_req->post_cl;
|
||||
ssize_t post_chunk;
|
||||
|
||||
PyObject *zero, *wsgi_socket;
|
||||
|
||||
PyObject *pydictkey, *pydictvalue;
|
||||
|
||||
static PyObject *uwsgi_version = NULL;
|
||||
|
||||
char *path_info;
|
||||
struct uwsgi_app *wi ;
|
||||
|
||||
int tmp_stderr;
|
||||
|
||||
if (uwsgi_version == NULL) {
|
||||
uwsgi_version = PyString_FromString(UWSGI_VERSION);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (wsgi_req->async_status == UWSGI_AGAIN) {
|
||||
@@ -107,6 +117,13 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi->limit_post) {
|
||||
if (wsgi_req->post_cl > uwsgi->limit_post) {
|
||||
uwsgi_log("Invalid (too big) CONTENT_LENGTH. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_THREADING
|
||||
if (uwsgi->has_threads && !uwsgi->workers[uwsgi->mywid].i_have_gil) {
|
||||
@@ -115,30 +132,56 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!uwsgi->ignore_script_name) {
|
||||
|
||||
if (!wsgi_req->script_name)
|
||||
wsgi_req->script_name = "";
|
||||
|
||||
if (uwsgi->vhost) {
|
||||
zero = PyString_FromStringAndSize(wsgi_req->host, wsgi_req->host_len);
|
||||
#ifdef PYTHREE
|
||||
zero = PyString_Concat(zero, PyString_FromString("|"));
|
||||
zero = PyString_Concat(zero, PyString_FromStringAndSize(wsgi_req->script_name, wsgi_req->script_name_len));
|
||||
#else
|
||||
PyString_Concat(&zero, PyString_FromString("|"));
|
||||
PyString_Concat(&zero, PyString_FromStringAndSize(wsgi_req->script_name, wsgi_req->script_name_len));
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("VirtualHost SCRIPT_NAME=%s\n", PyString_AsString(zero));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
zero = PyString_FromStringAndSize(wsgi_req->script_name, wsgi_req->script_name_len);
|
||||
}
|
||||
|
||||
|
||||
if (wsgi_req->script_name_len > 0) {
|
||||
zero = PyString_FromStringAndSize(wsgi_req->script_name, wsgi_req->script_name_len);
|
||||
if (PyDict_Contains(uwsgi->py_apps, zero)) {
|
||||
wsgi_req->app_id = PyInt_AsLong(PyDict_GetItem(uwsgi->py_apps, zero));
|
||||
}
|
||||
else {
|
||||
/* unavailable app for this SCRIPT_NAME */
|
||||
wsgi_req->app_id = -1;
|
||||
wsgi_req->app_id = PyInt_AsLong(PyDict_GetItem(uwsgi->py_apps, zero));
|
||||
}
|
||||
else if (wsgi_req->script_name_len > 1 || uwsgi->default_app < 0 || uwsgi->vhost) {
|
||||
/* unavailable app for this SCRIPT_NAME */
|
||||
wsgi_req->app_id = -1;
|
||||
if (wsgi_req->wsgi_script_len > 0 || (wsgi_req->wsgi_callable_len > 0 && wsgi_req->wsgi_module_len > 0)) {
|
||||
if ((wsgi_req->app_id = init_uwsgi_app(NULL, NULL)) == -1) {
|
||||
internal_server_error(wsgi_req->poll.fd, "wsgi application not found");
|
||||
Py_DECREF(zero);
|
||||
goto clear2;
|
||||
}
|
||||
wsgi_req->app_id = init_uwsgi_app(NULL, NULL);
|
||||
}
|
||||
}
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
}
|
||||
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
else {
|
||||
wsgi_req->app_id = 0;
|
||||
}
|
||||
|
||||
|
||||
if (wsgi_req->app_id == -1) {
|
||||
internal_server_error(wsgi_req->poll.fd, "wsgi application not found");
|
||||
goto clear2;
|
||||
// use default app ?
|
||||
if (!uwsgi->no_default_app && uwsgi->default_app >= 0) {
|
||||
wsgi_req->app_id = uwsgi->default_app ;
|
||||
}
|
||||
else {
|
||||
internal_server_error(wsgi_req->poll.fd, "wsgi application not found");
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -152,19 +195,27 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
|
||||
|
||||
// set the interpreter
|
||||
PyThreadState_Swap(wi->interpreter);
|
||||
if (wi->chdir) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("chdir to %s\n", wi->chdir);
|
||||
#endif
|
||||
if (chdir(wi->chdir)) {
|
||||
uwsgi_error("chdir()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wi->requests++;
|
||||
|
||||
|
||||
if (wsgi_req->protocol_len < 5) {
|
||||
uwsgi_log( "INVALID PROTOCOL: %.*s", wsgi_req->protocol_len, wsgi_req->protocol);
|
||||
uwsgi_log( "INVALID PROTOCOL: %.*s\n", wsgi_req->protocol_len, wsgi_req->protocol);
|
||||
internal_server_error(wsgi_req->poll.fd, "invalid HTTP protocol !!!");
|
||||
goto clear;
|
||||
|
||||
}
|
||||
if (strncmp(wsgi_req->protocol, "HTTP/", 5)) {
|
||||
uwsgi_log( "INVALID PROTOCOL: %.*s", wsgi_req->protocol_len, wsgi_req->protocol);
|
||||
uwsgi_log( "INVALID PROTOCOL: %.*s\n", wsgi_req->protocol_len, wsgi_req->protocol);
|
||||
internal_server_error(wsgi_req->poll.fd, "invalid HTTP protocol !!!");
|
||||
goto clear;
|
||||
}
|
||||
@@ -183,7 +234,11 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
|
||||
|
||||
|
||||
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
|
||||
//uwsgi_log("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
|
||||
/*
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
|
||||
#endif
|
||||
*/
|
||||
pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
|
||||
pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
|
||||
PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
|
||||
@@ -212,7 +267,40 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
|
||||
|
||||
// set wsgi vars
|
||||
|
||||
wsgi_req->async_post = fdopen(wsgi_req->poll.fd, "r");
|
||||
|
||||
if (uwsgi->post_buffering > 0 && wsgi_req->post_cl > (size_t) uwsgi->post_buffering) {
|
||||
wsgi_req->async_post = tmpfile();
|
||||
if (!wsgi_req->async_post) {
|
||||
uwsgi_error("tmpfile()");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
|
||||
while(post_remains > 0) {
|
||||
if (uwsgi->shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
inc_harakiri(uwsgi->shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
}
|
||||
if (post_remains > (size_t) uwsgi->post_buffering_bufsize) {
|
||||
post_chunk = read(wsgi_req->poll.fd, wsgi_req->post_buffering_buf, uwsgi->post_buffering_bufsize);
|
||||
}
|
||||
else {
|
||||
post_chunk = read(wsgi_req->poll.fd, wsgi_req->post_buffering_buf, post_remains);
|
||||
}
|
||||
if (post_chunk < 0) {
|
||||
uwsgi_error("read()");
|
||||
goto clear;
|
||||
}
|
||||
if (!fwrite(wsgi_req->post_buffering_buf, post_chunk, 1, wsgi_req->async_post)) {
|
||||
uwsgi_error("fwrite()");
|
||||
goto clear;
|
||||
}
|
||||
post_remains -= post_chunk;
|
||||
}
|
||||
rewind(wsgi_req->async_post);
|
||||
}
|
||||
else {
|
||||
wsgi_req->async_post = fdopen(wsgi_req->poll.fd, "r");
|
||||
}
|
||||
|
||||
wsgi_socket = PyFile_FromFile(wsgi_req->async_post, "wsgi_input", "r", NULL);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.input", wsgi_socket);
|
||||
@@ -267,11 +355,28 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.url_scheme", zero);
|
||||
Py_DECREF(zero);
|
||||
|
||||
|
||||
wsgi_req->async_app = wi->wsgi_callable ;
|
||||
|
||||
PyDict_SetItemString(uwsgi->embedded_dict, "env", wsgi_req->async_environ);
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.uwsgi.version", uwsgi_version);
|
||||
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
uwsgi_log("routing %d routes %d\n", uwsgi->routing, uwsgi->nroutes);
|
||||
if (uwsgi->routing && uwsgi->nroutes > 0) {
|
||||
check_route(uwsgi, wsgi_req);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// call
|
||||
|
||||
#ifdef UWSGI_PROFILER
|
||||
if (uwsgi->enable_profiler == 1) {
|
||||
PyDict_SetItem(wi->pymain_dict, PyString_FromFormat("uwsgi_environ__%d", wsgi_req->app_id), wsgi_req->async_environ);
|
||||
wsgi_req->async_result = python_call(wi->wsgi_cprofile_run, wsgi_req->async_args);
|
||||
wsgi_req->async_result = python_call(wi->wsgi_cprofile_run, wsgi_req->async_args, 0);
|
||||
if (wsgi_req->async_result) {
|
||||
wsgi_req->async_result = PyDict_GetItemString(wi->pymain_dict, "uwsgi_out");
|
||||
Py_INCREF((PyObject*)wsgi_req->async_result);
|
||||
@@ -283,7 +388,7 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
|
||||
|
||||
|
||||
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
|
||||
wsgi_req->async_result = python_call(wi->wsgi_callable, wsgi_req->async_args);
|
||||
wsgi_req->async_result = python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi->catch_exceptions);
|
||||
|
||||
#ifdef UWSGI_PROFILER
|
||||
}
|
||||
@@ -303,6 +408,36 @@ int uwsgi_request_wsgi(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req
|
||||
|
||||
|
||||
}
|
||||
else if (uwsgi->catch_exceptions) {
|
||||
|
||||
wsgi_req->response_size += write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len);
|
||||
wsgi_req->response_size += write(wsgi_req->poll.fd, " 500 Internal Server Error\r\n", 28 );
|
||||
wsgi_req->response_size += write(wsgi_req->poll.fd, "Content-type: text/plain\r\n\r\n", 28 );
|
||||
wsgi_req->header_cnt = 1 ;
|
||||
|
||||
/*
|
||||
sorry that is a hack to avoid the rewrite of PyErr_Print
|
||||
temporarily map (using dup2) stderr to wsgi_req->poll.fd
|
||||
*/
|
||||
tmp_stderr = dup(2);
|
||||
if (tmp_stderr < 0) {
|
||||
uwsgi_error("dup()");
|
||||
goto clear;
|
||||
}
|
||||
// map 2 to wsgi_req
|
||||
if (dup2(wsgi_req->poll.fd, 2) < 0) {
|
||||
close(tmp_stderr);
|
||||
uwsgi_error("dup2()");
|
||||
goto clear;
|
||||
}
|
||||
// print the error
|
||||
PyErr_Print();
|
||||
// ...resume the original stderr, in case of error we are damaged forever !!!
|
||||
if (dup2(tmp_stderr, 2) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
}
|
||||
close(tmp_stderr);
|
||||
}
|
||||
|
||||
clear:
|
||||
|
||||
|
||||
@@ -13,11 +13,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req(&uwsgi);
|
||||
|
||||
#ifndef UNBIT
|
||||
int base = 0;
|
||||
#else
|
||||
int base = 4;
|
||||
#endif
|
||||
|
||||
// use writev()
|
||||
|
||||
@@ -32,11 +28,8 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
|
||||
#ifndef UNBIT
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] == 0) {
|
||||
base = 4;
|
||||
#endif
|
||||
|
||||
|
||||
if (wsgi_req->protocol_len == 0) {
|
||||
wsgi_req->hvec[0].iov_base = (char *) http_protocol;
|
||||
@@ -59,7 +52,6 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
wsgi_req->status = atoi(wsgi_req->hvec[2].iov_base);
|
||||
wsgi_req->hvec[3].iov_base = nl;
|
||||
wsgi_req->hvec[3].iov_len = NL_SIZE;
|
||||
#ifndef UNBIT
|
||||
}
|
||||
else {
|
||||
// drop http status on cgi mode
|
||||
@@ -77,16 +69,6 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
wsgi_req->hvec[2].iov_base = nl;
|
||||
wsgi_req->hvec[2].iov_len = NL_SIZE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef UNBIT
|
||||
if (wsgi_req->unbit_flags & (unsigned long long) 1) {
|
||||
if (tmp_dir_fd >= 0 && tmp_filename[0] != 0 && wsgi_req->status == 200 && wsgi_req->method_len == 3 && wsgi_req->method[0] == 'G' && wsgi_req->method[1] == 'E' && wsgi_req->method[2] == 'T') {
|
||||
save_to_disk = openat(tmp_dir_fd, tmp_filename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
headers = PyTuple_GetItem(args, 1);
|
||||
|
||||
@@ -18,8 +18,23 @@ void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options
|
||||
|
||||
xmlChar *xml_uwsgi_mountpoint = NULL;
|
||||
xmlChar *xml_uwsgi_script = NULL;
|
||||
xmlChar *node_mode;
|
||||
struct option *lopt, *aopt;
|
||||
|
||||
char *colon ;
|
||||
|
||||
char *xml_id ;
|
||||
|
||||
colon = strchr(uwsgi.xml_config, ':');
|
||||
if (colon) {
|
||||
colon[0] = 0 ;
|
||||
colon++;
|
||||
if (*colon == 0) {
|
||||
uwsgi_log("invalid xml id\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log( "[uWSGI] using xml uwsgi id: %s\n", colon);
|
||||
}
|
||||
|
||||
doc = xmlReadFile(uwsgi.xml_config, NULL, 0);
|
||||
if (doc == NULL) {
|
||||
@@ -37,15 +52,55 @@ void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options
|
||||
exit(1);
|
||||
}
|
||||
if (strcmp((char *) element->name, "uwsgi")) {
|
||||
uwsgi_log( "[uWSGI] invalid xml root element, <uwsgi> expected.\n");
|
||||
exit(1);
|
||||
for (node = element->children; node; node = node->next) {
|
||||
element = NULL ;
|
||||
if (node->type == XML_ELEMENT_NODE) {
|
||||
if (!strcmp((char *) node->name, "uwsgi")) {
|
||||
xml_id = (char *) xmlGetProp(node, (const xmlChar *) "id");
|
||||
|
||||
if (colon && xml_id) {
|
||||
if ( strcmp(colon, xml_id) ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
element = node ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!element) {
|
||||
uwsgi_log( "[uWSGI] invalid xml root element, <uwsgi> expected.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (long_options) {
|
||||
// first check for pythonpath
|
||||
// first check for options
|
||||
for (node = element->children; node; node = node->next) {
|
||||
if (node->type == XML_ELEMENT_NODE) {
|
||||
if (node->type == XML_CDATA_SECTION_NODE) {
|
||||
if (node->content) {
|
||||
manage_opt(LONG_ARGS_EVAL_CONFIG, (char *) node->content);
|
||||
}
|
||||
}
|
||||
else if (node->type == XML_ELEMENT_NODE) {
|
||||
|
||||
if (!strcmp((char *) node->name, "app")) {
|
||||
uwsgi.xml_round2 = 1 ;
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
if (!strcmp((char *) node->name, "route")) {
|
||||
uwsgi.xml_round2 = 1 ;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp((char *) node->name, "routing")) {
|
||||
uwsgi.xml_round2 = 1 ;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
lopt = long_options;
|
||||
while ((aopt = lopt)) {
|
||||
if (!aopt->name)
|
||||
@@ -63,6 +118,20 @@ void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options
|
||||
}
|
||||
}
|
||||
|
||||
node_mode = xmlGetProp(node, (const xmlChar *) "mode") ;
|
||||
if (uwsgi.mode && node_mode) {
|
||||
if (strcmp(uwsgi.mode, (char *) node_mode)) {
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
xml_id = (char *) xmlGetProp(node, (const xmlChar *) "id") ;
|
||||
if (colon && xml_id) {
|
||||
if (strcmp(colon, xml_id)) {
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
if (aopt->flag) {
|
||||
*aopt->flag = aopt->val;
|
||||
}
|
||||
@@ -75,6 +144,7 @@ void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options
|
||||
}
|
||||
}
|
||||
}
|
||||
next:
|
||||
lopt++;
|
||||
}
|
||||
}
|
||||
@@ -82,7 +152,7 @@ void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options
|
||||
}
|
||||
else {
|
||||
|
||||
// ... then for wsgi apps
|
||||
// ... then for apps and routing
|
||||
for (node = element->children; node; node = node->next) {
|
||||
if (node->type == XML_ELEMENT_NODE) {
|
||||
|
||||
@@ -114,13 +184,81 @@ void uwsgi_xml_config(struct wsgi_request *wsgi_req, struct option *long_options
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef UWSGI_ROUTING
|
||||
else if (!strcmp((char *) node->name, "routing")) {
|
||||
unsigned char *default_route_mountpoint = NULL;
|
||||
unsigned char *default_route_callbase = NULL ;
|
||||
xmlChar *tmp_val;
|
||||
int default_route_modifier1 = 0;
|
||||
int default_route_modifier2 = 0;
|
||||
const char *errstr;
|
||||
int erroff;
|
||||
|
||||
default_route_mountpoint = xmlGetProp(node, (const xmlChar *) "mountpoint");
|
||||
default_route_callbase = xmlGetProp(node, (const xmlChar *) "base");
|
||||
|
||||
tmp_val = xmlGetProp(node, (const xmlChar *) "modifier1");
|
||||
if (tmp_val) {
|
||||
default_route_modifier1 = atoi( (char *)tmp_val);
|
||||
}
|
||||
|
||||
tmp_val = xmlGetProp(node, (const xmlChar *) "modifier2");
|
||||
if (tmp_val) {
|
||||
default_route_modifier2 = atoi( (char *) tmp_val);
|
||||
}
|
||||
|
||||
|
||||
for (node2 = node->children; node2; node2 = node2->next) {
|
||||
if (node2->type == XML_ELEMENT_NODE) {
|
||||
if (!strcmp((char *) node2->name, "route") && uwsgi.nroutes < MAX_UWSGI_ROUTES) {
|
||||
if (!node2->children) {
|
||||
uwsgi_log( "no route callable defined. skip.\n");
|
||||
continue;
|
||||
}
|
||||
uwsgi.routes[uwsgi.nroutes].mountpoint = (char *) default_route_mountpoint;
|
||||
uwsgi.routes[uwsgi.nroutes].callbase = (char *) default_route_callbase;
|
||||
uwsgi.routes[uwsgi.nroutes].modifier1 = default_route_modifier1;
|
||||
uwsgi.routes[uwsgi.nroutes].modifier2 = default_route_modifier2;
|
||||
// TODO check for action
|
||||
uwsgi.routes[uwsgi.nroutes].action = NULL;
|
||||
uwsgi.routes[uwsgi.nroutes].call = (char *) node2->children->content;
|
||||
if (uwsgi.routes[uwsgi.nroutes].call == NULL) {
|
||||
uwsgi_log( "no route callable defined. skip.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
tmp_val = xmlGetProp(node2, (const xmlChar *) "pattern");
|
||||
if (!tmp_val) {
|
||||
uwsgi_log( "no route pattern defined. skip.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
uwsgi.routes[uwsgi.nroutes].pattern = pcre_compile( (char *) tmp_val, 0, &errstr, &erroff, NULL);
|
||||
uwsgi.routes[uwsgi.nroutes].pattern_extra = pcre_study(uwsgi.routes[uwsgi.nroutes].pattern, 0, &errstr);
|
||||
|
||||
|
||||
pcre_fullinfo(uwsgi.routes[uwsgi.nroutes].pattern, uwsgi.routes[uwsgi.nroutes].pattern_extra, PCRE_INFO_CAPTURECOUNT, &uwsgi.routes[uwsgi.nroutes].args);
|
||||
|
||||
uwsgi_log("route call: %s %d\n", uwsgi.routes[uwsgi.nroutes].call, uwsgi.routes[uwsgi.nroutes].args);
|
||||
|
||||
uwsgi.nroutes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* We cannot free xml resources on the first round as the string pointer must be valid for all the server lifecycle */
|
||||
/* We cannot free xml resources on the first round (and with routing enabled) as the string pointer must be valid for all the server lifecycle */
|
||||
#ifdef UWSGI_ROUTING
|
||||
if (!long_options && !uwsgi.routing) {
|
||||
#else
|
||||
if (!long_options) {
|
||||
#endif
|
||||
xmlFreeDoc (doc);
|
||||
xmlCleanupParser ();
|
||||
}
|
||||
@@ -198,15 +336,11 @@ void uwsgi_startApp(void *userData, const char *name, const char **attrs) {
|
||||
wsgi_req->script_name_len = strlen(attrs[1]);
|
||||
}
|
||||
else {
|
||||
wsgi_req->script_name = "/";
|
||||
wsgi_req->script_name_len = 1;
|
||||
wsgi_req->script_name = "";
|
||||
wsgi_req->script_name_len = 0;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(name, "script")) {
|
||||
if (!wsgi_req->script_name_len) {
|
||||
uwsgi_log("you have not specified an app mountpoint.\n");
|
||||
exit(1);
|
||||
}
|
||||
current_xmlnode = 1 ;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user