Compare commits

..
65 Commits
Author SHA1 Message Date
Unbit 807060706f prepare for 1.9.2 2013-03-26 20:05:33 +01:00
Unbit a317f88d3c added the cache command to the ssi plugin 2013-03-26 20:03:37 +01:00
Unbit e17a7f0701 fixed a typo 2013-03-26 19:53:32 +01:00
Unbit db325eb9fe fixed readline() + post_buffering 2013-03-26 17:54:42 +01:00
Unbit b41a4c8c3b fixed python3 headers management 2013-03-26 16:45:57 +01:00
Unbit 73b4d11d18 added ssi router 2013-03-26 15:38:45 +01:00
Unbit 8162b87287 beta quality ssi plugin 2013-03-26 15:19:23 +01:00
Unbit 70e9e4f3ee added printenv 2013-03-26 12:24:17 +01:00
Unbit e61ae376b3 other improvements in the ssi plugin 2013-03-26 11:48:51 +01:00
Unbit 2d57b0e926 added preliminary ssi support 2013-03-26 11:33:00 +01:00
Unbit ae683af07a completed the geoip plugin [2] 2013-03-26 07:11:27 +01:00
Unbit 3c4f6a9171 completed the geoip plugin 2013-03-26 07:05:02 +01:00
Unbit 39986e546c fixed GeoIP plugin 2013-03-26 06:47:18 +01:00
Unbit 2e81a80f7b added preliminary geoip plugin 2013-03-25 19:11:20 +01:00
Unbit fcb3aa38c8 allows freeing route vars 2013-03-25 18:15:29 +01:00
Unbit 00a38d8ec5 fixed routing vars management 2013-03-25 18:10:41 +01:00
Unbit 07a0ab4227 pluggable routing vars 2013-03-25 18:05:57 +01:00
Unbit d4a9a2c543 fixed exceptions in the fiber plugin 2013-03-25 17:46:29 +01:00
Unbit 2b523fc60d added query string management functions 2013-03-25 10:21:20 +01:00
Unbit 0c26928236 added cookie management and --route-run 2013-03-25 09:56:53 +01:00
Unbit 8401e56a22 added 'empty' internal routing condition 2013-03-25 09:04:30 +01:00
Unbit 5109f9ae0b back to libxml2 default 2013-03-25 08:47:22 +01:00
Unbit c9bc06669a .ini file can backreference themselves 2013-03-25 08:47:00 +01:00
unbit a83fb2672c Merge pull request #189 from xtfxme/enhance/189-dashful-endif-endfor
Routing table appear to go nuts when used within a FOR loop
2013-03-24 23:18:50 -07:00
C Anthony Risinger 8f9ecb44d9 [#189] endfor/endif => end-for/end-if ...i know i'm not alone 2013-03-24 15:45:04 -05:00
Unbit bfcc09a8de prepare for cookie management in internal routing 2013-03-24 21:05:21 +01:00
Unbit f8a8c997db removed cache type in routing instruction 2013-03-24 20:30:56 +01:00
Unbit 132b996f30 added cachestore routing instruction 2013-03-24 19:43:41 +01:00
Unbit 12f970cdfb prepare for routing-governed caching 2013-03-24 19:24:13 +01:00
Unbit 9afa963225 prepare for gem 1.9.1 2013-03-24 11:39:44 +01:00
Unbit ed368d0d51 fixed signal copy on write 2013-03-24 10:30:01 +01:00
Unbit 21f21d34ba fixed legion scrolls api 2013-03-24 09:52:16 +01:00
Unbit f37823c809 completed --emperor-on-demand-dir 2013-03-23 10:34:36 +01:00
Unbit 6eaefcff5e added build profile for ubuntu ppa 2013-03-23 06:15:55 +01:00
Unbit 79235c1cc3 another memory report fix for Unbit 2013-03-23 04:41:58 +01:00
Unbit 29135f014b Unbit fixes 2013-03-23 04:11:33 +01:00
Unbit 13c998fb8d added uwsgi_main.c 2013-03-23 03:56:56 +01:00
Unbit 71bfd0d636 prepare for uWSGI 1.9.1 2013-03-23 03:52:19 +01:00
Unbit 51e99e0f5a removed UWSGI_INI 2013-03-23 03:15:33 +01:00
Unbit 66e7beefc4 fixed rack exceptions management 2013-03-22 19:53:47 +01:00
Unbit f2b10c35b7 fixed build without pcre 2013-03-22 11:15:13 +01:00
Unbit e951eba96c improved emperor on demand mode 2013-03-22 14:56:49 +01:00
Unbit 9fe18da7a3 added startswith endswith and regexp/re routing instructions 2013-03-22 10:14:34 +01:00
Unbit a14fdead14 added rpc router instruction 2013-03-22 09:26:11 +01:00
Unbit 9a671a4991 added %V magic var (contains UWSGI_VERSION) 2013-03-21 17:18:41 +01:00
Unbit 8f5e7b124a added --emperor-on-demand-exec 2013-03-21 16:55:23 +01:00
Unbit 5f7464d015 implemented --emperor-on-demand-ext 2013-03-21 16:42:24 +01:00
Unbit 238dd6c1d0 added a commodity mongodb plugin for system without mongoclient shared library 2013-03-21 15:18:09 +01:00
Roberta Giordano 82e4e54edc removed some unbit useless definition 2013-03-21 07:59:45 +01:00
Unbit 9946cbb9da added 'equal' routing func 2013-03-21 06:54:36 +01:00
Unbit 2474adb23a completed routing cache instruction 2013-03-21 06:31:26 +01:00
Unbit f40757bb67 free carbon_address memory 2013-03-21 06:19:31 +01:00
unbit bc29479930 Merge pull request #188 from prymitive/carbon_resolve_hostnames
allow connecting to carbon server using hostname resolved on every cycle...
2013-03-20 22:04:50 -07:00
Łukasz Mierzwa 4ec78edaa3 allow connecting to carbon server using hostname resolved on every cycle, fixes #186 2013-03-20 21:47:56 +01:00
Unbit aa0271158d allows build profiles to be stored on http/https/ftp 2013-03-20 19:44:46 +01:00
Unbit c0aa5bfe17 added the crypto logger 2013-03-20 16:22:40 +01:00
Unbit 3f8e6a8cc8 completed xslt plugin 2013-03-19 17:53:12 +01:00
Unbit ef0316fc2e Merge branch 'master' of github.com:unbit/uwsgi 2013-03-19 15:18:33 +01:00
Unbit 7274efab15 added xslt plugin 2013-03-19 15:18:03 +01:00
Unbit e44b62b6b2 on demand vassals 2013-03-18 15:42:34 +01:00
Unbit 31c041d435 added --exec-post-app 2013-03-18 13:32:09 +01:00
Unbit 35f47371ed first part of uwsgi_legion_scrolls() function api 2013-03-18 13:22:10 +01:00
unbit c5412e1620 Merge pull request #185 from guokr/master
Supporting JVM/Ring installing in Virtualenv
2013-03-18 03:09:03 -07:00
Mingli a9b4c52811 supporting virtualenv 2013-03-18 17:53:04 +08:00
Roberto De Ioris 5ce40b6ac8 fixed --req-logger after reload 2013-03-18 09:19:25 +01:00
59 changed files with 4185 additions and 1786 deletions
-5
View File
@@ -1,18 +1,13 @@
[uwsgi]
xml = auto
ini = true
yaml = true
json = auto
sqlite3 = auto
zeromq = auto
snmp = true
ssl = auto
async = true
ldap = auto
pcre = auto
routing = auto
alarm = auto
ipv6 = false
debug = false
unbit = false
xml_implementation = libxml2
+34
View File
@@ -0,0 +1,34 @@
[uwsgi]
xml = true
yaml = true
json = true
sqlite3 = true
zeromq = true
ssl = true
ldap = true
pcre = true
routing = true
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = libyaml
malloc_implementation = libc
extras =
plugins =
bin_name = /usr/lib/libuwsgi.so
append_version = ubuntu
plugin_dir = /usr/lib/uwsgi
embedded_plugins =
as_shared_library = true
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
+6
View File
@@ -0,0 +1,6 @@
[uwsgi]
main_plugin = python,gevent
inherit = base
plugins = jvm,ring
plugin_dir = .
+13 -5
View File
@@ -1,26 +1,34 @@
[uwsgi]
xml = true
ini = true
yaml = true
json = false
sqlite3 = false
zeromq = false
ldap = true
ssl = true
ldap = false
pcre = true
routing = true
alarm = true
debug = false
unbit = true
xml_implementation = expat
yaml_implementation = auto
malloc_implementation = libc
extras =
plugins =
bin_name = /opt/unbit/bin/uwsgi
bin_name = /opt/unbit/uwsgi19/lib/libuwsgi.so
append_version = unbit
plugin_dir = /opt/unbit/uwsgi_plugins
plugin_dir = /opt/unbit/uwsgi19/plugins
embedded_plugins =
as_shared_library = true
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
-1
View File
@@ -1,6 +1,5 @@
[uwsgi]
inherit = unbit
json = false
embedded_plugins = python
bin_name = ../bin/uwsgi
plugin_dir = ../bin/uwsgi_plugins
+24
View File
@@ -0,0 +1,24 @@
require 'socket'
require 'openssl'
secret = 'ciaociao'
iv = ''
address = '127.0.0.1'
port = 1717
algo = 'bf-cbc'
s = UDPSocket.new
s.bind(address, port)
cipher = OpenSSL::Cipher.new(algo)
cipher.decrypt
cipher.key = secret + ("\0" * (cipher.key_len - secret.length))
cipher.iv = iv + ("0" * (cipher.iv_len - iv.length))
loop do
msg, sender = s.recvfrom(8192)
cipher.reset
begin
puts cipher.update(msg) + cipher.final
rescue
end
end
+26
View File
@@ -328,3 +328,29 @@ int uwsgi_buffer_set_uh(struct uwsgi_buffer *ub, uint8_t modifier1, uint8_t modi
ub->buf[3] = modifier2;
return 0;
}
struct uwsgi_buffer *uwsgi_buffer_from_file(char *filename) {
struct stat st;
int fd = open(filename, O_RDONLY);
if (fd < 0) {
return NULL;
}
if (fstat(fd, &st)) {
close(fd);
return NULL;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(st.st_size);
ssize_t len = read(fd, ub->buf, st.st_size);
close(fd);
if (len != st.st_size) {
uwsgi_buffer_destroy(ub);
return NULL;
}
ub->pos = len;
return ub;
}
+81
View File
@@ -0,0 +1,81 @@
#include <uwsgi.h>
/*
cookie management functions (mainly used by the internal routing subsystem)
*/
static char *check_cookie(char *cookie, uint16_t cookie_len, char *key, uint16_t keylen, uint16_t *vallen) {
uint16_t orig_cookie_len = cookie_len-1;
// first lstrip white spaces
char *ptr = cookie;
uint16_t i;
for(i=0;i<cookie_len;i++) {
if (isspace((int)ptr[i])) {
cookie++;
cookie_len--;
}
else {
break;
}
}
// then rstrip (skipping the first char...)
for(i=orig_cookie_len;i>0;i--) {
if (isspace((int)ptr[i])) {
cookie_len--;
}
else {
break;
}
}
// now search for the first equal sign
char *equal = memchr(cookie, '=', cookie_len);
if (!equal) return NULL;
if (uwsgi_strncmp(key, keylen, cookie, equal-cookie)) {
return NULL;
}
cookie_len -= (equal-cookie)+1;
if (cookie_len == 0) return NULL;
*vallen = cookie_len;
return equal+1;
}
char *uwsgi_get_cookie(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
uint16_t i;
char *cookie = wsgi_req->cookie;
uint16_t cookie_len = 0;
char *ptr = wsgi_req->cookie;
//start splitting by ;
for(i=0;i<wsgi_req->cookie_len;i++) {
if (!cookie) {
cookie = ptr + i;
}
if (ptr[i] == ';') {
char *value = check_cookie(cookie, cookie_len, key, keylen, vallen);
if (value) {
return value;
}
cookie_len = 0;
cookie = NULL;
}
else {
cookie_len++;
}
}
if (cookie_len > 0) {
char *value = check_cookie(cookie, cookie_len, key, keylen, vallen);
if (value) {
return value;
}
}
return NULL;
}
+218 -51
View File
@@ -135,6 +135,77 @@ int uwsgi_emperor_is_valid(char *name) {
return 0;
}
static char *emperor_check_on_demand_socket(char *filename) {
size_t len = 0;
if (uwsgi.emperor_on_demand_extension) {
char *tmp = uwsgi_concat2(filename, uwsgi.emperor_on_demand_extension);
int fd = open(tmp, O_RDONLY);
free(tmp);
if (fd < 0) return NULL;
char *ret = uwsgi_read_fd(fd, &len, 1);
close(fd);
// change the first non prinabel character to 0
size_t i;
for(i=0;i<len;i++) {
if (ret[i] < 32) {
ret[i] = 0;
break;
}
}
if (ret[0] == 0) {
free(ret);
return NULL;
}
return ret;
}
else if (uwsgi.emperor_on_demand_directory) {
// we need to build the socket path automagically
char *start_of_vassal_name = uwsgi_get_last_char(filename, '/');
if (!start_of_vassal_name) {
start_of_vassal_name = filename;
}
else {
start_of_vassal_name++;
}
char *last_dot = uwsgi_get_last_char(filename, '.');
if (!last_dot) return NULL;
return uwsgi_concat4n(uwsgi.emperor_on_demand_directory, strlen(uwsgi.emperor_on_demand_directory), "/", 1, start_of_vassal_name, last_dot - start_of_vassal_name, ".socket", 7);
}
else if (uwsgi.emperor_on_demand_exec) {
int cpipe[2];
if (pipe(cpipe)) {
uwsgi_error("emperor_check_on_demand_socket()pipe()");
return NULL;
}
char *cmd = uwsgi_concat4(uwsgi.emperor_on_demand_exec, " \"", filename, "\"");
int r = uwsgi_run_command(cmd, NULL, cpipe[1]);
free(cmd);
if (r < 0) {
close(cpipe[0]);
close(cpipe[1]);
return NULL;
}
char *ret = uwsgi_read_fd(cpipe[0], &len, 1);
close(cpipe[0]);
close(cpipe[1]);
// change the first non prinabel character to 0
size_t i;
for(i=0;i<len;i++) {
if (ret[i] < 32) {
ret[i] = 0;
break;
}
}
if (ret[0] == 0) {
free(ret);
return NULL;
}
return ret;
}
return NULL;
}
// this is the monitor for non-glob directories
void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
struct uwsgi_instance *ui_current;
@@ -175,7 +246,9 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
}
}
else {
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
char *socket_name = emperor_check_on_demand_socket(de->d_name);
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid, socket_name);
if (socket_name) free(socket_name);
}
}
closedir(dir);
@@ -250,7 +323,9 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
}
}
else {
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
char *socket_name = emperor_check_on_demand_socket(g.gl_pathv[i]);
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid, socket_name);
if (socket_name) free(socket_name);
}
}
@@ -377,6 +452,22 @@ struct uwsgi_instance *emperor_get_by_fd(int fd) {
return NULL;
}
struct uwsgi_instance *emperor_get_by_socket_fd(int fd) {
struct uwsgi_instance *c_ui = ui;
while (c_ui->ui_next) {
c_ui = c_ui->ui_next;
// over engineering...
if (c_ui->on_demand_fd != -1 && c_ui->on_demand_fd == fd) {
return c_ui;
}
}
return NULL;
}
struct uwsgi_instance *emperor_get(char *name) {
@@ -430,6 +521,10 @@ void emperor_del(struct uwsgi_instance *c_ui) {
uwsgi.emperor_broodlord_count--;
}
if (c_ui->socket_name) {
free(c_ui->socket_name);
}
free(c_ui);
}
@@ -478,17 +573,10 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
uwsgi_log("[emperor] reload the uwsgi instance %s\n", c_ui->name);
}
void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid) {
void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid, char *socket_name) {
struct uwsgi_instance *c_ui = ui;
struct uwsgi_instance *n_ui = NULL;
pid_t pid;
char **vassal_argv;
char *uef;
char **uenvs;
int counter;
char *colon = NULL;
int i;
struct timeval tv;
#ifdef UWSGI_DEBUG
@@ -544,8 +632,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
c_ui = c_ui->ui_next;
}
n_ui = uwsgi_malloc(sizeof(struct uwsgi_instance));
memset(n_ui, 0, sizeof(struct uwsgi_instance));
n_ui = uwsgi_calloc(sizeof(struct uwsgi_instance));
if (config) {
n_ui->use_config = 1;
@@ -576,10 +663,60 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
n_ui->first_run = uwsgi_now();
n_ui->last_run = n_ui->first_run;
n_ui->on_demand_fd = -1;
if (socket_name) {
n_ui->socket_name = uwsgi_str(socket_name);
}
n_ui->pid = -1;
// ok here we check if we need to bind to the specified socket or continue with the activation
if (socket_name) {
char *tcp_port = strchr(socket_name, ':');
if (tcp_port) {
// disable deferred accept for this socket
int current_defer_accept = uwsgi.no_defer_accept;
uwsgi.no_defer_accept = 1;
n_ui->on_demand_fd = bind_to_tcp(socket_name, uwsgi.listen_queue, tcp_port);
uwsgi.no_defer_accept = current_defer_accept;
}
else {
n_ui->on_demand_fd = bind_to_unix(socket_name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
if (n_ui->on_demand_fd < 0) {
uwsgi_error("emperor_add()/bind()");
free(n_ui);
c_ui->ui_next = NULL;
return;
}
event_queue_add_fd_read(uwsgi.emperor_queue, n_ui->on_demand_fd);
uwsgi_log("[uwsgi-emperor] %s -> \"on demand\" instance detected, waiting for connections on socket \"%s\" ...\n", name, socket_name);
return;
}
if (uwsgi_emperor_vassal_start(n_ui)) {
// clear the vassal
free(n_ui);
c_ui->ui_next = NULL;
}
}
int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
int i;
char *colon = NULL;
int counter;
char **uenvs;
char *uef;
char **vassal_argv;
pid_t pid;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) {
uwsgi_error("socketpair()");
goto clear;
return -1;
}
event_queue_add_fd_read(uwsgi.emperor_queue, n_ui->pipe[0]);
@@ -587,7 +724,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
if (n_ui->use_config) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe_config)) {
uwsgi_error("socketpair()");
goto clear;
return -1;
}
}
@@ -606,6 +743,11 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
n_ui->pid = pid;
// close the right side of the pipe
close(n_ui->pipe[1]);
// close the "on demand" socket
if (n_ui->on_demand_fd > -1) {
close(n_ui->on_demand_fd);
n_ui->on_demand_fd = -1;
}
if (n_ui->use_config) {
close(n_ui->pipe_config[1]);
}
@@ -625,13 +767,13 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
}
}
return;
return 0;
}
else {
if (uwsgi.emperor_tyrant) {
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) uid, (int) gid, name);
if (setgid(gid)) {
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) n_ui->uid, (int) n_ui->gid, n_ui->name);
if (setgid(n_ui->gid)) {
uwsgi_error("setgid()");
exit(1);
}
@@ -640,7 +782,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
exit(1);
}
if (setuid(uid)) {
if (setuid(n_ui->uid)) {
uwsgi_error("setuid()");
exit(1);
}
@@ -720,7 +862,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
vassal_argv[0] = uwsgi.binary_path;
if (uwsgi.emperor_broodlord) {
colon = strchr(name, ':');
colon = strchr(n_ui->name, ':');
if (colon) {
colon[0] = 0;
}
@@ -728,17 +870,17 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
// initialize to a default value
vassal_argv[1] = "--inherit";
if (!strcmp(name + (strlen(name) - 4), ".xml"))
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".xml"))
vassal_argv[1] = "--xml";
if (!strcmp(name + (strlen(name) - 4), ".ini"))
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".ini"))
vassal_argv[1] = "--ini";
if (!strcmp(name + (strlen(name) - 4), ".yml"))
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".yml"))
vassal_argv[1] = "--yaml";
if (!strcmp(name + (strlen(name) - 5), ".yaml"))
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".yaml"))
vassal_argv[1] = "--yaml";
if (!strcmp(name + (strlen(name) - 3), ".js"))
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 3), ".js"))
vassal_argv[1] = "--json";
if (!strcmp(name + (strlen(name) - 5), ".json"))
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".json"))
vassal_argv[1] = "--json";
if (colon) {
@@ -746,16 +888,16 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
}
vassal_argv[2] = name;
vassal_argv[2] = n_ui->name;
if (uwsgi.emperor_magic_exec) {
if (!access(name, R_OK | X_OK)) {
vassal_argv[2] = uwsgi_concat2("exec://", name);
if (!access(n_ui->name, R_OK | X_OK)) {
vassal_argv[2] = uwsgi_concat2("exec://", n_ui->name);
}
}
if (n_ui->use_config) {
vassal_argv[2] = uwsgi_concat2("emperor://", name);
vassal_argv[2] = uwsgi_concat2("emperor://", n_ui->name);
}
counter = 3;
@@ -768,18 +910,29 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
}
vassal_argv[counter] = NULL;
// disable stdin
int stdin_fd = open("/dev/null", O_RDONLY);
if (stdin_fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
// disable stdin OR map it to the "on demand" socket
if (n_ui->on_demand_fd > -1) {
if (n_ui->on_demand_fd != 0) {
if (dup2(n_ui->on_demand_fd, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(n_ui->on_demand_fd);
}
}
if (stdin_fd != 0) {
if (dup2(stdin_fd, 0) < 0) {
uwsgi_error("dup2()");
else {
int stdin_fd = open("/dev/null", O_RDONLY);
if (stdin_fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
close(stdin_fd);
if (stdin_fd != 0) {
if (dup2(stdin_fd, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(stdin_fd);
}
}
// close all of the unneded fd
@@ -813,11 +966,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
exit(UWSGI_EXILE_CODE);
}
clear:
free(n_ui);
c_ui->ui_next = NULL;
return -1;
}
void uwsgi_imperial_monitor_glob_init(struct uwsgi_emperor_scanner *ues) {
@@ -975,6 +1124,8 @@ void emperor_loop() {
char notification_message[64];
struct rlimit rl;
uwsgi.disable_nuclear_blast = 1;
uwsgi.emperor_stats_fd = -1;
if (uwsgi.emperor_pidfile) {
@@ -1087,14 +1238,24 @@ void emperor_loop() {
else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) {
uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
char *zerg_name = uwsgi_concat3(ui_current->name, ":", "zerg");
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid);
// here we discard socket name as broodlord/zerg cannot be on demand
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid, NULL);
free(zerg_name);
}
}
}
else {
uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd);
close(interesting_fd);
ui_current = emperor_get_by_socket_fd(interesting_fd);
if (ui_current) {
event_queue_del_fd(uwsgi.emperor_queue, ui_current->on_demand_fd, event_queue_read());
if (uwsgi_emperor_vassal_start(ui_current)) {
emperor_del(ui_current);
}
}
else {
uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd);
close(interesting_fd);
}
}
}
@@ -1120,7 +1281,9 @@ void emperor_loop() {
has_children = 0;
while (ui_current->ui_next) {
ui_current = ui_current->ui_next;
has_children++;
if (ui_current->pid > -1) {
has_children++;
}
}
if (uwsgi.notify) {
@@ -1172,7 +1335,7 @@ void emperor_loop() {
}
else {
// UNSAFE
emperor_add(ui_current->scanner, ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid);
emperor_add(ui_current->scanner, ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid, ui_current->socket_name);
emperor_del(ui_current);
}
break;
@@ -1266,7 +1429,7 @@ void emperor_send_stats(int fd) {
if (uwsgi_stats_keyval_comma(us, "id", c_ui->name))
goto end0;
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) c_ui->pid))
if (uwsgi_stats_keyslong_comma(us, "pid", (long long) c_ui->pid))
goto end0;
if (uwsgi_stats_keylong_comma(us, "born", (unsigned long long) c_ui->born))
goto end0;
@@ -1285,6 +1448,9 @@ void emperor_send_stats(int fd) {
if (uwsgi_stats_keylong_comma(us, "zerg", (unsigned long long) c_ui->zerg))
goto end0;
if (uwsgi_stats_keyval_comma(us, "on_demand", c_ui->socket_name ? c_ui->socket_name : ""))
goto end0;
if (uwsgi_stats_keylong_comma(us, "uid", (unsigned long long) c_ui->uid))
goto end0;
if (uwsgi_stats_keylong_comma(us, "gid", (unsigned long long) c_ui->gid))
@@ -1403,6 +1569,7 @@ void uwsgi_emperor_start() {
else {
uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
}
if (uwsgi.emperor_pid < 0) {
uwsgi_error("pid()");
exit(1);
@@ -1436,7 +1603,7 @@ void uwsgi_check_emperor() {
}
void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char *config, time_t ts, uid_t uid, gid_t gid) {
void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char *config, time_t ts, uid_t uid, gid_t gid, char *socket_name) {
if (!uwsgi_emperor_is_valid(name))
return;
@@ -1473,6 +1640,6 @@ void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char
new_config = uwsgi_str(config);
new_config_len = strlen(new_config);
}
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid);
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid, socket_name);
}
}
+14 -6
View File
@@ -1,6 +1,4 @@
#ifdef UWSGI_INI
#include "uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
@@ -9,6 +7,8 @@ extern struct uwsgi_server uwsgi;
This memory must not be freed for all the server lifecycle
*/
static char *last_file = NULL;
void ini_rstrip(char *line) {
off_t i;
@@ -106,13 +106,23 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
if (colon[1] != 0) {
section_asked = colon + 1;
}
if (colon == file) {
file = last_file;
}
}
if (file[0] != 0) {
if (file[0] != 0 && file != last_file) {
uwsgi_log_initial("[uWSGI] getting INI configuration from %s\n", file);
}
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
if (file != last_file) {
if (last_file) {
free(last_file);
}
last_file = uwsgi_str(file);
}
while (len) {
ini_line = ini_get_line(ini, len);
@@ -157,5 +167,3 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
}
#endif
+54
View File
@@ -81,6 +81,37 @@ void uwsgi_parse_legion(char *key, uint16_t keylen, char *value, uint16_t vallen
}
}
// this function is called when a node is added or removed (heavy locking is needed)
static void legion_rebuild_scrolls(struct uwsgi_legion *ul) {
uint64_t max_size = ul->scrolls_max_size;
// first, try to add myself
if (ul->scroll_len + (uint64_t) 2 > max_size) {
uwsgi_log("[DANGER] you have configured a too much tiny buffer for the scrolls list !!! tune it with --legion-scroll-list-max-size\n");
ul->scroll_len = 0;
return;
}
char *ptr = ul->scrolls;
*ptr ++= (uint8_t) (ul->scroll_len & 0xff);
*ptr ++= (uint8_t) ((ul->scroll_len >> 8) &0xff);
memcpy(ptr, ul->scroll, ul->scroll_len); ptr += ul->scroll_len;
ul->scrolls_len = 2 + ul->scroll_len;
// ok start adding nodes;
struct uwsgi_legion_node *uln = ul->nodes_head;
while(uln) {
if (ul->scrolls_len + 2 + uln->scroll_len > max_size) {
uwsgi_log("[DANGER] you have configured a too much tiny buffer for the scrolls list !!! tune it with --legion-scroll-list-max-size\n");
return;
}
*ptr ++= (uint8_t) (uln->scroll_len & 0xff);
*ptr ++= (uint8_t) ((uln->scroll_len >> 8) &0xff);
memcpy(ptr, uln->scroll, uln->scroll_len); ptr += uln->scroll_len;
ul->scrolls_len += 2 + uln->scroll_len;
uln = uln->next;
}
}
// critical section (remember to lock when you use it)
struct uwsgi_legion_node *uwsgi_legion_add_node(struct uwsgi_legion *ul, uint16_t valor, char *name, uint16_t name_len, char *uuid) {
@@ -104,6 +135,7 @@ struct uwsgi_legion_node *uwsgi_legion_add_node(struct uwsgi_legion *ul, uint16_
ul->nodes_head = node;
}
return node;
@@ -141,6 +173,8 @@ void uwsgi_legion_remove_node(struct uwsgi_legion *ul, struct uwsgi_legion_node
}
free(node);
legion_rebuild_scrolls(ul);
}
struct uwsgi_legion_node *uwsgi_legion_get_node(struct uwsgi_legion *ul, uint64_t valor, char *name, uint16_t name_len, char *uuid) {
@@ -521,6 +555,8 @@ static void *legion_loop(void *foobar) {
node->scroll_len = legion_msg.scroll_len;
memcpy(node->scroll, legion_msg.scroll, node->scroll_len);
}
// we are still locked (and safe), let's rebuild the scrolls list
legion_rebuild_scrolls(ul);
uwsgi_rwunlock(ul->lock);
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
}
@@ -937,8 +973,14 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
uwsgi.legion_scroll_max_size = 4096;
}
if (!uwsgi.legion_scroll_list_max_size) {
uwsgi.legion_scroll_list_max_size = 32768;
}
ul->lord_scroll_size = uwsgi.legion_scroll_max_size;
ul->lord_scroll = uwsgi_calloc_shared(ul->lord_scroll_size);
ul->scrolls_max_size = uwsgi.legion_scroll_list_max_size;
ul->scrolls = uwsgi_calloc_shared(ul->scrolls_max_size);
uwsgi_legion_add(ul);
}
@@ -1020,3 +1062,15 @@ char *uwsgi_legion_lord_scroll(char *name, uint16_t *rlen) {
uwsgi_rwunlock(legion->lock);
return buf;
}
char *uwsgi_legion_scrolls(char *name, uint64_t *rlen) {
char *buf = NULL;
struct uwsgi_legion *legion = uwsgi_legion_get_by_name(name);
if (!legion) return NULL;
uwsgi_rlock(legion->lock);
buf = uwsgi_malloc(legion->scrolls_len);
memcpy(buf, legion->scrolls, legion->scrolls_len);
*rlen = legion->scrolls_len;
uwsgi_rwunlock(legion->lock);
return buf;
}
+7 -7
View File
@@ -642,12 +642,8 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
}
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} ", (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} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
#endif
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", (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);
logvec[logvecpos].iov_base = mempkt;
logvec[logvecpos].iov_len = rlen;
logvecpos++;
@@ -677,7 +673,11 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
void get_memusage(uint64_t * rss, uint64_t * vsz) {
#ifdef UNBIT
*vsz = syscall(356);
uint64_t ret[2];
ret[0] = 0; ret[1] = 0;
syscall(358, ret);
*vsz = ret[0];
*rss = ret[1] * uwsgi.page_size;
#elif defined(__linux__)
FILE *procfile;
int i;
+7
View File
@@ -354,6 +354,13 @@ static int uwsgi_proto_check_11(struct wsgi_request *wsgi_req, char *key, char *
return 0;
}
if (!uwsgi_proto_key("HTTP_COOKIE", 11)) {
wsgi_req->cookie = buf;
wsgi_req->cookie_len = len;
return 0;
}
if (!uwsgi_proto_key("UWSGI_APPID", 11)) {
wsgi_req->appid = buf;
wsgi_req->appid_len = len;
+57
View File
@@ -0,0 +1,57 @@
#include <uwsgi.h>
/*
QUERY_STRING management functions (mainly used by the internal routing subsystem)
*/
static char *check_qs(char *qs, uint16_t qs_len, char *key, uint16_t keylen, uint16_t *vallen) {
// search for the equal sign
char *equal = memchr(qs, '=', qs_len);
if (!equal) return NULL;
if (uwsgi_strncmp(key, keylen, qs, equal-qs)) {
return NULL;
}
qs_len -= (equal-qs)+1;
if (qs_len == 0) return NULL;
*vallen = qs_len;
return equal+1;
}
char *uwsgi_get_qs(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
uint16_t i;
char *qs = wsgi_req->query_string;
uint16_t qs_len = 0;
char *ptr = wsgi_req->query_string;
//start splitting by ;
for(i=0;i<wsgi_req->query_string_len;i++) {
if (!qs) {
qs = ptr + i;
}
if (ptr[i] == '&') {
char *value = check_qs(qs, qs_len, key, keylen, vallen);
if (value) {
return value;
}
qs_len = 0;
qs = NULL;
}
else {
qs_len++;
}
}
if (qs_len > 0) {
char *value = check_qs(qs, qs_len, key, keylen, vallen);
if (value) {
return value;
}
}
return NULL;
}
+14 -14
View File
@@ -108,64 +108,65 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
}
}
remains = UMIN(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark, wsgi_req->post_cl - wsgi_req->post_pos);
// read from a file
if (wsgi_req->post_file) {
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_readline_size - wsgi_req->post_readline_watermark, 1, wsgi_req->post_file);
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, remains, 1, wsgi_req->post_file);
if (ret == 0) {
uwsgi_error("consume_body_for_readline()/fread()");
return -1;
}
wsgi_req->post_pos += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
wsgi_req->post_readline_watermark += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
wsgi_req->post_pos += remains;
wsgi_req->post_readline_watermark += remains;
return 0;
}
// read from post_buffering memory
if (uwsgi.post_buffering) {
wsgi_req->post_pos += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
memcpy(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_buffering_buf + wsgi_req->post_pos, wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
wsgi_req->post_readline_watermark += wsgi_req->post_readline_size - wsgi_req->post_readline_watermark;
memcpy(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_buffering_buf + wsgi_req->post_pos, remains);
wsgi_req->post_pos += remains;
wsgi_req->post_readline_watermark += remains;
return 0;
}
// read from socket
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , remains);
if (len > 0) {
wsgi_req->post_pos += len;
wsgi_req->post_readline_watermark += len;
return 0;
}
if (len == 0) {
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_error(remains);
return -1;
}
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto wait;
}
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_error(remains);
return -1;
}
wait:
ret = uwsgi_wait_read_req(wsgi_req);
if (ret > 0) {
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , remains);
if (len > 0) {
wsgi_req->post_pos += len;
wsgi_req->post_readline_watermark += len;
return 0;
}
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_error(remains);
return -1;
}
// 0 means timeout
else if (ret == 0) {
uwsgi_read_timeout(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_timeout(remains);
return -1;
}
uwsgi_read_error(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark);
uwsgi_read_error(remains);
return -1;
}
@@ -347,7 +348,6 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
if (wsgi_req->post_file) {
if (fread(wsgi_req->post_read_buf + *rlen, remains, 1, wsgi_req->post_file) != 1) {
*rlen = -1;
uwsgi_log("%llu\n", remains);
uwsgi_error("uwsgi_request_body_read()/fread()");
return NULL;
}
+221 -4
View File
@@ -3,6 +3,43 @@
extern struct uwsgi_server uwsgi;
struct uwsgi_route_var *uwsgi_register_route_var(char *name, char *(*func)(struct wsgi_request *, char *, uint16_t, uint16_t *)) {
struct uwsgi_route_var *old_urv = NULL,*urv = uwsgi.route_vars;
while(urv) {
if (!strcmp(urv->name, name)) {
return urv;
}
old_urv = urv;
urv = urv->next;
}
urv = uwsgi_calloc(sizeof(struct uwsgi_route_var));
urv->name = name;
urv->name_len = strlen(name);
urv->func = func;
if (old_urv) {
old_urv->next = urv;
}
else {
uwsgi.route_vars = urv;
}
return urv;
}
struct uwsgi_route_var *uwsgi_get_route_var(char *name, uint16_t name_len) {
struct uwsgi_route_var *urv = uwsgi.route_vars;
while(urv) {
if (!uwsgi_strncmp(urv->name, urv->name_len, name, name_len)) {
return urv;
}
urv = urv->next;
}
return NULL;
}
struct uwsgi_buffer *uwsgi_routing_translate(struct wsgi_request *wsgi_req, struct uwsgi_route *ur, char *subject, uint16_t subject_len, char *data, size_t data_len) {
char *pass1 = data;
@@ -44,9 +81,32 @@ struct uwsgi_buffer *uwsgi_routing_translate(struct wsgi_request *wsgi_req, stru
case 2:
if (pass1[i] == '}') {
uint16_t vallen = 0;
char *value = uwsgi_get_var(wsgi_req, key, keylen, &vallen);
int need_free = 0;
char *value = NULL;
char *bracket = memchr(key, '[', keylen);
if (bracket && keylen > 0 && key[keylen-1] == ']') {
struct uwsgi_route_var *urv = uwsgi_get_route_var(key, bracket - key);
if (urv) {
need_free = urv->need_free;
value = urv->func(wsgi_req, bracket + 1, keylen - (urv->name_len+2), &vallen);
}
else {
value = uwsgi_get_var(wsgi_req, key, keylen, &vallen);
}
}
else {
value = uwsgi_get_var(wsgi_req, key, keylen, &vallen);
}
if (value) {
if (uwsgi_buffer_append(ub, value, vallen)) goto error;
if (uwsgi_buffer_append(ub, value, vallen)) {
if (need_free) {
free(value);
}
goto error;
}
if (need_free) {
free(value);
}
}
status = 0;
key = NULL;
@@ -108,6 +168,11 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t
wsgi_req->route_goto = 0;
if (!routes->if_func) {
// could be a "run"
if (!routes->subject) {
n = 0;
goto run;
}
if (!subject) {
char **subject2 = (char **) (((char *) (wsgi_req)) + routes->subject);
uint16_t *subject_len2 = (uint16_t *) (((char *) (wsgi_req)) + routes->subject_len);
@@ -137,6 +202,7 @@ int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t
}
}
run:
if (n >= 0) {
wsgi_req->is_routing = 1;
int ret = routes->func(wsgi_req, routes);
@@ -197,6 +263,8 @@ static void *uwsgi_route_get_condition_func(char *name) {
void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
char *space = NULL;
char *command = NULL;
struct uwsgi_route *old_ur = NULL,*ur = uwsgi.routes;
uint64_t pos = 0;
while(ur) {
@@ -223,7 +291,12 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
char *route = uwsgi_str(value);
char *space = strchr(route, ' ');
if (!strcmp(foobar, "run")) {
command = route;
goto done;
}
space = strchr(route, ' ');
if (!space) {
uwsgi_log("invalid route syntax\n");
exit(1);
@@ -299,7 +372,8 @@ void uwsgi_opt_add_route(char *opt, char *value, void *foobar) {
}
}
char *command = space + 1;
command = space + 1;
done:
ur->action = uwsgi_str(command);
char *colon = strchr(command, ':');
@@ -628,6 +702,133 @@ static int uwsgi_route_condition_isfile(struct wsgi_request *wsgi_req, struct uw
return 0;
}
static int uwsgi_route_condition_regexp(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
if (!ub) return -1;
pcre *pattern;
pcre_extra *pattern_extra;
char *re = uwsgi_concat2n(semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str), "", 0);
if (uwsgi_regexp_build(re, &pattern, &pattern_extra)) {
free(re);
uwsgi_buffer_destroy(ub);
return -1;
}
free(re);
if (uwsgi_regexp_match(pattern, pattern_extra, ub->buf, ub->pos) >= 0) {
uwsgi_buffer_destroy(ub);
pcre_free(pattern);
#ifdef PCRE_STUDY_JIT_COMPILE
pcre_free_study(pattern_extra);
#else
pcre_free(pattern_extra);
#endif
return 1;
}
uwsgi_buffer_destroy(ub);
pcre_free(pattern);
#ifdef PCRE_STUDY_JIT_COMPILE
pcre_free_study(pattern_extra);
#else
pcre_free(pattern_extra);
#endif
return 0;
}
static int uwsgi_route_condition_empty(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
if (!ub) return -1;
if (ub->pos == 0) {
uwsgi_buffer_destroy(ub);
return 1;
}
uwsgi_buffer_destroy(ub);
return 0;
}
static int uwsgi_route_condition_equal(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
if (!ub) return -1;
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
if (!ub2) {
uwsgi_buffer_destroy(ub);
return -1;
}
if(!uwsgi_strncmp(ub->buf, ub->pos, ub2->buf, ub2->pos)) {
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 1;
}
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 0;
}
static int uwsgi_route_condition_startswith(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
if (!ub) return -1;
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
if (!ub2) {
uwsgi_buffer_destroy(ub);
return -1;
}
if(!uwsgi_starts_with(ub->buf, ub->pos, ub2->buf, ub2->pos)) {
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 1;
}
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 0;
}
static int uwsgi_route_condition_endswith(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
if (!semicolon) return 0;
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
if (!ub) return -1;
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
if (!ub2) {
uwsgi_buffer_destroy(ub);
return -1;
}
if (ub2->pos < ub->pos) goto zero;
if(!uwsgi_strncmp(ub->buf + (ub->pos - ub2->pos), ub2->pos, ub2->buf, ub2->pos)) {
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 1;
}
zero:
uwsgi_buffer_destroy(ub);
uwsgi_buffer_destroy(ub2);
return 0;
}
static int uwsgi_route_condition_isdir(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
if (!ub) return -1;
@@ -685,6 +886,19 @@ void uwsgi_register_embedded_routers() {
uwsgi_register_route_condition("isdir", uwsgi_route_condition_isdir);
uwsgi_register_route_condition("islink", uwsgi_route_condition_islink);
uwsgi_register_route_condition("isexec", uwsgi_route_condition_isexec);
uwsgi_register_route_condition("equal", uwsgi_route_condition_equal);
uwsgi_register_route_condition("isequal", uwsgi_route_condition_equal);
uwsgi_register_route_condition("eq", uwsgi_route_condition_equal);
uwsgi_register_route_condition("==", uwsgi_route_condition_equal);
uwsgi_register_route_condition("startswith", uwsgi_route_condition_startswith);
uwsgi_register_route_condition("endswith", uwsgi_route_condition_endswith);
uwsgi_register_route_condition("regexp", uwsgi_route_condition_regexp);
uwsgi_register_route_condition("re", uwsgi_route_condition_regexp);
uwsgi_register_route_condition("empty", uwsgi_route_condition_empty);
uwsgi_register_route_var("cookie", uwsgi_get_cookie);
uwsgi_register_route_var("qs", uwsgi_get_qs);
}
struct uwsgi_router *uwsgi_register_router(char *name, int (*func) (struct uwsgi_route *, char *)) {
@@ -743,6 +957,9 @@ void uwsgi_routing_dump() {
if (routes->label) {
uwsgi_log("[rule: %llu] label: %s\n", (unsigned long long ) routes->pos, routes->label);
}
else if (!routes->subject_str && !routes->if_func) {
uwsgi_log("[rule: %llu] action: %s\n", (unsigned long long ) routes->pos, routes->action);
}
else {
uwsgi_log("[rule: %llu] subject: %s %s: %s%s action: %s\n", (unsigned long long ) routes->pos, routes->subject_str, routes->if_func ? "func" : "regexp", routes->if_negate ? "!" : "", routes->regexp, routes->action);
}
+10
View File
@@ -123,6 +123,16 @@ void uwsgi_setup_inherited_sockets() {
continue;
}
if (uwsgi.shared->worker_req_log_pipe[0] > -1) {
if (j == uwsgi.shared->worker_req_log_pipe[0])
continue;
}
if (uwsgi.shared->worker_req_log_pipe[1] > -1) {
if (j == uwsgi.shared->worker_req_log_pipe[1])
continue;
}
if (uwsgi.original_log_fd > -1) {
if (j == uwsgi.original_log_fd)
continue;
+1 -1
View File
@@ -137,7 +137,7 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
int i;
for(i=1;i<=uwsgi.numproc;i++) {
int pos = (i * 256);
memcpy(&uwsgi.shared->signal_table[pos], use, sizeof(struct uwsgi_signal_entry) * 256);
memcpy(&uwsgi.shared->signal_table[pos], &uwsgi.shared->signal_table[0], sizeof(struct uwsgi_signal_entry) * 256);
}
}
+15
View File
@@ -66,6 +66,7 @@ int bind_to_unix_dgram(char *socket_name) {
if (serverfd < 0) {
uwsgi_error("socket()");
uwsgi_nuclear_blast();
return -1;
}
if (unlink(socket_name) != 0 && errno != ENOENT) {
@@ -85,6 +86,7 @@ int bind_to_unix_dgram(char *socket_name) {
#endif
uwsgi_error("bind()");
uwsgi_nuclear_blast();
return -1;
}
return serverfd;
@@ -100,6 +102,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
if (strlen(socket_name) > 102) {
uwsgi_log("invalid socket name\n");
uwsgi_nuclear_blast();
return -1;
}
if (socket_name[0] == '@') {
@@ -113,6 +116,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
if (uws_addr == NULL) {
uwsgi_error("malloc()");
uwsgi_nuclear_blast();
return -1;
}
memset(uws_addr, 0, sizeof(struct sockaddr_un));
@@ -120,6 +124,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
if (serverfd < 0) {
uwsgi_error("socket()");
uwsgi_nuclear_blast();
return -1;
}
if (abstract_socket == 0) {
if (unlink(socket_name) != 0 && errno != ENOENT) {
@@ -157,12 +162,14 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
#endif
uwsgi_error("bind()");
uwsgi_nuclear_blast();
return -1;
}
if (listen(serverfd, listen_queue) != 0) {
uwsgi_error("listen()");
uwsgi_nuclear_blast();
return -1;
}
// chmod unix socket for lazy users
@@ -578,11 +585,13 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (serverfd < 0) {
uwsgi_error("socket()");
uwsgi_nuclear_blast();
return -1;
}
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
uwsgi_error("SO_REUSEADDR setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
#ifdef __linux__
@@ -593,6 +602,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (setsockopt(serverfd, SOL_IP, IP_FREEBIND, (const void *) &uwsgi.freebind, sizeof(int)) < 0) {
uwsgi_error("IP_FREEBIND setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
#endif
@@ -602,6 +612,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEPORT, (const void *) &uwsgi.reuse_port, sizeof(int)) < 0) {
uwsgi_error("SO_REUSEPORT setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
#else
uwsgi_log("!!! your system does not support SO_REUSEPORT !!!\n");
@@ -628,6 +639,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDTIMEO, (const void *) &tv, sizeof(struct timeval)) < 0) {
uwsgi_error("SO_SNDTIMEO setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
@@ -662,6 +674,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
}
uwsgi_error("bind()");
uwsgi_nuclear_blast();
return -1;
}
#ifdef __linux__
@@ -669,12 +682,14 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (somaxconn > 0 && uwsgi.listen_queue > somaxconn) {
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%li).\n", somaxconn);
uwsgi_nuclear_blast();
return -1;
}
#endif
if (listen(serverfd, listen_queue) != 0) {
uwsgi_error("listen()");
uwsgi_nuclear_blast();
return -1;
}
+42 -1
View File
@@ -315,6 +315,45 @@ int uwsgi_stats_keylong_comma(struct uwsgi_stats *us, char *key, unsigned long l
return uwsgi_stats_comma(us);
}
int uwsgi_stats_keyslong(struct uwsgi_stats *us, char *key, long long num) {
if (uwsgi_stats_apply_tabs(us))
return -1;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
if (ret < 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base)
return -1;
us->base = new_base;
us->size += us->chunk;
ptr = us->base + us->pos;
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
if (ret < 0)
return -1;
}
us->pos += ret;
return 0;
}
int uwsgi_stats_keyslong_comma(struct uwsgi_stats *us, char *key, long long num) {
int ret = uwsgi_stats_keyslong(us, key, num);
if (ret)
return -1;
return uwsgi_stats_comma(us);
}
void uwsgi_send_stats(int fd, struct uwsgi_stats *(*func) (void)) {
struct sockaddr_un client_src;
@@ -383,7 +422,9 @@ struct uwsgi_stats_pusher_instance *uwsgi_stats_pusher_add(struct uwsgi_stats_pu
uspi = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_instance));
uspi->pusher = pusher;
uspi->arg = uwsgi_str(arg);
if (arg) {
uspi->arg = uwsgi_str(arg);
}
uspi->raw = pusher->raw;
if (old_uspi) {
old_uspi->next = uspi;
+19
View File
@@ -622,6 +622,25 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
free(wsgi_req->proto_parser_buf);
}
// do we need to store the response in the cache
if (wsgi_req->cache_it) {
// only response with a body and a status code of 200 can be cached (TODO allows it to be configurable)
if (wsgi_req->cached_response && wsgi_req->status == 200 && wsgi_req->response_size > 0) {
uwsgi_cache_magic_set(wsgi_req->cache_it->buf, wsgi_req->cache_it->pos,
wsgi_req->cached_response->buf, wsgi_req->cached_response->pos, wsgi_req->cache_it_expires, UWSGI_CACHE_FLAG_UPDATE, wsgi_req->cache_it_to ? wsgi_req->cache_it_to->buf : NULL);
}
uwsgi_buffer_destroy(wsgi_req->cache_it);
}
if (wsgi_req->cache_it_to) {
uwsgi_buffer_destroy(wsgi_req->cache_it_to);
}
if (wsgi_req->cached_response) {
uwsgi_buffer_destroy(wsgi_req->cached_response);
}
if (!wsgi_req->do_not_account) {
uwsgi.workers[0].requests++;
uwsgi.workers[uwsgi.mywid].requests++;
+31 -11
View File
@@ -80,6 +80,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"for", required_argument, 0, "(opt logic) for cycle", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for, UWSGI_OPT_IMMEDIATE},
{"for-glob", required_argument, 0, "(opt logic) for cycle (expand glob)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_glob, UWSGI_OPT_IMMEDIATE},
{"endfor", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
{"end-for", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
{"if-opt", required_argument, 0, "(opt logic) check for option", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_opt, UWSGI_OPT_IMMEDIATE},
{"if-not-opt", required_argument, 0, "(opt logic) check for option", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_opt, UWSGI_OPT_IMMEDIATE},
@@ -108,6 +109,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"if-directory", required_argument, 0, "(opt logic) check for directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_dir, UWSGI_OPT_IMMEDIATE},
{"endif", optional_argument, 0, "(opt logic) end if", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
{"end-if", optional_argument, 0, "(opt logic) end if", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
{"blacklist", required_argument, 0, "set options blacklist context", uwsgi_opt_set_str, &uwsgi.blacklist_context, UWSGI_OPT_IMMEDIATE},
{"end-blacklist", no_argument, 0, "clear options blacklist context", uwsgi_opt_set_null, &uwsgi.blacklist_context, UWSGI_OPT_IMMEDIATE},
@@ -176,6 +178,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"emperor-throttle", required_argument, 0, "set throttling level (in milliseconds) for bad behaving vassals (default 1000)", uwsgi_opt_set_int, &uwsgi.emperor_throttle, 0},
{"emperor-max-throttle", required_argument, 0, "set max throttling level (in milliseconds) for bad behaving vassals (default 3 minutes)", uwsgi_opt_set_int, &uwsgi.emperor_max_throttle, 0},
{"emperor-magic-exec", no_argument, 0, "prefix vassals config files with exec:// if they have the executable bit", uwsgi_opt_true, &uwsgi.emperor_magic_exec, 0},
{"emperor-on-demand-extension", required_argument, 0, "search for text file (vassal name + extension) containing the on demand socket name", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_extension, 0},
{"emperor-on-demand-ext", required_argument, 0, "search for text file (vassal name + extension) containing the on demand socket name", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_extension, 0},
{"emperor-on-demand-directory", required_argument, 0, "enable on demand mode binding to the unix socket in the specified directory named like the vassal + .socket", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_directory, 0},
{"emperor-on-demand-dir", required_argument, 0, "enable on demand mode binding to the unix socket in the specified directory named like the vassal + .socket", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_directory, 0},
{"emperor-on-demand-exec", required_argument, 0, "use the output of the specified command as on demand socket name (the vassal name is passed as the only argument)", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_exec, 0},
{"imperial-monitor-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
{"imperial-monitors-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
{"vassals-inherit", required_argument, 0, "add config templates to vassals config", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
@@ -270,9 +277,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"exec-as-user", required_argument, 0, "run the specified command after privileges drop", uwsgi_opt_add_string_list, &uwsgi.exec_as_user, 0},
{"exec-as-user-atexit", required_argument, 0, "run the specified command before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.exec_as_user_atexit, 0},
{"exec-pre-app", required_argument, 0, "run the specified command before app loading", uwsgi_opt_add_string_list, &uwsgi.exec_pre_app, 0},
#ifdef UWSGI_INI
{"exec-post-app", required_argument, 0, "run the specified command after app loading", uwsgi_opt_add_string_list, &uwsgi.exec_post_app, 0},
{"ini", required_argument, 0, "load config from ini file", uwsgi_opt_load_ini, NULL, UWSGI_OPT_IMMEDIATE},
#endif
#ifdef UWSGI_YAML
{"yaml", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE},
{"yal", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE},
@@ -373,8 +379,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"legion-death", required_argument, 0, "action to call on legion death (shutdown of the instance)", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-quorum", required_argument, 0, "set the quorum of a legion", uwsgi_opt_legion_quorum, NULL, UWSGI_OPT_MASTER},
{"legion-scroll", required_argument, 0, "set the scroll of a legion", uwsgi_opt_legion_scroll, NULL, UWSGI_OPT_MASTER},
{"legion-scroll", required_argument, 0, "set the scroll of a legion", uwsgi_opt_legion_scroll, NULL, UWSGI_OPT_MASTER},
{"legion-scroll-max-size", required_argument, 0, "set max size of legion scroll buffer", uwsgi_opt_set_16bit, &uwsgi.legion_scroll_max_size, 0},
{"legion-scroll-list-max-size", required_argument, 0, "set max size of legion scroll list buffer", uwsgi_opt_set_64bit, &uwsgi.legion_scroll_list_max_size, 0},
{"subscriptions-sign-check", required_argument, 0, "set digest algorithm and certificate directory for secured subscription system", uwsgi_opt_scd, NULL, UWSGI_OPT_MASTER},
{"subscriptions-sign-check-tolerance", required_argument, 0, "set the maximum tolerance (in seconds) of clock skew for secured subscription system", uwsgi_opt_set_int, &uwsgi.subscriptions_sign_check_tolerance, UWSGI_OPT_MASTER},
#endif
@@ -506,6 +512,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"route-label", required_argument, 0, "add a routing label (for use with goto)", uwsgi_opt_add_route, NULL, 0},
{"route-if", required_argument, 0, "add a route based on condition", uwsgi_opt_add_route, "if", 0},
{"route-if-not", required_argument, 0, "add a route based on condition (negate version)", uwsgi_opt_add_route, "if-not", 0},
{"route-run", required_argument, 0, "always run the specified route action", uwsgi_opt_add_route, "run", 0},
{"router-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
{"routers-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
#endif
@@ -779,8 +786,12 @@ void config_magic_table_fill(char *filename, char **magic_table) {
char *section = uwsgi_get_last_char(filename, ':');
if (section) {
*section = 0;
if (section == filename) {
goto reuse;
}
}
// we have a special case for symlinks
if (uwsgi_is_link(filename)) {
if (filename[0] != '/') {
@@ -834,6 +845,7 @@ void config_magic_table_fill(char *filename, char **magic_table) {
if (uwsgi_get_last_char(magic_table['s'], '.'))
magic_table['n'] = uwsgi_concat2n(magic_table['s'], uwsgi_get_last_char(magic_table['s'], '.') - magic_table['s'], "", 0);
reuse:
if (section) {
magic_table['x'] = section+1;
*section = ':';
@@ -1034,6 +1046,9 @@ void grace_them_all(int signum) {
void uwsgi_nuclear_blast() {
// the Emperor (as an example) cannot nuke itself
if (uwsgi.disable_nuclear_blast) return;
if (!uwsgi.workers) {
reap_them_all(0);
}
@@ -1603,10 +1618,6 @@ int main(int argc, char *argv[], char *envp[]) {
int i;
#ifdef UNBIT
//struct uidsec_struct us;
#endif
struct utsname uuts;
// signal mask is inherited, and sme process manager could make a real mess...
@@ -1750,6 +1761,7 @@ int main(int argc, char *argv[], char *envp[]) {
// set a couple of 'static' magic vars
uwsgi.magic_table['v'] = uwsgi.cwd;
uwsgi.magic_table['h'] = uwsgi.hostname;
uwsgi.magic_table['V'] = UWSGI_VERSION;
// you can embed a ini file in the uWSGi binary with default options
#ifdef UWSGI_EMBED_CONFIG
@@ -3119,6 +3131,18 @@ void uwsgi_init_all_apps() {
}
}
usl = uwsgi.exec_post_app;
while (usl) {
uwsgi_log("running \"%s\" (post app)...\n", usl->value);
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
if (ret != 0) {
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
exit(1);
}
usl = usl->next;
}
}
void uwsgi_init_worker_mount_apps() {
@@ -3710,12 +3734,10 @@ void uwsgi_opt_deprecated(char *opt, char *value, void *message) {
void uwsgi_opt_load(char *opt, char *filename, void *none) {
#ifdef UWSGI_INI
if (uwsgi_endswith(filename, ".ini")) {
uwsgi_opt_load_ini(opt, filename, none);
return;
}
#endif
#ifdef UWSGI_XML
if (uwsgi_endswith(filename, ".xml")) {
uwsgi_opt_load_xml(opt, filename, none);
@@ -3763,12 +3785,10 @@ void uwsgi_opt_logic(char *opt, char *arg, void *func) {
void uwsgi_opt_noop(char *opt, char *foo, void *bar) {
}
#ifdef UWSGI_INI
void uwsgi_opt_load_ini(char *opt, char *filename, void *none) {
config_magic_table_fill(filename, uwsgi.magic_table);
uwsgi_ini_config(filename, uwsgi.magic_table);
}
#endif
#ifdef UWSGI_XML
void uwsgi_opt_load_xml(char *opt, char *filename, void *none) {
+13
View File
@@ -141,6 +141,7 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
return UWSGI_OK;
}
// this is the function called by all request plugins to send chunks to the client
int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
if (wsgi_req->write_errors) return -1;
@@ -182,6 +183,18 @@ sendbody:
// reset for the next write
wsgi_req->write_pos = 0;
// now we need to check if the chunk must be stored
if (wsgi_req->cache_it) {
if (!wsgi_req->cached_response) {
wsgi_req->cached_response = uwsgi_buffer_new(len);
}
// if we are unable to append the buffer, we just stop caching it
if (uwsgi_buffer_append(wsgi_req->cached_response, buf, len)) {
uwsgi_buffer_destroy(wsgi_req->cache_it);
wsgi_req->cache_it = NULL;
}
}
return UWSGI_OK;
}
+46 -10
View File
@@ -9,9 +9,10 @@
extern struct uwsgi_server uwsgi;
struct carbon_server_list {
char *value; // server address
int healthy;
int errors;
char *hostname;
char *port;
struct carbon_server_list *next;
};
@@ -33,6 +34,7 @@ struct uwsgi_carbon {
char *root_node;
char *hostname_dot_replacement;
char *hostname;
int resolve_hostname;
struct uwsgi_stats_pusher *pusher;
} u_carbon;
@@ -46,6 +48,8 @@ static struct uwsgi_option carbon_options[] = {
{"carbon-retry-delay", required_argument, 0, "set connection retry delay in seconds (default 7)", uwsgi_opt_set_int, &u_carbon.retry_delay, 0},
{"carbon-root", required_argument, 0, "set carbon metrics root node (default 'uwsgi')", uwsgi_opt_set_str, &u_carbon.root_node, 0},
{"carbon-hostname-dots", required_argument, 0, "set char to use as a replacement for dots in hostname (dots are not replaced by default)", uwsgi_opt_set_str, &u_carbon.hostname_dot_replacement, 0},
{"carbon-name-resolve", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
{"carbon-resolve-names", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -59,15 +63,32 @@ static void carbon_post_init() {
while(usl) {
struct carbon_server_list *u_server = uwsgi_calloc(sizeof(struct carbon_server_list));
u_server->value = usl->value;
u_server->healthy = 1;
u_server->errors = 0;
char *p = strtok(usl->value, ":");
while (p) {
if (!u_server->hostname) {
u_server->hostname = uwsgi_str(p);
}
else if (!u_server->port) {
u_server->port = uwsgi_str(p);
}
else break;
p = strtok(NULL, ":");
}
if (!u_server->hostname || !u_server->port) {
uwsgi_log("[carbon] invalid carbon server address (%s)\n", usl->value);
usl = usl->next;
continue;
}
if (u_carbon.servers_data) {
u_server->next = u_carbon.servers_data;
}
u_carbon.servers_data = u_server;
uwsgi_log("[carbon] added server %s\n", usl->value);
uwsgi_log("[carbon] added server %s:%s\n", u_server->hostname, u_server->port);
usl = usl->next;
}
@@ -80,7 +101,7 @@ static void carbon_post_init() {
if (u_carbon.timeout < 1) u_carbon.timeout = 3;
if (u_carbon.max_retries <= 0) u_carbon.max_retries = 1;
if (u_carbon.retry_delay <= 0) u_carbon.retry_delay = 7;
if (!u_carbon.id) {
if (!u_carbon.id) {
u_carbon.id = uwsgi_str(uwsgi.sockets->name);
for(i=0;i<(int)strlen(u_carbon.id);i++) {
@@ -145,6 +166,8 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
int i;
int fd;
int wok;
char *ip;
char *carbon_address = NULL;
for (i = 0; i < uwsgi.numproc; i++) {
u_carbon.current_busyness_values[i] = uwsgi.workers[i+1].running_time - u_carbon.last_busyness_values[i];
@@ -157,31 +180,44 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
if (retry_cycle && usl->healthy)
// skip healthy servers during retry cycle
goto nxt;
if (retry_cycle && usl->healthy == 0)
uwsgi_log("[carbon] Retrying failed server at %s (%d)\n", usl->value, usl->errors);
uwsgi_log("[carbon] Retrying failed server at %s (%d)\n", usl->hostname, usl->errors);
if (!retry_cycle) {
usl->healthy = 1;
usl->errors = 0;
}
fd = uwsgi_connect(usl->value, u_carbon.timeout, 0);
if (u_carbon.resolve_hostname) {
ip = uwsgi_resolve_ip(usl->hostname);
if (!ip) {
uwsgi_log("[carbon] Could not resolve hostname %s\n", usl->hostname);
goto nxt;
}
carbon_address = uwsgi_concat3(ip, ":", usl->port);
}
else {
carbon_address = uwsgi_concat3(usl->hostname, ":", usl->port);
}
fd = uwsgi_connect(carbon_address, u_carbon.timeout, 0);
if (fd < 0) {
uwsgi_log("[carbon] Could not connect to carbon server at %s\n", usl->value);
uwsgi_log("[carbon] Could not connect to carbon server at %s\n", carbon_address);
if (usl->errors < u_carbon.max_retries) {
u_carbon.need_retry = 1;
u_carbon.next_retry = uwsgi_now() + u_carbon.retry_delay;
} else {
uwsgi_log("[carbon] Maximum number of retries for %s (%d)\n",
usl->value, u_carbon.max_retries);
carbon_address, u_carbon.max_retries);
usl->healthy = 0;
usl->errors = 0;
}
usl->healthy = 0;
usl->errors++;
free(carbon_address);
goto nxt;
}
free(carbon_address);
// put the socket in non-blocking mode
uwsgi_socket_nb(fd);
+2 -2
View File
@@ -49,7 +49,7 @@ void uwsgi_imperial_monitor_amqp_event(struct uwsgi_emperor_scanner *ues) {
}
if (msgsize > 0) {
emperor_add(ues, amqp_routing_key, uwsgi_now(), config, msgsize, 0, 0);
emperor_add(ues, amqp_routing_key, uwsgi_now(), config, msgsize, 0, 0, NULL);
}
end0:
@@ -88,7 +88,7 @@ end0:
emperor_respawn(ui_current, uwsgi_now());
}
else {
emperor_add(ues, config_file, uwsgi_now(), NULL, 0, 0, 0);
emperor_add(ues, config_file, uwsgi_now(), NULL, 0, 0, 0, NULL);
}
free(config_file);
+4 -2
View File
@@ -1,4 +1,4 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
#include "client/dbclient.h"
@@ -60,7 +60,9 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues
vassal_gid = tmp_gid;
}
uwsgi_emperor_simple_do(ues, (char *) name, (char *) config, vassal_ts/1000, vassal_uid, vassal_gid);
const char *socket_name = p.getStringField("socket");
uwsgi_emperor_simple_do(ues, (char *) name, (char *) config, vassal_ts/1000, vassal_uid, vassal_gid, (char *) socket_name);
}
+1 -1
View File
@@ -1,4 +1,4 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *);
void uwsgi_imperial_monitor_mongodb_init(struct uwsgi_emperor_scanner *);
+8 -1
View File
@@ -1,7 +1,14 @@
import os
NAME='emperor_mongodb'
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
LDFLAGS = []
LIBS = ['-lmongoclient', '-lboost_thread','-lboost_filesystem']
LIBS = []
if not 'UWSGI_MONGODB_NOLIB' in os.environ:
LIBS.append('-lmongoclient')
LIBS.append('-lboost_thread')
LIBS.append('-lboost_filesystem')
GCC_LIST = ['plugin', 'emperor_mongodb.cc']
+5 -1
View File
@@ -68,7 +68,11 @@ void uwsgi_imperial_monitor_pg(struct uwsgi_emperor_scanner *ues) {
vassal_uid = uwsgi_str_num(q_uid, strlen(q_uid));
vassal_gid = uwsgi_str_num(q_gid, strlen(q_gid));
}
uwsgi_emperor_simple_do(ues, name, config, uwsgi_str_num(ts, len), vassal_uid, vassal_gid);
char *socket_name = NULL;
if (PQnfields(res) > 5) {
socket_name = PQgetvalue(res, i, 5);
}
uwsgi_emperor_simple_do(ues, name, config, uwsgi_str_num(ts, len), vassal_uid, vassal_gid, socket_name);
}
}
+23 -4
View File
@@ -64,15 +64,16 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
int64_t more = 0;
size_t more_size = sizeof(more);
int i;
zmq_msg_t msg[5];
zmq_msg_t msg[6];
zmq_msg_init(&msg[0]);
zmq_msg_init(&msg[1]);
zmq_msg_init(&msg[2]);
zmq_msg_init(&msg[3]);
zmq_msg_init(&msg[4]);
zmq_msg_init(&msg[5]);
for(i=0;i<5;i++) {
for(i=0;i<6;i++) {
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
zmq_recvmsg(ues->data, &msg[i], ZMQ_DONTWAIT);
#else
@@ -105,6 +106,11 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
char *ez_gid = NULL;
size_t ez_gid_len = 0;
char *ez_socket_name = NULL;
size_t ez_socket_name_len = 0;
char *socket_name = NULL;
// config
if (i > 1) {
ez_config = zmq_msg_data(&msg[2]);
@@ -123,6 +129,12 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
ez_gid_len = zmq_msg_size(&msg[4]);
}
// gid
if (i > 4) {
ez_socket_name = zmq_msg_data(&msg[5]);
ez_socket_name_len = zmq_msg_size(&msg[5]);
}
char *name = uwsgi_concat2n(ez_name, ez_name_len, "", 0);
// ok let's start checking commands
@@ -142,10 +154,16 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
vassal_gid = uwsgi_str_num(ez_gid, ez_gid_len);
}
uwsgi_emperor_simple_do(ues, name, config, uwsgi_now(), vassal_uid, vassal_gid);
if (ez_socket_name) {
socket_name = uwsgi_concat2n(ez_socket_name, ez_socket_name_len, "", 0);
}
uwsgi_emperor_simple_do(ues, name, config, uwsgi_now(), vassal_uid, vassal_gid, socket_name);
if (config) {
free(config);
}
if (socket_name) {
free(socket_name);
}
}
// destroy an instance
else if (!uwsgi_strncmp(ez_cmd, ez_cmd_len, "destroy", 6)) {
@@ -158,7 +176,7 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
}
}
else {
uwsgi_log("[emperor-zeromq] unkonwn command \"%.*s\"\n", (int)ez_cmd_len, ez_cmd);
uwsgi_log("[emperor-zeromq] unknown command \"%.*s\"\n", (int)ez_cmd_len, ez_cmd);
}
free(name);
@@ -168,6 +186,7 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
zmq_msg_close(&msg[2]);
zmq_msg_close(&msg[3]);
zmq_msg_close(&msg[4]);
zmq_msg_close(&msg[5]);
}
// this is the event manager
+2 -1
View File
@@ -2,6 +2,7 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_rack ur;
extern struct uwsgi_plugin rack_plugin;
struct ufib {
int enabled;
@@ -45,7 +46,7 @@ static void fiber_schedule_to_req() {
int error = 0;
rb_protect(rb_fiber_schedule_to_req, 0, &error);
if (error) {
uwsgi_ruby_exception();
rack_plugin.exception_log(NULL);
rb_gc_unregister_address(&ufiber.fib[id]);
uwsgi.wsgi_req->async_status = UWSGI_OK;
}
+141
View File
@@ -0,0 +1,141 @@
#include <uwsgi.h>
#include <GeoIP.h>
#include <GeoIPCity.h>
struct uwsgi_geoip {
char *country_db;
char *city_db;
GeoIP *country;
GeoIP *city;
} ugeoip;
struct uwsgi_option uwsgi_geoip_options[] = {
{"geoip-country", required_argument, 0, "load the specified geoip country database", uwsgi_opt_set_str, &ugeoip.country_db, 0},
{"geoip-city", required_argument, 0, "load the specified geoip city database", uwsgi_opt_set_str, &ugeoip.city_db, 0},
{ 0, 0, 0, 0, 0, 0, 0 }
};
static int uwsgi_geoip_init() {
if (ugeoip.country_db) {
ugeoip.country = GeoIP_open(ugeoip.country_db, GEOIP_MEMORY_CACHE);
if (!ugeoip.country) {
uwsgi_log("unable to open GeoIP country database: %s\n", ugeoip.country_db);
exit(1);
}
}
if (ugeoip.city_db) {
ugeoip.city = GeoIP_open(ugeoip.city_db, GEOIP_MEMORY_CACHE);
if (!ugeoip.city) {
uwsgi_log("unable to open GeoIP city database: %s\n", ugeoip.city_db);
exit(1);
}
}
return 0;
}
static char *uwsgi_route_var_geoip(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
uint32_t ip;
char ip_str[16];
// should be enough for geo coords
char lonlat[64];
memset(ip_str, 0, 16);
memcpy(ip_str, wsgi_req->remote_addr, wsgi_req->remote_addr_len);
if (inet_pton(AF_INET, ip_str, &ip) <= 0) {
return NULL;
}
ip = htonl(ip);
char *value = NULL;
// always prefer the city database;
GeoIP *g = ugeoip.city;
if (!g) {
g = ugeoip.country;
if (g) {
if (!uwsgi_strncmp(key, keylen, "country_code", 12)) {
value = (char *) GeoIP_country_code_by_ipnum(g, ip);
}
else if (!uwsgi_strncmp(key, keylen, "country_code3", 13)) {
value = (char *) GeoIP_country_code3_by_ipnum(g, ip);
}
else if (!uwsgi_strncmp(key, keylen, "country_name", 12)) {
value = (char *) GeoIP_country_name_by_ipnum(g, ip);
}
if (value) {
*vallen = strlen(value);
return uwsgi_str(value);
}
}
return NULL;
}
GeoIPRecord *gr = GeoIP_record_by_ipnum(g, ip);
if (!gr) return NULL;
// ok let's generate the output
if (!uwsgi_strncmp(key, keylen, "continent", 9)) {
value = gr->continent_code;
}
else if (!uwsgi_strncmp(key, keylen, "country_code", 12)) {
value = gr->country_code;
}
else if (!uwsgi_strncmp(key, keylen, "country_code3", 13)) {
value = gr->country_code3;
}
else if (!uwsgi_strncmp(key, keylen, "country_name", 12)) {
value = gr->country_name;
}
else if (!uwsgi_strncmp(key, keylen, "region", 6)) {
value = gr->region;
}
else if (!uwsgi_strncmp(key, keylen, "region_name", 11)) {
value = (char *) GeoIP_region_name_by_code(gr->country_code, gr->region);
}
else if (!uwsgi_strncmp(key, keylen, "city", 4)) {
value = gr->city;
}
else if (!uwsgi_strncmp(key, keylen, "postal_code", 11)) {
value = gr->postal_code;
}
else if (!uwsgi_strncmp(key, keylen, "latitude", 8) || !uwsgi_strncmp(key, keylen, "lat", 3)) {
snprintf(lonlat, 64, "%f", gr->latitude);
value = lonlat;
}
else if (!uwsgi_strncmp(key, keylen, "longitude", 9) || !uwsgi_strncmp(key, keylen, "lon", 3)) {
snprintf(lonlat, 64, "%f", gr->longitude);
value = lonlat;
}
else if (!uwsgi_strncmp(key, keylen, "dma", 3)) {
snprintf(lonlat, 64, "%d", gr->dma_code);
value = lonlat;
}
else if (!uwsgi_strncmp(key, keylen, "area", 4)) {
snprintf(lonlat, 64, "%d", gr->area_code);
value = lonlat;
}
if (value) {
*vallen = strlen(value);
char *ret = uwsgi_str(value);
GeoIPRecord_delete(gr);
return ret;
}
GeoIPRecord_delete(gr);
return NULL;
}
static void register_route_vars_geoip() {
struct uwsgi_route_var *urv = uwsgi_register_route_var("geoip", uwsgi_route_var_geoip);
urv->need_free = 1;
}
struct uwsgi_plugin geoip_plugin = {
.name = "geoip",
.options = uwsgi_geoip_options,
.init = uwsgi_geoip_init,
.on_load = register_route_vars_geoip,
};
+8
View File
@@ -0,0 +1,8 @@
NAME='geoip'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lGeoIP']
GCC_LIST = ['geoip']
+20 -6
View File
@@ -36,15 +36,15 @@ else:
JVM_LIBPATH = ["-L%s/jre/lib/%s/server" % (jvm, arch)]
break
try:
try:
JVM_INCPATH = ['-I"' + os.environ['UWSGICONFIG_JVM_INCPATH'] + '"']
except:
pass
except:
pass
try:
try:
JVM_LIBPATH = ['-L"' + os.environ['UWSGICONFIG_JVM_LIBPATH'] + '"']
except:
pass
except:
pass
if not JVM_INCPATH or not JVM_LIBPATH:
print("unable to autodetect the JVM path, please specify UWSGICONFIG_JVM_INCPATH and UWSGICONFIG_JVM_LIBPATH environment vars")
@@ -69,3 +69,17 @@ def post_build(config):
if os.system("cd %s/plugins/jvm ; jar cvf uwsgi.jar *.class" % os.getcwd()) != 0:
os._exit(1)
print("*** uwsgi.jar available in %s/plugins/jvm/uwsgi.jar ***" % os.getcwd())
env = os.environ.get('VIRTUAL_ENV')
if env:
src = "%s/plugins/jvm/uwsgi.jar" % os.getcwd()
tgt = "%s/lib/uwsgi.jar" % env
shutil.copyfile(src, tgt)
print("*** uwsgi.jar had been copied to %s" % tgt)
plugin = "%s/jvm_plugin.so" % os.getcwd()
if os.path.exists(plugin):
tgt = "%s/bin/jvm_plugin.so" % env
shutil.copyfile(plugin, tgt)
print("*** jvm_plugin.so had been copied to %s" % tgt)
+173
View File
@@ -0,0 +1,173 @@
#include <uwsgi.h>
/*
this is an UDP logger encrypting each packet with the choosen algo, key and iv.
It is useful in cloud services without persistent storage for which you want to send logs to an external system.
Syntax: --logger/--req-logger crypto:addr=<udp_address>,algo=<algorithm>,secret=<key>,iv=<iv>,prefix=<prefix>
example:
uwsgi --plugin logcrypto --logger crypto:addr=127.0.0.1:1717,algo=bf-cbc,secret=ciaociao -M -p 4 -s :3031
*/
extern struct uwsgi_server uwsgi;
struct uwsgi_crypto_logger_conf {
EVP_CIPHER_CTX *encrypt_ctx;
char *addr;
char *algo;
char *secret;
char *iv;
char *prefix;
size_t prefix_len;
};
static void uwsgi_crypto_logger_setup_encryption(struct uwsgi_crypto_logger_conf *uclc) {
if (!uwsgi.ssl_initialized) {
uwsgi_ssl_init();
}
uclc->encrypt_ctx = uwsgi_malloc(sizeof(EVP_CIPHER_CTX));
EVP_CIPHER_CTX_init(uclc->encrypt_ctx);
const EVP_CIPHER *cipher = EVP_get_cipherbyname(uclc->algo);
if (!cipher) {
uwsgi_log_safe("[uwsgi-logcrypto] unable to find algorithm/cipher\n");
exit(1);
}
int cipher_len = EVP_CIPHER_key_length(cipher);
size_t s_len = strlen(uclc->secret);
if ((unsigned int) cipher_len > s_len) {
char *secret_tmp = uwsgi_malloc(cipher_len);
memcpy(secret_tmp, uclc->secret, s_len);
memset(secret_tmp + s_len, 0, cipher_len - s_len);
uclc->secret = secret_tmp;
}
int iv_len = EVP_CIPHER_iv_length(cipher);
size_t s_iv_len = 0;
if (uclc->iv) {
s_iv_len = strlen(uclc->iv);
}
if ((unsigned int) iv_len > s_iv_len) {
char *secret_tmp = uwsgi_malloc(iv_len);
memcpy(secret_tmp, uclc->iv, s_iv_len);
memset(secret_tmp + s_iv_len, '0', iv_len - s_iv_len);
uclc->iv = secret_tmp;
}
if (EVP_EncryptInit_ex(uclc->encrypt_ctx, cipher, NULL, (const unsigned char *) uclc->secret, (const unsigned char *) uclc->iv) <= 0) {
uwsgi_error_safe("uwsgi_crypto_logger_setup_encryption()/EVP_EncryptInit_ex()");
exit(1);
}
}
static ssize_t uwsgi_crypto_logger(struct uwsgi_logger *ul, char *message, size_t len) {
struct uwsgi_crypto_logger_conf *uclc = (struct uwsgi_crypto_logger_conf *) ul->data;
if (!ul->configured) {
uclc = uwsgi_calloc(sizeof(struct uwsgi_crypto_logger_conf));
if (uwsgi_kvlist_parse(ul->arg, strlen(ul->arg), ',', '=',
"addr", &uclc->addr,
"algo", &uclc->algo,
"secret", &uclc->secret,
"iv", &uclc->iv,
"prefix", &uclc->prefix,
NULL)) {
uwsgi_log_safe("[uwsgi-logcrypto] unable to parse options\n");
exit(1);
}
if (!uclc->addr || !uclc->algo || !uclc->secret) {
uwsgi_log_safe("[uwsgi-logcrypto] you have to specify at least addr,algo and secret options\n");
exit(1);
}
if (uclc->prefix) {
uclc->prefix_len = strlen(uclc->prefix);
}
char *colon = strchr(uclc->addr, ':');
if (!colon) {
uwsgi_log_safe("[uwsgi-logcrypto] invalid UDP address\n");
exit(1);
}
ul->addr_len = socket_to_in_addr(uclc->addr, colon, 0, &ul->addr.sa_in);
ul->fd = socket(AF_INET, SOCK_DGRAM, 0);
if (ul->fd < 0) {
uwsgi_error_safe("uwsgi_crypto_logger()/socket()");
exit(1);
}
uwsgi_crypto_logger_setup_encryption(uclc);
ul->data = uclc;
ul->configured = 1;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
if (uwsgi_buffer_num64(ub, uwsgi_micros())) goto error;
if (uwsgi_buffer_append(ub, " ", 1)) goto error;
if (uclc->prefix) {
if (uwsgi_buffer_append(ub, uclc->prefix, uclc->prefix_len)) goto error;
if (uwsgi_buffer_append(ub, " ", 1)) goto error;
}
if (uwsgi_buffer_append(ub, message, len)) goto error;
// let's encrypt the message
unsigned char *encrypted = uwsgi_malloc(ub->pos + EVP_MAX_BLOCK_LENGTH);
if (EVP_EncryptInit_ex(uclc->encrypt_ctx, NULL, NULL, NULL, NULL) <= 0) {
uwsgi_error_safe("[uwsgi-logcrypto] EVP_EncryptInit_ex()");
free(encrypted);
goto error;
}
int e_len = 0;
if (EVP_EncryptUpdate(uclc->encrypt_ctx, encrypted, &e_len, (unsigned char *) ub->buf, ub->pos) <= 0) {
uwsgi_error("[uwsgi-logcrypto] EVP_EncryptUpdate()");
free(encrypted);
goto error;
}
int tmplen = 0;
if (EVP_EncryptFinal_ex(uclc->encrypt_ctx, encrypted + e_len, &tmplen) <= 0) {
uwsgi_error("[uwsgi-logcrypto] EVP_EncryptFinal_ex()");
free(encrypted);
goto error;
}
uwsgi_buffer_destroy(ub);
ssize_t rlen = sendto(ul->fd, encrypted, e_len + tmplen, 0, (struct sockaddr *) &ul->addr.sa_in, ul->addr_len);
free(encrypted);
return rlen;
error:
uwsgi_buffer_destroy(ub);
return -1;
}
static void uwsgi_logcrypto_register() {
uwsgi_register_logger("crypto", uwsgi_crypto_logger);
}
struct uwsgi_plugin logcrypto_plugin = {
.name = "logcrypto",
.on_load = uwsgi_logcrypto_register,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='logcrypto'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['logcrypto']
+9
View File
@@ -0,0 +1,9 @@
#include <uwsgi.h>
#include "client/dbclient.h"
extern "C" int uwsgi_mongodb_version() {
// this is only a hack to force the linked to embed libmongoclient.a
mongo::DBClientConnection c;
return 0;
}
+14
View File
@@ -0,0 +1,14 @@
#include <uwsgi.h>
/*
a fake plugin used for preloading mongodb library when only available as static.
*/
int uwsgi_mongodb_version(void);
struct uwsgi_plugin mongodb_plugin = {
.name = "mongodb",
.init = uwsgi_mongodb_version,
};
+8
View File
@@ -0,0 +1,8 @@
NAME='mongodb'
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
LDFLAGS = []
LIBS = ['-lmongoclient', '-lboost_thread','-lboost_filesystem']
GCC_LIST = ['plugin', 'foobar.cc']
-4
View File
@@ -55,7 +55,6 @@ void uwsgi_opt_pyver(char *opt, char *foo, void *bar) {
}
#ifdef UWSGI_INI
void uwsgi_opt_ini_paste(char *opt, char *value, void *foobar) {
uwsgi_opt_load_ini(opt, value, NULL);
@@ -72,7 +71,6 @@ void uwsgi_opt_ini_paste(char *opt, char *value, void *foobar) {
}
}
#endif
struct uwsgi_option uwsgi_python_options[] = {
{"wsgi-file", required_argument, 0, "load .wsgi file", uwsgi_opt_set_str, &up.file_config, 0},
@@ -121,10 +119,8 @@ struct uwsgi_option uwsgi_python_options[] = {
{"web3", required_argument, 0, "load a web3 app", uwsgi_opt_set_str, &up.web3, 0},
{"pump", required_argument, 0, "load a pump app", uwsgi_opt_set_str, &up.pump, 0},
{"wsgi-lite", required_argument, 0, "load a wsgi-lite app", uwsgi_opt_set_str, &up.wsgi_lite, 0},
#ifdef UWSGI_INI
{"ini-paste", required_argument, 0, "load a paste.deploy config file containing uwsgi section", uwsgi_opt_ini_paste, NULL, UWSGI_OPT_IMMEDIATE},
{"ini-paste-logged", required_argument, 0, "load a paste.deploy config file containing uwsgi section (load loggers too)", uwsgi_opt_ini_paste, NULL, UWSGI_OPT_IMMEDIATE},
#endif
{"reload-os-env", no_argument, 0, "force reload of os.environ at each request", uwsgi_opt_true, &up.reload_os_env, 0},
#ifndef __CYGWIN__
#ifndef UWSGI_PYPY
+32
View File
@@ -474,6 +474,37 @@ PyObject *py_uwsgi_lord_scroll(PyObject * self, PyObject * args) {
return ret;
}
static void scrolls_items(uint16_t pos, char *key, uint16_t keylen, void *data) {
PyObject *list = (PyObject *) data;
PyObject *zero = PyString_FromStringAndSize(key, keylen);
PyList_Append(list, zero);
Py_DECREF(zero);
}
PyObject *py_uwsgi_scrolls(PyObject * self, PyObject * args) {
char *legion_name = NULL;
if (!PyArg_ParseTuple(args, "s:scrolls", &legion_name)) {
return NULL;
}
uint64_t rlen = 0;
char *buf = uwsgi_legion_scrolls(legion_name, &rlen);
if (!buf) goto end;
PyObject *list = PyList_New(0);
if (uwsgi_hooked_parse_array(buf, rlen, scrolls_items, list)) {
goto error;
}
free(buf);
return list;
error:
free(buf);
end:
Py_INCREF(Py_None);
return Py_None;
}
#endif
PyObject *py_uwsgi_register_signal(PyObject * self, PyObject * args) {
@@ -2434,6 +2465,7 @@ static PyMethodDef uwsgi_advanced_methods[] = {
#ifdef UWSGI_SSL
{"i_am_the_lord", py_uwsgi_i_am_the_lord, METH_VARARGS, ""},
{"lord_scroll", py_uwsgi_lord_scroll, METH_VARARGS, ""},
{"scrolls", py_uwsgi_scrolls, METH_VARARGS, ""},
#endif
{"async_sleep", py_uwsgi_async_sleep, METH_VARARGS, ""},
{"async_connect", py_uwsgi_async_connect, METH_VARARGS, ""},
+22 -8
View File
@@ -58,11 +58,12 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
char *status_line = NULL;
size_t status_line_len = 0;
#ifdef PYTHREE
PyObject *zero = NULL;
PyObject *zero2 = NULL;
if (self != Py_None) {
PyObject *zero = PyUnicode_AsASCIIString(head);
zero = PyUnicode_AsASCIIString(head);
status_line = PyBytes_AsString(zero);
status_line_len = PyBytes_Size(zero);
Py_DECREF(zero);
}
else {
status_line = PyBytes_AsString(head);
@@ -73,9 +74,15 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
status_line_len = PyString_Size(head);
#endif
if (uwsgi_response_prepare_headers(wsgi_req, status_line, status_line_len)) {
#ifdef PYTHREE
Py_DECREF(zero);
#endif
return PyErr_Format(PyExc_TypeError, "unable to set HTTP status line");
}
#ifdef PYTHREE
Py_DECREF(zero);
#endif
headers = PyTuple_GetItem(args, 1);
if (!headers) {
@@ -125,10 +132,9 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
#ifdef PYTHREE
if (self != Py_None) {
PyObject *zero = PyUnicode_AsASCIIString(h_key);
zero = PyUnicode_AsASCIIString(h_key);
k = PyBytes_AsString(zero);
kl = PyBytes_Size(zero);
Py_DECREF(zero);
}
else {
k = PyBytes_AsString(h_key);
@@ -141,10 +147,9 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
#ifdef PYTHREE
if (self != Py_None) {
PyObject *zero = PyUnicode_AsASCIIString(h_value);
v = PyBytes_AsString(zero);
vl = PyBytes_Size(zero);
Py_DECREF(zero);
zero2 = PyUnicode_AsASCIIString(h_value);
v = PyBytes_AsString(zero2);
vl = PyBytes_Size(zero2);
}
else {
v = PyBytes_AsString(h_value);
@@ -156,9 +161,18 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
#endif
if (uwsgi_response_add_header(wsgi_req, k, kl, v, vl)) {
#ifdef PYTHREE
Py_DECREF(zero);
Py_DECREF(zero2);
#endif
return PyErr_Format(PyExc_TypeError, "unable to add header to the response");
}
#ifdef PYTHREE
Py_DECREF(zero);
Py_DECREF(zero2);
#endif
}
if (up.start_response_nodelay) {
+14 -14
View File
@@ -320,7 +320,7 @@ uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[],
ret = rb_protect(rack_call_rpc_handler, rb_args, &error);
if (error) {
uwsgi_manage_exception(NULL, 0);
uwsgi_ruby_exception_log(NULL);
return 0;
}
@@ -489,7 +489,7 @@ void uwsgi_rack_preinit_apps() {
int error = 0;
rb_protect( uwsgi_require_file, rb_str_new2(usl->value), &error ) ;
if (error) {
uwsgi_manage_exception(NULL, 0);
uwsgi_ruby_exception_log(NULL);
}
usl = usl->next;
}
@@ -519,7 +519,7 @@ void uwsgi_rack_init_apps(void) {
error = 0;
rb_protect( uwsgi_require_file, rb_str_new2(usl->value), &error ) ;
if (error) {
uwsgi_manage_exception(NULL, 0);
uwsgi_ruby_exception_log(NULL);
}
usl = usl->next;
}
@@ -527,7 +527,7 @@ void uwsgi_rack_init_apps(void) {
if (ur.rack) {
ur.dispatcher = rb_protect(init_rack_app, rb_str_new2(ur.rack), &error);
if (error) {
uwsgi_manage_exception(NULL, 0);
uwsgi_ruby_exception_log(NULL);
exit(1);
}
if (ur.dispatcher == Qnil) {
@@ -551,7 +551,7 @@ void uwsgi_rack_init_apps(void) {
uwsgi_log("loading rails app %s\n", ur.rails);
rb_protect( require_rails, 0, &error ) ;
if (error) {
uwsgi_manage_exception(NULL, 0);
uwsgi_ruby_exception_log(NULL);
exit(1);
}
uwsgi_log("rails app %s ready\n", ur.rails);
@@ -573,7 +573,7 @@ void uwsgi_rack_init_apps(void) {
if (acim_call == Qtrue) {
ur.dispatcher = rb_protect(uwsgi_rb_call_new, ac_dispatcher, &error);
if (error) {
uwsgi_manage_exception(NULL, 0);
uwsgi_ruby_exception_log(NULL);
exit(1);
}
}
@@ -583,7 +583,7 @@ void uwsgi_rack_init_apps(void) {
uwsgi_log("non-rack rails version detected...loading thin adapter...\n");
rb_protect( require_thin, 0, &error ) ;
if (error) {
uwsgi_manage_exception(NULL, 0);
uwsgi_ruby_exception_log(NULL);
exit(1);
}
VALUE thin_rack = rb_const_get(rb_cObject, rb_intern("Rack"));
@@ -591,7 +591,7 @@ void uwsgi_rack_init_apps(void) {
VALUE thin_rack_adapter_rails = rb_const_get(thin_rack_adapter, rb_intern("Rails"));
ur.dispatcher = rb_protect( uwsgi_rb_call_new, thin_rack_adapter_rails, &error);
if (error) {
uwsgi_manage_exception(NULL, 0);
uwsgi_ruby_exception_log(NULL);
exit(1);
}
}
@@ -963,7 +963,7 @@ VALUE init_rack_app( VALUE script ) {
#endif
rb_protect( require_rack, 0, &error ) ;
if (error) {
uwsgi_manage_exception(NULL, 0);
uwsgi_ruby_exception_log(NULL);
return Qnil;
}
@@ -1038,7 +1038,7 @@ int uwsgi_rack_mule(char *opt) {
if (uwsgi_endswith(opt, (char *)".rb")) {
rb_protect( uwsgi_require_file, rb_str_new2(opt), &error ) ;
if (error) {
uwsgi_manage_exception(NULL, 0);
uwsgi_ruby_exception_log(NULL);
return 0;
}
return 1;
@@ -1063,7 +1063,7 @@ void uwsgi_rb_post_fork() {
// call the post_fork_hook
rb_protect(uwsgi_rb_pfh, 0, &error);
if (error) {
uwsgi_manage_exception(NULL, 0);
uwsgi_ruby_exception_log(NULL);
}
}
@@ -1081,7 +1081,7 @@ int uwsgi_rack_mule_msg(char *message, size_t len) {
VALUE arg = rb_str_new(message, len);
rb_protect(uwsgi_rb_mmh, arg, &error);
if (error) {
uwsgi_manage_exception(NULL, 0);
uwsgi_ruby_exception_log(NULL);
}
return 1;
}
@@ -1107,7 +1107,7 @@ int uwsgi_rack_signal_handler(uint8_t sig, void *handler) {
rb_ary_store(args, 1, rbsig);
rb_protect(rack_call_signal_handler, args, &error);
if (error) {
uwsgi_manage_exception(NULL, 0);
uwsgi_ruby_exception_log(NULL);
rb_gc();
return -1;
}
@@ -1155,7 +1155,7 @@ int uwsgi_rack_spooler(char *filename, char *buf, uint16_t len, char *body, size
VALUE ret = rb_protect(uwsgi_rb_do_spooler, spool_dict, &error);
if (error) {
uwsgi_manage_exception(NULL, 0);
uwsgi_ruby_exception_log(NULL);
rb_gc();
return -1;
}
+13
View File
@@ -1,3 +1,6 @@
import os
import shutil
jvm_path = 'plugins/jvm'
up = {}
@@ -14,3 +17,13 @@ CFLAGS.append('-I%s' % jvm_path)
LDFLAGS = []
LIBS = []
GCC_LIST = ['ring_plugin']
def post_build(config):
env = os.environ.get('VIRTUAL_ENV')
if env:
plugin = "%s/ring_plugin.so" % os.getcwd()
if os.path.exists(plugin):
tgt = "%s/bin/ring_plugin.so" % env
shutil.copyfile(plugin, tgt)
print("*** ring_plugin.so had been copied to %s" % tgt)
+97 -66
View File
@@ -10,83 +10,133 @@ extern struct uwsgi_server uwsgi;
syntax:
route = /^foobar1(.*)/ cache:key=foo$1poo,type=body
route = /^foobar1 cache:var=PATH_INFO,type=body
route = /^foobar2 cache:var=REQUEST_URI,type=full
route = /^foobar3 cache:var=REQUEST_URI,type=body,content_type=text/html
route = /^foobar1(.*)/ cache:key=foo$1poo,content_type=text/html,name=foobar
*/
struct uwsgi_router_cache_conf {
// the name of the cache
char *name;
size_t name_len;
char *key;
size_t key_len;
char *var;
char *type;
long var_offset;
long var_offset_len;
char *content_type;
char *name;
size_t content_type_len;
// 0 -> full, 1 -> body
int type_num;
struct uwsgi_cache *cache;
char *expires_str;
uint64_t expires;
};
// be tolerant on errors
static int uwsgi_routing_func_cache_store(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_router_cache_conf *urcc = (struct uwsgi_router_cache_conf *) ur->data2;
// overwrite previous run
if (wsgi_req->cache_it) {
uwsgi_buffer_destroy(wsgi_req->cache_it);
wsgi_req->cache_it = NULL;
}
if (wsgi_req->cache_it_to) {
uwsgi_buffer_destroy(wsgi_req->cache_it_to);
wsgi_req->cache_it_to = NULL;
}
// build key and name
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
wsgi_req->cache_it = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->key, urcc->key_len);
if (!wsgi_req->cache_it) return UWSGI_ROUTE_NEXT;
if (urcc->name) {
wsgi_req->cache_it_to = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->name, urcc->name_len);
if (!wsgi_req->cache_it_to) {
uwsgi_buffer_destroy(wsgi_req->cache_it);
wsgi_req->cache_it = NULL;
}
}
wsgi_req->cache_it_expires = urcc->expires;
return UWSGI_ROUTE_NEXT;
}
static int uwsgi_routing_func_cache(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_router_cache_conf *urcc = (struct uwsgi_router_cache_conf *) ur->data2;
if (!uwsgi.cache_max_items) return UWSGI_ROUTE_NEXT;
char *c_k = NULL;
uint16_t c_k_len = 0;
int k_need_free = 0;
if (urcc->key) {
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
c_k = uwsgi_regexp_apply_ovec(*subject, *subject_len, urcc->key, urcc->key_len, ur->ovector, ur->ovn);
c_k_len = strlen(c_k);
k_need_free = 1;
}
else {
char **key = (char **) (((char *) wsgi_req) + urcc->var_offset);
uint16_t *keylen = (uint16_t *) (((char *) wsgi_req) + urcc->var_offset_len);
c_k = *key;
c_k_len = *keylen;
}
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->key, urcc->key_len);
if (!ub) return UWSGI_ROUTE_BREAK;
uint64_t valsize = 0;
char *value = uwsgi_cache_magic_get(c_k, c_k_len, &valsize, urcc->name);
char *value = uwsgi_cache_magic_get(ub->buf, ub->pos, &valsize, urcc->name);
uwsgi_buffer_destroy(ub);
if (value) {
if (urcc->type_num == 1) {
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto error;
if (uwsgi_response_add_content_type(wsgi_req, urcc->content_type, urcc->content_type_len)) goto error;
if (uwsgi_response_add_content_length(wsgi_req, valsize)) goto error;
}
// body only
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto error;
if (uwsgi_response_add_content_type(wsgi_req, urcc->content_type, urcc->content_type_len)) goto error;
if (uwsgi_response_add_content_length(wsgi_req, valsize)) goto error;
uwsgi_response_write_body_do(wsgi_req, value, valsize);
free(value);
if (k_need_free) free(c_k);
if (ur->custom)
return UWSGI_ROUTE_NEXT;
return UWSGI_ROUTE_BREAK;
}
if (k_need_free) free(c_k);
return UWSGI_ROUTE_NEXT;
error:
free(value);
if (k_need_free) free(c_k);
return UWSGI_ROUTE_BREAK;
}
static int uwsgi_router_cache_store(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_cache_store;
ur->data = args;
ur->data_len = strlen(args);
struct uwsgi_router_cache_conf *urcc = uwsgi_calloc(sizeof(struct uwsgi_router_cache_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"key", &urcc->key,
"name", &urcc->name,
"expires", &urcc->expires_str, NULL)) {
uwsgi_log("invalid cachestore route syntax: %s\n", args);
goto error;
}
if (urcc->key) {
urcc->key_len = strlen(urcc->key);
}
if (urcc->name) {
urcc->name_len = strlen(urcc->name);
}
if (!urcc->key) {
uwsgi_log("invalid cachestore route syntax: you need to specify a cache key\n");
goto error;
}
if (urcc->expires_str) {
urcc->expires = strtoul(urcc->expires_str, NULL, 10);
}
ur->data2 = urcc;
return 0;
error:
if (urcc->key) free(urcc->key);
if (urcc->name) free(urcc->name);
if (urcc->expires_str) free(urcc->expires_str);
return -1;
}
static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_cache;
ur->data = args;
@@ -94,10 +144,9 @@ static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) {
struct uwsgi_router_cache_conf *urcc = uwsgi_calloc(sizeof(struct uwsgi_router_cache_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"key", &urcc->key,
"var", &urcc->var,
"content_type", &urcc->content_type,
"name", &urcc->name,
"type", &urcc->type, NULL)) {
NULL)) {
uwsgi_log("invalid route syntax: %s\n", args);
exit(1);
}
@@ -106,35 +155,15 @@ static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) {
urcc->key_len = strlen(urcc->key);
}
if (!urcc->key && !urcc->var) {
uwsgi_log("invalid route syntax: you need to specify a cache key or var\n");
if (!urcc->key) {
uwsgi_log("invalid route syntax: you need to specify a cache key\n");
exit(1);
}
if (!urcc->type) urcc->type = "full";
if (!urcc->content_type) urcc->content_type = "text/html";
urcc->content_type_len = strlen(urcc->content_type);
if (urcc->var) {
if (!strcmp(urcc->var, "REQUEST_URI")) {
urcc->var_offset = offsetof(struct wsgi_request, uri);
urcc->var_offset_len = offsetof(struct wsgi_request, uri_len);
}
else if (!strcmp(urcc->var, "PATH_INFO")) {
urcc->var_offset = offsetof(struct wsgi_request, path_info);
urcc->var_offset_len = offsetof(struct wsgi_request, path_info_len);
}
else {
urcc->var_offset = offsetof(struct wsgi_request, uri);
urcc->var_offset_len = offsetof(struct wsgi_request, uri_len);
}
}
if (!strcmp(urcc->type, "body")) {
urcc->type_num = 1;
}
ur->data2 = urcc;
return 0;
}
@@ -148,6 +177,8 @@ static int uwsgi_router_cache_continue(struct uwsgi_route *ur, char *args) {
static void router_cache_register() {
uwsgi_register_router("cache", uwsgi_router_cache);
uwsgi_register_router("cache-continue", uwsgi_router_cache_continue);
uwsgi_register_router("cachestore", uwsgi_router_cache_store);
uwsgi_register_router("cache-store", uwsgi_router_cache_store);
}
struct uwsgi_plugin router_cache_plugin = {
+103
View File
@@ -40,10 +40,113 @@ static int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
return UWSGI_OK;
}
#ifdef UWSGI_ROUTING
static int uwsgi_routing_func_rpc(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
int ret = -1;
// this is the list of args
char *argv[UMAX8];
// this is the size of each argument
uint16_t argvs[UMAX8];
// this is a placeholder for tmp uwsgi_buffers
struct uwsgi_buffer *ubs[UMAX8];
char **r_argv = (char **) ur->data2;
uint16_t *r_argvs = (uint16_t *) ur->data3;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
uint64_t i;
for(i=0;i<ur->custom;i++) {
ubs[i] = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, r_argv[i], r_argvs[i]);
if (!ubs[i]) goto end;
argv[i] = ubs[i]->buf;
argvs[i] = ubs[i]->pos;
}
// ok we now need to check it it is a local call or a remote one
char *func = uwsgi_str(ur->data);
char *remote = NULL;
char *at = strchr(func, '@');
if (at) {
*at = 0;
remote = at+1;
}
uint16_t size;
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
free(func);
if (!response) goto end;
ret = UWSGI_ROUTE_BREAK;
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) {free(response) ; goto end;}
if (uwsgi_response_add_content_length(wsgi_req, size)) {free(response) ; goto end;}
uwsgi_response_write_body_do(wsgi_req, response, size);
free(response);
end:
for(i=0;i<ur->custom;i++) {
if (ubs[i] != NULL) {
uwsgi_buffer_destroy(ubs[i]);
}
}
return ret;
}
/*
ur->data = the func name
ur->custom = the number of arguments
ur->data2 = the pointer to the args
ur->data3 = the pointer to the args sizes
*/
static int uwsgi_router_rpc(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_rpc;
ur->custom = 0;
ur->data2 = uwsgi_calloc(sizeof(char *) * UMAX8);
ur->data3 = uwsgi_calloc(sizeof(uint16_t) * UMAX8);
char *p = strtok(args, " ");
while(p) {
if (!ur->data) {
ur->data = p;
}
else {
if (ur->custom >= UMAX8) {
uwsgi_log("unable to register route: maximum number of rpc args reached\n");
free(ur->data2);
free(ur->data3);
return -1;
}
char **argv = (char **) ur->data2;
uint16_t *argvs = (uint16_t *) ur->data3;
argv[ur->custom] = p;
argvs[ur->custom] = strlen(p);
ur->custom++;
}
p = strtok(NULL, " ");
}
if (!ur->data) {
uwsgi_log("unable to register route: you need to specify an rpc function\n");
free(ur->data2);
free(ur->data3);
return -1;
}
return 0;
}
static void router_rpc_register() {
uwsgi_register_router("call", uwsgi_router_rpc);
uwsgi_register_router("rpc", uwsgi_router_rpc);
}
#endif
struct uwsgi_plugin rpc_plugin = {
.name = "rpc",
.modifier1 = 173,
.request = uwsgi_rpc_request,
#ifdef UWSGI_ROUTING
.on_load = router_rpc_register,
#endif
};
+526
View File
@@ -0,0 +1,526 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
#define UWSGI_SSI_MAX_ARGS 8
/*
uWSGI server side includes implementation
*/
struct uwsgi_ssi_arg {
char *key;
size_t key_len;
char *value;
size_t val_len;
};
struct uwsgi_ssi_cmd {
char *name;
size_t name_len;
struct uwsgi_buffer *(*func)(struct wsgi_request *, struct uwsgi_ssi_arg *, int);
struct uwsgi_ssi_cmd *next;
};
struct uwsgi_ssi_cmd *uwsgi_ssi_commands = NULL;
static struct uwsgi_ssi_cmd* uwsgi_ssi_get_cmd(char *name, size_t name_len) {
struct uwsgi_ssi_cmd *usc = uwsgi_ssi_commands;
while(usc) {
if (!uwsgi_strncmp(usc->name, usc->name_len, name, name_len)) {
return usc;
}
usc = usc->next;
}
return NULL;
}
static struct uwsgi_ssi_cmd *uwsgi_register_ssi_command(char *name, struct uwsgi_buffer *(*func)(struct wsgi_request *, struct uwsgi_ssi_arg *, int)) {
struct uwsgi_ssi_cmd *old_usc = NULL,*usc = uwsgi_ssi_commands;
while(usc) {
if (!strcmp(usc->name, name)) {
return usc;
}
old_usc = usc;
usc = usc->next;
}
usc = uwsgi_calloc(sizeof(struct uwsgi_ssi_cmd));
usc->name = name;
usc->name_len = strlen(name);
usc->func = func;
if (old_usc) {
old_usc->next = usc;
}
else {
uwsgi_ssi_commands = usc;
}
return usc;
}
static int uwsgi_ssi_parse_args(struct wsgi_request *wsgi_req, char *buf, size_t len, struct uwsgi_ssi_arg *argv, int *argc) {
// status [0]null/= [1]" [2]" [3]\s
size_t i;
uint8_t status = 0;
char *key = buf;
size_t key_len = 0;
char *value = NULL;
size_t val_len = 0;
for(i=0;i<len;i++) {
switch(status) {
case 0:
if (buf[i] == '=') {
status = 1;
}
else {
key_len++;
}
break;
case 1:
if (buf[i] == '"') {
status = 2;
}
else {
return -1;
}
break;
case 2:
if (buf[i] == '"') {
status = 3;
argv[*argc].key = key; argv[*argc].key_len = key_len;
argv[*argc].value = value; argv[*argc].val_len = val_len;
*argc = *argc+1;
if (*argc >= UWSGI_SSI_MAX_ARGS) {
return -1;
}
key = NULL;
key_len = 0;
value = NULL;
val_len = 0;
}
else {
if (!value) {
value = buf + i;
}
val_len++;
}
break;
case 3:
if (!isspace((int)buf[i])) {
key = buf + i;
key_len = 1;
status = 0;
}
break;
default:
return -1;
}
}
return 0;
}
static struct uwsgi_buffer *uwsgi_ssi_parse_command(struct wsgi_request *wsgi_req, char *buf, size_t len) {
// storage for arguments
struct uwsgi_ssi_arg argv[UWSGI_SSI_MAX_ARGS];
int argc = 0;
// first remove white spaces from the begin and the end
char *cmd = buf;
size_t cmd_len = len;
size_t i;
for(i=0;i<len;i++) {
if (isspace((int)buf[i])) {
cmd++;
cmd_len--;
}
else {
break;
}
}
// then rstrip (skipping the first char...)
for(i=(len-1);i>0;i--) {
if (isspace((int)buf[i])) {
cmd_len--;
}
else {
break;
}
}
// now get the command
char *ssi_cmd = cmd;
size_t ssi_cmd_len = 0;
int found = 0;
for(i=0;i<cmd_len;i++) {
if (isspace(cmd[i])) {
found = 1;
break;
}
ssi_cmd_len++;
}
struct uwsgi_ssi_cmd *usc = uwsgi_ssi_get_cmd(ssi_cmd, ssi_cmd_len);
if (!usc) return NULL ;
if (!found) goto run;
// now split the args
char *cmd_args = cmd + ssi_cmd_len + 1;
size_t cmd_args_len = cmd_len - (ssi_cmd_len + 1);
for(i=(ssi_cmd_len + 1);i<cmd_len;i++) {
if (isspace((int)cmd[i])) {
cmd_args++;
cmd_args_len--;
}
else {
break;
}
}
if (uwsgi_ssi_parse_args(wsgi_req, cmd_args, cmd_args_len, argv, &argc)) {
return NULL;
}
run:
return usc->func(wsgi_req, argv, argc);
}
static struct uwsgi_buffer *uwsgi_ssi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
size_t i;
uint8_t status = 0;
char *cmd = NULL;
size_t cmd_len = 0;
struct uwsgi_buffer *ub = uwsgi_buffer_new(len);
// parsing status 0[null] 1[<] 2[!] 3[-] 4[-] 5[#/-] 6[-] 7[>]
// on status 6-7-8 the reset action come back to 5 instead of 0
for(i=0;i<len;i++) {
switch(status) {
case 0:
if (buf[i] == '<') {
status = 1;
}
else {
if (uwsgi_buffer_append(ub, &buf[i], 1)) goto error;
}
break;
case 1:
status = 0;
if (buf[i] == '!') {
status = 2;
}
else {
if (uwsgi_buffer_append(ub, "<", 1)) goto error;
if (uwsgi_buffer_append(ub, &buf[i], 1)) goto error;
}
break;
case 2:
status = 0;
if (buf[i] == '-') {
status = 3;
}
else {
if (uwsgi_buffer_append(ub, "<!", 2)) goto error;
if (uwsgi_buffer_append(ub, &buf[i], 1)) goto error;
}
break;
case 3:
status = 0;
if (buf[i] == '-') {
status = 4;
}
else {
if (uwsgi_buffer_append(ub, "<!-", 3)) goto error;
if (uwsgi_buffer_append(ub, &buf[i], 1)) goto error;
}
break;
case 4:
status = 0;
if (buf[i] == '#') {
status = 5;
}
else {
if (uwsgi_buffer_append(ub, "<!--", 4)) goto error;
if (uwsgi_buffer_append(ub, &buf[i], 1)) goto error;
}
break;
case 5:
if (buf[i] == '-') {
status = 6;
break;
}
if (!cmd) {
cmd = buf+i;
}
cmd_len++;
break;
case 6:
status = 5;
if (buf[i] == '-') {
status = 7;
}
else {
cmd_len+=2;
}
break;
case 7:
status = 5;
if (buf[i] == '>') {
status = 0;
struct uwsgi_buffer *ub_cmd = uwsgi_ssi_parse_command(wsgi_req, cmd, cmd_len);
if (ub_cmd) {
if (uwsgi_buffer_append(ub, ub_cmd->buf, ub_cmd->pos)) {
uwsgi_buffer_destroy(ub_cmd);
goto error;
}
uwsgi_buffer_destroy(ub_cmd);
}
cmd = NULL;
cmd_len = 0;
}
else {
cmd_len+=3;
}
break;
default:
goto error;
}
}
return ub;
error:
uwsgi_buffer_destroy(ub);
return NULL;
}
static int uwsgi_ssi_request(struct wsgi_request *wsgi_req) {
struct uwsgi_buffer *ub = NULL;
if (uwsgi_parse_vars(wsgi_req)) {
return -1;
}
if (!wsgi_req->document_root_len || !wsgi_req->path_info_len) {
uwsgi_log("[uwsgi-ssi] DOCUMENT_ROOT and PATH_INFO must be defined !!!\n");
uwsgi_500(wsgi_req);
return UWSGI_OK;
}
char *filename = uwsgi_concat3n(wsgi_req->document_root, wsgi_req->document_root_len, "/", 1, wsgi_req->path_info, wsgi_req->path_info_len);
size_t filename_len = wsgi_req->document_root_len + 1 + wsgi_req->path_info_len;
// we expand the path for future security implementations
char *real_filename = uwsgi_expand_path(filename, filename_len, NULL);
free(filename);
if (!real_filename) {
uwsgi_404(wsgi_req);
return UWSGI_OK;
}
struct uwsgi_buffer *ub_ssi = uwsgi_buffer_from_file(real_filename);
free(real_filename);
if (!ub_ssi) {
uwsgi_500(wsgi_req);
return UWSGI_OK;
}
ub = uwsgi_ssi_parse(wsgi_req, ub_ssi->buf, ub_ssi->pos);
uwsgi_buffer_destroy(ub_ssi);
if (!ub) {
uwsgi_500(wsgi_req);
return UWSGI_OK;
}
// prepare headers
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) {
uwsgi_500(wsgi_req);
goto end;
}
// content_length
if (uwsgi_response_add_content_length(wsgi_req, ub->pos)) {
uwsgi_500(wsgi_req);
goto end;
}
// content_type
if (uwsgi_response_add_content_type(wsgi_req, "text/html", 9)) {
uwsgi_500(wsgi_req);
goto end;
}
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
end:
if (ub) {
uwsgi_buffer_destroy(ub);
}
return UWSGI_OK;
}
static char *uwsgi_ssi_get_arg(struct uwsgi_ssi_arg *argv, int argc, char *key, size_t key_len, size_t *val_len) {
int i;
for(i=0;i<argc;i++) {
struct uwsgi_ssi_arg *arg = &argv[i];
if (!uwsgi_strncmp(arg->key, arg->key_len, key, key_len)) {
*val_len = arg->val_len;
return arg->value;
}
}
return NULL;
}
// echo command
static struct uwsgi_buffer *ssi_cmd_echo(struct wsgi_request *wsgi_req, struct uwsgi_ssi_arg *argv, int argc) {
size_t var_len = 0;
char *var = uwsgi_ssi_get_arg(argv, argc, "var", 3, &var_len);
if (!var || var_len == 0) return NULL;
uint16_t rlen = 0;
char *value = uwsgi_get_var(wsgi_req, var, var_len, &rlen);
if (!value) return NULL;
if (rlen == 0) return NULL;
struct uwsgi_buffer *ub = uwsgi_buffer_new(rlen);
if (uwsgi_buffer_append(ub, value, rlen)) {
uwsgi_buffer_destroy(ub);
return NULL;
}
return ub;
};
// printenv command
static struct uwsgi_buffer *ssi_cmd_printenv(struct wsgi_request *wsgi_req, struct uwsgi_ssi_arg *argv, int argc) {
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
int i;
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
if (uwsgi_buffer_append(ub, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len)) goto error;
if (uwsgi_buffer_append(ub, "=", 1)) goto error;
if (uwsgi_buffer_append(ub, wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len)) goto error;
if (uwsgi_buffer_append(ub, "\n", 1)) goto error;
}
return ub;
error:
uwsgi_buffer_destroy(ub);
return NULL;
};
// include command
static struct uwsgi_buffer *ssi_cmd_include(struct wsgi_request *wsgi_req, struct uwsgi_ssi_arg *argv, int argc) {
size_t var_len = 0;
char *var = uwsgi_ssi_get_arg(argv, argc, "file", 4, &var_len);
if (!var || var_len == 0) return NULL;
char *filename = uwsgi_concat2n(var, var_len, "", 0);
struct uwsgi_buffer *ub = uwsgi_buffer_from_file(filename);
free(filename);
return ub;
}
// cache command (uWSGI specific)
static struct uwsgi_buffer *ssi_cmd_cache(struct wsgi_request *wsgi_req, struct uwsgi_ssi_arg *argv, int argc) {
size_t var_len = 0;
char *var = uwsgi_ssi_get_arg(argv, argc, "key", 3, &var_len);
if (!var || var_len == 0) return NULL;
size_t cache_len = 0;
char *cache = uwsgi_ssi_get_arg(argv, argc, "name", 4, &cache_len);
char *cache_name = NULL;
if (cache && cache_len) {
cache_name = uwsgi_concat2n(cache, cache_len, "", 0);
}
uint64_t rlen = 0;
char *value = uwsgi_cache_magic_get(var, var_len, &rlen, cache_name);
if (cache_name) free(cache_name);
struct uwsgi_buffer *ub = NULL;
if (value) {
ub = uwsgi_buffer_new(rlen);
if (uwsgi_buffer_append(ub, value, rlen)) {
free(value);
uwsgi_buffer_destroy(ub);
return NULL;
}
free(value);
}
return ub;
}
static int uwsgi_routing_func_ssi(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_buffer *ub = NULL;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub_filename = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
if (!ub_filename) goto end;
struct uwsgi_buffer *ub_ssi = uwsgi_buffer_from_file(ub_filename->buf);
uwsgi_buffer_destroy(ub_filename);
if (!ub_ssi) goto end;
ub = uwsgi_ssi_parse(wsgi_req, ub_ssi->buf, ub_ssi->pos);
uwsgi_buffer_destroy(ub_ssi);
if (!ub) goto end;
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end;
if (uwsgi_response_add_content_length(wsgi_req, ub->pos)) goto end;
if (uwsgi_response_add_content_type(wsgi_req, "text/html", 9)) goto end;
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
end:
if (ub) uwsgi_buffer_destroy(ub);
return UWSGI_ROUTE_BREAK;
}
static int uwsgi_router_ssi(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_ssi;
ur->data = args;
ur->data_len = strlen(args);
return 0;
}
static int uwsgi_ssi_init() {
uwsgi_register_ssi_command("echo", ssi_cmd_echo);
uwsgi_register_ssi_command("printenv", ssi_cmd_printenv);
uwsgi_register_ssi_command("include", ssi_cmd_include);
uwsgi_register_ssi_command("cache", ssi_cmd_cache);
return 0;
}
static void uwsgi_ssi_register_router() {
uwsgi_register_router("ssi", uwsgi_router_ssi);
}
static void uwsgi_ssi_log(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
struct uwsgi_plugin ssi_plugin = {
.name = "ssi",
.modifier1 = 19,
.init = uwsgi_ssi_init,
.request = uwsgi_ssi_request,
.after_request = uwsgi_ssi_log,
.on_load = uwsgi_ssi_register_router,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='ssi'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['ssi']
+8 -1
View File
@@ -1,7 +1,14 @@
import os
NAME='stats_pusher_mongodb'
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
LDFLAGS = []
LIBS = ['-lmongoclient', '-lboost_thread','-lboost_filesystem']
LIBS = []
if not 'UWSGI_MONGODB_NOLIB' in os.environ:
LIBS.append('-lmongoclient')
LIBS.append('-lboost_thread')
LIBS.append('-lboost_filesystem')
GCC_LIST = ['plugin', 'stats_pusher_mongodb.cc']
+8
View File
@@ -0,0 +1,8 @@
import os
NAME='xslt'
CFLAGS = os.popen('xslt-config --cflags').read().rstrip().split()
LDFLAGS = os.popen('xslt-config --libs').read().rstrip().split()
LIBS = []
GCC_LIST = ['xslt']
+406
View File
@@ -0,0 +1,406 @@
#include <uwsgi.h>
#include <libxslt/xsltutils.h>
#include <libxslt/transform.h>
/*
XSLT request plugin
it takes an XML file as input (taken from DOCUMENT_ROOT + PATH_INFO by default)
it search for an XSLT stylesheet (by default in DOCUMENT_ROOT + PATH_INFO - ext + .xsl|.xslt)
it applies params (by default taken from the QUERY_STRING)
XSLT routing instruction
xslt:doc=<path1>,stylesheet=<path2>,params=<params>
*/
struct uwsgi_xslt_config {
struct uwsgi_string_list *docroot;
struct uwsgi_string_list *ext;
struct uwsgi_string_list *var;
struct uwsgi_string_list *stylesheet;
char *content_type;
uint16_t content_type_len;
} uxslt;
struct uwsgi_router_xslt_conf {
char *doc;
uint16_t doc_len;
char *stylesheet;
uint16_t stylesheet_len;
char *params;
uint16_t params_len;
char *content_type;
uint16_t content_type_len;
};
struct uwsgi_option uwsgi_xslt_options[] = {
{"xslt-docroot", required_argument, 0, "add a document_root for xslt processing", uwsgi_opt_add_string_list, &uxslt.docroot, 0},
{"xslt-ext", required_argument, 0, "search for xslt stylesheets with the specified extension", uwsgi_opt_add_string_list, &uxslt.ext, 0},
{"xslt-var", required_argument, 0, "get the xslt stylesheet path from the specified request var", uwsgi_opt_add_string_list, &uxslt.var, 0},
{"xslt-stylesheet", required_argument, 0, "if no xslt stylesheet file can be found, use the specified one", uwsgi_opt_add_string_list, &uxslt.stylesheet, 0},
{"xslt-content-type", required_argument, 0, "set the content-type for the xslt rsult (default: text/html)", uwsgi_opt_set_str, &uxslt.content_type, 0},
{NULL, 0, 0, NULL, NULL, NULL, 0},
};
static char *uwsgi_xslt_apply(char *xmlfile, char *xsltfile, char *params, int *rlen) {
char **vparams = NULL;
char *tmp_params = NULL;
uint16_t count = 0;
if (params) {
// first count the number of items
size_t i;
size_t params_len = strlen(params);
for(i=0;i<params_len;i++) {
if (params[i] == '=') {
count++;
}
}
vparams = uwsgi_calloc( sizeof(char *) * ((count * 2) + 1));
tmp_params = uwsgi_str(params);
char *p = strtok(tmp_params, "&");
int pos = 0;
while(p) {
char *equal = strchr(p, '=');
if (equal) {
*equal = 0;
vparams[pos] = p; pos++;
vparams[pos] = uwsgi_concat3("\"", equal+1, "\""); pos++;
}
p = strtok(NULL, "&");
}
}
// we reset them every time to avoid collision with other xml engines
xmlSubstituteEntitiesDefault(1);
xmlLoadExtDtdDefaultValue = 1;
xmlDocPtr doc = xmlParseFile(xmlfile);
if (!doc) {
if (vparams) {
int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
free(tmp_params);
free(vparams);
}
return NULL;
}
xsltStylesheetPtr ss = xsltParseStylesheetFile((const xmlChar *) xsltfile);
if (!ss) {
xmlFreeDoc(doc);
if (vparams) {
int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
free(tmp_params);
free(vparams);
}
return NULL;
}
xmlDocPtr res = xsltApplyStylesheet(ss, doc, (const char **) vparams);
if (!res) {
xsltFreeStylesheet(ss);
xmlFreeDoc(doc);
if (vparams) {
int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
free(tmp_params);
free(vparams);
}
return NULL;
}
xmlChar *output;
int ret = xsltSaveResultToString(&output, rlen, res, ss);
xsltFreeStylesheet(ss);
xmlFreeDoc(res);
xmlFreeDoc(doc);
if (vparams) {
int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
free(tmp_params);
free(vparams);
}
if (ret < 0) return NULL;
return (char *) output;
}
static int uwsgi_request_xslt(struct wsgi_request *wsgi_req) {
char *xmlfile = NULL;
char *output = NULL;
int output_rlen = 0;
char filename[PATH_MAX+1];
size_t filename_len = 0;
char stylesheet[PATH_MAX+1];
size_t stylesheet_len = 0;
char *params = NULL;
if (uwsgi_parse_vars(wsgi_req)) {
return -1;
}
// set default values
if (!uxslt.content_type_len) {
if (!uxslt.content_type) {
uxslt.content_type = "text/html";
}
uxslt.content_type_len = strlen(uxslt.content_type);
}
struct uwsgi_string_list *usl = uxslt.docroot;
// first check for static docroots
if (usl) {
while(usl) {
xmlfile = uwsgi_concat3n(usl->value, usl->len, "/", 1, wsgi_req->path_info, wsgi_req->path_info_len);
if (uwsgi_is_file(xmlfile)) {
break;
}
free(xmlfile);
xmlfile = NULL;
usl = usl->next;
}
}
// fallback to DOCUMENT_ROOT
else {
if (wsgi_req->document_root_len == 0) {
uwsgi_403(wsgi_req);
return UWSGI_OK;
}
xmlfile = uwsgi_concat3n(wsgi_req->document_root, wsgi_req->document_root_len, "/", 1, wsgi_req->path_info, wsgi_req->path_info_len);
}
if (!xmlfile) {
uwsgi_404(wsgi_req);
return UWSGI_OK;
}
// we have the full path, check if it is valid
if (!uwsgi_expand_path(xmlfile, strlen(xmlfile), filename)) {
free(xmlfile);
uwsgi_404(wsgi_req);
return UWSGI_OK;
}
free(xmlfile);
if (!uwsgi_is_file(filename)) {
uwsgi_403(wsgi_req);
return UWSGI_OK;
}
filename_len = strlen(filename);
// now search for the xslt file
int found = 0;
// first check for specific vars
usl = uxslt.var;
while(usl) {
uint16_t rlen;
char *value = uwsgi_get_var(wsgi_req, usl->value, usl->len, &rlen);
if (value) {
memcpy(stylesheet, value, rlen);
stylesheet[rlen] = 0;
stylesheet_len = rlen;
found = 1;
break;
}
usl = usl->next;
}
if (found) goto apply;
// then check for custom extensions
if (uxslt.ext) {
usl = uxslt.ext;
while(usl) {
char *tmp_path = uwsgi_concat2n(filename, filename_len, usl->value, usl->len);
if (uwsgi_is_file(tmp_path)) {
stylesheet_len = filename_len + usl->len;
memcpy(stylesheet, tmp_path, stylesheet_len);
stylesheet[stylesheet_len] = 0;
free(tmp_path);
found = 1;
break;
}
free(tmp_path);
usl = usl->next;
}
}
// use default extensions .xsl/.xslt
else {
char *tmp_path = uwsgi_concat2n(filename, filename_len, ".xsl", 4);
if (uwsgi_is_file(tmp_path)) {
stylesheet_len = filename_len + 4;
memcpy(stylesheet, tmp_path, stylesheet_len);
stylesheet[stylesheet_len] = 0;
free(tmp_path);
goto apply;
}
free(tmp_path);
tmp_path = uwsgi_concat2n(filename, filename_len, ".xslt", 5);
if (uwsgi_is_file(tmp_path)) {
stylesheet_len = filename_len + 5;
memcpy(stylesheet, tmp_path, stylesheet_len);
stylesheet[stylesheet_len] = 0;
found = 1;
}
free(tmp_path);
}
if (found) goto apply;
// finally check for static stylesheets
usl = uxslt.stylesheet;
while(usl) {
if (uwsgi_is_file(usl->value)) {
memcpy(stylesheet, usl->value, usl->len);
stylesheet_len = usl->len;
stylesheet[stylesheet_len] = 0;
found = 1;
break;
}
usl = usl->next;
}
if (found) goto apply;
uwsgi_404(wsgi_req);
return UWSGI_OK;
apply:
if (wsgi_req->query_string_len > 0) {
params = uwsgi_concat2n(wsgi_req->query_string, wsgi_req->query_string_len, "", 0);
}
// we have both the file and the stylesheet, let's run the engine
output = uwsgi_xslt_apply(filename, stylesheet, params, &output_rlen);
if (params) free(params);
if (!output) {
uwsgi_500(wsgi_req);
return UWSGI_OK;
}
// prepare headers
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) {
uwsgi_500(wsgi_req);
goto end;
}
// content_length
if (uwsgi_response_add_content_length(wsgi_req, output_rlen)) {
uwsgi_500(wsgi_req);
goto end;
}
// content_type
if (uwsgi_response_add_content_type(wsgi_req, uxslt.content_type, uxslt.content_type_len)) {
uwsgi_500(wsgi_req);
goto end;
}
uwsgi_response_write_body_do(wsgi_req, output, output_rlen);
end:
xmlFree(output);
return UWSGI_OK;
}
static void uwsgi_xslt_log(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
static int uwsgi_routing_func_xslt(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
struct uwsgi_router_xslt_conf *urxc = (struct uwsgi_router_xslt_conf *) ur->data2;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
struct uwsgi_buffer *ub_doc = NULL;
struct uwsgi_buffer *ub_stylesheet = NULL;
struct uwsgi_buffer *ub_params = NULL;
struct uwsgi_buffer *ub_content_type = NULL;
ub_doc = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urxc->doc, urxc->doc_len);
if (!ub_doc) goto end;
ub_stylesheet = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urxc->stylesheet, urxc->stylesheet_len);
if (!ub_stylesheet) goto end;
if (urxc->params) {
ub_params = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urxc->params, urxc->params_len);
if (!ub_params) goto end;
}
if (urxc->content_type) {
ub_content_type = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urxc->content_type, urxc->content_type_len);
if (!ub_content_type) goto end;
}
int rlen;
char *output = uwsgi_xslt_apply( ub_doc->buf, ub_stylesheet->buf, ub_params ? ub_params->buf : NULL, &rlen);
if (!output) goto end;
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end;
if (uwsgi_response_add_content_length(wsgi_req, rlen)) goto end;
if (uwsgi_response_add_content_type(wsgi_req, urxc->content_type, urxc->content_type_len)) goto end;
uwsgi_response_write_body_do(wsgi_req, output, rlen);
xmlFree(output);
end:
if (ub_doc) uwsgi_buffer_destroy(ub_doc);
if (ub_stylesheet) uwsgi_buffer_destroy(ub_stylesheet);
if (ub_params) uwsgi_buffer_destroy(ub_params);
if (ub_content_type) uwsgi_buffer_destroy(ub_content_type);
return UWSGI_ROUTE_BREAK;
}
static int uwsgi_router_xslt(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_xslt;
ur->data = args;
ur->data_len = strlen(args);
struct uwsgi_router_xslt_conf *urxc = uwsgi_calloc(sizeof(struct uwsgi_router_xslt_conf));
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
"doc", &urxc->doc,
"stylesheet", &urxc->stylesheet,
"content_type", &urxc->content_type,
"params", &urxc->params,
NULL)) {
uwsgi_log("invalid route syntax: %s\n", args);
exit(1);
}
if (!urxc->doc && !urxc->stylesheet) {
uwsgi_log("invalid route syntax: you need to specify a doc and a stylesheet\n");
exit(1);
}
urxc->doc_len = strlen(urxc->doc);
urxc->stylesheet_len = strlen(urxc->stylesheet);
if (urxc->params) urxc->params_len = strlen(urxc->params);
if (!urxc->content_type) urxc->content_type = "text/html";
urxc->content_type_len = strlen(urxc->content_type);
ur->data2 = urxc;
return 0;
}
static void router_xslt_register() {
uwsgi_register_router("xslt", uwsgi_router_xslt);
}
struct uwsgi_plugin xslt_plugin = {
.name = "xslt",
.modifier1 = 23,
.options = uwsgi_xslt_options,
.request = uwsgi_request_xslt,
.after_request = uwsgi_xslt_log,
.on_load = router_xslt_register,
};
+24
View File
@@ -0,0 +1,24 @@
<?xml version="1.0"?>
<!-- Edited by XMLSpy® -->
<catalog>
<cd>
<title>Quintessence</title>
<artist>Borknagar</artist>
</cd>
<cd>
<title>Torn Beyond Reason</title>
<artist>Woods Of Desolation</artist>
</cd>
<cd>
<title>Autumn Aurora</title>
<artist>Drudkh</artist>
</cd>
<cd>
<title>Om</title>
<artist>Negura Bunget</artist>
</cd>
<cd>
<title>Frostnacht</title>
<artist>Helrunar</artist>
</cd>
</catalog>
+25
View File
@@ -0,0 +1,25 @@
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>Blackmetal albums</h2>
<table border="1">
<tr bgcolor="black">
<th style="color:white">Title</th>
<th style="color:white">Artist</th>
</tr>
<xsl:for-each select="catalog/cd">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="artist"/></td>
<td>-<xsl:value-of select="$foobar"/>-</td>
<td><xsl:value-of select="$agent"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
+5
View File
@@ -0,0 +1,5 @@
[uwsgi]
http-socket = :9090
plugin = xslt
xml_storage = t/xslt
route = /(.*)$ xslt:doc=%(xml_storage)/$1.xml,stylesheet=%(xml_storage)/$1.xml.xslt,content_type=text/html,params=foobar=test&agent=${HTTP_USER_AGENT}
-51
View File
@@ -1,51 +0,0 @@
/* taken from http://wiki.unbit.it/UnbitKernel */
struct uidsec_struct {
/* network limits */
unsigned short ipv4_tcp_port;
unsigned short ipv4_udp_port;
unsigned short ipv4_tcp_control_port;
int ipv4_tcp_socket_protection;
unsigned long long ipv4_firewall_mask;
/* limits */
int fs_readonly;
/* process markers */
int domain_id;
int fcgi_id;
int scgi_id;
int apps_id;
int wapp_id;
int ssh_id;
int cron_id;
/* thread ? */
int cloned_vm;
/* process limit */
int max_dom_proc;
int max_apps_proc;
int max_apps_thread;
int max_ssh_proc;
int max_cron_proc;
/* misc */
int control_uid;
int listen_backlog;
int errors;
/* counters */
int accept_cnt;
int accept_last;
int fork_cnt;
int fork_last;
unsigned long long bio_read;
unsigned long long bio_write;
int memory_errors;
};
+1 -1
View File
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
s.name = 'uwsgi'
s.license = 'GPL-2'
s.version = `python -c "import uwsgiconfig as uc; print uc.uwsgi_version"`.sub(/-dev-.*/,'')
s.date = '2013-03-02'
s.date = '2013-03-26'
s.summary = "uWSGI"
s.description = "The uWSGI server for Ruby/Rack"
s.authors = ["Unbit"]
+1478 -1478
View File
File diff suppressed because it is too large Load Diff
+5
View File
@@ -0,0 +1,5 @@
int uwsgi_init(int, char **, char **);
int main(int argc, char *argv[], char **environ) {
return uwsgi_init(argc, argv, environ);
}
+35 -29
View File
@@ -1,6 +1,6 @@
# uWSGI build system
uwsgi_version = '1.9'
uwsgi_version = '1.9.2'
import os
import re
@@ -64,7 +64,6 @@ report['pcre'] = False
report['matheval'] = False
report['routing'] = False
report['capabilities'] = False
report['ini'] = False
report['yaml'] = False
report['json'] = False
report['ldap'] = False
@@ -422,6 +421,20 @@ def build_uwsgi(uc, print_only=False):
for pb in post_build:
pb(uc)
def open_profile(filename):
if filename.startswith('http://') or filename.startswith('https://') or filename.startswith('ftp://'):
wrapped = False
try:
import urllib2
except:
import urllib.request
wrapped = True
if wrapped:
import io
return io.TextIOWrapper(urllib.request.urlopen(filename), encoding='utf-8')
return urllib2.urlopen(filename)
return open(filename)
class uConf(object):
@@ -429,8 +442,6 @@ class uConf(object):
self.config = ConfigParser.ConfigParser()
if not mute:
print("using profile: %s" % filename)
if not os.path.exists(filename):
raise Exception("profile not found !!!")
if os.path.exists('uwsgibuild.lastprofile'):
ulp = open('uwsgibuild.lastprofile','r')
@@ -443,14 +454,14 @@ class uConf(object):
ulp.write(filename)
ulp.close()
self.config.read(filename)
self.config.readfp(open_profile(filename))
self.gcc_list = ['core/utils', 'core/protocol', 'core/socket', 'core/logging', 'core/master', 'core/master_utils', 'core/emperor',
'core/notify', 'core/mule', 'core/subscription', 'core/stats', 'core/sendfile', 'core/async', 'core/master_checks',
'core/offload', 'core/io', 'core/static', 'core/websockets', 'core/spooler', 'core/snmp', 'core/exceptions',
'core/setup_utils', 'core/clock', 'core/init', 'core/buffer', 'core/reader', 'core/writer', 'core/alarm',
'core/plugins', 'core/lock', 'core/cache', 'core/daemons', 'core/errors', 'core/hash', 'core/master_events',
'core/queue', 'core/event', 'core/signal', 'core/strings', 'core/progress', 'core/timebomb',
'core/rpc', 'core/gateway', 'core/loop', 'core/rb_timers', 'core/uwsgi']
'core/queue', 'core/event', 'core/signal', 'core/strings', 'core/progress', 'core/timebomb', 'core/ini',
'core/rpc', 'core/gateway', 'core/loop', 'core/cookie', 'core/querystring', 'core/rb_timers', 'core/uwsgi']
# add protocols
self.gcc_list.append('proto/base')
self.gcc_list.append('proto/uwsgi')
@@ -532,7 +543,8 @@ class uConf(object):
for option in self.config.options('uwsgi'):
interpolations[option] = self.get(option)
iconfig = ConfigParser.ConfigParser(interpolations)
iconfig.read(inherit)
iconfig.readfp(open_profile(inherit))
for opt in iconfig.options('uwsgi'):
if not self.config.has_option('uwsgi', opt):
self.set(opt, iconfig.get('uwsgi', opt))
@@ -615,7 +627,6 @@ class uConf(object):
self.libs.append('-lkvm')
if uwsgi_os == 'Haiku':
self.set('async', 'false')
self.libs.remove('-rdynamic')
self.libs.remove('-lpthread')
self.libs.append('-lroot')
@@ -923,11 +934,6 @@ class uConf(object):
self.cflags.append('-DUWSGI_VERSION_REVISION="' + uver_rev + '"')
self.cflags.append('-DUWSGI_VERSION_CUSTOM="\\"' + uver_custom + '\\""')
if self.get('ini'):
self.cflags.append("-DUWSGI_INI")
self.gcc_list.append('core/ini')
report['ini'] = True
if self.get('yaml'):
self.cflags.append("-DUWSGI_YAML")
self.gcc_list.append('core/yaml')
@@ -1081,38 +1087,41 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
print("Error: unable to find directory '%s'" % path)
sys.exit(1)
sys.path.insert(0, path)
import uwsgiplugin as up
if sys.argv[1] != '--plugin':
reload(up)
up = {}
try:
execfile('%s/uwsgiplugin.py' % path, up)
except:
f = open('%s/uwsgiplugin.py' % path)
exec(f.read(), up)
f.close()
requires = []
p_cflags = cflags[:]
p_ldflags = ldflags[:]
p_cflags += up.CFLAGS
p_ldflags += up.LDFLAGS
p_libs = up.LIBS
p_cflags += up['CFLAGS']
p_ldflags += up['LDFLAGS']
p_libs = up['LIBS']
post_build = None
try:
requires = up.REQUIRES
requires = up['REQUIRES']
except:
pass
try:
post_build = up.post_build
post_build = up['post_build']
except:
pass
p_cflags.insert(0, '-I.')
if name is None:
name = up.NAME
name = up['NAME']
else:
p_cflags.append("-D%s_plugin=%s_plugin" % (up.NAME, name))
p_cflags.append("-D%s_plugin=%s_plugin" % (up['NAME'], name))
try:
for opt in uc.config.options(name):
@@ -1132,7 +1141,7 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
if uwsgi_os == 'Darwin':
shared_flag = '-dynamiclib -undefined dynamic_lookup'
for cfile in up.GCC_LIST:
for cfile in up['GCC_LIST']:
if cfile.endswith('.a'):
gcc_list.append(cfile)
elif not cfile.endswith('.c') and not cfile.endswith('.cc') and not cfile.endswith('.m'):
@@ -1182,9 +1191,6 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
except:
pass
#for ofile in up.OBJ_LIST:
# gcc_list.insert(0,ofile)
need_pic = ' -fPIC'
# on cygwin we do not need PIC
if uwsgi_os.startswith('CYGWIN'):