comparison src/http/modules/ngx_http_gzip_filter.c @ 135:e29909bd9b8a

nginx-0.0.1-2003-09-28-23:29:06 import
author Igor Sysoev <igor@sysoev.ru>
date Sun, 28 Sep 2003 19:29:06 +0000
parents d57c6835225c
children da00cde00e8a
comparison
equal deleted inserted replaced
134:d57c6835225c 135:e29909bd9b8a
25 int hunks; 25 int hunks;
26 26
27 int length; 27 int length;
28 void *alloc; 28 void *alloc;
29 29
30 int flush; 30 unsigned flush:4;
31 unsigned redo:1;
32
31 u_int crc32; 33 u_int crc32;
32 z_stream zstream; 34 z_stream zstream;
33 } ngx_http_gzip_ctx_t; 35 } ngx_http_gzip_ctx_t;
34 36
35 37
123 static int ngx_http_gzip_header_filter(ngx_http_request_t *r) 125 static int ngx_http_gzip_header_filter(ngx_http_request_t *r)
124 { 126 {
125 ngx_http_gzip_ctx_t *ctx; 127 ngx_http_gzip_ctx_t *ctx;
126 ngx_http_gzip_conf_t *conf; 128 ngx_http_gzip_conf_t *conf;
127 129
128 if (r->headers_out.status != NGX_HTTP_OK 130 conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);
131
132 if (!conf->enable
133 || r->headers_out.status != NGX_HTTP_OK
129 || r->header_only 134 || r->header_only
130 /* || r->content_encoding */ 135 || r->main
131 /* || r->accept_encoding == NULL */ 136 /* TODO: conf->http_version */
132 || r->main) 137 || (r->headers_out.content_encoding
138 && r->headers_out.content_encoding->value.len)
139 || r->headers_in.accept_encoding == NULL
140 || ngx_strstr(r->headers_in.accept_encoding->value.data, "gzip") == NULL
141 )
133 { 142 {
134 return next_header_filter(r); 143 return next_header_filter(r);
135 } 144 }
136 145
137 conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module); 146 /* TODO: "text/html" -> custom types */
138 147 if (r->headers_out.content_type
139 if (!conf->enable 148 && ngx_strncasecmp(r->headers_out.content_type->value.data,
140 /* TODO: conf->version */ 149 "text/html", 5) != 0)
141 /* TODO: "text/" -> custom types */
142 || ngx_strncasecmp(r->headers_out.content_type->value.data,
143 "text/", 5) != 0)
144 { 150 {
145 return next_header_filter(r); 151 return next_header_filter(r);
146 } 152 }
147 153
148 ngx_http_create_ctx(r, ctx, ngx_http_gzip_filter_module, 154 ngx_http_create_ctx(r, ctx, ngx_http_gzip_filter_module,
149 sizeof(ngx_http_gzip_ctx_t), NGX_ERROR); 155 sizeof(ngx_http_gzip_ctx_t), NGX_ERROR);
156
157 ngx_test_null(r->headers_out.content_encoding,
158 ngx_push_table(r->headers_out.headers),
159 NGX_ERROR);
160
161 r->headers_out.content_encoding->key.len = 0;
162 r->headers_out.content_encoding->key.data = NULL;
163 r->headers_out.content_encoding->value.len = 4;
164 r->headers_out.content_encoding->value.data = "gzip";
150 165
151 ctx->length = r->headers_out.content_length; 166 ctx->length = r->headers_out.content_length;
152 r->headers_out.content_length = -1; 167 r->headers_out.content_length = -1;
153 r->filter |= NGX_HTTP_FILTER_NEED_IN_MEMORY; 168 r->filter |= NGX_HTTP_FILTER_NEED_IN_MEMORY;
154 169
210 if (ngx_chain_add_copy(r->pool, &ctx->in, in) == NGX_ERROR) { 225 if (ngx_chain_add_copy(r->pool, &ctx->in, in) == NGX_ERROR) {
211 return ngx_http_gzip_error(ctx); 226 return ngx_http_gzip_error(ctx);
212 } 227 }
213 } 228 }
214 229
215 while (ctx->in || ctx->out 230 for ( ;; ) {
216 || ctx->zstream.avail_in || ctx->zstream.avail_out 231
217 || ctx->flush != Z_NO_FLUSH)
218 {
219 for ( ;; ) { 232 for ( ;; ) {
220 233
221 if (ctx->in 234 /* is there a data to gzip ? */
222 && ctx->zstream.avail_in == 0 235
223 && ctx->flush == Z_NO_FLUSH) 236 if (ctx->zstream.avail_in == 0
224 { 237 && ctx->flush == Z_NO_FLUSH
238 && !ctx->redo) {
239
240 if (ctx->in == NULL) {
241 break;
242 }
243
225 ctx->in_hunk = ctx->in->hunk; 244 ctx->in_hunk = ctx->in->hunk;
226 ctx->in = ctx->in->next; 245 ctx->in = ctx->in->next;
227 246
247 ctx->zstream.next_in = ctx->in_hunk->pos;
228 ctx->zstream.avail_in = ctx->in_hunk->last - ctx->in_hunk->pos; 248 ctx->zstream.avail_in = ctx->in_hunk->last - ctx->in_hunk->pos;
229
230 if (ctx->zstream.avail_in == 0) {
231 continue;
232 }
233
234 ctx->zstream.next_in = ctx->in_hunk->pos;
235
236 ctx->crc32 = crc32(ctx->crc32, ctx->zstream.next_in,
237 ctx->zstream.avail_in);
238 249
239 if (ctx->in_hunk->type & NGX_HUNK_LAST) { 250 if (ctx->in_hunk->type & NGX_HUNK_LAST) {
240 ctx->flush = Z_FINISH; 251 ctx->flush = Z_FINISH;
241 252
242 } else if (ctx->in_hunk->type & NGX_HUNK_FLUSH) { 253 } else if (ctx->in_hunk->type & NGX_HUNK_FLUSH) {
243 ctx->flush = Z_SYNC_FLUSH; 254 ctx->flush = Z_SYNC_FLUSH;
244 } 255 }
256
257 if (ctx->zstream.avail_in == 0) {
258 if (ctx->flush == Z_NO_FLUSH) {
259 continue;
260 }
261
262 } else {
263 ctx->crc32 = crc32(ctx->crc32, ctx->zstream.next_in,
264 ctx->zstream.avail_in);
265 }
245 } 266 }
267
268 /* is there a space for the gzipped data ? */
246 269
247 if (ctx->zstream.avail_out == 0) { 270 if (ctx->zstream.avail_out == 0) {
248 if (ctx->free) { 271 if (ctx->free) {
249 ctx->out_hunk = ctx->free->hunk; 272 ctx->out_hunk = ctx->free->hunk;
250 ctx->free = ctx->free->next; 273 ctx->free = ctx->free->next;
255 0, 0), 278 0, 0),
256 ngx_http_gzip_error(ctx)); 279 ngx_http_gzip_error(ctx));
257 ctx->hunks++; 280 ctx->hunks++;
258 281
259 } else { 282 } else {
260 break; 283 break;
261 } 284 }
262 285
263 ctx->zstream.next_out = ctx->out_hunk->pos; 286 ctx->zstream.next_out = ctx->out_hunk->pos;
264 ctx->zstream.avail_out = conf->hunk_size; 287 ctx->zstream.avail_out = conf->hunk_size;
265 } 288 }
289
290 ngx_log_debug(r->connection->log, "deflate(): %08x %08x %d %d %d" _
291 ctx->zstream.next_in _ ctx->zstream.next_out _
292 ctx->zstream.avail_in _ ctx->zstream.avail_out _ ctx->flush);
266 293
267 rc = deflate(&ctx->zstream, ctx->flush); 294 rc = deflate(&ctx->zstream, ctx->flush);
268 if (rc != Z_OK && rc != Z_STREAM_END) { 295 if (rc != Z_OK && rc != Z_STREAM_END) {
269 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, 296 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
270 "deflate() failed: %d, %d", ctx->flush, rc); 297 "deflate() failed: %d, %d", ctx->flush, rc);
271 return ngx_http_gzip_error(ctx); 298 return ngx_http_gzip_error(ctx);
272 } 299 }
273 300
274 ngx_log_debug(r->connection->log, "deflate(): %d %d" _ ctx->flush _ rc); 301 ngx_log_debug(r->connection->log, "DEFLATE(): %08x %08x %d %d %d" _
302 ctx->zstream.next_in _ ctx->zstream.next_out _
303 ctx->zstream.avail_in _ ctx->zstream.avail_out _ rc);
275 304
276 ctx->in_hunk->pos = ctx->zstream.next_in; 305 ctx->in_hunk->pos = ctx->zstream.next_in;
277 306
278 if (ctx->zstream.avail_out == 0) { 307 if (ctx->zstream.avail_out == 0) {
279 ctx->out_hunk->last += conf->hunk_size; 308 ctx->out_hunk->last += conf->hunk_size;
280 ngx_add_hunk_to_chain(ce, ctx->out_hunk, r->pool, 309 ngx_add_hunk_to_chain(ce, ctx->out_hunk, r->pool,
281 ngx_http_gzip_error(ctx)); 310 ngx_http_gzip_error(ctx));
282 *ctx->last_out = ce; 311 *ctx->last_out = ce;
283 ctx->last_out = &ce->next; 312 ctx->last_out = &ce->next;
313 ctx->redo = 1;
284 314
285 } else { 315 } else {
286 ctx->out_hunk->last = ctx->zstream.next_out; 316 ctx->out_hunk->last = ctx->zstream.next_out;
317 ctx->redo = 0;
287 318
288 if (ctx->flush == Z_SYNC_FLUSH) { 319 if (ctx->flush == Z_SYNC_FLUSH) {
289 ctx->out_hunk->type |= NGX_HUNK_FLUSH; 320 ctx->out_hunk->type |= NGX_HUNK_FLUSH;
290 ctx->flush = Z_NO_FLUSH; 321 ctx->flush = Z_NO_FLUSH;
291 322
300 /* rc == Z_STREAM_END */ 331 /* rc == Z_STREAM_END */
301 332
302 zin = ctx->zstream.total_in; 333 zin = ctx->zstream.total_in;
303 zout = 10 + ctx->zstream.total_out + 8; 334 zout = 10 + ctx->zstream.total_out + 8;
304 335
336 rc = deflateEnd(&ctx->zstream);
337 if (rc != Z_OK) {
338 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
339 "deflateEnd() failed: %d", rc);
340 return ngx_http_gzip_error(ctx);
341 }
342
305 ctx->flush = Z_NO_FLUSH; 343 ctx->flush = Z_NO_FLUSH;
306 344
307 ngx_add_hunk_to_chain(ce, ctx->out_hunk, r->pool, 345 ngx_add_hunk_to_chain(ce, ctx->out_hunk, r->pool,
308 ngx_http_gzip_error(ctx)); 346 ngx_http_gzip_error(ctx));
309 *ctx->last_out = ce; 347 *ctx->last_out = ce;
310 ctx->last_out = &ce->next; 348 ctx->last_out = &ce->next;
311 349
312 if (ctx->zstream.avail_out >= 8) { 350 if (ctx->zstream.avail_out >= 8) {
313 trailer = (struct gztrailer *) &ctx->zstream.avail_in; 351 trailer = (struct gztrailer *) ctx->out_hunk->last;
314 ctx->out_hunk->type |= NGX_HUNK_LAST; 352 ctx->out_hunk->type |= NGX_HUNK_LAST;
315 ctx->out_hunk->last += 8; 353 ctx->out_hunk->last += 8;
316 354
317 } else { 355 } else {
318 /* STUB */ trailer = NULL; 356 ngx_test_null(h,
357 ngx_create_temp_hunk(r->pool, 8, 0, 0),
358 ngx_http_gzip_error(ctx));
359
360 h->type |= NGX_HUNK_LAST;
361
362 ngx_test_null(ce, ngx_alloc_chain_entry(r->pool),
363 ngx_http_gzip_error(ctx));
364 ce->hunk = h;
365 ce->next = NULL;
366 *ctx->last_out = ce;
367 ctx->last_out = &ce->next;
368 trailer = (struct gztrailer *) h->pos;
369 h->last += 8;
319 } 370 }
320 371
321 #if (HAVE_LITTLE_ENDIAN) 372 #if (HAVE_LITTLE_ENDIAN)
322 trailer->crc32 = ctx->crc32; 373 trailer->crc32 = ctx->crc32;
323 trailer->zlen = zin; 374 trailer->zlen = zin;
324 #else 375 #else
325 /* STUB */ 376 /* STUB */
326 #endif 377 #endif
327 378
328 deflateEnd(&ctx->zstream); 379 ctx->zstream.avail_in = 0;
380 ctx->zstream.avail_out = 0;
381 ngx_http_delete_ctx(r, ngx_http_gzip_filter_module);
329 #if 0 382 #if 0
330 ngx_free(); 383 ngx_free();
331 set ctx = NULL;
332 #endif 384 #endif
333 break; 385 break;
334 386
335 } else if (conf->no_buffer && ctx->in == NULL) { 387 } else if (conf->no_buffer && ctx->in == NULL) {
336 ngx_add_hunk_to_chain(ce, ctx->out_hunk, r->pool, 388 ngx_add_hunk_to_chain(ce, ctx->out_hunk, r->pool,
341 break; 393 break;
342 } 394 }
343 } 395 }
344 } 396 }
345 397
346 rc = next_body_filter(r, ctx->out); 398 if (ctx->out == NULL) {
347 if (rc == NGX_ERROR) { 399 if (ctx->in || ctx->zstream.avail_in) {
400 return NGX_AGAIN;
401 } else {
402 return NGX_OK;
403 }
404 }
405
406 if (next_body_filter(r, ctx->out) == NGX_ERROR) {
348 return ngx_http_gzip_error(ctx); 407 return ngx_http_gzip_error(ctx);
349 } 408 }
350 409
351 ngx_chain_update_chains(&ctx->free, &ctx->busy, &ctx->out); 410 ngx_chain_update_chains(&ctx->free, &ctx->busy, &ctx->out);
352 ctx->last_out = &ctx->out; 411 ctx->last_out = &ctx->out;
353 } 412 }
354
355 /* STUB */
356 return next_body_filter(r, NULL);
357 } 413 }
358 414
359 415
360 ngx_inline static int ngx_http_gzip_error(ngx_http_gzip_ctx_t *ctx) 416 ngx_inline static int ngx_http_gzip_error(ngx_http_gzip_ctx_t *ctx)
361 { 417 {
362 #if 0 418 #if 0
363 ngx_free(ctx->alloc); 419 ngx_free(ctx->alloc);
420 #else
421 deflateEnd(&ctx->zstream);
364 #endif 422 #endif
423
424 ctx->zstream.avail_in = 0;
425 ctx->zstream.avail_out = 0;
365 426
366 return NGX_ERROR; 427 return NGX_ERROR;
367 } 428 }
368 429
369 430