1 /*
2 * Redistribution and use in source and binary forms, with or
3 * without modification, are permitted provided that the following
4 * conditions are met:
5 *
6 * 1. Redistributions of source code must retain the above
7 * copyright notice, this list of conditions and the
8 * following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following
12 * disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY AUTHORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19 * AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * Copyright (C) 2015-2016 Tarantool AUTHORS:
30 * please see AUTHORS file.
31 */
32
33 #ifndef NGX_HTTP_TNT_CREATE_REQUEST_H_INCLUDED
34 #define NGX_HTTP_TNT_CREATE_REQUEST_H_INCLUDED
35
36 #include <ngx_core.h>
37 #include <ngx_http.h>
38 #include <tp_transcode.h>
39
40 typedef enum ngx_tnt_conf_states {
41 NGX_TNT_CONF_ON = 0x0001,
42 NGX_TNT_CONF_OFF = 0x0002,
43 NGX_TNT_CONF_PARSE_ARGS = 0x0004
44 } ngx_tnt_conf_states_e;
45
46 typedef struct {
47 ngx_http_upstream_conf_t upstream;
48 ngx_int_t index;
49
50 size_t in_multiplier;
51 size_t out_multiplier;
52
53 /** Preset method name
54 *
55 * if method is set then tp_transcode use only this method name and
56 * ignore method name from json and uri
57 */
58 ngx_str_t method;
59
60 /** Max allowed size of query + headers in bytes
61 */
62 size_t pass_http_request_buffer_size;
63
64 /** Pass query/headers to tarantool
65 *
66 * If this is set, then Tarantool recv. query args as lua table, e.g.
67 * /tnt_method?arg1=X&arg2=123
68 *
69 * Tarantool
70 * function tnt_method(http_req)
71 * {
72 * http_req['args']['arg1'] -- eq 'Y'
73 * http_req['args']['arg2'] -- eq '123'
74 * }
75 */
76 ngx_uint_t pass_http_request;
77
78 /** Http REST methods[default GET|PUT]
79 *
80 * if method in http_rest_methods, then tp_transcode expecting method name
81 * in url part, i.e. HOST/METHOD_NAME/TAIL?ARGS
82 *
83 * XXX Also see method
84 */
85 ngx_uint_t http_rest_methods;
86
87 /** Set of http methods[default POST|DELETE]
88 *
89 * If method in http_methods, then tp_transcode expecting method name in
90 * json protocol, i.e. {"method":STR}
91 *
92 * XXX Also see method
93 */
94 ngx_uint_t http_methods;
95
96 /** If is set to 'On', then the client will recv. pure result set, e.g.
97 * {}
98 * Otherwise
99 * {"result":[], "id": NUM}
100 */
101 ngx_uint_t pure_result;
102
103 /** Tarantool returns array of array as the result set of call,
104 * this option helps to avoid this behavior.
105 * For instance. If this option set to 2 then result will look
106 * alike result:{} instead of result:[[{}]]
107 */
108 ngx_uint_t multireturn_skip_count;
109
110 ngx_array_t *headers_source;
111
112 } ngx_http_tnt_loc_conf_t;
113
114
115 /** Set of allowed rest methods
116 */
117 static const ngx_uint_t ngx_http_tnt_allowed_methods =
118 (NGX_HTTP_POST|NGX_HTTP_GET|NGX_HTTP_PUT|NGX_HTTP_DELETE);
119
120 /** Current upstream state
121 */
122 enum ctx_state {
123 OK = 0,
124
125 INPUT_JSON_PARSE_FAILED,
126 INPUT_TO_LARGE,
127 INPUT_EMPTY,
128
129 READ_PAYLOAD,
130 READ_BODY,
131 SEND_REPLY
132 };
133
134 typedef struct ngx_http_tnt_ctx {
135
136 /** Reference to Tarantool payload e.g. size of TP message
137 */
138 struct {
139 u_char mem[6];
140 u_char *p, *e;
141 } payload;
142
143 enum ctx_state state;
144 /** in_err - error buffer
145 * tp_cache - buffer for store parts of TP message
146 */
147 ngx_buf_t *in_err, *tp_cache;
148
149 /** rest - how many bytes until transcoding is end
150 * payload_size - payload as int val
151 * rest_batch_size - how many parts until batch is end
152 * batch_size - number of parts in batch
153 */
154 ssize_t rest, payload_size;
155 int rest_batch_size, batch_size;
156
157 /** Greeting from tarantool
158 */
159 ngx_int_t greeting:1;
160
161 /** preset method & len
162 */
163 u_char preset_method[128];
164 u_char preset_method_len;
165 } ngx_http_tnt_ctx_t;
166
167 ngx_http_tnt_ctx_t * ngx_http_tnt_create_ctx(ngx_http_request_t *r);
168 void ngx_http_tnt_reset_ctx(ngx_http_tnt_ctx_t *ctx);
169
170 ngx_int_t ngx_http_tnt_init_handlers(ngx_http_request_t *r,
171 ngx_http_upstream_t *u,
172 ngx_http_tnt_loc_conf_t *tlcf);
173
174 /** create tarantool requests handlers [
175 */
176 ngx_int_t ngx_http_tnt_body_json_handler(ngx_http_request_t *r);
177 ngx_int_t ngx_http_tnt_query_handler(ngx_http_request_t *r);
178 /* ] */
179
180 ngx_int_t ngx_http_tnt_reinit_request(ngx_http_request_t *r);
181 ngx_int_t ngx_http_tnt_process_header(ngx_http_request_t *r);
182 void ngx_http_tnt_abort_request(ngx_http_request_t *r);
183 void ngx_http_tnt_finalize_request(ngx_http_request_t *r, ngx_int_t rc);
184
185 ngx_buf_t* ngx_http_tnt_set_err(ngx_http_request_t *r,
186 int errcode,
187 const u_char *msg,
188 size_t msglen);
189
190 /** Rrror & error code holder, functions [[
191 */
192 typedef struct ngx_http_tnt_error {
193 const ngx_str_t msg;
194 int code;
195 } ngx_http_tnt_error_t;
196
197 enum ngx_http_tnt_err_messages_idx {
198 REQUEST_TOO_LARGE = 0,
199 UNKNOWN_PARSE_ERROR = 1,
200 HTTP_REQUEST_TOO_LARGE = 2
201 };
202
203 const ngx_http_tnt_error_t *get_error_text(int type);
204 /** ]]
205 */
206
207 /** Size of JSON proto overhead
208 */
209 static inline size_t
ngx_http_tnt_overhead(void)210 ngx_http_tnt_overhead(void)
211 {
212 return sizeof("[{"
213 "'error': {"
214 "'code':-XXXXX,"
215 "'message':''"
216 "},"
217 "[['result':{},"
218 "'id':4294967295]]"
219 "}");
220 }
221
222 #endif
223