-
Notifications
You must be signed in to change notification settings - Fork 2
/
NgxModule.hpp
216 lines (195 loc) · 6.93 KB
/
NgxModule.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/*
* Copyright 2021 The casbin Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _NGX_MODULE_HPP
#define _NGX_MODULE_HPP
#include "NgxPool.hpp"
/**
* @name: NgxModuleConfig
* @msg: Get module config
* @param {T3:loacl config, T2: server config, T1: main config}
*/
template< typename T3 = void, typename T2 = void, typename T1 = void>
class NgxModuleConfig final {
public:
using ngx_session_type = ngx_http_request_t;
using ngx_conf_ctx_type = ngx_http_conf_ctx_t;
NgxModuleConfig(ngx_uint_t idx): m_idx(idx) {}
// use defalut
~NgxModuleConfig() = default;
// get model index
ngx_uint_t index() const {
return m_idx;
}
// trans data type by template
template<typename T, typename U>
T* get(U conf) const {
return reinterpret_cast<T*>(conf[index()]);
}
private:
ngx_uint_t m_idx = 0;
// trans (void* ) ctx to http_conf
ngx_http_conf_ctx_t* ctx(ngx_conf_t* cf) const {
return reinterpret_cast<ngx_http_conf_ctx_t*>(cf->ctx);
}
public:
// from config
// main http level
T1* main(ngx_conf_t* cf) const {
return get<T1>(ctx(cf)->main_conf);
}
// main srv level
T2* srv(ngx_conf_t* cf) const {
return get<T3>(ctx(cf)->srv_conf);
}
// main local level
T3* loc(ngx_conf_t* cf) const {
return get<T3>(ctx(cf)->loc_conf);
}
public:
// from http_request
// main http level
T1* main(ngx_http_request_t* r) const {
return get<T1>(r->main_conf);
}
// main srv level
T2* srv(ngx_http_request_t* r) const {
return get<T3>(r->srv_conf);
}
// main local level
T3* loc(ngx_http_request_t* r) const {
return get<T3>(r->loc_conf);
}
};
class NgxModuleCtx final {
public:
NgxModuleCtx(ngx_uint_t idx): m_idx(idx) {}
~NgxModuleCtx() = default;
public:
ngx_uint_t index() const {
return m_idx;
}
using raw_pointer = void*;
// return reference of void* so we can decide pointer point to where if we want.
raw_pointer& ctx(ngx_http_request_t* r) const {
return r->ctx[index()];
}
bool empty(ngx_http_request_t* r) const {
return !ctx(r);
}
void clear(ngx_http_request_t* r) const {
// if alloc memory, may cause memory leakage
ctx(r) = nullptr;
}
// if not exit then create
template<typename T>
T& data(ngx_http_request_t* r) const {
if (empty(r)) {
auto p = NgxPool(r->pool);
ctx(r) = p.alloc<T>();
}
return *reinterpret_cast<T*>(ctx(r));
}
private:
ngx_uint_t m_idx = 0;
};
template<typename T3 = void, typename T2 = void, typename T1 = void>
class NgxModule {
public:
typedef NgxModuleConfig<T3, T2, T1> config_type;
typedef NgxModuleCtx ctx_type;
// genete NgxModuleConfig by pass ctx_idx;
NgxModule(ngx_module_t& m): m_config(m.ctx_index), m_ctx(m.ctx_index){}
~NgxModule() = default;
// get ngxmodule config
const config_type& conf() const {
return m_config;
}
// get ngxmodule context
const ctx_type& ctx() const {
return m_ctx;
}
template<typename T>
T& data(ngx_http_request_t* r) const {
// why need template
return ctx().template data<T>(r);
}
private:
config_type m_config;
ctx_type m_ctx;
};
class NgxHttpCoreModule final: public NgxModule<ngx_http_core_loc_conf_t,
ngx_http_core_srv_conf_t,
ngx_http_core_main_conf_t> {
public:
using super_type = NgxModule<ngx_http_core_loc_conf_t,
ngx_http_core_srv_conf_t,
ngx_http_core_main_conf_t>;
using this_type = NgxHttpCoreModule;
public:
NgxHttpCoreModule(): super_type(ngx_http_core_module) {}
~NgxHttpCoreModule() = default;
public:
static NgxHttpCoreModule& instance() {
static NgxHttpCoreModule m;
return m;
}
// http handle call back
template<typename F>
void handler(ngx_conf_t* cf, F f, ngx_http_phases p) const {
auto c = conf().main(cf);
ngx_http_handler_pt* h = (ngx_http_handler_pt* )ngx_array_push(&(c->phases[p].handlers));
*h = f;
}
// http location call back
template<typename F>
void handler(ngx_conf_t* cf, F f) const {
conf().loc(cf)->handler = f;
}
};
// Undo: why do this
#define NGX_MOD_INSTANCE(T, mod, ... ) \
struct T { \
typedef NgxModule<__VA_ARGS__> mod_type; \
typedef mod_type::config_type config_type; \
static mod_type& instance() \
{ \
extern ngx_module_t mod; \
static mod_type m(mod); \
return m; \
} \
static const config_type& conf() \
{ return instance().conf();} \
};
#define NGX_MOD_CTX_INSTANCE(T, mod, c, ... ) \
struct T { \
typedef NgxModule<__VA_ARGS__> mod_type; \
typedef mod_type::config_type config_type; \
typedef NgxModuleCtx ctx_type; \
typedef c ctx_data_type; \
static mod_type& instance() \
{ \
extern ngx_module_t mod; \
static mod_type m(mod); \
return m; \
} \
static const config_type& conf() \
{ return instance().conf();} \
static const ctx_type& ctx() \
{ return instance().ctx();} \
static ctx_data_type& data(mod_type::ngx_session_type* r) \
{ return instance().template data<ctx_data_type>(r);} \
};
#endif