Bläddra i källkod

Fixed multiple worker_process issue

 * Added a content handler that overrides the original handler (but calls it). It is
used to add our own read_event_handler.

 * Implemented a read_event_handler that calls the original handler, and store the rest/content_length in our
own node.

 * modified the different handlers to use the new node fields
tags/v0.4
Brice Figureau 18 år sedan
förälder
incheckning
9a7740f118
3 ändrade filer med 150 tillägg och 88 borttagningar
  1. 7
    0
      CHANGES
  2. 2
    0
      README
  3. 141
    88
      ngx_http_uploadprogress_module.c

+ 7
- 0
CHANGES Visa fil

@@ -1,3 +1,10 @@
1
+nginx_upload_progress release 0.3                                  08 May 2008
2
+
3
+ * Incompatible change: track_uploads MUST be the last directive of a location
4
+   it also must be in a proxy_pass or fastcgi_pass location.
5
+
6
+ * fixed multiple worker_process issue
7
+
1 8
 nginx_upload_progress release 0.3                                  06 May 2008
2 9
 
3 10
  * fixed crash if the upload was denied by nginx because of any error

+ 2
- 0
README Visa fil

@@ -79,6 +79,8 @@ track_uploads
79 79
 	unique identifier used to get progress information. If the POST has no such information, the upload will not be tracked.
80 80
 	The tracked connections are kept at most <timeout> seconds after they have been finished to be able to serve 
81 81
 	unseful information to upload progress probes.
82
+  Warning: this directive must be the last directive of the location. It must be in a proxy_pass or fastcgi_pass
83
+  location.
82 84
 	
83 85
 report_uploads
84 86
 ++++++++++++++

+ 141
- 88
ngx_http_uploadprogress_module.c Visa fil

@@ -14,8 +14,10 @@ typedef struct ngx_http_uploadprogress_node_s ngx_http_uploadprogress_node_t;
14 14
 
15 15
 struct ngx_http_uploadprogress_node_s {
16 16
     ngx_rbtree_node_t                node;
17
-    ngx_http_request_t              *r;
18 17
     ngx_uint_t                       err_status;
18
+    ngx_uint_t                       rest;
19
+    ngx_uint_t                       length;
20
+    ngx_uint_t                       done;
19 21
     time_t                           timeout;
20 22
     struct ngx_http_uploadprogress_node_s *prev;
21 23
     struct ngx_http_uploadprogress_node_s *next;
@@ -37,8 +39,10 @@ typedef struct {
37 39
 
38 40
 typedef struct {
39 41
     ngx_shm_zone_t                  *shm_zone;
40
-		time_t                           timeout;
42
+    time_t                           timeout;
41 43
     ngx_event_t                      cleanup;
44
+    ngx_http_handler_pt              handler;
45
+    ngx_http_event_handler_pt        read_event_handler;
42 46
     u_char                           track;
43 47
 } ngx_http_uploadprogress_conf_t;
44 48
 
@@ -248,12 +252,78 @@ find_node(ngx_str_t * id, ngx_http_uploadprogress_ctx_t * ctx, ngx_log_t * log)
248 252
     return NULL;
249 253
 }
250 254
 
255
+static void ngx_http_uploadprogress_event_handler(ngx_http_request_t *r);
251 256
 
252 257
 static ngx_int_t
253 258
 ngx_http_uploadprogress_content_handler(ngx_http_request_t *r)
254 259
 {
255
-  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "upload-progress: ngx_http_uploadprogress_content_handler");
256
-	return ngx_http_proxy_handler(r);
260
+    ngx_int_t                        rc;
261
+    ngx_http_uploadprogress_conf_t  *upcf;
262
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "upload-progress: ngx_http_uploadprogress_content_handler");
263
+    upcf = ngx_http_get_module_loc_conf(r, ngx_http_uploadprogress_module);
264
+
265
+    /* call the original request handler */
266
+    rc = upcf->handler(r);
267
+
268
+    /* hijack the read_event_handler */
269
+    upcf->read_event_handler = r->read_event_handler;
270
+    r->read_event_handler = ngx_http_uploadprogress_event_handler;
271
+
272
+    return rc;
273
+}
274
+
275
+static void ngx_http_uploadprogress_event_handler(ngx_http_request_t *r)
276
+{
277
+    ngx_str_t                       *id;
278
+    ngx_slab_pool_t                 *shpool;
279
+    ngx_http_uploadprogress_ctx_t   *ctx;
280
+    ngx_http_uploadprogress_node_t  *up;
281
+    ngx_http_uploadprogress_conf_t  *upcf;
282
+
283
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "upload-progress: ngx_http_uploadprogress_event_handler");
284
+    
285
+    /* call the original read event handler */
286
+    upcf = ngx_http_get_module_loc_conf(r, ngx_http_uploadprogress_module);
287
+    upcf->read_event_handler(r);
288
+
289
+    /* find node, update rest */
290
+    id = get_tracking_id(r);
291
+
292
+    if (id == NULL) {
293
+        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
294
+                       "upload-progress: read_event_handler cant find id");
295
+        return;
296
+    }
297
+
298
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
299
+                   "upload-progress: read_event_handler found id: %V", id);
300
+
301
+    if (upcf->shm_zone == NULL) {
302
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
303
+                       "upload-progress: read_event_handler no shm_zone for id: %V", id);
304
+        return;
305
+    }
306
+
307
+    ctx = upcf->shm_zone->data;
308
+
309
+    /* get the original connection of the upload */
310
+    shpool = (ngx_slab_pool_t *) upcf->shm_zone->shm.addr;
311
+
312
+    ngx_shmtx_lock(&shpool->mutex);
313
+
314
+    up = find_node(id, ctx, r->connection->log);
315
+    if (up != NULL) {
316
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
317
+                       "upload-progress: read_event_handler found node: %V", id);
318
+				up->rest = r->request_body->rest;
319
+				up->length = r->headers_in.content_length_n;
320
+        ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
321
+                       "upload-progress: read_event_handler storing rest %uO/%uO for %V", up->rest, up->length, id);
322
+    } else {
323
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
324
+                       "upload-progress: read_event_handler not found: %V", id);
325
+    }
326
+    ngx_shmtx_unlock(&shpool->mutex);
257 327
 }
258 328
 
259 329
 /* This generates the response for the report */
@@ -263,8 +333,7 @@ ngx_http_reportuploads_handler(ngx_http_request_t * r)
263 333
     ngx_str_t                       *id;
264 334
     ngx_buf_t                       *b;
265 335
     ngx_chain_t                      out;
266
-    ngx_http_request_t              *orig;
267
-    ngx_int_t                        rc, size;
336
+    ngx_int_t                        rc, size, found=0, rest=0, length=0, done=0, err_status=0;
268 337
     ngx_uint_t                       len, i;
269 338
     ngx_slab_pool_t                 *shpool;
270 339
     ngx_http_uploadprogress_conf_t  *upcf;
@@ -303,7 +372,6 @@ ngx_http_reportuploads_handler(ngx_http_request_t * r)
303 372
         return NGX_DECLINED;
304 373
     }
305 374
 
306
-    orig = NULL;
307 375
     ctx = upcf->shm_zone->data;
308 376
 
309 377
     /* get the original connection of the upload */
@@ -315,7 +383,11 @@ ngx_http_reportuploads_handler(ngx_http_request_t * r)
315 383
     if (up != NULL) {
316 384
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
317 385
                        "reportuploads found node: %V", id);
318
-        orig = up->r;
386
+				rest = up->rest;
387
+				length = up->length;
388
+				done = up->done;
389
+				err_status = up->err_status;
390
+				found = 1;
319 391
     } else {
320 392
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
321 393
                        "reportuploads not found: %V", id);
@@ -395,17 +467,21 @@ ngx_http_reportuploads_handler(ngx_http_request_t * r)
395 467
         }
396 468
     }
397 469
 
398
-    if (orig == NULL || orig->request_body == NULL) {
399
-        if (up == NULL ) {
400
-            size = sizeof("new Object({ 'state' : 'starting' })\r\n");
401
-        } else if (up != NULL && up->err_status >= NGX_HTTP_SPECIAL_RESPONSE) {
402
-            size = sizeof("new Object({ 'state' : 'error', 'status' : ") + NGX_INT_T_LEN + sizeof(" })\r\n");
403
-        } else {
404
-            size = sizeof("new Object({ 'state' : 'done' })\r\n");
405
-        }
406
-    } else if (orig->err_status == NGX_HTTP_REQUEST_ENTITY_TOO_LARGE) {
407
-        size = sizeof("new Object({ 'state' : 'error', 'status' : 413 })\r\n");
408
-    } else {
470
+/*
471
+ There are 4 possibilities
472
+   * request not yet started: found = false
473
+   * request in error:        err_status >= NGX_HTTP_SPECIAL_RESPONSE
474
+   * request finished:        done = true
475
+   * reauest in progress:     rest > 0 
476
+ */
477
+
478
+    if (!found) {
479
+      size = sizeof("new Object({ 'state' : 'starting' })\r\n");			
480
+		} else if (err_status >= NGX_HTTP_SPECIAL_RESPONSE) {
481
+        size = sizeof("new Object({ 'state' : 'error', 'status' : ") + NGX_INT_T_LEN + sizeof(" })\r\n");
482
+		} else if (done) {
483
+    		size = sizeof("new Object({ 'state' : 'done' })\r\n");
484
+	  } else {
409 485
         size =
410 486
             sizeof("new Object({ 'state' : 'uploading', 'received' : ") +
411 487
             NGX_INT_T_LEN + sizeof(" })\r\n");
@@ -420,56 +496,37 @@ ngx_http_reportuploads_handler(ngx_http_request_t * r)
420 496
     out.buf = b;
421 497
     out.next = NULL;
422 498
 
423
-    if (orig == NULL || orig->request_body == NULL ) {
424
-        if (up == NULL) {
425
-            b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'starting' })\r\n",
426
-                                 sizeof("new Object({ 'state' : 'starting' })\r\n") -
427
-                                 1);
428
-            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
429
-                           "reportuploads returning starting");
430
-        } else if (up != NULL && up->err_status >= NGX_HTTP_SPECIAL_RESPONSE) {
431
-            b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'error', 'status' : ",
432
-                                   sizeof("new Object({ 'state' : 'error', 'status' : ") - 1);
433
-        		b->last =	ngx_sprintf(b->last, "%ui })\r\n", up->err_status );
434
-            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
435
-                           "reportuploads returning error condition: %ui", up->err_status);
436
-        }
437
-				else {
438
-            b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'done' })\r\n",
439
-                                   sizeof("new Object({ 'state' : 'done' })\r\n") -
440
-                                 1);
441
-            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
442
-                           "reportuploads returning done");
443
-				}
444
-    } else if (orig->err_status == NGX_HTTP_REQUEST_ENTITY_TOO_LARGE) {
445
-        b->last =
446
-            ngx_cpymem(b->last,
447
-                       "new Object({ 'state' : 'error', 'status' : 413 })\r\n",
448
-                       sizeof
449
-                       ("new Object({ 'state' : 'error', 'status' : 413 })\r\n") -
450
-                       1);
451
-        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
452
-                       "reportuploads returning error 413");
453
-    } else {
454
-        b->last =
455
-            ngx_cpymem(b->last, "new Object({ 'state' : 'uploading', 'received' : ",
456
-                         sizeof("new Object({ 'state' : 'uploading', 'received' : ") -
457
-                       1);
458
-
459
-        b->last =
460
-            ngx_sprintf(b->last, "%uO, 'size' : %uO })\r\n",
461
-                        (orig->headers_in.content_length_n -
462
-                         orig->request_body->rest),
463
-                        orig->headers_in.content_length_n);
464
-
465
-        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
466
-                       "reportuploads returning %uO / %uO",
467
-                       (orig->headers_in.content_length_n -
468
-                        orig->request_body->rest),
469
-                       orig->headers_in.content_length_n);
470
-
499
+    if (!found) {
500
+      b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'starting' })\r\n",
501
+                           sizeof("new Object({ 'state' : 'starting' })\r\n") -
502
+                           1);
503
+      ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
504
+                     "reportuploads returning starting");
505
+		} else if (err_status >= NGX_HTTP_SPECIAL_RESPONSE) {
506
+      b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'error', 'status' : ",
507
+                             sizeof("new Object({ 'state' : 'error', 'status' : ") - 1);
508
+  		b->last =	ngx_sprintf(b->last, "%ui })\r\n", err_status );
509
+      ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
510
+                     "reportuploads returning error condition: %ui", err_status);
511
+		} else if (done) {
512
+      b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'done' })\r\n",
513
+                             sizeof("new Object({ 'state' : 'done' })\r\n") -
514
+                           1);
515
+      ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
516
+                     "reportuploads returning done");
517
+	  } else {
518
+      b->last =
519
+          ngx_cpymem(b->last, "new Object({ 'state' : 'uploading', 'received' : ",
520
+                       sizeof("new Object({ 'state' : 'uploading', 'received' : ") -
521
+                     1);
522
+
523
+      b->last = ngx_sprintf(b->last, "%uO, 'size' : %uO })\r\n", (length - rest), length);
524
+
525
+      ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
526
+				"reportuploads returning %uO / %uO",(length - rest), length );
471 527
     }
472 528
 
529
+
473 530
     r->headers_out.status = NGX_HTTP_OK;
474 531
     r->headers_out.content_length_n = b->last - b->pos;
475 532
 
@@ -480,7 +537,7 @@ ngx_http_reportuploads_handler(ngx_http_request_t * r)
480 537
         return rc;
481 538
     }
482 539
 
483
-    return ngx_http_output_filter(r, &out);;
540
+    return ngx_http_output_filter(r, &out);
484 541
 }
485 542
 
486 543
 /* 
@@ -568,7 +625,6 @@ ngx_http_uploadprogress_handler(ngx_http_request_t * r)
568 625
 
569 626
     node->key = hash;
570 627
     up->len = (u_char) id->len;
571
-    up->r = r;
572 628
     up->err_status = r->err_status;
573 629
 
574 630
     up->next = ctx->list_head.next;
@@ -694,16 +750,16 @@ ngx_clean_old_connections(ngx_event_t * ev)
694 750
         up = (ngx_http_uploadprogress_node_t *) node;
695 751
 
696 752
         ngx_log_debug3(NGX_LOG_DEBUG_HTTP, shm_zone->shm.log, 0,
697
-                       "uploadprogress clean: scanning %08XD (req %p) timeout at %T",
698
-                       node->key, up->r, up->timeout);
753
+                       "uploadprogress clean: scanning %08XD (req done %ui) timeout at %T",
754
+                       node->key, up->done, up->timeout);
699 755
 
700
-        if (up->r == NULL && up->timeout < now) {
756
+        if (up->done && up->timeout < now) {
701 757
             up->next->prev = up->prev;
702 758
             up->prev->next = up->next;
703 759
 
704 760
             ngx_log_debug3(NGX_LOG_DEBUG_HTTP, shm_zone->shm.log, 0,
705
-                           "uploadprogress clean: removing %08XD (req %p) ",
706
-                           node->key, up->r, up->timeout);
761
+                           "uploadprogress clean: removing %08XD (req %ui) ",
762
+                           node->key, up->done, up->timeout);
707 763
 
708 764
             ngx_rbtree_delete(ctx->rbtree, node);
709 765
             ngx_slab_free_locked(shpool, node);
@@ -741,8 +797,10 @@ ngx_http_uploadprogress_cleanup(void *data)
741 797
     node = upcln->node;
742 798
     up = (ngx_http_uploadprogress_node_t *) node;
743 799
 
744
-    up->r = NULL;               /* mark the original request as done */
800
+    ngx_shmtx_lock(&shpool->mutex);
801
+    up->done = 1;               /* mark the original request as done */
745 802
     up->timeout = ngx_time() + upcln->timeout;      /* keep tracking for 60s */
803
+    ngx_shmtx_unlock(&shpool->mutex);
746 804
 
747 805
     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, upcln->shm_zone->shm.log, 0,
748 806
                    "uploadprogress cleanup: connection %08XD to be deleted at %T",
@@ -845,7 +903,6 @@ ngx_http_uploadprogress_errortracker(ngx_http_request_t * r)
845 903
         if ((up = find_node(id, ctx, r->connection->log)) != NULL) {
846 904
             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
847 905
                            "trackuploads error-tracking found node for id: %V", id);
848
-            up->r = NULL;       /* don't really track it since it errors */
849 906
             up->err_status = r->err_status;
850 907
             ngx_shmtx_unlock(&shpool->mutex);
851 908
             goto finish;
@@ -871,7 +928,6 @@ ngx_http_uploadprogress_errortracker(ngx_http_request_t * r)
871 928
 
872 929
         node->key = hash;
873 930
         up->len = (u_char) id->len;
874
-        up->r = NULL;           /* don't really track it since it errors */
875 931
         up->err_status = r->err_status;
876 932
         ngx_memcpy(up->data, id->data, id->len);
877 933
 
@@ -896,7 +952,7 @@ ngx_http_uploadprogress_errortracker(ngx_http_request_t * r)
896 952
         upcln = cln->data;
897 953
         upcln->shm_zone = upcf->shm_zone;
898 954
         upcln->node = node;
899
-        upcln->timeout = upcf->timeout;				
955
+        upcln->timeout = upcf->timeout;
900 956
 
901 957
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
902 958
                        "trackuploads error-tracking adding: %08XD", node->key);
@@ -1031,9 +1087,7 @@ ngx_http_upload_progress(ngx_conf_t * cf, ngx_command_t * cmd, void *conf)
1031 1087
 static char*
1032 1088
 ngx_http_track_uploads(ngx_conf_t * cf, ngx_command_t * cmd, void *conf)
1033 1089
 {
1034
-    ngx_http_handler_pt        *h;
1035
-    ngx_http_core_main_conf_t  *cmcf;
1036
-
1090
+    ngx_http_core_loc_conf_t        *clcf;
1037 1091
     ngx_http_uploadprogress_conf_t  *lzcf = conf;
1038 1092
     ngx_str_t                       *value;
1039 1093
 
@@ -1070,14 +1124,13 @@ ngx_http_track_uploads(ngx_conf_t * cf, ngx_command_t * cmd, void *conf)
1070 1124
         return NGX_CONF_ERROR;
1071 1125
     }
1072 1126
 
1073
-    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
1074
-
1075
-    h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
1076
-    if (h == NULL) {
1077
-        return NGX_ERROR;
1127
+    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
1128
+    lzcf->handler = clcf->handler;
1129
+    if ( lzcf->handler == NULL )
1130
+    {
1131
+        return "track_upload should be the last directive in the location, after either proxy_pass or fastcgi_pass";
1078 1132
     }
1079
-
1080
-    *h = ngx_http_uploadprogress_content_handler;
1133
+    clcf->handler = ngx_http_uploadprogress_content_handler;
1081 1134
     return NGX_CONF_OK;
1082 1135
 }
1083 1136
 

Laddar…
Avbryt
Spara