webroar 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. data/CHANGELOG +48 -1
  2. data/README +11 -14
  3. data/Rakefile +1 -1
  4. data/conf/mime_type.yml +172 -166
  5. data/conf/server_internal_config.yml +30 -8
  6. data/doc/user-guide.html +294 -153
  7. data/doc/user-guide.txt +9 -13
  8. data/lib/command_runner.rb +1 -0
  9. data/lib/dependencies.rb +18 -15
  10. data/lib/installer.rb +115 -50
  11. data/src/admin_panel/app/controllers/admin_controller.rb +1 -15
  12. data/src/admin_panel/app/controllers/application_controller.rb +2 -2
  13. data/src/admin_panel/app/controllers/application_specification_controller.rb +2 -1
  14. data/src/admin_panel/app/controllers/headers_controller.rb +73 -0
  15. data/src/admin_panel/app/controllers/mail_specification_controller.rb +10 -0
  16. data/src/admin_panel/app/controllers/server_specification_controller.rb +14 -0
  17. data/src/admin_panel/app/helpers/admin_helper.rb +0 -85
  18. data/src/admin_panel/app/models/app.rb +1 -1
  19. data/src/admin_panel/app/models/application_specification.rb +33 -25
  20. data/src/admin_panel/app/models/headers.rb +116 -0
  21. data/src/admin_panel/app/models/mail_specification.rb +20 -5
  22. data/src/admin_panel/app/models/server_specification.rb +2 -7
  23. data/src/admin_panel/app/views/admin/configuration.html.erb +10 -5
  24. data/src/admin_panel/app/views/exceptions/_exception_list_partial.html.erb +4 -4
  25. data/src/admin_panel/app/views/graph/_graph_page.html.erb +3 -0
  26. data/src/admin_panel/app/views/headers/_add_expires_text_box.html.erb +35 -0
  27. data/src/admin_panel/app/views/headers/_expires_by_type_form.html.erb +65 -0
  28. data/src/admin_panel/app/views/headers/_headers_table.html.erb +113 -0
  29. data/src/admin_panel/app/views/mail_specification/_current_spec.html.erb +168 -0
  30. data/src/admin_panel/app/views/{admin → server_specification}/_add_div.html.erb +1 -1
  31. data/src/admin_panel/config/initializers/application_constants.rb +6 -0
  32. data/src/admin_panel/lib/control.rb +6 -3
  33. data/src/admin_panel/lib/scgi.rb +74 -21
  34. data/src/admin_panel/lib/yaml_writer.rb +51 -17
  35. data/src/admin_panel/public/javascripts/application.js +20 -1
  36. data/src/head/wr_access_log.c +2 -2
  37. data/src/head/wr_application.c +294 -236
  38. data/src/head/wr_application.h +8 -8
  39. data/src/head/wr_configurator.c +451 -517
  40. data/src/head/wr_configurator.h +10 -115
  41. data/src/head/wr_connection.c +26 -25
  42. data/src/head/wr_connection.h +2 -3
  43. data/src/head/wr_controller.c +110 -93
  44. data/src/head/wr_controller.h +6 -6
  45. data/src/head/wr_main.c +31 -24
  46. data/src/head/wr_request.c +70 -93
  47. data/src/head/wr_request.h +0 -4
  48. data/src/head/wr_resolver.c +21 -15
  49. data/src/head/wr_resolver.h +2 -2
  50. data/src/head/wr_server.c +36 -26
  51. data/src/head/wr_server.h +5 -5
  52. data/src/head/wr_worker.c +551 -512
  53. data/src/head/wr_worker.h +33 -20
  54. data/src/helper/wr_config.c +316 -0
  55. data/src/helper/wr_config.h +235 -0
  56. data/src/helper/wr_helper.h +1 -5
  57. data/src/helper/wr_logger.c +4 -4
  58. data/src/helper/wr_scgi.c +3 -4
  59. data/src/helper/wr_scgi.h +2 -0
  60. data/src/helper/wr_string.h +2 -2
  61. data/src/helper/wr_util.c +3 -1
  62. data/src/helper/wr_util.h +0 -0
  63. data/src/helper/wr_yaml_parser.c +30 -0
  64. data/src/helper/wr_yaml_parser.h +1 -0
  65. data/src/ruby_lib/exception_tracker/instrumentation/action_controller.rb +2 -1
  66. data/src/ruby_lib/mailer/smtpmail.rb +7 -4
  67. data/src/ruby_lib/profiler/instrumentation/action_controller.rb +2 -1
  68. data/src/ruby_lib/profiler/instrumentation/active_record.rb +3 -0
  69. data/src/ruby_lib/rack/adapter/rails.rb +14 -7
  70. data/src/ruby_lib/ruby_interface/client.rb +1 -1
  71. data/src/ruby_lib/ruby_interface/version.rb +2 -2
  72. data/src/ruby_lib/webroar_app_loader.rb +4 -2
  73. data/src/worker/wkr_controller.c +200 -140
  74. data/src/worker/wkr_http.c +14 -28
  75. data/src/worker/wkr_http.h +4 -4
  76. data/src/worker/wkr_http_request.c +12 -11
  77. data/src/worker/wkr_http_request.h +7 -8
  78. data/src/worker/wkr_http_response.c +10 -14
  79. data/src/worker/wkr_http_response.h +0 -1
  80. data/src/worker/wkr_main.c +74 -140
  81. data/src/worker/wkr_static.c +295 -108
  82. data/src/worker/wkr_static.h +20 -7
  83. data/src/worker/worker.c +245 -70
  84. data/src/worker/worker.h +46 -34
  85. data/tasks/compile.rake +128 -175
  86. data/tasks/test.rake +345 -469
  87. data/test/spec/webroar_command_spec.rb +23 -0
  88. metadata +173 -43
  89. data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/README +0 -34
  90. data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/Rakefile +0 -13
  91. data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/init.rb +0 -5
  92. data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/lib/action_mailer_tls.rb +0 -16
  93. data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/lib/smtp_tls.rb +0 -123
  94. data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/test/tls_test.rb +0 -42
  95. data/src/head/wr_config.h +0 -165
  96. data/src/ruby_lib/mailer/action_mailer_tls.rb +0 -16
  97. data/src/ruby_lib/mailer/smtp_tls.rb +0 -123
@@ -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
- #include "wkr_static.h"
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*, const char*, struct stat *);
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*, const char*, struct stat *);
65
- void http_resp_304(http_t*, const char*, struct stat *);
66
- void http_resp_403(http_t*, const char*, struct stat *);
67
- void http_resp_404(http_t*, const char*, struct stat *);
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
- static char* get_file_ext(const char *path) {
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
- static void set_expires_time(char *ext, long int expires) {
112
+ void set_expires_time(static_server_t * s, char *ext, long int expires) {
114
113
  int index;
115
- char tmp_ext[WR_STR_LEN], *p;
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
- static static_file_t* get_mime_type(const char *path) {
146
- char *ext = get_file_ext(path);
147
- char tmp_ext[WR_STR_LEN], *p;
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
- static short get_resp_code(http_t *h, const char *path, struct stat *buf) {
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->st_mode) != 0) {
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->st_mtime, modify_tm);
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
- static long int get_default_expires(node_t *root) {
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
- static int create_dictionary(const char *mapping_file, long int expires) {
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
- node = root;
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
- static void set_expires_by_type(node_t *root) {
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
- void http_resp_200(http_t *h, const char *path, struct stat *buf) {
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[WR_LONG_LONG_STR_LEN], expire_date[WR_STR_LEN] = "", current_date[WR_STR_LEN] = "", modify_date[WR_STR_LEN] = "";
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(path);
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, WR_STR_LEN);
308
- time_to_httpdate(buf->st_mtime, modify_date, WR_STR_LEN);
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, WR_STR_LEN);
313
- len = sprintf(str, "HTTP/1.1 200 OK\r\nDate: %s\r\nServer: %s-%s\r\nLast-Modified: %s\r\nExpires: %s\r\nCache-Control: max-age=%ld, public\r\nConnection: %s\r\nContent-Type: %s\r\nContent-Length: %d\r\n\r\n",
314
- current_date, WR_SERVER, WR_VERSION, modify_date, expire_date, ext->expires,
315
- (conn_header ? conn_header : CONNECTION_CLOSE), ext->mime_type, buf->st_size);
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\nCache-Control: no-cache\r\nConnection: %s\r\nContent-Type: %s\r\nContent-Length: %d\r\n\r\n",
318
- current_date, WR_SERVER, WR_VERSION, modify_date,
319
- (conn_header ? conn_header : CONNECTION_CLOSE), ext->mime_type, buf->st_size);
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, const char *path, struct stat *buf) {
426
+ void http_resp_304(http_t *h) {
333
427
  LOG_FUNCTION
334
- char str[WR_LONG_LONG_STR_LEN], expire_date[WR_STR_LEN] = "", current_date[WR_STR_LEN] = "";
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(path);
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, WR_STR_LEN);
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, WR_STR_LEN);
345
- len = sprintf(str, "HTTP/1.1 304 Not Modified\r\nDate: %s\r\nServer: %s-%s\r\nExpires: %s\r\nCache-Control: max-age=%ld, public\r\nConnection: %s\r\n\r\n",
346
- current_date, WR_SERVER, WR_VERSION, expire_date, ext->expires,
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\nCache-Control: no-cache\r\nConnection: %s\r\n\r\n",
350
- current_date, WR_SERVER, WR_VERSION, (conn_header ? conn_header : CONNECTION_CLOSE));
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, const char *path, struct stat *buf) {
451
+ void http_resp_403(http_t *h) {
358
452
  LOG_FUNCTION
359
- char str[WR_LONG_LONG_STR_LEN], current_date[WR_STR_LEN];
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, WR_STR_LEN);
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, WR_SERVER, WR_VERSION);
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, WR_SERVER, WR_VERSION,
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, const char *path, struct stat *buf) {
472
+ void http_resp_404(http_t *h) {
379
473
  LOG_FUNCTION
380
- char str[WR_LONG_LONG_STR_LEN], current_date[WR_STR_LEN];
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, WR_STR_LEN);
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, WR_SERVER, WR_VERSION);
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, WR_SERVER, WR_VERSION,
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(char *root_path) {
493
+ void send_static_worker_pid() {
400
494
  LOG_FUNCTION
401
495
  node_t *root = NULL;
402
- char file_name[WR_LONG_STR_LEN];
496
+
403
497
  // Read pid queue related configuration
404
- sprintf(file_name, "%s%s", root_path, WR_SERVER_INTERNAL_CONF_PATH);
405
- root = yaml_parse(file_name);
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[WR_SHORT_STR_LEN];
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", WR_STATIC_FILE_SERVER_NAME, getpid());
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(char *root_path) {
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
- sprintf(file_name, "%s%s", root_path, WR_CONF_PATH);
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 -1;
557
+ return FALSE;
469
558
  }
470
559
  expires = get_default_expires(root);
471
-
472
- sprintf(file_name, "%s%s", root_path, WR_MIME_TYPE_PATH);
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 -1;
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(root_path);
483
- return 0;
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(http_t *h) {
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
- struct stat buf;
508
- const char *path = scgi_header_value_get(h->req->scgi, WR_HTTP_FILE_PATH);
509
-
510
- LOG_DEBUG(DEBUG, "Path = %s", path);
511
- resp_code = get_resp_code(h, path, &buf);
512
- http_status[resp_code].fun(h, path, &buf);
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