comparison ngx_http_auth_request_module.c @ 0:436da5355bd5

Auth request module.
author Maxim Dounin <mdounin@mdounin.ru>
date Sat, 20 Feb 2010 14:30:30 +0300
parents
children dfc5ae42367a
comparison
equal deleted inserted replaced
-1:000000000000 0:436da5355bd5
1
2 /*
3 * Copyright (C) Maxim Dounin
4 */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_http.h>
10
11
12 typedef struct {
13 ngx_str_t uri;
14 } ngx_http_auth_request_conf_t;
15
16 typedef struct {
17 ngx_uint_t done;
18 ngx_uint_t status;
19 ngx_http_request_t *subrequest;
20 } ngx_http_auth_request_ctx_t;
21
22
23 static ngx_int_t ngx_http_auth_request_handler(ngx_http_request_t *r);
24 static ngx_int_t ngx_http_auth_request_done(ngx_http_request_t *r,
25 void *data, ngx_int_t rc);
26 static void *ngx_http_auth_request_create_conf(ngx_conf_t *cf);
27 static char *ngx_http_auth_request_merge_conf(ngx_conf_t *cf,
28 void *parent, void *child);
29 static ngx_int_t ngx_http_auth_request_init(ngx_conf_t *cf);
30
31
32 static ngx_command_t ngx_http_auth_request_commands[] = {
33
34 { ngx_string("auth_request"),
35 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
36 ngx_conf_set_str_slot,
37 NGX_HTTP_LOC_CONF_OFFSET,
38 offsetof(ngx_http_auth_request_conf_t, uri),
39 NULL },
40
41 ngx_null_command
42 };
43
44
45 static ngx_http_module_t ngx_http_auth_request_module_ctx = {
46 NULL, /* preconfiguration */
47 ngx_http_auth_request_init, /* postconfiguration */
48
49 NULL, /* create main configuration */
50 NULL, /* init main configuration */
51
52 NULL, /* create server configuration */
53 NULL, /* merge server configuration */
54
55 ngx_http_auth_request_create_conf, /* create location configuration */
56 ngx_http_auth_request_merge_conf /* merge location configuration */
57 };
58
59
60 ngx_module_t ngx_http_auth_request_module = {
61 NGX_MODULE_V1,
62 &ngx_http_auth_request_module_ctx, /* module context */
63 ngx_http_auth_request_commands, /* module directives */
64 NGX_HTTP_MODULE, /* module type */
65 NULL, /* init master */
66 NULL, /* init module */
67 NULL, /* init process */
68 NULL, /* init thread */
69 NULL, /* exit thread */
70 NULL, /* exit process */
71 NULL, /* exit master */
72 NGX_MODULE_V1_PADDING
73 };
74
75
76 static ngx_int_t
77 ngx_http_auth_request_handler(ngx_http_request_t *r)
78 {
79 ngx_table_elt_t *h, *ho;
80 ngx_http_request_t *sr;
81 ngx_http_post_subrequest_t *ps;
82 ngx_http_auth_request_ctx_t *ctx;
83 ngx_http_auth_request_conf_t *arcf;
84
85 arcf = ngx_http_get_module_loc_conf(r, ngx_http_auth_request_module);
86
87 if (arcf->uri.len == 0) {
88 return NGX_DECLINED;
89 }
90
91 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
92 "auth request handler");
93
94 ctx = ngx_http_get_module_ctx(r, ngx_http_auth_request_module);
95
96 if (ctx != NULL) {
97 if (!ctx->done) {
98 return NGX_AGAIN;
99 }
100
101 if (ctx->status == NGX_HTTP_FORBIDDEN) {
102 return ctx->status;
103 }
104
105 if (ctx->status == NGX_HTTP_UNAUTHORIZED) {
106 sr = ctx->subrequest;
107
108 h = sr->headers_out.www_authenticate;
109
110 if (!h && sr->upstream) {
111 h = sr->upstream->headers_in.www_authenticate;
112 }
113
114 if (h) {
115 ho = ngx_list_push(&r->headers_out.headers);
116 if (ho == NULL) {
117 return NGX_ERROR;
118 }
119
120 *ho = *h;
121
122 r->headers_out.www_authenticate = ho;
123 }
124
125 return ctx->status;
126 }
127
128 if (ctx->status >= NGX_HTTP_OK
129 && ctx->status < NGX_HTTP_SPECIAL_RESPONSE)
130 {
131 return NGX_OK;
132 }
133
134 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
135 "auth request unexpected status: %d", ctx->status);
136
137 return NGX_HTTP_INTERNAL_SERVER_ERROR;
138 }
139
140 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_auth_request_ctx_t));
141 if (ctx == NULL) {
142 return NGX_ERROR;
143 }
144
145 ps = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
146 if (ps == NULL) {
147 return NGX_ERROR;
148 }
149
150 ps->handler = ngx_http_auth_request_done;
151 ps->data = ctx;
152
153 if (ngx_http_subrequest(r, &arcf->uri, NULL, &sr, ps,
154 NGX_HTTP_SUBREQUEST_WAITED)
155 != NGX_OK)
156 {
157 return NGX_ERROR;
158 }
159
160 sr->header_only = 1;
161
162 ctx->subrequest = sr;
163
164 ngx_http_set_ctx(r, ctx, ngx_http_auth_request_module);
165
166 return NGX_AGAIN;
167 }
168
169
170 static ngx_int_t
171 ngx_http_auth_request_done(ngx_http_request_t *r, void *data, ngx_int_t rc)
172 {
173 ngx_http_auth_request_ctx_t *ctx = data;
174
175 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
176 "auth request done s:%d", r->headers_out.status);
177
178 ctx->done = 1;
179 ctx->status = r->headers_out.status;
180
181 return rc;
182 }
183
184
185 static void *
186 ngx_http_auth_request_create_conf(ngx_conf_t *cf)
187 {
188 ngx_http_auth_request_conf_t *conf;
189
190 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_auth_request_conf_t));
191 if (conf == NULL) {
192 return NULL;
193 }
194
195 /*
196 * set by ngx_pcalloc():
197 *
198 * conf->uri.len = { 0, NULL };
199 */
200
201 return conf;
202 }
203
204
205 static char *
206 ngx_http_auth_request_merge_conf(ngx_conf_t *cf, void *parent, void *child)
207 {
208 ngx_http_auth_request_conf_t *prev = parent;
209 ngx_http_auth_request_conf_t *conf = child;
210
211 ngx_conf_merge_str_value(conf->uri, prev->uri, "");
212
213 return NGX_CONF_OK;
214 }
215
216
217 static ngx_int_t
218 ngx_http_auth_request_init(ngx_conf_t *cf)
219 {
220 ngx_http_handler_pt *h;
221 ngx_http_core_main_conf_t *cmcf;
222
223 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
224
225 h = ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers);
226 if (h == NULL) {
227 return NGX_ERROR;
228 }
229
230 *h = ngx_http_auth_request_handler;
231
232 return NGX_OK;
233 }