ソースを参照

Response is now generated from templates

tags/v0.7
Valery Kholodkov 17年前
コミット
639b0a3122
1個のファイルの変更188行の追加38行の削除
  1. 188
    38
      ngx_http_uploadprogress_module.c

+ 188
- 38
ngx_http_uploadprogress_module.c ファイルの表示

@@ -10,6 +10,20 @@
10 10
 
11 11
 #define TIMER_FREQUENCY 15 * 1000
12 12
 
13
+typedef enum {
14
+    uploadprogress_state_starting = 0,
15
+    uploadprogress_state_error = 1, 
16
+    uploadprogress_state_done = 2, 
17
+    uploadprogress_state_uploading = 3, 
18
+    uploadprogress_state_none
19
+} ngx_http_uploadprogress_state_t; 
20
+
21
+typedef struct {
22
+    ngx_str_t                           name;
23
+    ngx_http_uploadprogress_state_t     idx;
24
+    ngx_str_t                           def;
25
+} ngx_http_uploadprogress_state_map_t;
26
+
13 27
 typedef struct ngx_http_uploadprogress_node_s ngx_http_uploadprogress_node_t;
14 28
 
15 29
 struct ngx_http_uploadprogress_node_s {
@@ -38,6 +52,11 @@ typedef struct {
38 52
     ngx_http_uploadprogress_node_t   list_tail;
39 53
 } ngx_http_uploadprogress_ctx_t;
40 54
 
55
+typedef struct {
56
+    ngx_array_t                     *values;
57
+    ngx_array_t                     *lengths;
58
+} ngx_http_uploadprogress_template_t;
59
+
41 60
 typedef struct {
42 61
     ngx_shm_zone_t                  *shm_zone;
43 62
     time_t                           timeout;
@@ -45,6 +64,7 @@ typedef struct {
45 64
     ngx_http_handler_pt              handler;
46 65
     u_char                           track;
47 66
     ngx_str_t                        content_type;
67
+    ngx_array_t                      templates;
48 68
 } ngx_http_uploadprogress_conf_t;
49 69
 
50 70
 typedef struct {
@@ -61,6 +81,7 @@ static char *ngx_http_uploadprogress_merge_loc_conf(ngx_conf_t *cf, void *parent
61 81
 static char *ngx_http_track_uploads(ngx_conf_t * cf, ngx_command_t * cmd, void *conf);
62 82
 static char *ngx_http_report_uploads(ngx_conf_t * cf, ngx_command_t * cmd, void *conf);
63 83
 static char *ngx_http_upload_progress(ngx_conf_t * cf, ngx_command_t * cmd, void *conf);
84
+static char* ngx_http_upload_progress_template(ngx_conf_t * cf, ngx_command_t * cmd, void *conf);
64 85
 static void ngx_clean_old_connections(ngx_event_t * ev);
65 86
 static ngx_int_t ngx_http_uploadprogress_content_handler(ngx_http_request_t *r);
66 87
 
@@ -96,6 +117,13 @@ static ngx_command_t ngx_http_uploadprogress_commands[] = {
96 117
      offsetof(ngx_http_uploadprogress_conf_t, content_type),
97 118
      NULL},
98 119
 
120
+    {ngx_string("upload_progress_template"),
121
+     NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_TAKE2,
122
+     ngx_http_upload_progress_template,
123
+     NGX_HTTP_LOC_CONF_OFFSET,
124
+     offsetof(ngx_http_uploadprogress_conf_t, templates),
125
+     NULL},
126
+
99 127
     ngx_null_command
100 128
 };
101 129
 
@@ -132,6 +160,22 @@ ngx_module_t                     ngx_http_uploadprogress_module = {
132 160
 
133 161
 static ngx_str_t x_progress_id = ngx_string("X-Progress-ID");
134 162
 
163
+static ngx_http_uploadprogress_state_map_t ngx_http_uploadprogress_state_map[] = {
164
+    {ngx_string("starting"),  uploadprogress_state_starting,
165
+     ngx_string("new Object({ 'state' : 'starting' })\r\n")},
166
+
167
+    {ngx_string("error"),     uploadprogress_state_error,
168
+     ngx_string("new Object({ 'state' : 'error', 'status' : $uploadprogress_status })\r\n")},
169
+
170
+    {ngx_string("done"),      uploadprogress_state_done,
171
+     ngx_string("new Object({ 'state' : 'done' })\r\n")},
172
+
173
+    {ngx_string("uploading"), uploadprogress_state_uploading,
174
+     ngx_string("new Object({ 'state' : 'uploading', 'received' : $uploadprogress_received, 'size' : $uploadprogress_length })\r\n")},
175
+};
176
+
177
+static ngx_array_t ngx_http_uploadprogress_global_templates;
178
+
135 179
 static ngx_str_t*
136 180
 get_tracking_id(ngx_http_request_t * r)
137 181
 {
@@ -400,10 +444,10 @@ static void ngx_http_uploadprogress_event_handler(ngx_http_request_t *r)
400 444
 static ngx_int_t
401 445
 ngx_http_reportuploads_handler(ngx_http_request_t * r)
402 446
 {
403
-    ngx_str_t                       *id;
447
+    ngx_str_t                       *id, response;
404 448
     ngx_buf_t                       *b;
405 449
     ngx_chain_t                      out;
406
-    ngx_int_t                        rc, size, found=0, done=0, err_status=0;
450
+    ngx_int_t                        rc, found=0, done=0, err_status=0;
407 451
     off_t                            rest=0, length=0;
408 452
     ngx_uint_t                       len, i;
409 453
     ngx_slab_pool_t                 *shpool;
@@ -411,6 +455,8 @@ ngx_http_reportuploads_handler(ngx_http_request_t * r)
411 455
     ngx_http_uploadprogress_ctx_t   *ctx;
412 456
     ngx_http_uploadprogress_node_t  *up;
413 457
     ngx_table_elt_t                 *expires, *cc, **ccp;
458
+    ngx_http_uploadprogress_state_t  state;
459
+    ngx_http_uploadprogress_template_t  *t;
414 460
 
415 461
     if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) {
416 462
         return NGX_HTTP_NOT_ALLOWED;
@@ -549,55 +595,42 @@ ngx_http_reportuploads_handler(ngx_http_request_t * r)
549 595
  */
550 596
 
551 597
     if (!found) {
552
-        size = sizeof("new Object({ 'state' : 'starting' })\r\n");
598
+        state = uploadprogress_state_starting;
553 599
     } else if (err_status >= NGX_HTTP_SPECIAL_RESPONSE) {
554
-        size = sizeof("new Object({ 'state' : 'error', 'status' : ") + NGX_INT_T_LEN + sizeof(" })\r\n");
600
+        state = uploadprogress_state_error;
555 601
     } else if (done) {
556
-        size = sizeof("new Object({ 'state' : 'done' })\r\n");
602
+        state = uploadprogress_state_done;
557 603
     } else if ( length == 0 && rest == 0 ) {
558
-        size = sizeof("new Object({ 'state' : 'starting' })\r\n");
604
+        state = uploadprogress_state_starting;
559 605
     } else {
560
-        size = sizeof("new Object({ 'state' : 'uploading', 'received' : ") + NGX_INT_T_LEN + sizeof(" })\r\n");
561
-        size += sizeof(", 'size' : ") + NGX_INT_T_LEN;
606
+        state = uploadprogress_state_uploading;
562 607
     }
563 608
 
564
-    b = ngx_create_temp_buf(r->pool, size);
565
-    if (b == NULL) {
609
+    t = upcf->templates.elts;
610
+
611
+    if (ngx_http_script_run(r, &response, t[(ngx_uint_t)state].lengths->elts, 0,
612
+        t[(ngx_uint_t)state].values->elts) == NULL)
613
+    {
566 614
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
567 615
     }
568 616
 
569
-    out.buf = b;
570
-    out.next = NULL;
617
+    ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
618
+        "upload progress: state=%d, err_status=%ui, remaining=%uO, length=%uO",
619
+        state, err_status, (length - rest), length);
571 620
 
572
-    if (!found) {
573
-        b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'starting' })\r\n",
574
-                            sizeof("new Object({ 'state' : 'starting' })\r\n") - 1);
575
-        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "reportuploads returning starting");
576
-    } else if (err_status >= NGX_HTTP_SPECIAL_RESPONSE) {
577
-        b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'error', 'status' : ",
578
-                             sizeof("new Object({ 'state' : 'error', 'status' : ") - 1);
579
-        b->last = ngx_sprintf(b->last, "%ui })\r\n", err_status );
580
-        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
581
-                        "reportuploads returning error condition: %ui", err_status);
582
-    } else if (done) {
583
-        b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'done' })\r\n",
584
-                             sizeof("new Object({ 'state' : 'done' })\r\n") - 1);
585
-        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
586
-                        "reportuploads returning done");
587
-    } else if (length == 0 && rest == 0) {
588
-        b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'starting' })\r\n",
589
-                            sizeof("new Object({ 'state' : 'starting' })\r\n") - 1);
590
-        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "reportuploads returning starting");
591
-    } else {
592
-        b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'uploading', 'received' : ",
593
-                             sizeof("new Object({ 'state' : 'uploading', 'received' : ") - 1);
621
+    b = ngx_calloc_buf(r->pool);
622
+    if (b == NULL) {
623
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
624
+    }
594 625
 
595
-        b->last = ngx_sprintf(b->last, "%uO, 'size' : %uO })\r\n", (length - rest), length);
626
+    b->pos = b->start = response.data;
627
+    b->last = b->end = response.data + response.len;
596 628
 
597
-        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
598
-                        "reportuploads returning %uO / %uO",(length - rest), length );
599
-    }
629
+    b->temporary = 1;
630
+    b->memory = 1;
600 631
 
632
+    out.buf = b;
633
+    out.next = NULL;
601 634
 
602 635
     r->headers_out.status = NGX_HTTP_OK;
603 636
     r->headers_out.content_length_n = b->last - b->pos;
@@ -1087,6 +1120,10 @@ ngx_http_uploadprogress_init(ngx_conf_t * cf)
1087 1120
 {
1088 1121
     ngx_http_handler_pt             *h;
1089 1122
     ngx_http_core_main_conf_t       *cmcf;
1123
+    ngx_http_uploadprogress_template_t   *t;
1124
+    ngx_http_uploadprogress_state_map_t  *m;
1125
+    ngx_http_script_compile_t             sc;
1126
+    ssize_t                               n;
1090 1127
 
1091 1128
     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
1092 1129
 
@@ -1108,6 +1145,37 @@ ngx_http_uploadprogress_init(ngx_conf_t * cf)
1108 1145
     ngx_http_next_header_filter = ngx_http_top_header_filter;
1109 1146
     ngx_http_top_header_filter = ngx_http_uploadprogress_errortracker;
1110 1147
 
1148
+    /*
1149
+     * Compile global templates
1150
+     */
1151
+    if(ngx_array_init(&ngx_http_uploadprogress_global_templates, cf->pool, 4,
1152
+        sizeof(ngx_http_uploadprogress_template_t)) != NGX_OK) {
1153
+        return NGX_ERROR;
1154
+    }
1155
+
1156
+    m = ngx_http_uploadprogress_state_map;
1157
+    t = ngx_http_uploadprogress_global_templates.elts;
1158
+
1159
+    while(m->name.data != NULL) {
1160
+        n = ngx_http_script_variables_count(&m->def);
1161
+
1162
+        ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
1163
+
1164
+        sc.cf = cf;
1165
+        sc.source = &m->def;
1166
+        sc.lengths = &t->lengths;
1167
+        sc.values = &t->values;
1168
+        sc.variables = n;
1169
+        sc.complete_lengths = 1;
1170
+        sc.complete_values = 1;
1171
+
1172
+        if (ngx_http_script_compile(&sc) != NGX_OK) {
1173
+            return NGX_ERROR;
1174
+        }
1175
+        
1176
+        m++;
1177
+    }
1178
+
1111 1179
     return NGX_OK;
1112 1180
 }
1113 1181
 
@@ -1115,11 +1183,24 @@ static void*
1115 1183
 ngx_http_uploadprogress_create_loc_conf(ngx_conf_t * cf)
1116 1184
 {
1117 1185
     ngx_http_uploadprogress_conf_t  *conf;
1186
+    ngx_http_uploadprogress_template_t   *t;
1187
+    ngx_uint_t                            i;
1118 1188
 
1119 1189
     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_uploadprogress_conf_t));
1120 1190
     if (conf == NULL) {
1121 1191
         return NGX_CONF_ERROR;
1122 1192
     }
1193
+
1194
+    if(ngx_array_init(&conf->templates, cf->pool, 4, sizeof(ngx_http_uploadprogress_template_t)) != NGX_OK) {
1195
+        return NGX_CONF_ERROR;
1196
+    }
1197
+
1198
+    t = conf->templates.elts;
1199
+    for(i = 0;i < conf->templates.nelts; i++) {
1200
+        t[i].values = NULL;
1201
+        t[i].lengths = NULL;
1202
+    } 
1203
+
1123 1204
     return conf;
1124 1205
 }
1125 1206
 
@@ -1129,6 +1210,8 @@ ngx_http_uploadprogress_merge_loc_conf(ngx_conf_t * cf, void *parent, void *chil
1129 1210
 {
1130 1211
     ngx_http_uploadprogress_conf_t  *prev = parent;
1131 1212
     ngx_http_uploadprogress_conf_t  *conf = child;
1213
+    ngx_http_uploadprogress_template_t   *t, *pt, *gt;
1214
+    ngx_uint_t                            i;
1132 1215
 
1133 1216
     if (conf->shm_zone == NULL) {
1134 1217
         *conf = *prev;
@@ -1136,6 +1219,23 @@ ngx_http_uploadprogress_merge_loc_conf(ngx_conf_t * cf, void *parent, void *chil
1136 1219
 
1137 1220
     ngx_conf_merge_str_value(conf->content_type, prev->content_type, "text/javascript");
1138 1221
 
1222
+    t = conf->templates.elts;
1223
+    pt = prev->templates.elts;
1224
+    gt = ngx_http_uploadprogress_global_templates.elts;
1225
+
1226
+    for(i = 0;i < conf->templates.nelts; i++) {
1227
+        if(t[i].values == NULL) {
1228
+            if(pt[i].values == NULL) {
1229
+                t[i].values = gt[i].values;
1230
+                t[i].lengths = gt[i].lengths;
1231
+            }
1232
+            else{
1233
+                t[i].values = pt[i].values;
1234
+                t[i].lengths = pt[i].lengths;
1235
+            }
1236
+        }
1237
+    } 
1238
+
1139 1239
     return NGX_CONF_OK;
1140 1240
 }
1141 1241
 
@@ -1287,3 +1387,53 @@ ngx_http_report_uploads(ngx_conf_t * cf, ngx_command_t * cmd, void *conf)
1287 1387
 
1288 1388
     return NGX_CONF_OK;
1289 1389
 }
1390
+
1391
+static char*
1392
+ngx_http_upload_progress_template(ngx_conf_t * cf, ngx_command_t * cmd, void *conf)
1393
+{
1394
+    ngx_http_uploadprogress_conf_t       *upcf = conf;
1395
+    ssize_t                               n;
1396
+    ngx_str_t                            *value;
1397
+    ngx_http_uploadprogress_state_map_t  *m;
1398
+    ngx_http_uploadprogress_template_t   *t;
1399
+    ngx_http_script_compile_t             sc;
1400
+
1401
+    value = cf->args->elts;
1402
+
1403
+    m = ngx_http_uploadprogress_state_map;
1404
+
1405
+    while(m->name.data != NULL) {
1406
+        if((value[1].len == m->name.len && !ngx_strncmp(value[1].data, m->name.data, m->name.len))
1407
+           || (value[1].len == 2 && !ngx_strncmp(value[1].data, m->name.data, 2))) {
1408
+            break;
1409
+        }
1410
+        m++;
1411
+    }
1412
+
1413
+    if (m->name.data == NULL) {
1414
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1415
+                           "unknown state \"%V\"", &value[1]);
1416
+        return NGX_CONF_ERROR;
1417
+    }
1418
+
1419
+    t = (ngx_http_uploadprogress_template_t*)upcf->templates.elts + (ngx_uint_t)m->idx;
1420
+
1421
+    n = ngx_http_script_variables_count(&value[2]);
1422
+
1423
+    ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
1424
+
1425
+    sc.cf = cf;
1426
+    sc.source = &value[2];
1427
+    sc.lengths = &t->lengths;
1428
+    sc.values = &t->values;
1429
+    sc.variables = n;
1430
+    sc.complete_lengths = 1;
1431
+    sc.complete_values = 1;
1432
+
1433
+    if (ngx_http_script_compile(&sc) != NGX_OK) {
1434
+        return NGX_CONF_ERROR;
1435
+    }
1436
+
1437
+    return NGX_CONF_OK;
1438
+}
1439
+

読み込み中…
キャンセル
保存