summaryrefslogblamecommitdiffhomepage
path: root/src/nxt_http_compress.c
blob: 980ed0bc7e648875b4cc73b915a8f8706ec3fedc (plain) (tree)
1
2
3
4
5
6
7
8
9







                                  
                  







                           
                                   




                       
                     


                      


                                     





                                                     




                                                  




                                                    




                                                   



         

                                                                 




                                    

                                                                              






                                                             
                                          
                       
 





                                                                        






                                                                                




                                                                            
                                                                               
                                               
































                                                                       


























                                                                


         
























                                                                               

















                                                                          
/*
 * Copyright (C) Alejandro Colomar
 * Copyright (C) NGINX, Inc.
 */


#include "nxt_http_compress.h"

#include <errno.h>
#include <stddef.h>

#include <nxt_unit_cdefs.h>

#include "nxt_clang.h"
#include "nxt_conf.h"
#include "nxt_errno.h"
#include "nxt_http.h"
#include "nxt_http_compress_gzip.h"
#include "nxt_list.h"
#include "nxt_main.h"
#include "nxt_mp.h"
#include "nxt_router.h"
#include "nxt_string.h"
#include "nxt_tstr.h"
#include "nxt_types.h"


#define NXT_DEFAULT_COMPRESSION  (-1)


static nxt_conf_map_t  nxt_http_compress_conf[] = {
    {
        nxt_string("encoding"),
        NXT_CONF_MAP_STR,
        offsetof(nxt_http_compress_conf_t, encoding),
    },
    {
        nxt_string("level"),
        NXT_CONF_MAP_INT8,
        offsetof(nxt_http_compress_conf_t, level),
    },
    {
        nxt_string("min_length"),
        NXT_CONF_MAP_SIZE,
        offsetof(nxt_http_compress_conf_t, min_len),
    },
    {
        nxt_string("mime_types"),
        NXT_CONF_MAP_PTR,
        offsetof(nxt_http_compress_conf_t, mtypes),
    },
};


nxt_int_t
nxt_http_compress_init(nxt_task_t *task, nxt_router_conf_t *rtcf,
    nxt_http_action_t *action, nxt_http_action_conf_t *acf)
{
    nxt_mp_t                  *mp;
    nxt_int_t                 ret;
    nxt_http_compress_conf_t  *conf;

    static nxt_str_t          hdr_a_e = nxt_string("$header_accept_encoding");

    mp = rtcf->mem_pool;

    conf = nxt_mp_zget(mp, sizeof(nxt_http_compress_conf_t));
    if (nxt_slow_path(conf == NULL)) {
        return NXT_ERROR;
    }

    conf->level = NXT_DEFAULT_COMPRESSION;
    conf->min_len = 20;

    ret = nxt_conf_map_object(mp, acf->compress, nxt_http_compress_conf,
                              nxt_nitems(nxt_http_compress_conf), conf);
    if (nxt_slow_path(ret == NXT_ERROR)) {
        return NXT_ERROR;
    }

    if (conf->mtypes != NULL) {
        conf->mtrule = nxt_http_route_types_rule_create(task, mp, conf->mtypes);
        if (nxt_slow_path(conf->mtrule == NULL)) {
            return NXT_ERROR;
        }
    }

    conf->accept_encoding = nxt_tstr_compile(rtcf->tstr_state, &hdr_a_e, 0);
    if (nxt_slow_path(conf->accept_encoding == NULL)) {
        return NXT_ERROR;
    }

    if (NXT_WITH_ZLIB && nxt_str_eq(&conf->encoding, "gzip", strlen("gzip"))) {
        conf->handler = nxt_http_compress_gzip;

    } else {
        return NXT_ERROR;
    }

    action->compress = conf;

    return NXT_OK;
}


nxt_int_t
nxt_http_compress_append_field(nxt_task_t *task, nxt_http_request_t *r,
    nxt_str_t *field, nxt_str_t *value)
{
    nxt_http_field_t  *f;

    f = nxt_list_add(r->resp.fields);
    if (nxt_slow_path(f == NULL)) {
        return NXT_ERROR;
    }

    f->hash = 0;
    f->skip = 0;
    f->hopbyhop = 0;

    f->name_length = field->length;
    f->value_length = value->length;
    f->name = field->start;
    f->value = value->start;

    return NXT_OK;
}


ssize_t
nxt_http_compress_resp_content_length(nxt_http_response_t *resp)
{
    size_t     cl;
    nxt_str_t  str;

    if (resp->content_length_n != -1) {
        return resp->content_length_n;
    }

    if (resp->content_length == NULL) {
        return -1;
    }

    str.length = resp->content_length->value_length;
    str.start = resp->content_length->value;

    errno = 0;
    cl = nxt_atoul(&str);
    if (errno != 0) {
        return -1;
    }

    return cl;
}


nxt_int_t
nxt_http_compress_accept_encoding(nxt_task_t *task, nxt_http_request_t *r,
    nxt_tstr_t *accept_encoding, nxt_str_t *encoding)
{
    nxt_int_t          ret;
    nxt_str_t          str;
    nxt_router_conf_t  *rtcf;

    rtcf = r->conf->socket_conf->router_conf;

    ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, &r->tstr_cache,
                              r, r->mem_pool);
    if (nxt_slow_path(ret == NXT_ERROR)) {
        return NXT_ERROR;
    }

    nxt_tstr_query(task, r->tstr_query, accept_encoding, &str);
    if (nxt_slow_path(nxt_tstr_query_failed(r->tstr_query))) {
        return NXT_ERROR;
    }

    return nxt_strstr_eq(&str, encoding);
}


nxt_int_t
nxt_http_compressible_mtype(nxt_task_t *task, nxt_http_request_t *r,
    nxt_http_route_rule_t *mtrule)
{
    const nxt_str_t   *type;

    static nxt_str_t  unknown_mtype = nxt_string("");

    if (mtrule == NULL) {
        return 1;
    }

    type = r->resp.mtype;
    if (type == NULL) {
        type = &unknown_mtype;
    }

    return nxt_http_route_test_rule(r, mtrule, type->start, type->length);
}