webroar 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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