diff --git a/include/maxscale/service.h b/include/maxscale/service.h index d16a4d07e..2168191be 100644 --- a/include/maxscale/service.h +++ b/include/maxscale/service.h @@ -322,7 +322,18 @@ json_t* service_list_to_json(const char* host); * * @return Array of JSON format listeners */ -json_t* service_listeners_to_json(const SERVICE* service, const char* host); +json_t* service_listener_list_to_json(const SERVICE* service, const char* host); + +/** + * @brief Convert service listener to JSON + * + * @param service Service whose listener is converted + * @param name The name of the listener + * @param host Hostname of this server + * + * @return JSON format listener + */ +json_t* service_listener_to_json(const SERVICE* service, const char* name, const char* host); /** * @brief Get links to services that relate to a server diff --git a/server/core/resource.cc b/server/core/resource.cc index a4d469405..c48395d2a 100644 --- a/server/core/resource.cc +++ b/server/core/resource.cc @@ -410,10 +410,33 @@ HttpResponse cb_get_service(const HttpRequest& request) return HttpResponse(MHD_HTTP_INTERNAL_SERVER_ERROR, runtime_get_json_error()); } -HttpResponse cb_get_service_listeners(const HttpRequest& request) +HttpResponse cb_get_all_service_listeners(const HttpRequest& request) { SERVICE* service = service_find(request.uri_part(1).c_str()); - return HttpResponse(MHD_HTTP_OK, service_listeners_to_json(service, request.host())); + return HttpResponse(MHD_HTTP_OK, service_listener_list_to_json(service, request.host())); +} + +HttpResponse cb_get_service_listener(const HttpRequest& request) +{ + SERVICE* service = service_find(request.uri_part(1).c_str()); + + if (service) + { + std::string listener = request.uri_part(3); + + if (!service_has_named_listener(service, listener.c_str())) + { + return HttpResponse(MHD_HTTP_NOT_FOUND); + } + else + { + return HttpResponse(MHD_HTTP_OK, + service_listener_to_json(service, listener.c_str(), + request.host())); + } + } + + return HttpResponse(MHD_HTTP_INTERNAL_SERVER_ERROR, runtime_get_json_error()); } HttpResponse cb_all_filters(const HttpRequest& request) @@ -717,8 +740,10 @@ public: m_get.push_back(SResource(new Resource(cb_all_services, 1, "services"))); m_get.push_back(SResource(new Resource(cb_get_service, 2, "services", ":service"))); - m_get.push_back(SResource(new Resource(cb_get_service_listeners, 3, + m_get.push_back(SResource(new Resource(cb_get_all_service_listeners, 3, "services", ":service", "listeners"))); + m_get.push_back(SResource(new Resource(cb_get_service_listener, 4, + "services", ":service", "listeners", "?"))); m_get.push_back(SResource(new Resource(cb_all_filters, 1, "filters"))); m_get.push_back(SResource(new Resource(cb_get_filter, 2, "filters", ":filter"))); diff --git a/server/core/service.cc b/server/core/service.cc index e0dfa8ed9..caf8e20f8 100644 --- a/server/core/service.cc +++ b/server/core/service.cc @@ -2498,7 +2498,7 @@ static inline bool have_active_servers(const SERVICE* service) return false; } -json_t* service_listeners_json_data(const SERVICE* service) +static json_t* service_all_listeners_json_data(const SERVICE* service) { json_t* arr = json_array(); LISTENER_ITERATOR iter; @@ -2515,6 +2515,22 @@ json_t* service_listeners_json_data(const SERVICE* service) return arr; } +static json_t* service_listener_json_data(const SERVICE* service, const char* name) +{ + LISTENER_ITERATOR iter; + + for (SERV_LISTENER *listener = listener_iterator_init(service, &iter); + listener; listener = listener_iterator_next(&iter)) + { + if (listener_is_active(listener) && strcmp(listener->name, name) == 0) + { + return listener_to_json(listener); + } + } + + return NULL; +} + json_t* service_attributes(const SERVICE* service) { json_t* attr = json_object(); @@ -2544,7 +2560,7 @@ json_t* service_attributes(const SERVICE* service) /** Add service parameters and listeners */ json_object_set_new(attr, CN_PARAMETERS, service_parameters_to_json(service)); - json_object_set_new(attr, CN_LISTENERS, service_listeners_json_data(service)); + json_object_set_new(attr, CN_LISTENERS, service_all_listeners_json_data(service)); return attr; } @@ -2608,7 +2624,7 @@ json_t* service_to_json(const SERVICE* service, const char* host) return mxs_json_resource(host, self.c_str(), service_json_data(service, host)); } -json_t* service_listeners_to_json(const SERVICE* service, const char* host) +json_t* service_listener_list_to_json(const SERVICE* service, const char* host) { /** This needs to be done here as the listeners are sort of sub-resources * of the service. */ @@ -2616,7 +2632,19 @@ json_t* service_listeners_to_json(const SERVICE* service, const char* host) self += service->name; self += "/listeners"; - return mxs_json_resource(host, self.c_str(), service_listeners_json_data(service)); + return mxs_json_resource(host, self.c_str(), service_all_listeners_json_data(service)); +} + +json_t* service_listener_to_json(const SERVICE* service, const char* name, const char* host) +{ + /** This needs to be done here as the listeners are sort of sub-resources + * of the service. */ + string self = MXS_JSON_API_SERVICES; + self += service->name; + self += "/listeners/"; + self += name; + + return mxs_json_resource(host, self.c_str(), service_listener_json_data(service, name)); } json_t* service_list_to_json(const char* host) diff --git a/server/core/test/rest-api/test/schema_validation.js b/server/core/test/rest-api/test/schema_validation.js index 29540f3cc..dbdce53ce 100644 --- a/server/core/test/rest-api/test/schema_validation.js +++ b/server/core/test/rest-api/test/schema_validation.js @@ -82,6 +82,7 @@ describe("Resource Self Links", function() { "/servers/server2", "/services/RW-Split-Router", "/services/RW-Split-Router/listeners", + "/services/RW-Split-Router/listeners/RW-Split-Listener", "/monitors/MySQL-Monitor", "/filters/Hint", "/sessions/1",