nginx-0.7.8
Igor Sysoev
is at rambler-co.ru
Tue Aug 5 18:29:28 MSD 2008
On Tue, Aug 05, 2008 at 09:00:29PM +0700, Denis F. Latypoff wrote:
> Hello Igor,
>
> Tuesday, August 5, 2008, 8:23:03 PM, you wrote:
>
> > On Tue, Aug 05, 2008 at 05:19:20PM +0400, Igor Sysoev wrote:
>
> >> > > То есть, нужно искать по импортам до первого ненулевого mediaType ?
> >> > > Ну, и естественно, сначала проверять mediaType в самом xsl.
> >> >
> >> > Да. И encoding тоже.
> >>
> >> OK.
>
> > Патч. Те же и encoding.
>
> 1) s/ngx_log_debug1/ngx_log_debug3/ ngx_http_xslt_filter_module.c:780
> 2) на indent можно забить: "XSLT-процессор не обязан выполнять это
> требование, и в этом случае трудно
> предугадать точную форму вывода"
>
> Все в порядке, вроде потестил с многоэтажными import'ами, все как по
> спеке.
Новый патч. Включает всё, что было, + единственные копии XSLT-деревьев.
--
Игорь Сысоев
http://sysoev.ru
-------------- next part --------------
Index: src/http/modules/ngx_http_xslt_filter_module.c
===================================================================
--- src/http/modules/ngx_http_xslt_filter_module.c (revision 1469)
+++ src/http/modules/ngx_http_xslt_filter_module.c (working copy)
@@ -22,6 +22,17 @@
typedef struct {
+ u_char *name;
+ xsltStylesheetPtr stylesheet;
+} ngx_http_xslt_sheet_file_t;
+
+
+typedef struct {
+ ngx_array_t sheet_files; /* ngx_http_xslt_sheet_file_t */
+} ngx_http_xslt_filter_main_conf_t;
+
+
+typedef struct {
ngx_array_t *lengths;
ngx_array_t *values;
} ngx_http_xslt_param_t;
@@ -35,10 +46,10 @@
typedef struct {
xmlDtdPtr dtd;
- ngx_array_t sheets; /* ngx_http_xslt_sheet_t */
+ ngx_array_t sheets; /* ngx_http_xslt_sheet_t */
ngx_hash_t types;
ngx_array_t *types_keys;
-} ngx_http_xslt_filter_conf_t;
+} ngx_http_xslt_filter_loc_conf_t;
typedef struct {
@@ -47,8 +58,8 @@
xmlSAXHandler *sax;
ngx_http_request_t *request;
ngx_array_t params;
- unsigned done:1;
- unsigned html:1;
+
+ ngx_uint_t done; /* unsigned done:1; */
} ngx_http_xslt_filter_ctx_t;
@@ -109,6 +120,8 @@
ngx_http_xslt_filter_ctx_t *ctx);
static ngx_int_t ngx_http_xslt_params(ngx_http_request_t *r,
ngx_http_xslt_filter_ctx_t *ctx, ngx_array_t *params);
+static u_char *ngx_http_xslt_content_type(xsltStylesheetPtr s);
+static u_char *ngx_http_xslt_encoding(xsltStylesheetPtr s);
static void ngx_http_xslt_cleanup(void *data);
static char *ngx_http_xslt_entities(ngx_conf_t *cf, ngx_command_t *cmd,
@@ -116,6 +129,7 @@
static char *ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static void ngx_http_xslt_cleanup_stylesheet(void *data);
+static void *ngx_http_xslt_filter_create_main_conf(ngx_conf_t *cf);
static void *ngx_http_xslt_filter_create_conf(ngx_conf_t *cf);
static char *ngx_http_xslt_filter_merge_conf(ngx_conf_t *cf, void *parent,
void *child);
@@ -131,24 +145,24 @@
static ngx_command_t ngx_http_xslt_filter_commands[] = {
{ ngx_string("xml_entities"),
- NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_http_xslt_entities,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },
{ ngx_string("xslt_stylesheet"),
- NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_1MORE,
+ NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
ngx_http_xslt_stylesheet,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },
{ ngx_string("xslt_types"),
- NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_1MORE,
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
ngx_http_types_slot,
NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_xslt_filter_conf_t, types_keys),
+ offsetof(ngx_http_xslt_filter_loc_conf_t, types_keys),
&ngx_http_xslt_default_types[0] },
ngx_null_command
@@ -159,7 +173,7 @@
NULL, /* preconfiguration */
ngx_http_xslt_filter_init, /* postconfiguration */
- NULL, /* create main configuration */
+ ngx_http_xslt_filter_create_main_conf, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
@@ -193,8 +207,8 @@
static ngx_int_t
ngx_http_xslt_header_filter(ngx_http_request_t *r)
{
- ngx_http_xslt_filter_ctx_t *ctx;
- ngx_http_xslt_filter_conf_t *conf;
+ ngx_http_xslt_filter_ctx_t *ctx;
+ ngx_http_xslt_filter_loc_conf_t *conf;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"xslt filter header");
@@ -316,12 +330,6 @@
NGX_HTTP_INTERNAL_SERVER_ERROR);
}
- if (ctx->html) {
- r->headers_out.content_type_len = sizeof("text/html") - 1;
- r->headers_out.content_type.len = sizeof("text/html") - 1;
- r->headers_out.content_type.data = (u_char *) "text/html";
- }
-
r->headers_out.content_length_n = b->last - b->pos;
if (r->headers_out.content_length) {
@@ -481,10 +489,10 @@
{
ngx_http_xslt_filter_ctx_t *ctx = data;
- xmlDocPtr doc;
- xmlDtdPtr dtd;
- ngx_http_request_t *r;
- ngx_http_xslt_filter_conf_t *conf;
+ xmlDocPtr doc;
+ xmlDtdPtr dtd;
+ ngx_http_request_t *r;
+ ngx_http_xslt_filter_loc_conf_t *conf;
r = ctx->request;
@@ -511,8 +519,6 @@
return;
}
- dtd->name = xmlStrdup(name);
-
if (doc->children == NULL) {
xmlAddChild((xmlNodePtr) doc, (xmlNodePtr) dtd);
@@ -732,13 +738,14 @@
ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r,
ngx_http_xslt_filter_ctx_t *ctx)
{
- int len, rc;
- ngx_buf_t *b;
- ngx_uint_t i;
- xmlChar *buf;
- xmlDocPtr doc, res;
- ngx_http_xslt_sheet_t *sheet;
- ngx_http_xslt_filter_conf_t *conf;
+ int len, rc, doc_type;
+ u_char *type, *encoding;
+ ngx_buf_t *b;
+ ngx_uint_t i;
+ xmlChar *buf;
+ xmlDocPtr doc, res;
+ ngx_http_xslt_sheet_t *sheet;
+ ngx_http_xslt_filter_loc_conf_t *conf;
conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module);
sheet = conf->sheets.elts;
@@ -776,11 +783,17 @@
ctx->params.nelts = 0;
}
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "xslt filter doc type: %d", doc->type);
+ /* there must be at least one stylesheet */
- ctx->html = (doc->type == XML_HTML_DOCUMENT_NODE) ? 1 : 0;
+ type = ngx_http_xslt_content_type(sheet[i - 1].stylesheet);
+ encoding = ngx_http_xslt_encoding(sheet[i - 1].stylesheet);
+ doc_type = doc->type;
+ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "xslt filter type: %d t:%s e:%s",
+ doc_type, type ? type : (u_char *) "(null)",
+ encoding ? encoding : (u_char *) "(null)");
+
rc = xsltSaveResultToString(&buf, &len, doc, sheet[i - 1].stylesheet);
xmlFreeDoc(doc);
@@ -808,6 +821,25 @@
b->memory = 1;
b->last_buf = 1;
+ if (type) {
+ len = ngx_strlen(type);
+
+ r->headers_out.content_type_len = len;
+ r->headers_out.content_type.len = len;
+ r->headers_out.content_type.data = type;
+
+ } else if (doc_type == XML_HTML_DOCUMENT_NODE) {
+
+ r->headers_out.content_type_len = sizeof("text/html") - 1;
+ r->headers_out.content_type.len = sizeof("text/html") - 1;
+ r->headers_out.content_type.data = (u_char *) "text/html";
+ }
+
+ if (encoding) {
+ r->headers_out.charset.len = ngx_strlen(encoding);
+ r->headers_out.charset.data = encoding;
+ }
+
return b;
}
@@ -906,6 +938,50 @@
}
+static u_char *
+ngx_http_xslt_content_type(xsltStylesheetPtr s)
+{
+ u_char *type;
+
+ if (s->mediaType) {
+ return s->mediaType;
+ }
+
+ for (s = s->imports; s; s = s->next) {
+
+ type = ngx_http_xslt_content_type(s);
+
+ if (type) {
+ return type;
+ }
+ }
+
+ return NULL;
+}
+
+
+static u_char *
+ngx_http_xslt_encoding(xsltStylesheetPtr s)
+{
+ u_char *encoding;
+
+ if (s->encoding) {
+ return s->encoding;
+ }
+
+ for (s = s->imports; s; s = s->next) {
+
+ encoding = ngx_http_xslt_encoding(s);
+
+ if (encoding) {
+ return encoding;
+ }
+ }
+
+ return NULL;
+}
+
+
static void
ngx_http_xslt_cleanup(void *data)
{
@@ -916,7 +992,7 @@
static char *
ngx_http_xslt_entities(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
- ngx_http_xslt_filter_conf_t *xlcf = conf;
+ ngx_http_xslt_filter_loc_conf_t *xlcf = conf;
ngx_str_t *value;
@@ -941,14 +1017,16 @@
static char *
ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
- ngx_http_xslt_filter_conf_t *xlcf = conf;
+ ngx_http_xslt_filter_loc_conf_t *xlcf = conf;
- ngx_str_t *value;
- ngx_uint_t i, n;
- ngx_pool_cleanup_t *cln;
- ngx_http_xslt_sheet_t *sheet;
- ngx_http_xslt_param_t *param;
- ngx_http_script_compile_t sc;
+ ngx_str_t *value;
+ ngx_uint_t i, n;
+ ngx_pool_cleanup_t *cln;
+ ngx_http_xslt_sheet_t *sheet;
+ ngx_http_xslt_param_t *param;
+ ngx_http_script_compile_t sc;
+ ngx_http_xslt_sheet_file_t *file;
+ ngx_http_xslt_filter_main_conf_t *xmcf;
value = cf->args->elts;
@@ -972,6 +1050,16 @@
return NGX_CONF_ERROR;
}
+ xmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_xslt_filter_module);
+
+ file = xmcf->sheet_files.elts;
+ for (i = 0; i < xmcf->sheet_files.nelts; i++) {
+ if (ngx_strcmp(file[i].name, &value[1].data) == 0) {
+ sheet->stylesheet = file[i].stylesheet;
+ goto found;
+ }
+ }
+
cln = ngx_pool_cleanup_add(cf->pool, 0);
if (cln == NULL) {
return NGX_CONF_ERROR;
@@ -988,6 +1076,16 @@
cln->handler = ngx_http_xslt_cleanup_stylesheet;
cln->data = sheet->stylesheet;
+ file = ngx_array_push(&xmcf->sheet_files);
+ if (file == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ file->name = value[1].data;
+ file->stylesheet = sheet->stylesheet;
+
+found:
+
n = cf->args->nelts;
if (n == 2) {
@@ -1039,13 +1137,33 @@
}
+static void *
+ngx_http_xslt_filter_create_main_conf(ngx_conf_t *cf)
+{
+ ngx_http_xslt_filter_main_conf_t *conf;
+ conf = ngx_palloc(cf->pool, sizeof(ngx_http_xslt_filter_main_conf_t));
+ if (conf == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ if (ngx_array_init(&conf->sheet_files, cf->pool, 1,
+ sizeof(ngx_http_xslt_sheet_file_t))
+ != NGX_OK)
+ {
+ return NULL;
+ }
+
+ return conf;
+}
+
+
static void *
ngx_http_xslt_filter_create_conf(ngx_conf_t *cf)
{
- ngx_http_xslt_filter_conf_t *conf;
+ ngx_http_xslt_filter_loc_conf_t *conf;
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_xslt_filter_conf_t));
+ conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_xslt_filter_loc_conf_t));
if (conf == NULL) {
return NGX_CONF_ERROR;
}
@@ -1066,8 +1184,8 @@
static char *
ngx_http_xslt_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child)
{
- ngx_http_xslt_filter_conf_t *prev = parent;
- ngx_http_xslt_filter_conf_t *conf = child;
+ ngx_http_xslt_filter_loc_conf_t *prev = parent;
+ ngx_http_xslt_filter_loc_conf_t *conf = child;
if (conf->dtd == NULL) {
conf->dtd = prev->dtd;
More information about the nginx-ru
mailing list