webroar 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +48 -1
- data/README +11 -14
- data/Rakefile +1 -1
- data/conf/mime_type.yml +172 -166
- data/conf/server_internal_config.yml +30 -8
- data/doc/user-guide.html +294 -153
- data/doc/user-guide.txt +9 -13
- data/lib/command_runner.rb +1 -0
- data/lib/dependencies.rb +18 -15
- data/lib/installer.rb +115 -50
- data/src/admin_panel/app/controllers/admin_controller.rb +1 -15
- data/src/admin_panel/app/controllers/application_controller.rb +2 -2
- data/src/admin_panel/app/controllers/application_specification_controller.rb +2 -1
- data/src/admin_panel/app/controllers/headers_controller.rb +73 -0
- data/src/admin_panel/app/controllers/mail_specification_controller.rb +10 -0
- data/src/admin_panel/app/controllers/server_specification_controller.rb +14 -0
- data/src/admin_panel/app/helpers/admin_helper.rb +0 -85
- data/src/admin_panel/app/models/app.rb +1 -1
- data/src/admin_panel/app/models/application_specification.rb +33 -25
- data/src/admin_panel/app/models/headers.rb +116 -0
- data/src/admin_panel/app/models/mail_specification.rb +20 -5
- data/src/admin_panel/app/models/server_specification.rb +2 -7
- data/src/admin_panel/app/views/admin/configuration.html.erb +10 -5
- data/src/admin_panel/app/views/exceptions/_exception_list_partial.html.erb +4 -4
- data/src/admin_panel/app/views/graph/_graph_page.html.erb +3 -0
- data/src/admin_panel/app/views/headers/_add_expires_text_box.html.erb +35 -0
- data/src/admin_panel/app/views/headers/_expires_by_type_form.html.erb +65 -0
- data/src/admin_panel/app/views/headers/_headers_table.html.erb +113 -0
- data/src/admin_panel/app/views/mail_specification/_current_spec.html.erb +168 -0
- data/src/admin_panel/app/views/{admin → server_specification}/_add_div.html.erb +1 -1
- data/src/admin_panel/config/initializers/application_constants.rb +6 -0
- data/src/admin_panel/lib/control.rb +6 -3
- data/src/admin_panel/lib/scgi.rb +74 -21
- data/src/admin_panel/lib/yaml_writer.rb +51 -17
- data/src/admin_panel/public/javascripts/application.js +20 -1
- data/src/head/wr_access_log.c +2 -2
- data/src/head/wr_application.c +294 -236
- data/src/head/wr_application.h +8 -8
- data/src/head/wr_configurator.c +451 -517
- data/src/head/wr_configurator.h +10 -115
- data/src/head/wr_connection.c +26 -25
- data/src/head/wr_connection.h +2 -3
- data/src/head/wr_controller.c +110 -93
- data/src/head/wr_controller.h +6 -6
- data/src/head/wr_main.c +31 -24
- data/src/head/wr_request.c +70 -93
- data/src/head/wr_request.h +0 -4
- data/src/head/wr_resolver.c +21 -15
- data/src/head/wr_resolver.h +2 -2
- data/src/head/wr_server.c +36 -26
- data/src/head/wr_server.h +5 -5
- data/src/head/wr_worker.c +551 -512
- data/src/head/wr_worker.h +33 -20
- data/src/helper/wr_config.c +316 -0
- data/src/helper/wr_config.h +235 -0
- data/src/helper/wr_helper.h +1 -5
- data/src/helper/wr_logger.c +4 -4
- data/src/helper/wr_scgi.c +3 -4
- data/src/helper/wr_scgi.h +2 -0
- data/src/helper/wr_string.h +2 -2
- data/src/helper/wr_util.c +3 -1
- data/src/helper/wr_util.h +0 -0
- data/src/helper/wr_yaml_parser.c +30 -0
- data/src/helper/wr_yaml_parser.h +1 -0
- data/src/ruby_lib/exception_tracker/instrumentation/action_controller.rb +2 -1
- data/src/ruby_lib/mailer/smtpmail.rb +7 -4
- data/src/ruby_lib/profiler/instrumentation/action_controller.rb +2 -1
- data/src/ruby_lib/profiler/instrumentation/active_record.rb +3 -0
- data/src/ruby_lib/rack/adapter/rails.rb +14 -7
- data/src/ruby_lib/ruby_interface/client.rb +1 -1
- data/src/ruby_lib/ruby_interface/version.rb +2 -2
- data/src/ruby_lib/webroar_app_loader.rb +4 -2
- data/src/worker/wkr_controller.c +200 -140
- data/src/worker/wkr_http.c +14 -28
- data/src/worker/wkr_http.h +4 -4
- data/src/worker/wkr_http_request.c +12 -11
- data/src/worker/wkr_http_request.h +7 -8
- data/src/worker/wkr_http_response.c +10 -14
- data/src/worker/wkr_http_response.h +0 -1
- data/src/worker/wkr_main.c +74 -140
- data/src/worker/wkr_static.c +295 -108
- data/src/worker/wkr_static.h +20 -7
- data/src/worker/worker.c +245 -70
- data/src/worker/worker.h +46 -34
- data/tasks/compile.rake +128 -175
- data/tasks/test.rake +345 -469
- data/test/spec/webroar_command_spec.rb +23 -0
- metadata +173 -43
- data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/README +0 -34
- data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/Rakefile +0 -13
- data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/init.rb +0 -5
- data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/lib/action_mailer_tls.rb +0 -16
- data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/lib/smtp_tls.rb +0 -123
- data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/test/tls_test.rb +0 -42
- data/src/head/wr_config.h +0 -165
- data/src/ruby_lib/mailer/action_mailer_tls.rb +0 -16
- data/src/ruby_lib/mailer/smtp_tls.rb +0 -123
data/src/worker/wkr_static.c
CHANGED
@@ -27,10 +27,12 @@
|
|
27
27
|
#include <string.h>
|
28
28
|
#include <fcntl.h>
|
29
29
|
|
30
|
+
#ifdef W_ZLIB
|
31
|
+
#include <zlib.h>
|
32
|
+
#endif
|
30
33
|
|
31
|
-
|
34
|
+
extern config_t *Config;
|
32
35
|
|
33
|
-
#define MAP_SIZE 36
|
34
36
|
#define DEFAULT_EXPIRES "Headers/expires"
|
35
37
|
#define EXPIRES_BY_TYPE "Headers/expires_by_type"
|
36
38
|
#define EXPIRES_BY_TYPE_EXT "expires_by_type/ext"
|
@@ -52,7 +54,7 @@ typedef enum {
|
|
52
54
|
HTTP_STATUS_404
|
53
55
|
} resp_status_t;
|
54
56
|
|
55
|
-
typedef void (*resp_fun_t) (http_t
|
57
|
+
typedef void (*resp_fun_t) (http_t*);
|
56
58
|
|
57
59
|
typedef struct {
|
58
60
|
wr_u_short code;
|
@@ -61,10 +63,10 @@ typedef struct {
|
|
61
63
|
resp_fun_t fun;
|
62
64
|
} http_status_t;
|
63
65
|
|
64
|
-
void http_resp_200(http_t
|
65
|
-
void http_resp_304(http_t
|
66
|
-
void http_resp_403(http_t
|
67
|
-
void http_resp_404(http_t
|
66
|
+
void http_resp_200(http_t*);
|
67
|
+
void http_resp_304(http_t*);
|
68
|
+
void http_resp_403(http_t*);
|
69
|
+
void http_resp_404(http_t*);
|
68
70
|
|
69
71
|
static http_status_t http_status [] = {
|
70
72
|
{200, "200 OK", "", http_resp_200},
|
@@ -89,15 +91,12 @@ Content-Length: %d\r\n\r\n"
|
|
89
91
|
<br><hr>%s-%s\
|
90
92
|
</body></html>"
|
91
93
|
|
92
|
-
// Static mapping object
|
93
|
-
static static_file_t* map[MAP_SIZE + 1];
|
94
|
-
|
95
94
|
/**************************************
|
96
95
|
* Private Functions
|
97
96
|
*************************************/
|
98
97
|
|
99
98
|
/** Searches path backward and returns pointer to the first character of extension */
|
100
|
-
|
99
|
+
char* get_file_ext(const char *path) {
|
101
100
|
int len = strlen(path);
|
102
101
|
char *ext = path + len;
|
103
102
|
while (len) {
|
@@ -110,9 +109,9 @@ static char* get_file_ext(const char *path) {
|
|
110
109
|
}
|
111
110
|
|
112
111
|
/** Set expires time based on file type */
|
113
|
-
|
112
|
+
void set_expires_time(static_server_t * s, char *ext, long int expires) {
|
114
113
|
int index;
|
115
|
-
char tmp_ext[
|
114
|
+
char tmp_ext[STR_SIZE64], *p;
|
116
115
|
strcpy(tmp_ext, ext);
|
117
116
|
p = tmp_ext;
|
118
117
|
while(*p){
|
@@ -130,9 +129,10 @@ static void set_expires_time(char *ext, long int expires) {
|
|
130
129
|
}
|
131
130
|
|
132
131
|
if (index >= 0 && index < MAP_SIZE) {
|
133
|
-
static_file_t *e = map[index];
|
132
|
+
static_file_t *e = s->map[index];
|
134
133
|
while (e) {
|
135
134
|
if (strcmp(e->ext, tmp_ext) == 0) {
|
135
|
+
//HTTP/1.1 servers SHOULD NOT send Expires dates more than one year in the future.
|
136
136
|
e->expires = expires;
|
137
137
|
break;
|
138
138
|
}
|
@@ -142,9 +142,9 @@ static void set_expires_time(char *ext, long int expires) {
|
|
142
142
|
}
|
143
143
|
|
144
144
|
/* Get mime-type */
|
145
|
-
|
146
|
-
char *ext = get_file_ext(path);
|
147
|
-
char tmp_ext[
|
145
|
+
static_file_t* get_mime_type(static_server_t *s) {
|
146
|
+
char *ext = get_file_ext(s->path);
|
147
|
+
char tmp_ext[STR_SIZE64], *p;
|
148
148
|
strcpy(tmp_ext, ext);
|
149
149
|
p = tmp_ext;
|
150
150
|
while(*p){
|
@@ -164,7 +164,7 @@ static static_file_t* get_mime_type(const char *path) {
|
|
164
164
|
}
|
165
165
|
|
166
166
|
if (index >= 0 && index < MAP_SIZE) {
|
167
|
-
static_file_t *e = map[index];
|
167
|
+
static_file_t *e = s->map[index];
|
168
168
|
while (e) {
|
169
169
|
if (strcmp(e->ext, tmp_ext) == 0) {
|
170
170
|
return e;
|
@@ -173,39 +173,38 @@ static static_file_t* get_mime_type(const char *path) {
|
|
173
173
|
}
|
174
174
|
}
|
175
175
|
}
|
176
|
-
return map[MAP_SIZE];
|
176
|
+
return s->map[MAP_SIZE];
|
177
177
|
}
|
178
178
|
|
179
179
|
/** Get response code */
|
180
|
-
|
180
|
+
short get_resp_code(static_server_t *s) {
|
181
181
|
LOG_FUNCTION
|
182
|
-
const char *modify = scgi_header_value_get(h->req->scgi, HTTP_HEADER_IF_MODIFIED_SINCE);
|
183
182
|
time_t modify_tm;
|
184
183
|
|
185
|
-
if (path == NULL) {
|
184
|
+
if (s->path == NULL) {
|
186
185
|
LOG_ERROR(WARN, "Requested file path is NULL.");
|
187
186
|
return HTTP_STATUS_404;
|
188
187
|
}
|
189
188
|
|
190
|
-
if (stat(path, buf)) {
|
191
|
-
LOG_ERROR(WARN, "Requested file %s does not exist.", path);
|
189
|
+
if (stat(s->path, &(s->buf))) {
|
190
|
+
LOG_ERROR(WARN, "Requested file %s does not exist.", s->path);
|
192
191
|
return HTTP_STATUS_404;
|
193
192
|
}
|
194
193
|
|
195
|
-
if (S_ISDIR(buf
|
196
|
-
LOG_ERROR(WARN, "%s is a directory.", path)
|
194
|
+
if (S_ISDIR(s->buf.st_mode) != 0) {
|
195
|
+
LOG_ERROR(WARN, "%s is a directory.", s->path)
|
197
196
|
return HTTP_STATUS_404;
|
198
197
|
}
|
199
198
|
|
200
|
-
if (strstr(path, "..")) {
|
201
|
-
LOG_ERROR(WARN, "Requested file path %s is forbidden.", path);
|
199
|
+
if (strstr(s->path, "..")) {
|
200
|
+
LOG_ERROR(WARN, "Requested file path %s is forbidden.", s->path);
|
202
201
|
return HTTP_STATUS_403;
|
203
202
|
}
|
204
203
|
// Compare 'If-Modified-Since' time with file modication time
|
205
|
-
if (modify) {
|
204
|
+
if (s->modify) {
|
206
205
|
// Assume 'If-Modified-Since' date zone is GMT
|
207
|
-
modify_tm = httpdate_to_c_time(modify) - timezone;
|
208
|
-
long int diff = difftime(buf
|
206
|
+
modify_tm = httpdate_to_c_time(s->modify) - timezone;
|
207
|
+
long int diff = difftime(s->buf.st_mtime, modify_tm);
|
209
208
|
if (diff <= 0) {
|
210
209
|
return HTTP_STATUS_304;
|
211
210
|
}
|
@@ -213,7 +212,7 @@ static short get_resp_code(http_t *h, const char *path, struct stat *buf) {
|
|
213
212
|
return HTTP_STATUS_200;
|
214
213
|
}
|
215
214
|
|
216
|
-
|
215
|
+
long int get_default_expires(node_t *root) {
|
217
216
|
char *node_value = get_node_value(root, DEFAULT_EXPIRES);
|
218
217
|
|
219
218
|
if (node_value == NULL) {
|
@@ -226,21 +225,31 @@ static long int get_default_expires(node_t *root) {
|
|
226
225
|
}
|
227
226
|
}
|
228
227
|
|
229
|
-
|
228
|
+
/** Read 'mime_type.yml' file and create dictionary for supported Content-Type. */
|
229
|
+
int create_dictionary(static_server_t *s, const char *mapping_file, long int expires) {
|
230
230
|
node_t *root = yaml_parse(mapping_file), *node;
|
231
231
|
static_file_t *ext;
|
232
232
|
int index;
|
233
233
|
|
234
234
|
// Initialize map with NULL value
|
235
235
|
for (index = 0; index < MAP_SIZE; index++) {
|
236
|
-
map[index] = NULL;
|
236
|
+
s->map[index] = NULL;
|
237
237
|
}
|
238
238
|
|
239
239
|
if (root == NULL) {
|
240
240
|
LOG_ERROR(SEVERE, "Could not read the file %s", mapping_file);
|
241
241
|
return -1;
|
242
242
|
}
|
243
|
-
|
243
|
+
|
244
|
+
node = get_nodes(root, "File Extensions");
|
245
|
+
|
246
|
+
if (root == NULL || node->child == NULL) {
|
247
|
+
LOG_ERROR(SEVERE, "Could not read 'File Extensions' from the file %s", mapping_file);
|
248
|
+
return -1;
|
249
|
+
}
|
250
|
+
|
251
|
+
node = node->child;
|
252
|
+
|
244
253
|
while (node) {
|
245
254
|
ext = wr_malloc(static_file_t);
|
246
255
|
strcpy(ext->ext, node->name);
|
@@ -256,8 +265,8 @@ static int create_dictionary(const char *mapping_file, long int expires) {
|
|
256
265
|
}
|
257
266
|
|
258
267
|
if (index >= 0 && index < MAP_SIZE) {
|
259
|
-
ext->next = map[index];
|
260
|
-
map[index] = ext;
|
268
|
+
ext->next = s->map[index];
|
269
|
+
s->map[index] = ext;
|
261
270
|
}else {
|
262
271
|
LOG_ERROR(WARN, "Mapping index out of bound for extension = %s", ext->ext);
|
263
272
|
free(ext);
|
@@ -272,12 +281,12 @@ static int create_dictionary(const char *mapping_file, long int expires) {
|
|
272
281
|
strcpy(ext->mime_type, "text/plain");
|
273
282
|
ext->expires = expires;
|
274
283
|
ext->next = NULL;
|
275
|
-
map[MAP_SIZE] = ext;
|
284
|
+
s->map[MAP_SIZE] = ext;
|
276
285
|
|
277
286
|
return 0;
|
278
287
|
}
|
279
288
|
|
280
|
-
|
289
|
+
void set_expires_by_type(static_server_t *s, node_t *root) {
|
281
290
|
node_t *node = get_nodes(root, EXPIRES_BY_TYPE);
|
282
291
|
long int expires;
|
283
292
|
char *types, *expires_str, *type;
|
@@ -287,122 +296,207 @@ static void set_expires_by_type(node_t *root) {
|
|
287
296
|
expires = atol(expires_str);
|
288
297
|
type = strtok(types, " ,");
|
289
298
|
while (type != NULL) {
|
290
|
-
set_expires_time(type, expires);
|
299
|
+
set_expires_time(s, type, expires);
|
291
300
|
type = strtok(NULL, " ,");
|
292
301
|
}
|
293
302
|
node = NODE_NEXT(node);
|
294
303
|
}
|
295
304
|
}
|
296
305
|
|
297
|
-
|
306
|
+
|
307
|
+
#ifdef W_ZLIB
|
308
|
+
|
309
|
+
/** Compress file */
|
310
|
+
/* Compress file if its size is >10kb and < 1mb and its mime-type has either
|
311
|
+
* text or xml */
|
312
|
+
|
313
|
+
int file_compress(http_t *h, static_file_t *ext){
|
314
|
+
LOG_FUNCTION
|
315
|
+
h->stat->encoding = scgi_header_value_get(h->req->scgi, "HTTP_ACCEPT_ENCODING");
|
316
|
+
h->stat->user_agent = scgi_header_value_get(h->req->scgi, "HTTP_USER_AGENT");
|
317
|
+
|
318
|
+
if(h->stat->buf.st_size >= Config->Worker.Compress.lower_limit
|
319
|
+
&& h->stat->buf.st_size <= Config->Worker.Compress.upper_limit
|
320
|
+
&& h->stat->encoding && strstr(h->stat->encoding,"deflate")){
|
321
|
+
|
322
|
+
#ifdef W_REGEX
|
323
|
+
if(h->stat->r_content_type){
|
324
|
+
if(regexec(h->stat->r_content_type, ext->mime_type, 0, NULL, 0) !=0 ) return FALSE;
|
325
|
+
}
|
326
|
+
|
327
|
+
if(h->stat->r_user_agent && h->stat->user_agent){
|
328
|
+
if(regexec(h->stat->r_user_agent, h->stat->user_agent, 0, NULL, 0) !=0 ) return FALSE;
|
329
|
+
}
|
330
|
+
#else
|
331
|
+
// Encode assets having Content-Type either 'text' or 'xml'.
|
332
|
+
if(strstr(ext->mime_type, "text") == NULL && strstr(ext->mime_type, "xml") == NULL
|
333
|
+
&& strstr(ext->mime_type, "css") == NULL && strstr(ext->mime_type, "javascript") == NULL){
|
334
|
+
return FALSE;
|
335
|
+
}
|
336
|
+
#endif
|
337
|
+
|
338
|
+
wr_u_int read;
|
339
|
+
FILE *file;
|
340
|
+
wr_buffer_create(h->stat->buffer, h->stat->buf.st_size);
|
341
|
+
file = fopen(h->stat->path, "r");
|
342
|
+
|
343
|
+
if(file == NULL) return FALSE;
|
344
|
+
|
345
|
+
while(h->stat->buffer->len < h->stat->buf.st_size){
|
346
|
+
read = fread(h->stat->buffer->str + h->stat->buffer->len, sizeof(char),
|
347
|
+
h->stat->buf.st_size - h->stat->buffer->len, file);
|
348
|
+
if(read < 0){
|
349
|
+
fclose(file);
|
350
|
+
wr_buffer_null(h->stat->buffer);
|
351
|
+
return FALSE;
|
352
|
+
}
|
353
|
+
h->stat->buffer->len += read;
|
354
|
+
}
|
355
|
+
|
356
|
+
fclose(file);
|
357
|
+
|
358
|
+
//zlib states that the source buffer must be at least 0.1 times larger than
|
359
|
+
//the source buffer plus 12 bytes to cope with the overhead of zlib data streams
|
360
|
+
wr_buffer_create(h->resp->resp_body, h->stat->buf.st_size + h->stat->buf.st_size*0.1 + 12);
|
361
|
+
h->resp->resp_body->len = h->resp->resp_body->size;
|
362
|
+
//now compress the data
|
363
|
+
if(compress2((Bytef*)h->resp->resp_body->str, (uLongf*)&h->resp->resp_body->len,
|
364
|
+
(const Bytef*)h->stat->buffer->str, (uLongf)h->stat->buffer->len, Z_DEFAULT_COMPRESSION) != Z_OK){
|
365
|
+
wr_buffer_null(h->stat->buffer);
|
366
|
+
wr_buffer_null(h->resp->resp_body);
|
367
|
+
return FALSE;
|
368
|
+
}
|
369
|
+
wr_buffer_null(h->stat->buffer);
|
370
|
+
|
371
|
+
return TRUE;
|
372
|
+
}
|
373
|
+
return FALSE;
|
374
|
+
}
|
375
|
+
|
376
|
+
#endif
|
377
|
+
|
378
|
+
void http_resp_200(http_t *h) {
|
298
379
|
LOG_FUNCTION
|
299
|
-
char str[
|
380
|
+
char str[STR_SIZE512], expire_date[STR_SIZE64] = "", current_date[STR_SIZE64] = "", modify_date[STR_SIZE64] = "";
|
300
381
|
int len;
|
382
|
+
int ret_val;
|
301
383
|
time_t t;
|
302
384
|
|
303
|
-
static_file_t *ext = get_mime_type(
|
385
|
+
static_file_t *ext = get_mime_type(h->stat);
|
304
386
|
LOG_DEBUG(DEBUG,"File extension = %s, mimetype = %s, expires = %d ", ext->ext, ext->mime_type, ext->expires);
|
305
387
|
const char *conn_header = scgi_header_value_get(h->req->scgi, HTTP_HEADER_CONNECTION);
|
306
388
|
|
307
|
-
t = get_time(current_date,
|
308
|
-
time_to_httpdate(buf
|
389
|
+
t = get_time(current_date, STR_SIZE64);
|
390
|
+
time_to_httpdate(h->stat->buf.st_mtime, modify_date, STR_SIZE64);
|
391
|
+
|
392
|
+
#ifdef W_ZLIB
|
393
|
+
ret_val = file_compress(h, ext);
|
394
|
+
if(ret_val == FALSE){
|
395
|
+
#endif
|
396
|
+
h->resp->resp_body->len = h->stat->buf.st_size;
|
397
|
+
#ifdef _POSIX_C_SOURCE
|
398
|
+
h->resp->file = open(h->stat->path, O_RDONLY);
|
399
|
+
#else
|
400
|
+
h->resp->file = fopen(h->stat->path, "r");
|
401
|
+
#endif
|
402
|
+
#ifdef W_ZLIB
|
403
|
+
}
|
404
|
+
#endif
|
309
405
|
|
310
406
|
if (ext->expires > 0) {
|
311
407
|
t += ext->expires;
|
312
|
-
time_to_httpdate(t, expire_date,
|
313
|
-
len = sprintf(str, "HTTP/1.1 200 OK\r\nDate: %s\r\nServer: %s-%s\r\nLast-Modified: %s\r\nExpires: %s\r\
|
314
|
-
current_date,
|
315
|
-
(conn_header ? conn_header : CONNECTION_CLOSE),
|
408
|
+
time_to_httpdate(t, expire_date, STR_SIZE64);
|
409
|
+
len = sprintf(str, "HTTP/1.1 200 OK\r\nDate: %s\r\nServer: %s-%s\r\nLast-Modified: %s\r\nExpires: %s\r\nConnection: %s\r\n%sContent-Type: %s\r\nContent-Length: %d\r\n\r\n",
|
410
|
+
current_date, Config->Worker.Server.name.str, Config->Worker.Server.version.str, modify_date, expire_date,
|
411
|
+
(conn_header ? conn_header : CONNECTION_CLOSE),
|
412
|
+
(ret_val == TRUE ? "Content-Encoding: deflate\r\n" : ""),
|
413
|
+
ext->mime_type, h->resp->resp_body->len);
|
316
414
|
}else {
|
317
|
-
len = sprintf(str, "HTTP/1.1 200 OK\r\nDate: %s\r\nServer: %s-%s\r\nLast-Modified: %s\r\
|
318
|
-
current_date,
|
319
|
-
(conn_header ? conn_header : CONNECTION_CLOSE),
|
415
|
+
len = sprintf(str, "HTTP/1.1 200 OK\r\nDate: %s\r\nServer: %s-%s\r\nLast-Modified: %s\r\nConnection: %s\r\n%sContent-Type: %s\r\nContent-Length: %d\r\n\r\n",
|
416
|
+
current_date, Config->Worker.Server.name.str, Config->Worker.Server.version.str, modify_date,
|
417
|
+
(conn_header ? conn_header : CONNECTION_CLOSE),
|
418
|
+
(ret_val == TRUE ? "Content-Encoding: deflate\r\n" : ""),
|
419
|
+
ext->mime_type, h->resp->resp_body->len);
|
320
420
|
}
|
321
421
|
|
322
422
|
wr_string_new(h->resp->header, str, len);
|
323
|
-
h->resp->resp_body->len = buf->st_size;
|
324
423
|
h->resp->resp_code = http_status[HTTP_STATUS_200].code;
|
325
|
-
#ifdef _POSIX_C_SOURCE
|
326
|
-
h->resp->file = open(path, O_RDONLY);
|
327
|
-
#else
|
328
|
-
h->resp->file = fopen(path, "r");
|
329
|
-
#endif
|
330
424
|
}
|
331
425
|
|
332
|
-
void http_resp_304(http_t *h
|
426
|
+
void http_resp_304(http_t *h) {
|
333
427
|
LOG_FUNCTION
|
334
|
-
char str[
|
428
|
+
char str[STR_SIZE512], expire_date[STR_SIZE64] = "", current_date[STR_SIZE64] = "";
|
335
429
|
int len;
|
336
430
|
time_t t;
|
337
|
-
static_file_t *ext = get_mime_type(
|
431
|
+
static_file_t *ext = get_mime_type(h->stat);
|
338
432
|
LOG_DEBUG(DEBUG,"File extension = %s, mimetype = %s, expires = %d ", ext->ext, ext->mime_type, ext->expires);
|
339
433
|
const char *conn_header = scgi_header_value_get(h->req->scgi, HTTP_HEADER_CONNECTION);
|
340
434
|
|
341
|
-
t = get_time(current_date,
|
435
|
+
t = get_time(current_date, STR_SIZE64);
|
342
436
|
if (ext->expires > 0) {
|
343
437
|
t = t + ext->expires;
|
344
|
-
time_to_httpdate(t, expire_date,
|
345
|
-
len = sprintf(str, "HTTP/1.1 304 Not Modified\r\nDate: %s\r\nServer: %s-%s\r\nExpires: %s\r\
|
346
|
-
current_date,
|
438
|
+
time_to_httpdate(t, expire_date, STR_SIZE64);
|
439
|
+
len = sprintf(str, "HTTP/1.1 304 Not Modified\r\nDate: %s\r\nServer: %s-%s\r\nExpires: %s\r\nConnection: %s\r\n\r\n",
|
440
|
+
current_date, Config->Worker.Server.name.str, Config->Worker.Server.version.str, expire_date,
|
347
441
|
(conn_header ? conn_header : CONNECTION_CLOSE));
|
348
442
|
}else {
|
349
|
-
len = sprintf(str, "HTTP/1.1 304 Not Modified\r\nDate: %s\r\nServer: %s-%s\r\
|
350
|
-
current_date,
|
443
|
+
len = sprintf(str, "HTTP/1.1 304 Not Modified\r\nDate: %s\r\nServer: %s-%s\r\nConnection: %s\r\n\r\n",
|
444
|
+
current_date, Config->Worker.Server.name.str, Config->Worker.Server.version.str, (conn_header ? conn_header : CONNECTION_CLOSE));
|
351
445
|
}
|
352
446
|
|
353
447
|
wr_string_new(h->resp->header, str, len);
|
354
448
|
h->resp->resp_code = http_status[HTTP_STATUS_304].code;
|
355
449
|
}
|
356
450
|
|
357
|
-
void http_resp_403(http_t *h
|
451
|
+
void http_resp_403(http_t *h) {
|
358
452
|
LOG_FUNCTION
|
359
|
-
char str[
|
453
|
+
char str[STR_SIZE512], current_date[STR_SIZE64];
|
360
454
|
const char *conn_header = scgi_header_value_get(h->req->scgi, HTTP_HEADER_CONNECTION);
|
361
455
|
int len;
|
362
456
|
|
363
|
-
get_time(current_date,
|
457
|
+
get_time(current_date, STR_SIZE64);
|
364
458
|
|
365
459
|
len = sprintf(str, HTTP_RESP_ERR_BODY,
|
366
460
|
http_status[HTTP_STATUS_403].phrase, http_status[HTTP_STATUS_403].phrase + 4,
|
367
|
-
http_status[HTTP_STATUS_403].message,
|
461
|
+
http_status[HTTP_STATUS_403].message, Config->Worker.Server.name.str, Config->Worker.Server.version.str);
|
368
462
|
wr_buffer_create(h->resp->resp_body, len);
|
369
463
|
wr_buffer_add(h->resp->resp_body, str, len);
|
370
464
|
|
371
465
|
len = sprintf(str, HTTP_RESP_ERR_HEADERS,
|
372
|
-
current_date, http_status[HTTP_STATUS_403].phrase,
|
466
|
+
current_date, http_status[HTTP_STATUS_403].phrase, Config->Worker.Server.name.str, Config->Worker.Server.version.str,
|
373
467
|
(conn_header ? conn_header : CONNECTION_CLOSE), len);
|
374
468
|
wr_string_new(h->resp->header, str, len);
|
375
469
|
h->resp->resp_code = http_status[HTTP_STATUS_403].code;
|
376
470
|
}
|
377
471
|
|
378
|
-
void http_resp_404(http_t *h
|
472
|
+
void http_resp_404(http_t *h) {
|
379
473
|
LOG_FUNCTION
|
380
|
-
char str[
|
474
|
+
char str[STR_SIZE512], current_date[STR_SIZE64];
|
381
475
|
const char *conn_header = scgi_header_value_get(h->req->scgi, HTTP_HEADER_CONNECTION);
|
382
476
|
int len;
|
383
477
|
|
384
|
-
get_time(current_date,
|
478
|
+
get_time(current_date, STR_SIZE64);
|
385
479
|
|
386
480
|
len = sprintf(str, HTTP_RESP_ERR_BODY,
|
387
481
|
http_status[HTTP_STATUS_404].phrase, http_status[HTTP_STATUS_404].phrase + 4,
|
388
|
-
http_status[HTTP_STATUS_404].message,
|
482
|
+
http_status[HTTP_STATUS_404].message, Config->Worker.Server.name.str, Config->Worker.Server.version.str);
|
389
483
|
wr_buffer_create(h->resp->resp_body, len);
|
390
484
|
wr_buffer_add(h->resp->resp_body, str, len);
|
391
485
|
|
392
486
|
len = sprintf(str, HTTP_RESP_ERR_HEADERS,
|
393
|
-
current_date, http_status[HTTP_STATUS_404].phrase,
|
487
|
+
current_date, http_status[HTTP_STATUS_404].phrase, Config->Worker.Server.name.str, Config->Worker.Server.version.str,
|
394
488
|
(conn_header ? conn_header : CONNECTION_CLOSE), len);
|
395
489
|
wr_string_new(h->resp->header, str, len);
|
396
490
|
h->resp->resp_code = http_status[HTTP_STATUS_404].code;
|
397
491
|
}
|
398
492
|
|
399
|
-
void send_static_worker_pid(
|
493
|
+
void send_static_worker_pid() {
|
400
494
|
LOG_FUNCTION
|
401
495
|
node_t *root = NULL;
|
402
|
-
|
496
|
+
|
403
497
|
// Read pid queue related configuration
|
404
|
-
|
405
|
-
root = yaml_parse(
|
498
|
+
|
499
|
+
root = yaml_parse(Config->Worker.File.internal_config.str);
|
406
500
|
if(root == NULL) {
|
407
501
|
LOG_ERROR(SEVERE, "Could not parse server_internal_config.yml file. PID can not be sent to analyzer");
|
408
502
|
return;
|
@@ -410,7 +504,7 @@ void send_static_worker_pid(char *root_path) {
|
|
410
504
|
char *host = NULL, *port = NULL, *queue_name = NULL;
|
411
505
|
wr_msg_queue_server_t *msg_queue_server = NULL;
|
412
506
|
wr_msg_queue_conn_t *msg_queue_conn = NULL;
|
413
|
-
char msg_value[
|
507
|
+
char msg_value[STR_SIZE32];
|
414
508
|
int rv;
|
415
509
|
|
416
510
|
host = get_node_value(root, WR_MSG_QUEUE_SERVER_HOST);
|
@@ -435,7 +529,7 @@ void send_static_worker_pid(char *root_path) {
|
|
435
529
|
LOG_ERROR(WARN, "Error establising connection with message queue server");
|
436
530
|
goto err;
|
437
531
|
}
|
438
|
-
rv = sprintf(msg_value, "%s:%d",
|
532
|
+
rv = sprintf(msg_value, "%s:%d", Config->Worker.static_server.str, getpid());
|
439
533
|
rv = wr_msg_queue_set(msg_queue_conn, queue_name, msg_value, rv);
|
440
534
|
if (rv < 0) {
|
441
535
|
LOG_ERROR(SEVERE, "Failed to send PID to message queue");
|
@@ -450,47 +544,41 @@ err:
|
|
450
544
|
}
|
451
545
|
}
|
452
546
|
|
453
|
-
/**************************************
|
454
|
-
* Public Functions
|
455
|
-
*************************************/
|
456
547
|
|
457
548
|
/* Initialize extension and mime-type map */
|
458
|
-
int static_module_init(
|
549
|
+
int static_module_init(static_server_t *s) {
|
459
550
|
LOG_FUNCTION
|
460
551
|
node_t *root;
|
461
|
-
char file_name[100];
|
462
552
|
long int expires;
|
463
|
-
|
464
|
-
|
465
|
-
root = yaml_parse(file_name);
|
553
|
+
|
554
|
+
root = yaml_parse(Config->Worker.File.config.str);
|
466
555
|
if (root == NULL) {
|
467
556
|
LOG_ERROR(SEVERE, "Could not read config.yml file");
|
468
|
-
return
|
557
|
+
return FALSE;
|
469
558
|
}
|
470
559
|
expires = get_default_expires(root);
|
471
|
-
|
472
|
-
|
473
|
-
if (create_dictionary(file_name, expires) != 0) {
|
560
|
+
|
561
|
+
if (create_dictionary(s, Config->Worker.File.mime_type.str, expires) != 0) {
|
474
562
|
node_free(root);
|
475
|
-
return
|
563
|
+
return FALSE;
|
476
564
|
}
|
477
565
|
|
478
|
-
set_expires_by_type(root);
|
566
|
+
set_expires_by_type(s, root);
|
479
567
|
|
480
568
|
node_free(root);
|
481
569
|
|
482
|
-
send_static_worker_pid(
|
483
|
-
return
|
570
|
+
send_static_worker_pid();
|
571
|
+
return TRUE;
|
484
572
|
}
|
485
573
|
|
486
574
|
/* Free extension and mime-type map */
|
487
|
-
void static_module_free() {
|
575
|
+
void static_module_free(static_server_t *s) {
|
488
576
|
LOG_FUNCTION
|
489
577
|
int i;
|
490
578
|
static_file_t *ext, *next_ext;
|
491
579
|
|
492
580
|
for (i = 0; i <= MAP_SIZE; i++) {
|
493
|
-
ext = map[i];
|
581
|
+
ext = s->map[i];
|
494
582
|
while (ext) {
|
495
583
|
next_ext = ext->next;
|
496
584
|
free(ext);
|
@@ -499,17 +587,116 @@ void static_module_free() {
|
|
499
587
|
}
|
500
588
|
}
|
501
589
|
|
590
|
+
/**************************************
|
591
|
+
* Public Functions
|
592
|
+
*************************************/
|
593
|
+
|
594
|
+
/** Create new static server */
|
595
|
+
static_server_t * static_server_new(void* ptr){
|
596
|
+
LOG_FUNCTION
|
597
|
+
|
598
|
+
wkr_t* w = (wkr_t*)ptr;
|
599
|
+
|
600
|
+
static_server_t *s = wr_malloc(static_server_t);
|
601
|
+
if(s == NULL) return NULL;
|
602
|
+
|
603
|
+
#ifdef W_ZLIB
|
604
|
+
if(w->tmp->lower_limit > 0)
|
605
|
+
Config->Worker.Compress.lower_limit = w->tmp->lower_limit;
|
606
|
+
|
607
|
+
if(w->tmp->upper_limit > 0)
|
608
|
+
Config->Worker.Compress.upper_limit = w->tmp->upper_limit;
|
609
|
+
|
610
|
+
#ifdef W_REGEX
|
611
|
+
s->r_content_type = NULL;
|
612
|
+
if(!wr_string_is_empty(w->tmp->r_content_type)){
|
613
|
+
int err_no;
|
614
|
+
s->r_content_type = wr_malloc(regex_t);
|
615
|
+
// #define REG_EXTENDED 1
|
616
|
+
if((err_no = regcomp(s->r_content_type, w->tmp->r_content_type.str, 1))!=0){ /* Compile the regex */
|
617
|
+
size_t length;
|
618
|
+
char *buffer;
|
619
|
+
length = regerror (err_no, s->r_content_type, NULL, 0);
|
620
|
+
buffer = malloc(length);
|
621
|
+
regerror (err_no, s->r_content_type, buffer, length);
|
622
|
+
LOG_ERROR(SEVERE, "%s", buffer); /* Print the error */
|
623
|
+
LOG_ERROR(SEVERE, "Now Static Workers allow encoding for only 'text' and 'xml' Content-Type.");
|
624
|
+
free(buffer);
|
625
|
+
regfree(s->r_content_type);
|
626
|
+
if((err_no = regcomp(s->r_content_type, "text|xml", 1))!=0){
|
627
|
+
regfree(s->r_content_type);
|
628
|
+
free(s->r_content_type);
|
629
|
+
s->r_content_type = NULL;
|
630
|
+
}
|
631
|
+
}
|
632
|
+
}
|
633
|
+
|
634
|
+
s->r_user_agent = NULL;
|
635
|
+
// Do not apply validation on User-Agent if it is not given or it is '.*'(allow all).
|
636
|
+
if(!wr_string_is_empty(w->tmp->r_user_agent) && strcmp(w->tmp->r_user_agent.str,".*") != 0){
|
637
|
+
int err_no;
|
638
|
+
s->r_user_agent = wr_malloc(regex_t);
|
639
|
+
if((err_no = regcomp(s->r_user_agent, w->tmp->r_content_type.str, 1))!=0){ /* Compile the regex */
|
640
|
+
size_t length;
|
641
|
+
char *buffer;
|
642
|
+
length = regerror (err_no, s->r_user_agent, NULL, 0);
|
643
|
+
buffer = malloc(length);
|
644
|
+
regerror (err_no, s->r_user_agent, buffer, length);
|
645
|
+
LOG_ERROR(SEVERE, "%s", buffer); /* Print the error */
|
646
|
+
LOG_ERROR(SEVERE, "Now Static Workers serves encoded assets to all User-Agent.");
|
647
|
+
free(buffer);
|
648
|
+
regfree(s->r_user_agent);
|
649
|
+
free(s->r_user_agent);
|
650
|
+
s->r_user_agent = NULL;
|
651
|
+
}
|
652
|
+
}
|
653
|
+
#endif
|
654
|
+
|
655
|
+
#endif
|
656
|
+
|
657
|
+
if(static_module_init(s) == FALSE){
|
658
|
+
free(s);
|
659
|
+
return NULL;
|
660
|
+
}
|
661
|
+
wr_buffer_new(s->buffer);
|
662
|
+
|
663
|
+
return s;
|
664
|
+
}
|
665
|
+
|
666
|
+
/** Delete static server */
|
667
|
+
void static_server_free(static_server_t *s){
|
668
|
+
if(s){
|
669
|
+
if(s->buffer) wr_buffer_free(s->buffer);
|
670
|
+
static_module_free(s);
|
671
|
+
|
672
|
+
#if defined(W_ZLIB) && defined(W_REGEX)
|
673
|
+
if(s->r_user_agent){
|
674
|
+
regfree(s->r_user_agent);
|
675
|
+
free(s->r_user_agent);
|
676
|
+
}
|
677
|
+
if(s->r_content_type){
|
678
|
+
regfree(s->r_content_type);
|
679
|
+
free(s->r_content_type);
|
680
|
+
}
|
681
|
+
#endif
|
682
|
+
|
683
|
+
free(s);
|
684
|
+
}
|
685
|
+
}
|
686
|
+
|
502
687
|
/* Serve static file content */
|
503
|
-
void static_file_process(
|
688
|
+
void static_file_process(void *http) {
|
504
689
|
LOG_FUNCTION
|
690
|
+
http_t *h = (http_t*) http;
|
505
691
|
wkr_t *w = h->wkr;
|
506
692
|
short resp_code;
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
693
|
+
|
694
|
+
h->stat->path = scgi_header_value_get(h->req->scgi, Config->Worker.Header.file_path.str);
|
695
|
+
h->stat->modify = scgi_header_value_get(h->req->scgi, HTTP_HEADER_IF_MODIFIED_SINCE);
|
696
|
+
|
697
|
+
LOG_DEBUG(DEBUG, "Path = %s", h->stat->path);
|
698
|
+
resp_code = get_resp_code(h->stat);
|
699
|
+
http_status[resp_code].fun(h);
|
513
700
|
http_req_set(h->req);
|
514
701
|
http_resp_process(h->resp);
|
515
702
|
|