Compare commits

...

5 Commits

Author SHA1 Message Date
f4d178b3f6
Update copyright years 2020-09-01 21:03:53 +02:00
ee5317f865
json-rpc-test-server: reject non-null params in "ping" 2020-09-01 20:56:03 +02:00
20558ecd2b
json-rpc-test-server: make sure to set the id in responses 2020-09-01 20:55:22 +02:00
f6225ac6cc
Warn on unexpected "id" fields 2020-09-01 20:54:23 +02:00
16ec8261dc
Make the verbose mode also show the raw input
To make it more useful for debugging.  We might also tie this
to the --debug option, though that would be a bit chaotic.
2020-09-01 20:37:08 +02:00
3 changed files with 45 additions and 18 deletions

View File

@ -1,4 +1,4 @@
Copyright (c) 2014 - 2018, Přemysl Eric Janouch <p@janouch.name> Copyright (c) 2014 - 2020, Přemysl Eric Janouch <p@janouch.name>
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted. purpose with or without fee is hereby granted.

View File

@ -1,7 +1,7 @@
/* /*
* json-rpc-shell.c: simple JSON-RPC 2.0 shell * json-rpc-shell.c: simple JSON-RPC 2.0 shell
* *
* Copyright (c) 2014 - 2016, Přemysl Eric Janouch <p@janouch.name> * Copyright (c) 2014 - 2020, Přemysl Eric Janouch <p@janouch.name>
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted. * purpose with or without fee is hereby granted.
@ -2739,8 +2739,19 @@ display_via_pipeline (struct app_context *ctx,
} }
static bool static bool
parse_response (struct app_context *ctx, struct str *buf, const char *pipeline) process_response (struct app_context *ctx, const json_t *id, struct str *buf,
const char *pipeline)
{ {
if (!id)
{
printf ("[Notification]\n");
if (!buf->len)
return true;
print_warning ("we have been sent data back for a notification");
return false;
}
json_error_t e; json_error_t e;
json_t *response; json_t *response;
if (!(response = json_loadb (buf->str, buf->len, JSON_DECODE_ANY, &e))) if (!(response = json_loadb (buf->str, buf->len, JSON_DECODE_ANY, &e)))
@ -2759,10 +2770,16 @@ parse_response (struct app_context *ctx, struct str *buf, const char *pipeline)
else if (!json_is_string (v) || strcmp (json_string_value (v), "2.0")) else if (!json_is_string (v) || strcmp (json_string_value (v), "2.0"))
print_warning ("invalid `%s' field in response", "jsonrpc"); print_warning ("invalid `%s' field in response", "jsonrpc");
json_t *returned_id = json_object_get (response, "id");
json_t *result = json_object_get (response, "result"); json_t *result = json_object_get (response, "result");
json_t *error = json_object_get (response, "error"); json_t *error = json_object_get (response, "error");
json_t *data = NULL; json_t *data = NULL;
if (!returned_id)
print_warning ("`%s' field not present in response", "id");
if (!json_equal (id, returned_id))
print_warning ("mismatching `%s' field in response", "id");
if (!result && !error) if (!result && !error)
PARSE_FAIL ("neither `result' nor `error' present in response"); PARSE_FAIL ("neither `result' nor `error' present in response");
if (result && error) if (result && error)
@ -2892,26 +2909,28 @@ make_json_rpc_call (struct app_context *ctx,
goto fail; goto fail;
} }
bool success = false; if (ctx->verbose)
if (id) {
success = parse_response (ctx, &buf, pipeline); char *buf_term =
iconv_xstrdup (ctx->term_from_utf8, buf.str, buf.len, NULL);
if (!buf_term)
print_error ("%s: %s", "verbose", "character conversion failed");
else else
{ {
printf ("[Notification]\n"); print_attributed (ctx, stdout, ATTR_INCOMING, "%s", buf_term);
if (buf.len) fputs ("\n", stdout);
print_warning ("we have been sent data back for a notification"); }
else free (buf_term);
success = true;
} }
if (!success) if (!process_response (ctx, id, &buf, pipeline))
{ {
char *s = iconv_xstrdup (ctx->term_from_utf8, char *s = iconv_xstrdup (ctx->term_from_utf8,
buf.str, buf.len + 1 /* null byte */, NULL); buf.str, buf.len + 1 /* null byte */, NULL);
if (!s) if (!s)
print_error ("character conversion failed for `%s'", print_error ("character conversion failed for `%s'",
"raw response data"); "raw response data");
else else if (!ctx->verbose /* already printed */)
printf ("%s: %s\n", "raw response data", s); printf ("%s: %s\n", "raw response data", s);
free (s); free (s);
} }

View File

@ -1,7 +1,7 @@
/* /*
* json-rpc-test-server.c: JSON-RPC 2.0 demo server * json-rpc-test-server.c: JSON-RPC 2.0 demo server
* *
* Copyright (c) 2015 - 2018, Přemysl Eric Janouch <p@janouch.name> * Copyright (c) 2015 - 2020, Přemysl Eric Janouch <p@janouch.name>
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted. * purpose with or without fee is hereby granted.
@ -1428,6 +1428,8 @@ end:
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/// Handlers must not set the `id` field in their responses, that will be filled
/// in automatically according to whether the request is a notification or not.
typedef json_t *(*json_rpc_handler_fn) (struct server_context *, json_t *); typedef json_t *(*json_rpc_handler_fn) (struct server_context *, json_t *);
struct json_rpc_handler_info struct json_rpc_handler_info
@ -1447,7 +1449,10 @@ static json_t *
json_rpc_ping (struct server_context *ctx, json_t *params) json_rpc_ping (struct server_context *ctx, json_t *params)
{ {
(void) ctx; (void) ctx;
(void) params;
if (params && !json_is_null (params))
return json_rpc_response (NULL, NULL,
json_rpc_error (JSON_RPC_ERROR_INVALID_PARAMS, NULL));
return json_rpc_response (NULL, json_string ("pong"), NULL); return json_rpc_response (NULL, json_string ("pong"), NULL);
} }
@ -1493,7 +1498,10 @@ process_json_rpc_request (struct server_context *ctx, json_t *request)
json_t *response = handler->handler (ctx, params); json_t *response = handler->handler (ctx, params);
if (id) if (id)
{
(void) json_object_set (response, "id", id);
return response; return response;
}
// Notifications don't get responses // Notifications don't get responses
json_decref (response); json_decref (response);