Skip to content

Commit dcd56d1

Browse files
committed
#8 #1
1 parent 6448fef commit dcd56d1

File tree

5 files changed

+117
-97
lines changed

5 files changed

+117
-97
lines changed

ngx_http_tnt_module.c

Lines changed: 56 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ static inline ngx_int_t ngx_http_tnt_read_greetings(ngx_http_request_t *r,
5757
static inline ngx_int_t ngx_http_tnt_say_error(ngx_http_request_t *r,
5858
ngx_http_tnt_ctx_t *ctx, ngx_int_t code);
5959
static inline void ngx_http_tnt_cleanup(ngx_http_request_t *r);
60+
static inline ngx_int_t ngx_http_set_input_parse_errmsg(ngx_http_request_t *r,
61+
ngx_http_tnt_ctx_t *ctx);
6062

6163
static ngx_int_t ngx_http_tnt_create_request(ngx_http_request_t *r);
6264
static ngx_int_t ngx_http_tnt_reinit_request(ngx_http_request_t *r);
@@ -74,43 +76,30 @@ static char *ngx_http_tnt_pass(ngx_conf_t *cf, ngx_command_t *cmd,
7476
void *conf);
7577

7678

77-
static size_t JSON_RPC_MAGIC = sizeof(
78-
"{"
79-
"'error': {"
80-
"'code':18446744073709551615,"
81-
"'message':''"
82-
"},"
83-
"'result':{}, "
84-
"'id':18446744073709551615"
85-
"}") - 1;
79+
static size_t JSON_RPC_MAGIC = sizeof("{"
80+
"'error': {"
81+
"'code':-XXXXX,"
82+
"'message':''"
83+
"},"
84+
"'result':{},"
85+
"'id':4294967295"
86+
"}") - 1;
8687

8788
static const u_char REQUEST_TOO_LARGE[] = "{"
88-
"\"result\":null,"
8989
"\"error\":{"
90+
"\"code\":-32001,"
9091
"\"message\":"
9192
"\"Request too large, consider increasing your "
9293
"server's setting 'client_body_buffer_size'\""
93-
"}"
94-
"}";
95-
96-
static const u_char UNKNOWN_PARSE_ERROR[] = "{\"result\":null,"
97-
"\"error\":{"
98-
"\"message\":"
99-
"\"Unknown parse error\""
100-
"}"
101-
"}";
102-
103-
static const char ERR_RES_FMT[] = "{"
104-
"\"result\":null,"
105-
"\"error\":{"
106-
"\"message\":\"%s\""
107-
"}"
108-
"}";
109-
110-
static const size_t ERR_RES_SIZE = sizeof("{'result':null,"
111-
"'error':{'message':''}"
112-
"}") - 1;
94+
"}"
95+
"}";
11396

97+
static const u_char UNKNOWN_PARSE_ERROR[] = "{"
98+
"\"error\":{"
99+
"\"code\":-32002,"
100+
"\"message\":\"Unknown parse error\""
101+
"}"
102+
"}";
114103

115104
static ngx_conf_bitmask_t ngx_http_tnt_next_upstream_masks[] = {
116105
{ ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
@@ -358,16 +347,8 @@ ngx_http_tnt_create_request(ngx_http_request_t *r)
358347
{
359348
dd("[input] failed: '%s'", ctx->in_t.errmsg);
360349

361-
if (ctx->in_t.errmsg[0] != 0) {
362-
ctx->errmsg.len = ngx_strlen(ctx->in_t.errmsg) + ERR_RES_SIZE;
363-
ctx->errmsg.data = ngx_palloc(r->pool, ctx->errmsg.len);
364-
if (ctx->errmsg.data == NULL) {
365-
goto error_exit;
366-
}
367-
368-
ngx_snprintf(ctx->errmsg.data, ctx->errmsg.len, ERR_RES_FMT,
369-
ctx->in_t.errmsg);
370-
350+
if (ngx_http_set_input_parse_errmsg(r, ctx) == NGX_ERROR) {
351+
return NGX_ERROR;
371352
}
372353

373354
ctx->state = INPUT_JSON_PARSE_FAILED;
@@ -387,16 +368,8 @@ ngx_http_tnt_create_request(ngx_http_request_t *r)
387368
{
388369
dd("[input] failed to complete");
389370

390-
if (ctx->in_t.errmsg[0] != 0) {
391-
ctx->errmsg.len = ngx_strlen(ctx->in_t.errmsg) + ERR_RES_SIZE;
392-
ctx->errmsg.data = ngx_palloc(r->pool, ctx->errmsg.len);
393-
if (ctx->errmsg.data == NULL) {
394-
goto error_exit;
395-
}
396-
397-
ngx_snprintf(ctx->errmsg.data, ctx->errmsg.len, ERR_RES_FMT,
398-
ctx->in_t.errmsg);
399-
371+
if (ngx_http_set_input_parse_errmsg(r, ctx) == NGX_ERROR) {
372+
return NGX_ERROR;
400373
}
401374

402375
ctx->state = INPUT_JSON_PARSE_FAILED;
@@ -848,6 +821,39 @@ ngx_http_tnt_read_greetings(ngx_http_request_t *r,
848821
}
849822

850823

824+
static inline ngx_int_t
825+
ngx_http_set_input_parse_errmsg(ngx_http_request_t *r,
826+
ngx_http_tnt_ctx_t *ctx)
827+
{
828+
static const char ERR_RES_FMT[] = "{"
829+
"\"error\":{"
830+
"\"code\":%d,"
831+
"\"message\":\"%s\""
832+
"}"
833+
"}";
834+
835+
static const size_t ERR_RES_SIZE = sizeof("{"
836+
"'error':{"
837+
"'message':'',"
838+
"'code':-XXXXX"
839+
"}"
840+
"}") - 1;
841+
842+
if (ctx->in_t.errmsg[0] != 0) {
843+
ctx->errmsg.len = ngx_strlen(ctx->in_t.errmsg) + ERR_RES_SIZE;
844+
ctx->errmsg.data = ngx_palloc(r->pool, ctx->errmsg.len);
845+
if (ctx->errmsg.data == NULL) {
846+
return NGX_ERROR;
847+
}
848+
849+
ngx_snprintf(ctx->errmsg.data, ctx->errmsg.len, ERR_RES_FMT,
850+
ctx->in_t.errcode, ctx->in_t.errmsg);
851+
852+
}
853+
854+
return NGX_OK;
855+
}
856+
851857
static inline ngx_int_t ngx_http_tnt_say_error(ngx_http_request_t *r,
852858
ngx_http_tnt_ctx_t *ctx,
853859
ngx_int_t code)

test/client.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@ def request_raw(data):
3636
def request(data):
3737
return request_raw(json.dumps(data))
3838

39-
def assert_if_not_error(s):
40-
assert('result' in s), 'expected result'
39+
def assert_if_not_error(s, code = None):
4140
assert('error' in s), 'expected error'
4241
assert('message' in s['error']), 'expected error message'
42+
assert('code' in s['error']), 'expected error message'
43+
if code:
44+
assert(s['error']['code'] == code), 'expected code'
4345

4446
def echo_check(r, bad_request_expected = False):
4547
(rc, res) = request(r)
@@ -56,7 +58,7 @@ def echo_check(r, bad_request_expected = False):
5658
# Spec. cases
5759
(rc, res) = request_raw('{"method":"call", "params":["name", __wrong__], "id":555}');
5860
assert(rc == 400), 'expected 400'
59-
assert_if_not_error(res)
61+
assert_if_not_error(res, -32700)
6062

6163
(rc, res) = request_raw('');
6264
assert(rc == 500), 'expected 500'

test/echo.lua

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
json=require('json');
22

3-
function echo(a)
4-
if type(a) == 'table' then
5-
return {{a}}
6-
end
7-
return {a}
3+
function call(a,a1,a2,a3)
4+
return {a, a1, a2, a3}
85
end
96

107
function big_echo()

tp_transcode.c

Lines changed: 52 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "tp.h"
77
#include "tp_transcode.h"
88

9+
#define DEBUG
910
#if defined DEBUG
1011
#define dd(...) fprintf(stderr, __VA_ARGS__)
1112
#else
@@ -39,7 +40,14 @@ while (0)
3940

4041
enum { MAX_STACK_SIZE = 254 - 1 };
4142
enum type { TYPE_MAP = 1, TYPE_ARRAY = 2 };
42-
enum stage { START = 0, PARAMS = 4, ID = 8, METHOD = 16 };
43+
enum stage {
44+
INIT = 0,
45+
BATCH = 1,
46+
WAIT_NEXT = 2,
47+
PARAMS = 4,
48+
ID = 8,
49+
METHOD = 16
50+
};
4351

4452
typedef struct {
4553
char *ptr;
@@ -200,7 +208,7 @@ yajl_integer(void *ctx, long long v)
200208
}
201209

202210
s_ctx->id = v;
203-
s_ctx->stage = START;
211+
s_ctx->stage = WAIT_NEXT;
204212
}
205213

206214
return 1;
@@ -320,7 +328,7 @@ yajl_string(void *ctx, const unsigned char * str, size_t len)
320328

321329
dd("METHOD END\n");
322330

323-
s_ctx->stage = START;
331+
s_ctx->stage = WAIT_NEXT;
324332
s_ctx->been_stages |= METHOD;
325333

326334
return rc;
@@ -334,6 +342,11 @@ yajl_map_key(void *ctx, const unsigned char * key, size_t len)
334342
{
335343
yajl_ctx_t *s_ctx = (yajl_ctx_t *)ctx;
336344

345+
if (mp_unlikely(s_ctx->stage == INIT)) {
346+
dd("MESSAGE START\n");
347+
s_ctx->stage = WAIT_NEXT;
348+
}
349+
337350
if (mp_likely(s_ctx->stage == PARAMS)) {
338351

339352
dd("key: %.*s\n", (int)len, key);
@@ -343,7 +356,7 @@ yajl_map_key(void *ctx, const unsigned char * key, size_t len)
343356
if (mp_unlikely(!tp_encode_str(&s_ctx->tp, (char *)key, len)))
344357
say_overflow_r_2(s_ctx);
345358

346-
} else if (s_ctx->stage == START) {
359+
} else if (s_ctx->stage == WAIT_NEXT) {
347360

348361
if (len == sizeof("params") - 1
349362
&& key[0] == 'p'
@@ -377,15 +390,9 @@ yajl_map_key(void *ctx, const unsigned char * key, size_t len)
377390
s_ctx->stage = METHOD;
378391
}
379392
else
380-
{
381-
const int l = len > 32 ? 32 : len;
382-
say_error(s_ctx,
383-
"unknown key '%.*s', allowed: 'method', 'params', 'id'",
384-
l, key);
385-
return 0;
386-
}
393+
dd("SKIPING: %.*s\n", (int)len, key);
387394
} else
388-
s_ctx->stage = START;
395+
s_ctx->stage = WAIT_NEXT;
389396

390397
return 1;
391398
}
@@ -438,10 +445,10 @@ yajl_end_map(void *ctx)
438445

439446
if (mp_unlikely(item->type & PARAMS)) {
440447
dd("PARAMS END\n");
441-
s_ctx->stage = START;
448+
s_ctx->stage = WAIT_NEXT;
442449
}
443450
} else
444-
s_ctx->stage = START;
451+
s_ctx->stage = WAIT_NEXT;
445452

446453
return 1;
447454
}
@@ -451,6 +458,11 @@ yajl_start_array(void *ctx)
451458
{
452459
yajl_ctx_t *s_ctx = (yajl_ctx_t *)ctx;
453460

461+
if (mp_unlikely(s_ctx->stage == INIT)) {
462+
say_error(s_ctx, "Batch not suported yet");
463+
return 0;
464+
}
465+
454466
if (mp_unlikely(s_ctx->stage != PARAMS))
455467
return 1;
456468

@@ -493,10 +505,10 @@ yajl_end_array(void *ctx)
493505

494506
if (mp_unlikely(item->type & PARAMS)) {
495507
dd("PARAMS END\n");
496-
s_ctx->stage = START;
508+
s_ctx->stage = WAIT_NEXT;
497509
}
498510
} else
499-
s_ctx->stage = START;
511+
s_ctx->stage = WAIT_NEXT;
500512

501513
return 1;
502514
}
@@ -515,7 +527,7 @@ yajl_json2tp_create(tp_transcode_t *tc, char *output, size_t output_size)
515527

516528
memset(ctx, 0 , sizeof(yajl_ctx_t));
517529

518-
ctx->stage = START;
530+
ctx->stage = INIT;
519531

520532
ctx->output_size = output_size;
521533
tp_init(&ctx->tp, (char *)output, output_size, NULL, NULL);
@@ -604,6 +616,7 @@ yajl_json2tp_transcode(void *ctx, const char *input, size_t input_size)
604616
if (mp_unlikely(stat != yajl_status_ok)) {
605617

606618
if (s_ctx->tc->errmsg[0] == 0) {
619+
s_ctx->tc->errcode = -32700;
607620
stat = yajl_complete_parse(s_ctx->hand);
608621
unsigned char *err = yajl_get_error(s_ctx->hand, 0,
609622
input_, input_size);
@@ -624,38 +637,36 @@ yajl_json2tp_transcode(void *ctx, const char *input, size_t input_size)
624637
static enum tt_result
625638
yajl_json2tp_complete(void *ctx, size_t *complete_msg_size)
626639
{
627-
static const char * unknown_error =
628-
"json _must_ contain 'method':'tnt_call',"
629-
"'params':object ";
630-
631640
yajl_ctx_t *s_ctx = (yajl_ctx_t *)ctx;
632641

633642
char *p = &s_ctx->tc->errmsg[0];
634643
char *e = &s_ctx->tc->errmsg[0] + sizeof(s_ctx->tc->errmsg) - 1;
635644

636645
const yajl_status stat = yajl_complete_parse(s_ctx->hand);
637-
if (mp_unlikely(stat != yajl_status_ok)) {
638-
639-
if (s_ctx->tc->errmsg[0] == 0)
640-
p += snprintf(p, e - p, "%s", unknown_error);
641-
646+
if (mp_likely(stat == yajl_status_ok)) {
647+
tp_reqid(&s_ctx->tp, s_ctx->id);
648+
*complete_msg_size = tp_used(&s_ctx->tp);
649+
return TP_TRANSCODE_OK;
650+
} else if (s_ctx->tc->errmsg[0] != 0) {
651+
p += snprintf(p, e - p, "%s", s_ctx->tc->errmsg);
652+
s_ctx->tc->errcode = -32000;
642653
return TP_TRANSCODE_ERROR;
643654
}
644655

645-
if (mp_unlikely(
646-
!(s_ctx->been_stages & METHOD
647-
&& s_ctx->been_stages & PARAMS)
648-
|| !s_ctx->been_stages))
649-
{
650-
p += snprintf(p, e - p, "%s", unknown_error);
651-
return TP_TRANSCODE_ERROR;
656+
if (mp_unlikely(!(s_ctx->been_stages & METHOD))) {
657+
p += snprintf(p, e - p, "Method not found");
658+
} else if (mp_unlikely(!(s_ctx->been_stages & PARAMS))) {
659+
p += snprintf(p, e - p, "Params not found");
660+
} else if (mp_unlikely(!(s_ctx->been_stages & ID))) {
661+
p += snprintf(p, e - p, "Id not found");
662+
} else {
663+
p += snprintf(p, e - p,
664+
"call _must_ contains 'method':'tnt_call',"
665+
"'params':object ");
652666
}
653667

654-
tp_reqid(&s_ctx->tp, s_ctx->id);
655-
656-
*complete_msg_size = tp_used(&s_ctx->tp);
657-
658-
return TP_TRANSCODE_OK;
668+
s_ctx->tc->errcode = -32600;
669+
return TP_TRANSCODE_ERROR;
659670
}
660671

661672
/**
@@ -935,6 +946,7 @@ tp2json_transcode(void *ctx_, const char *in, size_t in_size)
935946
return TP_TRANSCODE_OK;
936947

937948
error_exit:
949+
ctx->tc->errcode = -32700;
938950
ctx->pos = ctx->output;
939951
return TP_TRANSCODE_ERROR;
940952
}
@@ -1027,6 +1039,8 @@ tp_transcode_init(tp_transcode_t *t, char *output, size_t output_size,
10271039
if (mp_unlikely(!t->codec.ctx))
10281040
return TP_TRANSCODE_ERROR;
10291041

1042+
t->errcode = -32700;
1043+
10301044
return TP_TRANSCODE_OK;
10311045
}
10321046

0 commit comments

Comments
 (0)