diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a97c1da0..b0d85b5fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Changed +- relay/api: allow array with multiple requests in websocket frame received from client - core, plugins: simplify help on parameters that can be repeated in commands ### Added diff --git a/doc/en/weechat_relay_api.en.adoc b/doc/en/weechat_relay_api.en.adoc index 50c0dd0e8..6d653f868 100644 --- a/doc/en/weechat_relay_api.en.adoc +++ b/doc/en/weechat_relay_api.en.adoc @@ -1389,6 +1389,10 @@ Requests to WeeChat are made with a JSON object containing these fields: * `body` (object or array): the body (optional, for `POST` and `PUT` methods) * `request_id` (string): identifier sent back in the response +Multiple requests can be sent at once using an array of objects, each object +being a separate request. + +Requests are executed in the order received (see example below). + Responses to client are made with a JSON object containing these fields: * `code` (integer): HTTP response code (example: `200`) @@ -1478,6 +1482,69 @@ Response: } ---- +Requests example: send two requests at once: get list of all buffers with lines +and nicks, then synchronize with the remote: + +[source,json] +---- +[ + { + "request": "GET /api/buffers?lines=-1000&nicks=true&colors=weechat", + "request_id": "initial_sync" + }, + { + "request": "POST /api/sync", + "body": { + "colors": "weechat" + } + } +] +---- + +[NOTE] +It is recommended to send the synchronization request together with the first +request that is fetching data, so that no events are missed. + +First response (body with buffers is truncated for readability): + +[source,json] +---- +{ + "code": 200, + "message": "OK", + "request": "GET /api/buffers?lines=-1000&nicks=true&colors=weechat", + "request_body": null, + "request_id": "initial_sync", + "body_type": "buffers", + "body": [ + { + "id": 1709932823238637, + "name": "core.weechat", + "short_name": "weechat", + "number": 1, + "type": "formatted" + } + ] +} +---- + +Second response: + +[source,json] +---- +{ + "code": 204, + "message": "No Content", + "request": "POST /api/sync", + "request_body": { + "colors": "weechat" + }, + "request_id": null, + "body_type": null, + "body": null +} +---- + WeeChat pushes data to the client at any time on some events: when lines are displayed, buffers added/removed/changed, nicks added/removed/changed, etc. diff --git a/doc/fr/weechat_relay_api.fr.adoc b/doc/fr/weechat_relay_api.fr.adoc index fac89c2e5..5dce736b6 100644 --- a/doc/fr/weechat_relay_api.fr.adoc +++ b/doc/fr/weechat_relay_api.fr.adoc @@ -1406,6 +1406,10 @@ les champs suivants : * `body` (objet ou tableau) : le corps (facultatif, pour les méthodes `POST` et `PUT`) * `request_id` (chaîne) : identifiant renvoyé dans la réponse +Plusieurs requêtes peuvent être envoyées simultanément avec un tableau d'objets, +chaque objet étant une requête séparée. + +Les requêtes sont exécutées dans l'ordre reçu (voir l'exemple ci-dessous). + Les réponses vers le client sont faites avec un objet JSON qui contient les champs suivants : @@ -1499,6 +1503,69 @@ Réponse : } ---- +Exemple de requêtes : envoyer deux requêtes en même temps : obtenir la liste des +tampons avec les lignes et les pseudos, puis se synchroniser avec le relay distant : + +[source,json] +---- +[ + { + "request": "GET /api/buffers?lines=-1000&nicks=true&colors=weechat", + "request_id": "initial_sync" + }, + { + "request": "POST /api/sync", + "body": { + "colors": "weechat" + } + } +] +---- + +[NOTE] +Il est recommandé d'envoyer la requête de synchronisation en même temps que la +première requête qui récupère les données, afin qu'aucun évènement ne soit manqué. + +Première réponse (le "body" avec les tampons est tronqué pour la lisibilité) : + +[source,json] +---- +{ + "code": 200, + "message": "OK", + "request": "GET /api/buffers?lines=-1000&nicks=true&colors=weechat", + "request_body": null, + "request_id": "initial_sync", + "body_type": "buffers", + "body": [ + { + "id": 1709932823238637, + "name": "core.weechat", + "short_name": "weechat", + "number": 1, + "type": "formatted" + } + ] +} +---- + +Seconde réponse : + +[source,json] +---- +{ + "code": 204, + "message": "No Content", + "request": "POST /api/sync", + "request_body": { + "colors": "weechat" + }, + "request_id": null, + "body_type": null, + "body": null +} +---- + WeeChat pousse des données au client à tout moment sur des évènements : lorsque des lignes sont affichées, des tampons ajoutés/supprimés/changés, des pseudos ajoutés/supprimés/changés, etc. diff --git a/src/plugins/relay/api/relay-api-protocol.c b/src/plugins/relay/api/relay-api-protocol.c index 6300e2b4f..8fb1e274b 100644 --- a/src/plugins/relay/api/relay-api-protocol.c +++ b/src/plugins/relay/api/relay-api-protocol.c @@ -916,6 +916,71 @@ RELAY_API_PROTOCOL_CALLBACK(sync) return RELAY_API_PROTOCOL_RC_OK; } +/* + * Reads one request from client. + */ + +void +relay_api_protocol_recv_json_request (struct t_relay_client *client, + cJSON *json) +{ + cJSON *json_request, *json_request_id, *json_body; + const char *ptr_request_id; + char *string_body; + int length; + + relay_http_request_reinit (client->http_req); + + json_request_id = cJSON_GetObjectItem (json, "request_id"); + if (json_request_id + && !cJSON_IsString (json_request_id) + && !cJSON_IsNull (json_request_id)) + { + goto error; + } + ptr_request_id = (json_request_id) ? + cJSON_GetStringValue (json_request_id) : NULL; + free (client->http_req->id); + client->http_req->id = NULL; + client->http_req->id = (ptr_request_id) ? strdup (ptr_request_id) : NULL; + + json_request = cJSON_GetObjectItem (json, "request"); + if (!json_request || !cJSON_IsString (json_request)) + goto error; + + if (!relay_http_parse_method_path (client->http_req, + cJSON_GetStringValue (json_request))) + { + goto error; + } + + json_body = cJSON_GetObjectItem (json, "body"); + if (json_body) + { + string_body = cJSON_PrintUnformatted (json_body); + if (string_body) + { + length = strlen (string_body); + client->http_req->body = malloc (length + 1); + if (client->http_req->body) + { + memcpy (client->http_req->body, string_body, length + 1); + client->http_req->content_length = length; + client->http_req->body_size = length; + } + free (string_body); + } + } + + relay_api_protocol_recv_http (client); + + return; + +error: + relay_api_msg_send_json (client, RELAY_HTTP_400_BAD_REQUEST, + NULL, NULL, NULL); +} + /* * Reads JSON string from a client: when connected via websocket (persistent * connection), the client is sending JSON data as a request, which is @@ -939,74 +1004,50 @@ RELAY_API_PROTOCOL_CALLBACK(sync) * Content-Type: application/json * * {"buffer": "irc.libera.#weechat","command": "hello!"} + * + * The JSON can also be an array of requests, for example to fetch all buffers + * data and synchronize at same time: + * + * [ + * { + * "request": "GET /api/buffers?lines=-1000&nicks=true&colors=weechat", + * "request_id": "initial_sync" + * }, + * { + * "request": "POST /api/sync", + * "body": { + * "colors":"weechat" + * } + * } + * ] */ void relay_api_protocol_recv_json (struct t_relay_client *client, const char *json) { - cJSON *json_obj, *json_request, *json_body, *json_request_id; - const char *ptr_request_id; - char *string_body; - int length; - - relay_http_request_reinit (client->http_req); + cJSON *json_obj, *json_request; json_obj = cJSON_Parse (json); if (!json_obj) - goto error; - - json_request = cJSON_GetObjectItem (json_obj, "request"); - if (!json_request) - goto error; - - if (!cJSON_IsString (json_request)) - goto error; - - if (!relay_http_parse_method_path (client->http_req, - cJSON_GetStringValue (json_request))) { - goto error; + relay_api_msg_send_json (client, RELAY_HTTP_400_BAD_REQUEST, + NULL, NULL, NULL); + return; } - json_body = cJSON_GetObjectItem (json_obj, "body"); - if (json_body) + if (cJSON_IsArray (json_obj)) { - string_body = cJSON_PrintUnformatted (json_body); - if (string_body) + cJSON_ArrayForEach (json_request, json_obj) { - length = strlen (string_body); - client->http_req->body = malloc (length + 1); - if (client->http_req->body) - { - memcpy (client->http_req->body, string_body, length + 1); - client->http_req->content_length = length; - client->http_req->body_size = length; - } - free (string_body); + relay_api_protocol_recv_json_request (client, json_request); } } - - free (client->http_req->id); - client->http_req->id = NULL; - json_request_id = cJSON_GetObjectItem (json_obj, "request_id"); - if (json_request_id) + else { - if (!cJSON_IsString (json_request_id) && !cJSON_IsNull (json_request_id)) - goto error; - ptr_request_id = cJSON_GetStringValue (json_request_id); - client->http_req->id = (ptr_request_id) ? - strdup (ptr_request_id) : NULL; + relay_api_protocol_recv_json_request (client, json_obj); } - relay_api_protocol_recv_http (client); - goto end; - -error: - relay_api_msg_send_json (client, RELAY_HTTP_400_BAD_REQUEST, NULL, NULL, NULL); - -end: - if (json_obj) - cJSON_Delete (json_obj); + cJSON_Delete (json_obj); } /* diff --git a/src/plugins/relay/api/relay-api.h b/src/plugins/relay/api/relay-api.h index 00015870a..4476bd82b 100644 --- a/src/plugins/relay/api/relay-api.h +++ b/src/plugins/relay/api/relay-api.h @@ -24,7 +24,7 @@ struct t_relay_client; enum t_relay_status; #define RELAY_API_VERSION_MAJOR 0 -#define RELAY_API_VERSION_MINOR 2 +#define RELAY_API_VERSION_MINOR 3 #define RELAY_API_VERSION_PATCH 0 #define RELAY_API_VERSION_NUMBER \ ((RELAY_API_VERSION_MAJOR << 16) \ diff --git a/tests/unit/plugins/relay/api/test-relay-api-protocol.cpp b/tests/unit/plugins/relay/api/test-relay-api-protocol.cpp index 140c3f70b..fe48dd35c 100644 --- a/tests/unit/plugins/relay/api/test-relay-api-protocol.cpp +++ b/tests/unit/plugins/relay/api/test-relay-api-protocol.cpp @@ -51,7 +51,7 @@ extern int relay_api_protocol_command_delay; #define WEE_CHECK_HTTP_CODE(__code, __message) \ STRNCMP_EQUAL("HTTP/1.1 " #__code " " __message "\r\n", \ - data_sent, \ + data_sent[0], \ strlen ("HTTP/1.1 " #__code " " __message "\r\n")); #define WEE_CHECK_TEXT(__code, __message, __request, __body) \ @@ -63,7 +63,7 @@ extern int relay_api_protocol_command_delay; "\"body_type\":null," \ "\"body\":null" \ "}", \ - data_sent); + data_sent[0]); #define WEE_CHECK_OBJ_STR(__expected, __json, __name) \ json_obj = cJSON_GetObjectItem (__json, __name); \ @@ -92,9 +92,9 @@ extern int relay_api_protocol_command_delay; struct t_relay_server *ptr_relay_server = NULL; struct t_relay_client *ptr_relay_client = NULL; -char *data_sent = NULL; -int data_sent_size = 0; -cJSON *json_body_sent = NULL; +int data_sent_index = 0; +char *data_sent[4] = { NULL, NULL, NULL, NULL }; +cJSON *json_body_sent[4] = { NULL, NULL, NULL, NULL }; TEST_GROUP(RelayApiProtocol) { @@ -104,17 +104,16 @@ TEST_GROUP(RelayApiProtocolWithClient) { void free_data_sent () { - if (data_sent) + int i; + + for (i = 0; i < 4; i++) { - free (data_sent); - data_sent = NULL; - } - data_sent_size = 0; - if (json_body_sent) - { - cJSON_Delete (json_body_sent); - json_body_sent = NULL; + free (data_sent[i]); + data_sent[i] = NULL; + cJSON_Delete (json_body_sent[i]); + json_body_sent[i] = NULL; } + data_sent_index = 0; } void test_client_recv_http_raw (const char *http_request) @@ -172,30 +171,21 @@ TEST_GROUP(RelayApiProtocolWithClient) (void) client; - if (data_sent) - { - free (data_sent); - data_sent = NULL; - } - data_sent_size = 0; - if (json_body_sent) - { - cJSON_Delete (json_body_sent); - json_body_sent = NULL; - } + data_sent[data_sent_index] = (char *)malloc (data_size + 1); + memcpy (data_sent[data_sent_index], data, data_size); + data_sent[data_sent_index][data_size] = '\0'; - data_sent = (char *)malloc (data_size + 1); - memcpy (data_sent, data, data_size); - data_sent[data_size] = '\0'; - data_sent_size = data_size; - - pos_body = strstr (data_sent, "\r\n\r\n"); + pos_body = strstr (data_sent[data_sent_index], "\r\n\r\n"); if (pos_body) - json_body_sent = cJSON_Parse(pos_body + 4); + json_body_sent[data_sent_index] = cJSON_Parse(pos_body + 4); + + data_sent_index++; } void setup () { + int i; + /* disable auto-open of relay buffer */ config_file_option_set (relay_config_look_auto_open_buffer, "off", 1); @@ -218,9 +208,12 @@ TEST_GROUP(RelayApiProtocolWithClient) ptr_relay_client = relay_client_new (-1, "test", ptr_relay_server); ptr_relay_client->fake_send_func = &fake_send_func; - data_sent = NULL; - data_sent_size = 0; - json_body_sent = NULL; + for (i = 0; i < 4; i++) + { + data_sent[i] = NULL; + json_body_sent[i] = NULL; + } + data_sent_index = 0; } void teardown () @@ -288,7 +281,7 @@ TEST(RelayApiProtocolWithClient, CbOptions) "Content-Type: application/json; charset=utf-8\r\n" "Content-Length: 0\r\n" "\r\n", - data_sent); + data_sent[0]); } /* @@ -308,7 +301,7 @@ TEST(RelayApiProtocolWithClient, CbHandshake) "{\"password_hash_algo\":null," "\"password_hash_iterations\":100000," "\"totp\":false}", - data_sent); + data_sent[0]); /* empty body */ test_client_recv_http ("POST /api/handshake", NULL, "{}"); @@ -320,7 +313,7 @@ TEST(RelayApiProtocolWithClient, CbHandshake) "{\"password_hash_algo\":null," "\"password_hash_iterations\":100000," "\"totp\":false}", - data_sent); + data_sent[0]); /* unknown password hash algorithm */ test_client_recv_http ("POST /api/handshake", NULL, @@ -333,7 +326,7 @@ TEST(RelayApiProtocolWithClient, CbHandshake) "{\"password_hash_algo\":null," "\"password_hash_iterations\":100000," "\"totp\":false}", - data_sent); + data_sent[0]); /* two supported hash algorithms */ test_client_recv_http ( @@ -348,7 +341,7 @@ TEST(RelayApiProtocolWithClient, CbHandshake) "{\"password_hash_algo\":\"pbkdf2+sha512\"," "\"password_hash_iterations\":100000," "\"totp\":false}", - data_sent); + data_sent[0]); } /* @@ -362,7 +355,7 @@ TEST(RelayApiProtocolWithClient, CbVersion) test_client_recv_http ("GET /api/version", NULL, NULL); WEE_CHECK_HTTP_CODE(200, "OK"); - json = json_body_sent; + json = json_body_sent[0]; WEE_CHECK_OBJ_STR(version_get_version (), json, "weechat_version"); WEE_CHECK_OBJ_STR(version_get_git (), json, "weechat_version_git"); WEE_CHECK_OBJ_NUM(util_version_number (version_get_version ()), @@ -389,7 +382,7 @@ TEST(RelayApiProtocolWithClient, CbBuffers) "Content-Length: 41\r\n" "\r\n" "{\"error\": \"Buffer \\\"invalid\\\" not found\"}", - data_sent); + data_sent[0]); /* error: invalid buffer id */ test_client_recv_http ("GET /api/buffers/123", NULL, NULL); @@ -399,7 +392,7 @@ TEST(RelayApiProtocolWithClient, CbBuffers) "Content-Length: 37\r\n" "\r\n" "{\"error\": \"Buffer \\\"123\\\" not found\"}", - data_sent); + data_sent[0]); /* error: invalid sub-resource */ test_client_recv_http ("GET /api/buffers/core.weechat/invalid", NULL, NULL); @@ -409,7 +402,7 @@ TEST(RelayApiProtocolWithClient, CbBuffers) "Content-Length: 59\r\n" "\r\n" "{\"error\": \"Sub-resource of buffers not found: \\\"invalid\\\"\"}", - data_sent); + data_sent[0]); /* error: too many parameters in path */ test_client_recv_http ("GET /api/buffers/core.weechat/too/many/parameters", @@ -419,14 +412,14 @@ TEST(RelayApiProtocolWithClient, CbBuffers) "Content-Type: application/json; charset=utf-8\r\n" "Content-Length: 0\r\n" "\r\n", - data_sent); + data_sent[0]); /* get all buffers */ test_client_recv_http ("GET /api/buffers", NULL, NULL); WEE_CHECK_HTTP_CODE(200, "OK"); - CHECK(json_body_sent); - CHECK(cJSON_IsArray (json_body_sent)); - json = cJSON_GetArrayItem (json_body_sent, 0); + CHECK(json_body_sent[0]); + CHECK(cJSON_IsArray (json_body_sent[0])); + json = cJSON_GetArrayItem (json_body_sent[0], 0); CHECK(json); CHECK(cJSON_IsObject (json)); WEE_CHECK_OBJ_NUM(gui_buffers->id, json, "id"); @@ -453,9 +446,9 @@ TEST(RelayApiProtocolWithClient, CbBuffers) gui_buffer_set (gui_buffers, "input_multiline", "1"); test_client_recv_http ("GET /api/buffers/core.weechat", NULL, NULL); WEE_CHECK_HTTP_CODE(200, "OK"); - CHECK(json_body_sent); - CHECK(cJSON_IsObject (json_body_sent)); - json = json_body_sent; + CHECK(json_body_sent[0]); + CHECK(cJSON_IsObject (json_body_sent[0])); + json = json_body_sent[0]; WEE_CHECK_OBJ_NUM(gui_buffers->id, json, "id"); WEE_CHECK_OBJ_STR("core.weechat", json, "name"); WEE_CHECK_OBJ_STR("weechat", json, "short_name"); @@ -481,9 +474,9 @@ TEST(RelayApiProtocolWithClient, CbBuffers) "GET /api/buffers/%lld", gui_buffers->id); test_client_recv_http (str_http, NULL, NULL); WEE_CHECK_HTTP_CODE(200, "OK"); - CHECK(json_body_sent); - CHECK(cJSON_IsObject (json_body_sent)); - json = json_body_sent; + CHECK(json_body_sent[0]); + CHECK(cJSON_IsObject (json_body_sent[0])); + json = json_body_sent[0]; WEE_CHECK_OBJ_NUM(gui_buffers->id, json, "id"); WEE_CHECK_OBJ_STR("core.weechat", json, "name"); WEE_CHECK_OBJ_STR("weechat", json, "short_name"); @@ -506,9 +499,9 @@ TEST(RelayApiProtocolWithClient, CbBuffers) gui_chat_printf (NULL, "test line 2"); test_client_recv_http ("GET /api/buffers/core.weechat/lines?lines=-2", NULL, NULL); WEE_CHECK_HTTP_CODE(200, "OK"); - CHECK(json_body_sent); - CHECK(cJSON_IsArray (json_body_sent)); - json = cJSON_GetArrayItem (json_body_sent, 0); + CHECK(json_body_sent[0]); + CHECK(cJSON_IsArray (json_body_sent[0])); + json = cJSON_GetArrayItem (json_body_sent[0], 0); CHECK(json); CHECK(cJSON_IsObject (json)); WEE_CHECK_OBJ_NUM(gui_buffers->own_lines->last_line->prev_line->data->id, json, "id"); @@ -518,7 +511,7 @@ TEST(RelayApiProtocolWithClient, CbBuffers) WEE_CHECK_OBJ_BOOL(0, json, "highlight"); WEE_CHECK_OBJ_STR("", json, "prefix"); WEE_CHECK_OBJ_STR("test line 1", json, "message"); - json = cJSON_GetArrayItem (json_body_sent, 1); + json = cJSON_GetArrayItem (json_body_sent[0], 1); CHECK(json); CHECK(cJSON_IsObject (json)); WEE_CHECK_OBJ_NUM(gui_buffers->own_lines->last_line->data->id, json, "id"); @@ -532,9 +525,9 @@ TEST(RelayApiProtocolWithClient, CbBuffers) /* get nicks */ test_client_recv_http ("GET /api/buffers/core.weechat/nicks", NULL, NULL); WEE_CHECK_HTTP_CODE(200, "OK"); - CHECK(json_body_sent); - CHECK(cJSON_IsObject (json_body_sent)); - json = json_body_sent; + CHECK(json_body_sent[0]); + CHECK(cJSON_IsObject (json_body_sent[0])); + json = json_body_sent[0]; WEE_CHECK_OBJ_STR("root", json, "name"); WEE_CHECK_OBJ_STR("", json, "color"); json_groups = cJSON_GetObjectItem (json, "groups"); @@ -555,9 +548,9 @@ TEST(RelayApiProtocolWithClient, CbHotlist) /* get hotlist (empty) */ test_client_recv_http ("GET /api/hotlist", NULL, NULL); WEE_CHECK_HTTP_CODE(200, "OK"); - CHECK(json_body_sent); - CHECK(cJSON_IsArray (json_body_sent)); - LONGS_EQUAL(0, cJSON_GetArraySize (json_body_sent)); + CHECK(json_body_sent[0]); + CHECK(cJSON_IsArray (json_body_sent[0])); + LONGS_EQUAL(0, cJSON_GetArraySize (json_body_sent[0])); gui_hotlist_add (gui_buffers, GUI_HOTLIST_LOW, NULL, 0); gui_hotlist_add (gui_buffers, GUI_HOTLIST_MESSAGE, NULL, 0); @@ -573,10 +566,10 @@ TEST(RelayApiProtocolWithClient, CbHotlist) /* get hotlist (one buffer) */ test_client_recv_http ("GET /api/hotlist", NULL, NULL); WEE_CHECK_HTTP_CODE(200, "OK"); - CHECK(json_body_sent); - CHECK(cJSON_IsArray (json_body_sent)); - LONGS_EQUAL(1, cJSON_GetArraySize (json_body_sent)); - json = cJSON_GetArrayItem (json_body_sent, 0); + CHECK(json_body_sent[0]); + CHECK(cJSON_IsArray (json_body_sent[0])); + LONGS_EQUAL(1, cJSON_GetArraySize (json_body_sent[0])); + json = cJSON_GetArrayItem (json_body_sent[0], 0); CHECK(json); CHECK(cJSON_IsObject (json)); WEE_CHECK_OBJ_NUM(GUI_HOTLIST_HIGHLIGHT, json, "priority"); @@ -622,7 +615,7 @@ TEST(RelayApiProtocolWithClient, CbInput) "Content-Type: application/json; charset=utf-8\r\n" "Content-Length: 0\r\n" "\r\n", - data_sent); + data_sent[0]); /* error: invalid buffer name */ test_client_recv_http ("POST /api/input", @@ -635,7 +628,7 @@ TEST(RelayApiProtocolWithClient, CbInput) "Content-Length: 41\r\n" "\r\n" "{\"error\": \"Buffer \\\"invalid\\\" not found\"}", - data_sent); + data_sent[0]); /* on core buffer, without buffer name */ record_start (); @@ -693,12 +686,12 @@ TEST(RelayApiProtocolWithClient, CbPing) "Content-Type: application/json; charset=utf-8\r\n" "Content-Length: 0\r\n" "\r\n", - data_sent); + data_sent[0]); /* ping with a body */ test_client_recv_http ("POST /api/ping", NULL, "{\"data\": \"abcdef\"}"); WEE_CHECK_HTTP_CODE(200, "OK"); - json = json_body_sent; + json = json_body_sent[0]; WEE_CHECK_OBJ_STR("abcdef", json, "data"); } @@ -717,7 +710,7 @@ TEST(RelayApiProtocolWithClient, CbSync) "\r\n" "{\"error\": \"Sync resource is available only with " "a websocket connection\"}", - data_sent); + data_sent[0]); } /* @@ -741,7 +734,7 @@ TEST(RelayApiProtocolWithClient, CbSyncWebsocket) "Connection: Upgrade\r\n" "Sec-WebSocket-Accept: Z5uTZwvwYNDm9w4HFGk26ijp/p0=\r\n" "\r\n", - data_sent); + data_sent[0]); test_client_recv_text ("{\"request\": \"POST /api/sync\"}"); WEE_CHECK_TEXT(204, "No Content", "POST /api/sync", "null"); @@ -785,6 +778,7 @@ TEST(RelayApiProtocolWithClient, CbSyncWebsocket) /* * Tests functions: + * relay_api_protocol_recv_json_request * relay_api_protocol_recv_json */ @@ -804,7 +798,7 @@ TEST(RelayApiProtocolWithClient, RecvJson) "Connection: Upgrade\r\n" "Sec-WebSocket-Accept: Z5uTZwvwYNDm9w4HFGk26ijp/p0=\r\n" "\r\n", - data_sent); + data_sent[0]); /* error: empty string */ test_client_recv_text (""); @@ -833,6 +827,46 @@ TEST(RelayApiProtocolWithClient, RecvJson) /* error: invalid request (string, resource not found) */ test_client_recv_text ("{\"request\": \"GET /api/unknown\", \"body\": {\"test\": 123}}"); WEE_CHECK_TEXT(404, "Not Found", "GET /api/unknown", "{\"test\":123}"); + + /* ping */ + test_client_recv_text ("{\"request\": \"POST /api/ping\", \"request_id\": \"ping\"}"); + STRCMP_EQUAL("{\"code\":204," + "\"message\":\"No Content\"," + "\"request\":\"POST /api/ping\"," + "\"request_body\":null," + "\"request_id\":\"ping\"," + "\"body_type\":null," + "\"body\":null" + "}", + data_sent[0]); + + /* 2 ping */ + test_client_recv_text ("[" + "{\"request\": \"POST /api/ping\", " + "\"request_id\": \"ping1\", " + "\"body\": {\"data\": \"p1\"}}, " + "{\"request\": \"POST /api/ping\", " + "\"request_id\": \"ping2\", " + "\"body\": {\"data\": \"p2\"}}" + "]"); + STRCMP_EQUAL("{\"code\":200," + "\"message\":\"OK\"," + "\"request\":\"POST /api/ping\"," + "\"request_body\":{\"data\":\"p1\"}," + "\"request_id\":\"ping1\"," + "\"body_type\":\"ping\"," + "\"body\":{\"data\":\"p1\"}" + "}", + data_sent[0]); + STRCMP_EQUAL("{\"code\":200," + "\"message\":\"OK\"," + "\"request\":\"POST /api/ping\"," + "\"request_body\":{\"data\":\"p2\"}," + "\"request_id\":\"ping2\"," + "\"body_type\":\"ping\"," + "\"body\":{\"data\":\"p2\"}" + "}", + data_sent[1]); } /* @@ -849,7 +883,7 @@ TEST(RelayApiProtocolWithClient, RecvHttp404) "Content-Type: application/json; charset=utf-8\r\n" "Content-Length: 0\r\n" "\r\n", - data_sent); + data_sent[0]); /* resource not found: error 404 */ test_client_recv_http ("GET /unknown HTTP/1.1", NULL, NULL); @@ -858,7 +892,7 @@ TEST(RelayApiProtocolWithClient, RecvHttp404) "Content-Type: application/json; charset=utf-8\r\n" "Content-Length: 0\r\n" "\r\n", - data_sent); + data_sent[0]); /* resource not found: error 404 */ test_client_recv_http ("GET /unknown/abc HTTP/1.1", NULL, NULL); @@ -867,7 +901,7 @@ TEST(RelayApiProtocolWithClient, RecvHttp404) "Content-Type: application/json; charset=utf-8\r\n" "Content-Length: 0\r\n" "\r\n", - data_sent); + data_sent[0]); /* resource not found: error 404 */ test_client_recv_http ("GET /api HTTP/1.1", NULL, NULL); @@ -876,7 +910,7 @@ TEST(RelayApiProtocolWithClient, RecvHttp404) "Content-Type: application/json; charset=utf-8\r\n" "Content-Length: 0\r\n" "\r\n", - data_sent); + data_sent[0]); /* resource not found: error 404 */ test_client_recv_http ("GET /api/unknown HTTP/1.1", NULL, NULL); @@ -885,7 +919,7 @@ TEST(RelayApiProtocolWithClient, RecvHttp404) "Content-Type: application/json; charset=utf-8\r\n" "Content-Length: 0\r\n" "\r\n", - data_sent); + data_sent[0]); } /* @@ -904,7 +938,7 @@ TEST(RelayApiProtocolWithClient, RecvHttpMissingPassword) "Content-Length: 29\r\n" "\r\n" "{\"error\": \"Missing password\"}", - data_sent); + data_sent[0]); } /* @@ -924,5 +958,5 @@ TEST(RelayApiProtocolWithClient, RecvHttpInvalidPassword) "Content-Length: 29\r\n" "\r\n" "{\"error\": \"Invalid password\"}", - data_sent); + data_sent[0]); }