From d073a807b0dd88898f3aec368c5addfbd218e4fd Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Wed, 20 Dec 2017 15:31:05 +0100 Subject: [PATCH] API: Add 'pretty' parameter for beautified JSON response bodies fixes #5877 --- doc/12-icinga2-api.md | 95 +++++++++++++++------------- doc/15-troubleshooting.md | 6 +- lib/remote/actionshandler.cpp | 6 +- lib/remote/configfileshandler.cpp | 12 ++-- lib/remote/configpackageshandler.cpp | 16 ++--- lib/remote/configpackageshandler.hpp | 2 +- lib/remote/configstageshandler.cpp | 20 +++--- lib/remote/consolehandler.cpp | 14 ++-- lib/remote/consolehandler.hpp | 4 +- lib/remote/createobjecthandler.cpp | 8 +-- lib/remote/deleteobjecthandler.cpp | 6 +- lib/remote/eventshandler.cpp | 6 +- lib/remote/httphandler.cpp | 4 +- lib/remote/httpserverconnection.cpp | 4 +- lib/remote/httputility.cpp | 19 ++++-- lib/remote/httputility.hpp | 4 +- lib/remote/infohandler.cpp | 2 +- lib/remote/modifyobjecthandler.cpp | 8 +-- lib/remote/objectqueryhandler.cpp | 22 +++---- lib/remote/statushandler.cpp | 4 +- lib/remote/templatequeryhandler.cpp | 6 +- lib/remote/typequeryhandler.cpp | 4 +- lib/remote/variablequeryhandler.cpp | 4 +- 23 files changed, 145 insertions(+), 131 deletions(-) diff --git a/doc/12-icinga2-api.md b/doc/12-icinga2-api.md index 15471e9c6..0e52e655e 100644 --- a/doc/12-icinga2-api.md +++ b/doc/12-icinga2-api.md @@ -82,9 +82,16 @@ The output will be sent back as a JSON object: ] } -Tip: If you are working on the CLI with curl you can also use [jq](https://stedolan.github.io/jq/) -to format the returned JSON output in a readable manner. The documentation -prefers `python -m json.tool` as Python is available nearly everywhere. +> **Tip** +> +> You can use the `pretty` parameter to beautify the JSON response with Icinga v2.9+. + +You can also use [jq](https://stedolan.github.io/jq/) or `python -m json.tool` +in combination with curl on the CLI. + +``` +curl ... | python -m json.tool +``` > **Note** > @@ -332,7 +339,7 @@ action which can be used for both hosts and services. When using advanced filter type using the `type` parameter: $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/reschedule-check' \ - -d '{ "type": "Service", "filter": "service.name==\"ping6\"" }' | python -m json.tool + -d '{ "type": "Service", "filter": "service.name==\"ping6\"", "pretty": true }' When building filters you have to ensure that values such as `"linux-servers"` are escaped properly according to the rules of the Icinga 2 configuration @@ -343,7 +350,7 @@ variables which should be made available to your filter expression. This way you to worry about escaping values: $ curl -k -s -u 'root:icinga' -H 'Accept: application/json' -H 'X-HTTP-Method-Override: GET' -X POST 'https://localhost:5665/v1/objects/hosts' \ - -d '{ "filter": "host.vars.os == os", "filter_vars": { "os": "Linux" } }' + -d '{ "filter": "host.vars.os == os", "filter_vars": { "os": "Linux" }, "pretty": true }' We're using [X-HTTP-Method-Override](12-icinga2-api.md#icinga2-api-requests-method-override) here because the HTTP specification does not allow message bodies for GET requests. @@ -409,7 +416,7 @@ URL path when querying a single object. For objects with composite names You can limit the output to specific attributes using the `attrs` URL parameter: - $ curl -k -s -u root:icinga 'https://localhost:5665/v1/objects/hosts/example.localdomain?attrs=name&attrs=address' | python -m json.tool + $ curl -k -s -u root:icinga 'https://localhost:5665/v1/objects/hosts/example.localdomain?attrs=name&attrs=address&pretty=1' { "results": [ { @@ -477,7 +484,7 @@ custom attribute set to `Linux`. The result set contains the `display_name` and attributes for the service. The query also returns the host's `name` and `address` attribute via a join: - $ curl -k -s -u root:icinga 'https://localhost:5665/v1/objects/services?attrs=display_name&attrs=check_command&joins=host.name&joins=host.address&filter=host.vars.os==%22Linux%22' | python -m json.tool + $ curl -k -s -u root:icinga 'https://localhost:5665/v1/objects/services?attrs=display_name&attrs=check_command&joins=host.name&joins=host.address&filter=host.vars.os==%22Linux%22&pretty=1' { "results": [ @@ -525,7 +532,7 @@ and no downtime or acknowledgement set). We're using [X-HTTP-Method-Override](12 here because we want to pass all query attributes in the request body. $ curl -k -s -u root:icinga -H 'Accept: application/json' -H 'X-HTTP-Method-Override: GET' -X POST 'https://127.0.0.1:5665/v1/objects/services' \ - -d '{ "joins": [ "host.name", "host.address" ], "attrs": [ "name", "state", "downtime_depth", "acknowledgement" ], "filter": "service.state != ServiceOK && service.downtime_depth == 0.0 && service.acknowledgement == 0.0" }' | python -m json.tool + -d '{ "joins": [ "host.name", "host.address" ], "attrs": [ "name", "state", "downtime_depth", "acknowledgement" ], "filter": "service.state != ServiceOK && service.downtime_depth == 0.0 && service.acknowledgement == 0.0", "pretty": true }' { "results": [ @@ -554,7 +561,7 @@ URL endpoint with `joins` and `filter` request parameters using the [X-HTTP-Meth method: $ curl -k -s -u root:icinga -H 'Accept: application/json' -H 'X-HTTP-Method-Override: GET' -X POST 'https://localhost:5665/v1/objects/comments' \ - -d '{ "joins": [ "service.name", "service.acknowledgement", "service.acknowledgement_expiry" ], "attrs": [ "author", "text" ], "filter": "service.acknowledgement!=0 && service.acknowledgement_expiry==0" }' | python -m json.tool + -d '{ "joins": [ "service.name", "service.acknowledgement", "service.acknowledgement_expiry" ], "attrs": [ "author", "text" ], "filter": "service.acknowledgement!=0 && service.acknowledgement_expiry==0", "pretty": true }' { "results": [ @@ -597,8 +604,7 @@ If attributes are of the Dictionary type, you can also use the indexer format. T Example for creating the new host object `example.localdomain`: $ curl -k -s -u root:icinga -H 'Accept: application/json' -X PUT 'https://localhost:5665/v1/objects/hosts/example.localdomain' \ - -d '{ "templates": [ "generic-host" ], "attrs": { "address": "192.168.1.1", "check_command": "hostalive", "vars.os" : "Linux" } }' \ - | python -m json.tool + -d '{ "templates": [ "generic-host" ], "attrs": { "address": "192.168.1.1", "check_command": "hostalive", "vars.os" : "Linux" }, "pretty": true }' { "results": [ { @@ -613,8 +619,7 @@ contains a detailed error message. The following example is missing the `check_c which is required for host objects: $ curl -k -s -u root:icinga -H 'Accept: application/json' -X PUT 'https://localhost:5665/v1/objects/hosts/example.localdomain' \ - -d '{ "attrs": { "address": "192.168.1.1", "vars.os" : "Linux" } }' \ - | python -m json.tool + -d '{ "attrs": { "address": "192.168.1.1", "vars.os" : "Linux" }, "pretty": true }' { "results": [ { @@ -668,8 +673,7 @@ If attributes are of the Dictionary type, you can also use the indexer format: The following example updates the `address` attribute and the custom attribute `os` for the `example.localdomain` host: $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/objects/hosts/example.localdomain' \ - -d '{ "attrs": { "address": "192.168.1.2", "vars.os" : "Windows" } }' \ - | python -m json.tool + -d '{ "attrs": { "address": "192.168.1.2", "vars.os" : "Windows" }, "pretty": true }' { "results": [ { @@ -695,7 +699,7 @@ In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters Example for deleting the host object `example.localdomain`: - $ curl -k -s -u root:icinga -H 'Accept: application/json' -X DELETE 'https://localhost:5665/v1/objects/hosts/example.localdomain?cascade=1' | python -m json.tool + $ curl -k -s -u root:icinga -H 'Accept: application/json' -X DELETE 'https://localhost:5665/v1/objects/hosts/example.localdomain?cascade=1&pretty=1' { "results": [ { @@ -813,7 +817,7 @@ In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters Example for the service `passive-ping6`: $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/process-check-result?service=example.localdomain!passive-ping6' \ - -d '{ "exit_status": 2, "plugin_output": "PING CRITICAL - Packet loss = 100%", "performance_data": [ "rta=5000.000000ms;3000.000000;5000.000000;0.000000", "pl=100%;80;100;0" ], "check_source": "example.localdomain" }' | python -m json.tool + -d '{ "exit_status": 2, "plugin_output": "PING CRITICAL - Packet loss = 100%", "performance_data": [ "rta=5000.000000ms;3000.000000;5000.000000;0.000000", "pl=100%;80;100;0" ], "check_source": "example.localdomain", "pretty": true }' { "results": [ @@ -855,7 +859,7 @@ The example reschedules all services with the name "ping6" to immediately perfor allowed for the service (`force_check=true`). $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/reschedule-check' \ - -d '{ "type": "Service", "filter": "service.name==\"ping6\"", "force_check": true }' | python -m json.tool + -d '{ "type": "Service", "filter": "service.name==\"ping6\"", "force_check": true, "pretty": true }' { "results": [ @@ -886,7 +890,7 @@ Example for a custom host notification announcing a global maintenance to host owners: $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/send-custom-notification' \ - -d '{ "type": "Host", "author": "icingaadmin", "comment": "System is going down for maintenance", "force": true }' | python -m json.tool + -d '{ "type": "Host", "author": "icingaadmin", "comment": "System is going down for maintenance", "force": true, "pretty": true }' { "results": [ @@ -918,7 +922,7 @@ In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters Example: $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/delay-notification' \ - -d '{ "type": "Service", "timestamp": 1446389894 }' | python -m json.tool + -d '{ "type": "Service", "timestamp": 1446389894, "pretty": true }' { "results": [ @@ -955,7 +959,7 @@ The following example acknowledges all services which are in a hard critical sta a notification for them: $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/acknowledge-problem?type=Service&filter=service.state==2&service.state_type=1' \ - -d '{ "author": "icingaadmin", "comment": "Global outage. Working on it.", "notify": true }' | python -m json.tool + -d '{ "author": "icingaadmin", "comment": "Global outage. Working on it.", "notify": true, "pretty": true }' { "results": [ @@ -981,7 +985,7 @@ A [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid ty The example removes all service acknowledgements: - $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-acknowledgement?type=Service' | python -m json.tool + $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-acknowledgement?type=Service&pretty=1' { "results": [ @@ -1010,7 +1014,7 @@ In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters The following example adds a comment for all `ping4` services: - $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/add-comment?type=Service&filter=service.name==%22ping4%22' -d '{ "author": "icingaadmin", "comment": "Troubleticket #123456789 opened." }' | python -m json.tool + $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/add-comment?type=Service&filter=service.name==%22ping4%22' -d '{ "author": "icingaadmin", "comment": "Troubleticket #123456789 opened.", "pretty": true }' { "results": [ { @@ -1041,7 +1045,7 @@ A [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid ty Example for a simple filter using the `comment` URL parameter: - $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-comment?comment=example2.localdomain!ping4!mbmif.local-1446986367-0' | python -m json.tool + $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-comment?comment=example2.localdomain!ping4!mbmif.local-1446986367-0&pretty=1' { "results": [ { @@ -1053,7 +1057,7 @@ Example for a simple filter using the `comment` URL parameter: Example for removing all service comments using a service name filter for `ping4`: - $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-comment?filter=service.name==%22ping4%22&type=Service' | python -m json.tool + $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-comment?filter=service.name==%22ping4%22&type=Service&pretty=1' { "results": [ { @@ -1089,7 +1093,7 @@ In addition to these parameters a [filter](12-icinga2-api.md#icinga2-api-filters Example: - $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/schedule-downtime?type=Service&filter=service.name==%22ping4%22' -d '{ "start_time": 1446388806, "end_time": 1446389806, "duration": 1000, "author": "icingaadmin", "comment": "IPv4 network maintenance" }' | python -m json.tool + $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/schedule-downtime?type=Service&filter=service.name==%22ping4%22' -d '{ "start_time": 1446388806, "end_time": 1446389806, "duration": 1000, "author": "icingaadmin", "comment": "IPv4 network maintenance", "pretty": true }' { "results": [ { @@ -1120,7 +1124,7 @@ A [filter](12-icinga2-api.md#icinga2-api-filters) must be provided. The valid ty Example for a simple filter using the `downtime` URL parameter: - $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-downtime?downtime=example.localdomain!ping4!mbmif.local-1446979168-6' | python -m json.tool + $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-downtime?downtime=example.localdomain!ping4!mbmif.local-1446979168-6&pretty=1' { "results": [ { @@ -1132,7 +1136,7 @@ Example for a simple filter using the `downtime` URL parameter: Example for removing all host downtimes using a host name filter for `example.localdomain`: - $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-downtime?filter=host.name==%22example.localdomain%22&type=Host' | python -m json.tool + $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/remove-downtime?filter=host.name==%22example.localdomain%22&type=Host&pretty=1' { "results": [ { @@ -1152,8 +1156,9 @@ filter variables explained in the [advanced filters](12-icinga2-api.md#icinga2-a "filter_vars": { "filterHost": "example.localdomain", "filterAuthor": "icingaadmin" - } - }' | python -m json.tool + }, + "pretty": true + }' { "results": [ @@ -1174,7 +1179,7 @@ This action does not support a target type or filter. Example: - $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/shutdown-process' | python -m json.tool + $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/shutdown-process?pretty=1' { "results": [ @@ -1195,7 +1200,7 @@ This action does not support a target type or filter. Example: - $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/restart-process' | python -m json.tool + $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/restart-process?pretty=1' { "results": [ @@ -1220,7 +1225,7 @@ Send a `POST` request to the URL endpoint `/v1/actions/generate-ticket`. Example: $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/generate-ticket' \ - -d '{ "cn": "icinga2-client1.localdomain" }' | python -m json.tool + -d '{ "cn": "icinga2-client1.localdomain", "pretty": true }' { "results": [ { @@ -1431,7 +1436,7 @@ Send a `GET` request to the URL endpoint `/v1/status` to retrieve status informa Example: - $ curl -k -s -u root:icinga 'https://localhost:5665/v1/status' | python -m json.tool + $ curl -k -s -u root:icinga 'https://localhost:5665/v1/status?pretty=1' { "results": [ { @@ -1451,7 +1456,7 @@ Example: You can limit the output by specifying a status type in the URL, e.g. `IcingaApplication`: - $ curl -k -s -u root:icinga 'https://localhost:5665/v1/status/IcingaApplication' | python -m json.tool + $ curl -k -s -u root:icinga 'https://localhost:5665/v1/status/IcingaApplication?pretty=1' { "results": [ { @@ -1494,7 +1499,7 @@ Send a `POST` request to a new config package called `example-cmdb` in this exam will create a new empty configuration package. $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST \ - 'https://localhost:5665/v1/config/packages/example-cmdb' | python -m json.tool + 'https://localhost:5665/v1/config/packages/example-cmdb?pretty=1' { "results": [ { @@ -1539,8 +1544,8 @@ directory. Note: This example contains an error (`chec_command`). This is intentional. $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST \ - -d '{ "files": { "conf.d/test.conf": "object Host \"cmdb-host\" { chec_command = \"dummy\" }" } }' \ - 'https://localhost:5665/v1/config/stages/example-cmdb' | python -m json.tool + -d '{ "files": { "conf.d/test.conf": "object Host \"cmdb-host\" { chec_command = \"dummy\" }" }, "pretty": true }' \ + 'https://localhost:5665/v1/config/stages/example-cmdb' { "results": [ { @@ -1583,7 +1588,7 @@ A list of packages and their stages can be retrieved by sending a `GET` request The following example contains one configuration package `example-cmdb`. The package does not currently have an active stage. - $ curl -k -s -u root:icinga 'https://localhost:5665/v1/config/packages' | python -m json.tool + $ curl -k -s -u root:icinga 'https://localhost:5665/v1/config/packages?pretty=1' { "results": [ { @@ -1603,7 +1608,7 @@ In order to retrieve a list of files for a stage you can send a `GET` request to the URL endpoint `/v1/config/stages`. You need to include the package name (`example-cmdb`) and stage name (`example.localdomain-1441625839-0`) in the URL: - $ curl -k -s -u root:icinga 'https://localhost:5665/v1/config/stages/example-cmdb/example.localdomain-1441625839-0' | python -m json.tool + $ curl -k -s -u root:icinga 'https://localhost:5665/v1/config/stages/example-cmdb/example.localdomain-1441625839-0?pretty=1' { "results": [ ... @@ -1684,7 +1689,7 @@ The following example removes the failed configuration stage `example.localdomai in the `example-cmdb` configuration package: $ curl -k -s -u root:icinga -H 'Accept: application/json' -X DELETE \ - 'https://localhost:5665/v1/config/stages/example-cmdb/example.localdomain-1441133065-1' | python -m json.tool + 'https://localhost:5665/v1/config/stages/example-cmdb/example.localdomain-1441133065-1?pretty=1' { "results": [ { @@ -1704,7 +1709,7 @@ with the package name in the URL path. This example entirely deletes the configuration package `example-cmdb`: $ curl -k -s -u root:icinga -H 'Accept: application/json' -X DELETE \ - 'https://localhost:5665/v1/config/packages/example-cmdb' | python -m json.tool + 'https://localhost:5665/v1/config/packages/example-cmdb?pretty=1' { "results": [ { @@ -1734,7 +1739,7 @@ Each response entry in the results array contains the following attributes: In order to view a specific configuration object type specify its name inside the URL path: - $ curl -k -s -u root:icinga 'https://localhost:5665/v1/types/Object' | python -m json.tool + $ curl -k -s -u root:icinga 'https://localhost:5665/v1/types/Object?pretty=1' { "results": [ { @@ -1791,7 +1796,7 @@ If you specify a session identifier, the same script context can be reused for m Example for fetching the command line from the local host's last check result: - $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/console/execute-script?command=get_host(NodeName).last_check_result.command&sandboxed=0&session=bb75fd7c-c686-407d-9688-582c04227756' | python -m json.tool + $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/console/execute-script?command=get_host(NodeName).last_check_result.command&sandboxed=0&session=bb75fd7c-c686-407d-9688-582c04227756&pretty=1' { "results": [ { @@ -1813,7 +1818,7 @@ Example for fetching the command line from the local host's last check result: Example for fetching auto-completion suggestions for the `Host.` type. This works in a similar fashion when pressing TAB inside the [console CLI command](11-cli-commands.md#cli-command-console): - $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/console/auto-complete-script?command=Host.&sandboxed=0&session=bb75fd7c-c686-407d-9688-582c04227756' | python -m json.tool + $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/console/auto-complete-script?command=Host.&sandboxed=0&session=bb75fd7c-c686-407d-9688-582c04227756&pretty=1' { "results": [ { diff --git a/doc/15-troubleshooting.md b/doc/15-troubleshooting.md index f5473ff75..c0fad94f6 100644 --- a/doc/15-troubleshooting.md +++ b/doc/15-troubleshooting.md @@ -296,7 +296,7 @@ on the name: ``` $ curl -k -s -u root:icinga -H 'Accept: application/json' -H 'X-HTTP-Method-Override: GET' -X POST 'https://localhost:5665/v1/objects/services' \ --d '{ "filter": "regex(pattern, service.name)", "filter_vars": { "pattern": "^http" }, "attrs": [ "__name", "last_check_result" ] }' | python -m json.tool +-d '{ "filter": "regex(pattern, service.name)", "filter_vars": { "pattern": "^http" }, "attrs": [ "__name", "last_check_result" ], "pretty": true }' { "results": [ { @@ -388,7 +388,7 @@ Example for retrieving the check source from all `disk` services using a ``` $ curl -k -s -u root:icinga -H 'Accept: application/json' -H 'X-HTTP-Method-Override: GET' -X POST 'https://localhost:5665/v1/objects/services' \ --d '{ "filter": "regex(pattern, service.name)", "filter_vars": { "pattern": "^disk" }, "attrs": [ "__name", "last_check_result" ] }' | python -m json.tool +-d '{ "filter": "regex(pattern, service.name)", "filter_vars": { "pattern": "^disk" }, "attrs": [ "__name", "last_check_result" ], "pretty": true }' { "results": [ { @@ -547,7 +547,7 @@ The REST API provides the [status](12-icinga2-api.md#icinga2-api-status) URL end on Icinga and its features. ``` -# curl -k -s -u root:icinga 'https://localhost:5665/v1/status' | python -m json.tool | less +# curl -k -s -u root:icinga 'https://localhost:5665/v1/status?pretty=1' | less ``` You can also calculate late check results via the REST API: diff --git a/lib/remote/actionshandler.cpp b/lib/remote/actionshandler.cpp index 8ddeb7a16..7663d02be 100644 --- a/lib/remote/actionshandler.cpp +++ b/lib/remote/actionshandler.cpp @@ -44,7 +44,7 @@ bool ActionsHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& reques ApiAction::Ptr action = ApiAction::GetByName(actionName); if (!action) { - HttpUtility::SendJsonError(response, 404, "Action '" + actionName + "' does not exist."); + HttpUtility::SendJsonError(response, params, 404, "Action '" + actionName + "' does not exist."); return true; } @@ -62,7 +62,7 @@ bool ActionsHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& reques try { objs = FilterUtility::GetFilterTargets(qd, params, user); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, 404, + HttpUtility::SendJsonError(response, params, 404, "No objects found.", HttpUtility::GetLastParameter(params, "verboseErrors") ? DiagnosticInformation(ex) : ""); return true; @@ -94,7 +94,7 @@ bool ActionsHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& reques result->Set("results", results); response.SetStatus(200, "OK"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); return true; } diff --git a/lib/remote/configfileshandler.cpp b/lib/remote/configfileshandler.cpp index 3ca2e686e..77acb96b6 100644 --- a/lib/remote/configfileshandler.cpp +++ b/lib/remote/configfileshandler.cpp @@ -48,7 +48,7 @@ bool ConfigFilesHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re } if (request.Headers->Get("accept") == "application/json") { - HttpUtility::SendJsonError(response, 400, "Invalid Accept header. Either remove the Accept header or set it to 'application/octet-stream'."); + HttpUtility::SendJsonError(response, params, 400, "Invalid Accept header. Either remove the Accept header or set it to 'application/octet-stream'."); return true; } @@ -58,26 +58,26 @@ bool ConfigFilesHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re String stageName = HttpUtility::GetLastParameter(params, "stage"); if (!ConfigPackageUtility::ValidateName(packageName)) { - HttpUtility::SendJsonError(response, 400, "Invalid package name."); + HttpUtility::SendJsonError(response, params, 400, "Invalid package name."); return true; } if (!ConfigPackageUtility::ValidateName(stageName)) { - HttpUtility::SendJsonError(response, 400, "Invalid stage name."); + HttpUtility::SendJsonError(response, params, 400, "Invalid stage name."); return true; } String relativePath = HttpUtility::GetLastParameter(params, "path"); if (ConfigPackageUtility::ContainsDotDot(relativePath)) { - HttpUtility::SendJsonError(response, 400, "Path contains '..' (not allowed)."); + HttpUtility::SendJsonError(response, params, 400, "Path contains '..' (not allowed)."); return true; } String path = ConfigPackageUtility::GetPackageDir() + "/" + packageName + "/" + stageName + "/" + relativePath; if (!Utility::PathExists(path)) { - HttpUtility::SendJsonError(response, 404, "Path not found."); + HttpUtility::SendJsonError(response, params, 404, "Path not found."); return true; } @@ -90,7 +90,7 @@ bool ConfigFilesHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re response.AddHeader("Content-Type", "application/octet-stream"); response.WriteBody(content.CStr(), content.GetLength()); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, 500, "Could not read file.", + HttpUtility::SendJsonError(response, params, 500, "Could not read file.", HttpUtility::GetLastParameter(params, "verboseErrors") ? DiagnosticInformation(ex) : ""); } diff --git a/lib/remote/configpackageshandler.cpp b/lib/remote/configpackageshandler.cpp index ca6d3bc2e..68cb5dd9d 100644 --- a/lib/remote/configpackageshandler.cpp +++ b/lib/remote/configpackageshandler.cpp @@ -34,7 +34,7 @@ bool ConfigPackagesHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& return false; if (request.RequestMethod == "GET") - HandleGet(user, request, response); + HandleGet(user, request, response, params); else if (request.RequestMethod == "POST") HandlePost(user, request, response, params); else if (request.RequestMethod == "DELETE") @@ -45,7 +45,7 @@ bool ConfigPackagesHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& return true; } -void ConfigPackagesHandler::HandleGet(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response) +void ConfigPackagesHandler::HandleGet(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response, const Dictionary::Ptr& params) { FilterUtility::CheckPermission(user, "config/query"); @@ -68,7 +68,7 @@ void ConfigPackagesHandler::HandleGet(const ApiUser::Ptr& user, HttpRequest& req result->Set("results", results); response.SetStatus(200, "OK"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); } void ConfigPackagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response, const Dictionary::Ptr& params) @@ -81,7 +81,7 @@ void ConfigPackagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& re String packageName = HttpUtility::GetLastParameter(params, "package"); if (!ConfigPackageUtility::ValidateName(packageName)) { - HttpUtility::SendJsonError(response, 400, "Invalid package name."); + HttpUtility::SendJsonError(response, params, 400, "Invalid package name."); return; } @@ -91,7 +91,7 @@ void ConfigPackagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& re boost::mutex::scoped_lock lock(ConfigPackageUtility::GetStaticMutex()); ConfigPackageUtility::CreatePackage(packageName); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, 500, "Could not create package.", + HttpUtility::SendJsonError(response, params, 500, "Could not create package.", HttpUtility::GetLastParameter(params, "verboseErrors") ? DiagnosticInformation(ex) : ""); return; } @@ -106,7 +106,7 @@ void ConfigPackagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& re result->Set("results", results); response.SetStatus(200, "OK"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); } void ConfigPackagesHandler::HandleDelete(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response, const Dictionary::Ptr& params) @@ -119,7 +119,7 @@ void ConfigPackagesHandler::HandleDelete(const ApiUser::Ptr& user, HttpRequest& String packageName = HttpUtility::GetLastParameter(params, "package"); if (!ConfigPackageUtility::ValidateName(packageName)) { - HttpUtility::SendJsonError(response, 400, "Invalid package name."); + HttpUtility::SendJsonError(response, params, 400, "Invalid package name."); return; } @@ -148,6 +148,6 @@ void ConfigPackagesHandler::HandleDelete(const ApiUser::Ptr& user, HttpRequest& result->Set("results", results); response.SetStatus(code, (code == 200) ? "OK" : "Internal Server Error"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); } diff --git a/lib/remote/configpackageshandler.hpp b/lib/remote/configpackageshandler.hpp index c57a33ee9..4663fbf18 100644 --- a/lib/remote/configpackageshandler.hpp +++ b/lib/remote/configpackageshandler.hpp @@ -35,7 +35,7 @@ public: private: void HandleGet(const ApiUser::Ptr& user, HttpRequest& request, - HttpResponse& response); + HttpResponse& response, const Dictionary::Ptr& params); void HandlePost(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response, const Dictionary::Ptr& params); void HandleDelete(const ApiUser::Ptr& user, HttpRequest& request, diff --git a/lib/remote/configstageshandler.cpp b/lib/remote/configstageshandler.cpp index 52756a4c6..56110a71a 100644 --- a/lib/remote/configstageshandler.cpp +++ b/lib/remote/configstageshandler.cpp @@ -60,10 +60,10 @@ void ConfigStagesHandler::HandleGet(const ApiUser::Ptr& user, HttpRequest& reque String stageName = HttpUtility::GetLastParameter(params, "stage"); if (!ConfigPackageUtility::ValidateName(packageName)) - return HttpUtility::SendJsonError(response, 400, "Invalid package name."); + return HttpUtility::SendJsonError(response, params, 400, "Invalid package name."); if (!ConfigPackageUtility::ValidateName(stageName)) - return HttpUtility::SendJsonError(response, 400, "Invalid stage name."); + return HttpUtility::SendJsonError(response, params, 400, "Invalid stage name."); Array::Ptr results = new Array(); @@ -83,7 +83,7 @@ void ConfigStagesHandler::HandleGet(const ApiUser::Ptr& user, HttpRequest& reque result->Set("results", results); response.SetStatus(200, "OK"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); } void ConfigStagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response, const Dictionary::Ptr& params) @@ -96,7 +96,7 @@ void ConfigStagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& requ String packageName = HttpUtility::GetLastParameter(params, "package"); if (!ConfigPackageUtility::ValidateName(packageName)) - return HttpUtility::SendJsonError(response, 400, "Invalid package name."); + return HttpUtility::SendJsonError(response, params, 400, "Invalid package name."); bool reload = true; if (params->Contains("reload")) @@ -116,7 +116,7 @@ void ConfigStagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& requ /* validate the config. on success, activate stage and reload */ ConfigPackageUtility::AsyncTryActivateStage(packageName, stageName, reload); } catch (const std::exception& ex) { - return HttpUtility::SendJsonError(response, 500, + return HttpUtility::SendJsonError(response, params, 500, "Stage creation failed.", HttpUtility::GetLastParameter(params, "verboseErrors") ? DiagnosticInformation(ex) : ""); } @@ -138,7 +138,7 @@ void ConfigStagesHandler::HandlePost(const ApiUser::Ptr& user, HttpRequest& requ result->Set("results", results); response.SetStatus(200, "OK"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); } void ConfigStagesHandler::HandleDelete(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response, const Dictionary::Ptr& params) @@ -155,15 +155,15 @@ void ConfigStagesHandler::HandleDelete(const ApiUser::Ptr& user, HttpRequest& re String stageName = HttpUtility::GetLastParameter(params, "stage"); if (!ConfigPackageUtility::ValidateName(packageName)) - return HttpUtility::SendJsonError(response, 400, "Invalid package name."); + return HttpUtility::SendJsonError(response, params, 400, "Invalid package name."); if (!ConfigPackageUtility::ValidateName(stageName)) - return HttpUtility::SendJsonError(response, 400, "Invalid stage name."); + return HttpUtility::SendJsonError(response, params, 400, "Invalid stage name."); try { ConfigPackageUtility::DeleteStage(packageName, stageName); } catch (const std::exception& ex) { - return HttpUtility::SendJsonError(response, 500, + return HttpUtility::SendJsonError(response, params, 500, "Failed to delete stage.", HttpUtility::GetLastParameter(params, "verboseErrors") ? DiagnosticInformation(ex) : ""); } @@ -180,6 +180,6 @@ void ConfigStagesHandler::HandleDelete(const ApiUser::Ptr& user, HttpRequest& re result->Set("results", results); response.SetStatus(200, "OK"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); } diff --git a/lib/remote/consolehandler.cpp b/lib/remote/consolehandler.cpp index 13f957b96..575db34bd 100644 --- a/lib/remote/consolehandler.cpp +++ b/lib/remote/consolehandler.cpp @@ -94,16 +94,16 @@ bool ConsoleHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& reques bool sandboxed = HttpUtility::GetLastParameter(params, "sandboxed"); if (methodName == "execute-script") - return ExecuteScriptHelper(request, response, command, session, sandboxed); + return ExecuteScriptHelper(request, response, params, command, session, sandboxed); else if (methodName == "auto-complete-script") - return AutocompleteScriptHelper(request, response, command, session, sandboxed); + return AutocompleteScriptHelper(request, response, params, command, session, sandboxed); - HttpUtility::SendJsonError(response, 400, "Invalid method specified: " + methodName); + HttpUtility::SendJsonError(response, params, 400, "Invalid method specified: " + methodName); return true; } bool ConsoleHandler::ExecuteScriptHelper(HttpRequest& request, HttpResponse& response, - const String& command, const String& session, bool sandboxed) + const Dictionary::Ptr& params, const String& command, const String& session, bool sandboxed) { Log(LogNotice, "Console") << "Executing expression: " << command; @@ -168,13 +168,13 @@ bool ConsoleHandler::ExecuteScriptHelper(HttpRequest& request, HttpResponse& res result->Set("results", results); response.SetStatus(200, "OK"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); return true; } bool ConsoleHandler::AutocompleteScriptHelper(HttpRequest& request, HttpResponse& response, - const String& command, const String& session, bool sandboxed) + const Dictionary::Ptr& params, const String& command, const String& session, bool sandboxed) { Log(LogInformation, "Console") << "Auto-completing expression: " << command; @@ -205,7 +205,7 @@ bool ConsoleHandler::AutocompleteScriptHelper(HttpRequest& request, HttpResponse result->Set("results", results); response.SetStatus(200, "OK"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); return true; } diff --git a/lib/remote/consolehandler.hpp b/lib/remote/consolehandler.hpp index 6e63c0c77..762cb83d4 100644 --- a/lib/remote/consolehandler.hpp +++ b/lib/remote/consolehandler.hpp @@ -46,9 +46,9 @@ public: private: static bool ExecuteScriptHelper(HttpRequest& request, HttpResponse& response, - const String& command, const String& session, bool sandboxed); + const Dictionary::Ptr& params, const String& command, const String& session, bool sandboxed); static bool AutocompleteScriptHelper(HttpRequest& request, HttpResponse& response, - const String& command, const String& session, bool sandboxed); + const Dictionary::Ptr& params, const String& command, const String& session, bool sandboxed); }; diff --git a/lib/remote/createobjecthandler.cpp b/lib/remote/createobjecthandler.cpp index d0a846d62..6455a8af6 100644 --- a/lib/remote/createobjecthandler.cpp +++ b/lib/remote/createobjecthandler.cpp @@ -43,7 +43,7 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r Type::Ptr type = FilterUtility::TypeFromPluralName(request.RequestUrl->GetPath()[2]); if (!type) { - HttpUtility::SendJsonError(response, 400, "Invalid type specified."); + HttpUtility::SendJsonError(response, params, 400, "Invalid type specified."); return true; } @@ -98,7 +98,7 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r result1->Set("status", "Object could not be created."); response.SetStatus(500, "Object could not be created"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); return true; } @@ -109,7 +109,7 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r result1->Set("status", "Object could not be created."); response.SetStatus(500, "Object could not be created"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); return true; } @@ -125,7 +125,7 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r result1->Set("status", "Object was not created but 'ignore_on_error' was set to true"); response.SetStatus(200, "OK"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); return true; } diff --git a/lib/remote/deleteobjecthandler.cpp b/lib/remote/deleteobjecthandler.cpp index 3ccdd60e9..daa5685e3 100644 --- a/lib/remote/deleteobjecthandler.cpp +++ b/lib/remote/deleteobjecthandler.cpp @@ -43,7 +43,7 @@ bool DeleteObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r Type::Ptr type = FilterUtility::TypeFromPluralName(request.RequestUrl->GetPath()[2]); if (!type) { - HttpUtility::SendJsonError(response, 400, "Invalid type specified."); + HttpUtility::SendJsonError(response, params, 400, "Invalid type specified."); return true; } @@ -64,7 +64,7 @@ bool DeleteObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r try { objs = FilterUtility::GetFilterTargets(qd, params, user); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, 404, + HttpUtility::SendJsonError(response, params, 404, "No objects found.", HttpUtility::GetLastParameter(params, "verboseErrors") ? DiagnosticInformation(ex) : ""); return true; @@ -103,7 +103,7 @@ bool DeleteObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r else response.SetStatus(200, "OK"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); return true; } diff --git a/lib/remote/eventshandler.cpp b/lib/remote/eventshandler.cpp index 5b5e827c6..bfdca28dc 100644 --- a/lib/remote/eventshandler.cpp +++ b/lib/remote/eventshandler.cpp @@ -39,14 +39,14 @@ bool EventsHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& request return false; if (request.ProtocolVersion == HttpVersion10) { - HttpUtility::SendJsonError(response, 400, "HTTP/1.0 not supported for event streams."); + HttpUtility::SendJsonError(response, params, 400, "HTTP/1.0 not supported for event streams."); return true; } Array::Ptr types = params->Get("types"); if (!types) { - HttpUtility::SendJsonError(response, 400, "'types' query parameter is required."); + HttpUtility::SendJsonError(response, params, 400, "'types' query parameter is required."); return true; } @@ -60,7 +60,7 @@ bool EventsHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& request String queueName = HttpUtility::GetLastParameter(params, "queue"); if (queueName.IsEmpty()) { - HttpUtility::SendJsonError(response, 400, "'queue' query parameter is required."); + HttpUtility::SendJsonError(response, params, 400, "'queue' query parameter is required."); return true; } diff --git a/lib/remote/httphandler.cpp b/lib/remote/httphandler.cpp index ed753f373..e8fa64427 100644 --- a/lib/remote/httphandler.cpp +++ b/lib/remote/httphandler.cpp @@ -100,7 +100,7 @@ void HttpHandler::ProcessRequest(const ApiUser::Ptr& user, HttpRequest& request, try { params = HttpUtility::FetchRequestParameters(request); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, 400, "Invalid request body: " + DiagnosticInformation(ex, false)); + HttpUtility::SendJsonError(response, params, 400, "Invalid request body: " + DiagnosticInformation(ex, false)); return; } @@ -114,7 +114,7 @@ void HttpHandler::ProcessRequest(const ApiUser::Ptr& user, HttpRequest& request, if (!processed) { String path = boost::algorithm::join(request.RequestUrl->GetPath(), "/"); - HttpUtility::SendJsonError(response, 404, "The requested path '" + path + + HttpUtility::SendJsonError(response, params, 404, "The requested path '" + path + "' could not be found or the request method is not valid for this path."); return; } diff --git a/lib/remote/httpserverconnection.cpp b/lib/remote/httpserverconnection.cpp index abc5a23b2..ce3bcd22c 100644 --- a/lib/remote/httpserverconnection.cpp +++ b/lib/remote/httpserverconnection.cpp @@ -231,7 +231,7 @@ void HttpServerConnection::ProcessMessageAsync(HttpRequest& request) result->Set("error", 401); result->Set("status", "Unauthorized. Please check your user credentials."); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, nullptr, result); } else { response.AddHeader("Content-Type", "text/html"); String msg = "

Unauthorized. Please check your user credentials.

"; @@ -253,7 +253,7 @@ void HttpServerConnection::ProcessMessageAsync(HttpRequest& request) result->Set("error", 503); result->Set("status", errorInfo); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, nullptr, result); } else { response.AddHeader("Content-Type", "text/plain"); response.WriteBody(errorInfo.CStr(), errorInfo.GetLength()); diff --git a/lib/remote/httputility.cpp b/lib/remote/httputility.cpp index a911e8c7b..7b0fa8e3c 100644 --- a/lib/remote/httputility.cpp +++ b/lib/remote/httputility.cpp @@ -53,11 +53,17 @@ Dictionary::Ptr HttpUtility::FetchRequestParameters(HttpRequest& request) return result; } -void HttpUtility::SendJsonBody(HttpResponse& response, const Value& val) +void HttpUtility::SendJsonBody(HttpResponse& response, const Dictionary::Ptr& params, const Value& val) { response.AddHeader("Content-Type", "application/json"); - String body = JsonEncode(val); + bool prettyPrint = false; + + if (params) + prettyPrint = GetLastParameter(params, "pretty"); + + String body = JsonEncode(val, prettyPrint); + response.WriteBody(body.CStr(), body.GetLength()); } @@ -76,17 +82,20 @@ Value HttpUtility::GetLastParameter(const Dictionary::Ptr& params, const String& return arr->Get(arr->GetLength() - 1); } -void HttpUtility::SendJsonError(HttpResponse& response, const int code, - const String& info, const String& diagnosticInformation) +void HttpUtility::SendJsonError(HttpResponse& response, const Dictionary::Ptr& params, + int code, const String& info, const String& diagnosticInformation) { Dictionary::Ptr result = new Dictionary(); response.SetStatus(code, HttpUtility::GetErrorNameByCode(code)); result->Set("error", code); + if (!info.IsEmpty()) result->Set("status", info); + if (!diagnosticInformation.IsEmpty()) result->Set("diagnostic information", diagnosticInformation); - HttpUtility::SendJsonBody(response, result); + + HttpUtility::SendJsonBody(response, params, result); } String HttpUtility::GetErrorNameByCode(const int code) diff --git a/lib/remote/httputility.hpp b/lib/remote/httputility.hpp index bebc4f684..2bc3690d8 100644 --- a/lib/remote/httputility.hpp +++ b/lib/remote/httputility.hpp @@ -37,9 +37,9 @@ class HttpUtility public: static Dictionary::Ptr FetchRequestParameters(HttpRequest& request); - static void SendJsonBody(HttpResponse& response, const Value& val); + static void SendJsonBody(HttpResponse& response, const Dictionary::Ptr& params, const Value& val); static Value GetLastParameter(const Dictionary::Ptr& params, const String& key); - static void SendJsonError(HttpResponse& response, const int code, + static void SendJsonError(HttpResponse& response, const Dictionary::Ptr& params, const int code, const String& verbose = String(), const String& diagnosticInformation = String()); private: diff --git a/lib/remote/infohandler.cpp b/lib/remote/infohandler.cpp index 754948d33..c36546453 100644 --- a/lib/remote/infohandler.cpp +++ b/lib/remote/infohandler.cpp @@ -80,7 +80,7 @@ bool InfoHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, Dictionary::Ptr result = new Dictionary(); result->Set("results", results); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); } else { response.AddHeader("Content-Type", "text/html"); diff --git a/lib/remote/modifyobjecthandler.cpp b/lib/remote/modifyobjecthandler.cpp index d1339e959..65e59fcf0 100644 --- a/lib/remote/modifyobjecthandler.cpp +++ b/lib/remote/modifyobjecthandler.cpp @@ -41,7 +41,7 @@ bool ModifyObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r Type::Ptr type = FilterUtility::TypeFromPluralName(request.RequestUrl->GetPath()[2]); if (!type) { - HttpUtility::SendJsonError(response, 400, "Invalid type specified."); + HttpUtility::SendJsonError(response, params, 400, "Invalid type specified."); return true; } @@ -62,7 +62,7 @@ bool ModifyObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r try { objs = FilterUtility::GetFilterTargets(qd, params, user); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, 404, + HttpUtility::SendJsonError(response, params, 404, "No objects found.", HttpUtility::GetLastParameter(params, "verboseErrors") ? DiagnosticInformation(ex) : ""); return true; @@ -71,7 +71,7 @@ bool ModifyObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r Value attrsVal = params->Get("attrs"); if (attrsVal.GetReflectionType() != Dictionary::TypeInstance) { - HttpUtility::SendJsonError(response, 400, + HttpUtility::SendJsonError(response, params, 400, "Invalid type for 'attrs' attribute specified. Dictionary type is required.", Empty); return true; } @@ -111,7 +111,7 @@ bool ModifyObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r result->Set("results", results); response.SetStatus(200, "OK"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); return true; } diff --git a/lib/remote/objectqueryhandler.cpp b/lib/remote/objectqueryhandler.cpp index f687b104b..90520a9e6 100644 --- a/lib/remote/objectqueryhandler.cpp +++ b/lib/remote/objectqueryhandler.cpp @@ -115,7 +115,7 @@ bool ObjectQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re Type::Ptr type = FilterUtility::TypeFromPluralName(request.RequestUrl->GetPath()[2]); if (!type) { - HttpUtility::SendJsonError(response, 400, "Invalid type specified."); + HttpUtility::SendJsonError(response, params, 400, "Invalid type specified."); return true; } @@ -128,7 +128,7 @@ bool ObjectQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re try { uattrs = params->Get("attrs"); } catch (const std::exception&) { - HttpUtility::SendJsonError(response, 400, + HttpUtility::SendJsonError(response, params, 400, "Invalid type for 'attrs' attribute specified. Array type is required.", Empty); return true; } @@ -136,7 +136,7 @@ bool ObjectQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re try { ujoins = params->Get("joins"); } catch (const std::exception&) { - HttpUtility::SendJsonError(response, 400, + HttpUtility::SendJsonError(response, params, 400, "Invalid type for 'joins' attribute specified. Array type is required.", Empty); return true; } @@ -144,7 +144,7 @@ bool ObjectQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re try { umetas = params->Get("meta"); } catch (const std::exception&) { - HttpUtility::SendJsonError(response, 400, + HttpUtility::SendJsonError(response, params, 400, "Invalid type for 'meta' attribute specified. Array type is required.", Empty); return true; } @@ -164,7 +164,7 @@ bool ObjectQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re try { objs = FilterUtility::GetFilterTargets(qd, params, user); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, 404, + HttpUtility::SendJsonError(response, params, 404, "No objects found.", HttpUtility::GetLastParameter(params, "verboseErrors") ? DiagnosticInformation(ex) : ""); return true; @@ -234,7 +234,7 @@ bool ObjectQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re dinfo->Set("last_column", di.LastColumn); metaAttrs->Set("location", dinfo); } else { - HttpUtility::SendJsonError(response, 400, "Invalid field specified for meta: " + meta); + HttpUtility::SendJsonError(response, params, 400, "Invalid field specified for meta: " + meta); return true; } } @@ -243,7 +243,7 @@ bool ObjectQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re try { result1->Set("attrs", SerializeObjectAttrs(obj, String(), uattrs, false, false)); } catch (const ScriptError& ex) { - HttpUtility::SendJsonError(response, 400, ex.what()); + HttpUtility::SendJsonError(response, params, 400, ex.what()); return true; } @@ -255,14 +255,14 @@ bool ObjectQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re int fid = type->GetFieldId(joinAttr); if (fid < 0) { - HttpUtility::SendJsonError(response, 400, "Invalid field specified for join: " + joinAttr); + HttpUtility::SendJsonError(response, params, 400, "Invalid field specified for join: " + joinAttr); return true; } Field field = type->GetFieldInfo(fid); if (!(field.Attributes & FANavigation)) { - HttpUtility::SendJsonError(response, 400, "Not a joinable field: " + joinAttr); + HttpUtility::SendJsonError(response, params, 400, "Not a joinable field: " + joinAttr); return true; } @@ -276,7 +276,7 @@ bool ObjectQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re try { joins->Set(prefix, SerializeObjectAttrs(joinedObj, prefix, ujoins, true, allJoins)); } catch (const ScriptError& ex) { - HttpUtility::SendJsonError(response, 400, ex.what()); + HttpUtility::SendJsonError(response, params, 400, ex.what()); return true; } } @@ -286,7 +286,7 @@ bool ObjectQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re result->Set("results", results); response.SetStatus(200, "OK"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); return true; } diff --git a/lib/remote/statushandler.cpp b/lib/remote/statushandler.cpp index 03627f513..a489a3e25 100644 --- a/lib/remote/statushandler.cpp +++ b/lib/remote/statushandler.cpp @@ -104,7 +104,7 @@ bool StatusHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& request try { objs = FilterUtility::GetFilterTargets(qd, params, user); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, 404, + HttpUtility::SendJsonError(response, params, 404, "No objects found.", HttpUtility::GetLastParameter(params, "verboseErrors") ? DiagnosticInformation(ex) : ""); return true; @@ -116,7 +116,7 @@ bool StatusHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& request result->Set("results", results); response.SetStatus(200, "OK"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); return true; } diff --git a/lib/remote/templatequeryhandler.cpp b/lib/remote/templatequeryhandler.cpp index 6dd5b2d89..c8d101c1e 100644 --- a/lib/remote/templatequeryhandler.cpp +++ b/lib/remote/templatequeryhandler.cpp @@ -104,7 +104,7 @@ bool TemplateQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& Type::Ptr type = FilterUtility::TypeFromPluralName(request.RequestUrl->GetPath()[2]); if (!type) { - HttpUtility::SendJsonError(response, 400, "Invalid type specified."); + HttpUtility::SendJsonError(response, params, 400, "Invalid type specified."); return true; } @@ -126,7 +126,7 @@ bool TemplateQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& try { objs = FilterUtility::GetFilterTargets(qd, params, user, "tmpl"); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, 404, + HttpUtility::SendJsonError(response, params, 404, "No templates found.", HttpUtility::GetLastParameter(params, "verboseErrors") ? DiagnosticInformation(ex) : ""); return true; @@ -142,7 +142,7 @@ bool TemplateQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& result->Set("results", results); response.SetStatus(200, "OK"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); return true; } diff --git a/lib/remote/typequeryhandler.cpp b/lib/remote/typequeryhandler.cpp index 2a26e3be2..70427c2f2 100644 --- a/lib/remote/typequeryhandler.cpp +++ b/lib/remote/typequeryhandler.cpp @@ -90,7 +90,7 @@ bool TypeQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& requ try { objs = FilterUtility::GetFilterTargets(qd, params, user); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, 404, + HttpUtility::SendJsonError(response, params, 404, "No objects found.", HttpUtility::GetLastParameter(params, "verboseErrors") ? DiagnosticInformation(ex) : ""); return true; @@ -157,7 +157,7 @@ bool TypeQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& requ result->Set("results", results); response.SetStatus(200, "OK"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); return true; } diff --git a/lib/remote/variablequeryhandler.cpp b/lib/remote/variablequeryhandler.cpp index 416170962..6a601a4c2 100644 --- a/lib/remote/variablequeryhandler.cpp +++ b/lib/remote/variablequeryhandler.cpp @@ -96,7 +96,7 @@ bool VariableQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& try { objs = FilterUtility::GetFilterTargets(qd, params, user, "variable"); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, 404, + HttpUtility::SendJsonError(response, params, 404, "No variables found.", HttpUtility::GetLastParameter(params, "verboseErrors") ? DiagnosticInformation(ex) : ""); return true; @@ -118,7 +118,7 @@ bool VariableQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& result->Set("results", results); response.SetStatus(200, "OK"); - HttpUtility::SendJsonBody(response, result); + HttpUtility::SendJsonBody(response, params, result); return true; }