diff options
author | gjoranv <gv@verizonmedia.com> | 2020-01-23 12:39:19 +0100 |
---|---|---|
committer | gjoranv <gv@verizonmedia.com> | 2020-01-23 12:40:04 +0100 |
commit | 6be753f4021e5ef8ece22d19898dbb18e0005bf4 (patch) | |
tree | 4bd83c8464b07d6234955964f37a2fb38637d895 /container-core/src | |
parent | b492c6d6b5f46bc484d249ef5aa3768d7dd91c71 (diff) |
Move metrics handler utilities to new package in container-core
Diffstat (limited to 'container-core/src')
5 files changed, 171 insertions, 0 deletions
diff --git a/container-core/src/main/java/com/yahoo/container/handler/metrics/ErrorResponse.java b/container-core/src/main/java/com/yahoo/container/handler/metrics/ErrorResponse.java new file mode 100644 index 00000000000..321f7b3994a --- /dev/null +++ b/container-core/src/main/java/com/yahoo/container/handler/metrics/ErrorResponse.java @@ -0,0 +1,32 @@ +// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.container.handler.metrics; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.Map; +import java.util.logging.Logger; + +import static java.util.logging.Level.WARNING; + +/** + * @author gjoranv + */ +public class ErrorResponse extends JsonResponse { + private static Logger log = Logger.getLogger(ErrorResponse.class.getName()); + + private static ObjectMapper objectMapper = new ObjectMapper(); + + public ErrorResponse(int code, String message) { + super(code, asErrorJson(message)); + } + + static String asErrorJson(String message) { + try { + return objectMapper.writeValueAsString(Map.of("error", message)); + } catch (JsonProcessingException e) { + log.log(WARNING, "Could not encode error message to json:", e); + return "Could not encode error message to json, check the log for details."; + } + } +} diff --git a/container-core/src/main/java/com/yahoo/container/handler/metrics/HttpHandlerBase.java b/container-core/src/main/java/com/yahoo/container/handler/metrics/HttpHandlerBase.java new file mode 100644 index 00000000000..92840cee48f --- /dev/null +++ b/container-core/src/main/java/com/yahoo/container/handler/metrics/HttpHandlerBase.java @@ -0,0 +1,78 @@ +// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.container.handler.metrics; + +import com.yahoo.container.jdisc.HttpRequest; +import com.yahoo.container.jdisc.HttpResponse; +import com.yahoo.container.jdisc.ThreadedHttpRequestHandler; +import com.yahoo.restapi.Path; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.net.URI; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.Executor; + +import static com.yahoo.jdisc.Response.Status.INTERNAL_SERVER_ERROR; +import static com.yahoo.jdisc.Response.Status.METHOD_NOT_ALLOWED; +import static com.yahoo.jdisc.Response.Status.NOT_FOUND; +import static com.yahoo.jdisc.Response.Status.OK; +import static com.yahoo.jdisc.http.HttpRequest.Method.GET; +import static java.util.logging.Level.WARNING; + +/** + * @author gjoranv + */ +public abstract class HttpHandlerBase extends ThreadedHttpRequestHandler { + + protected HttpHandlerBase(Executor executor) { + super(executor); + } + + protected abstract Optional<HttpResponse> doHandle(URI requestUri, Path apiPath, String consumer); + + @Override + public final HttpResponse handle(HttpRequest request) { + if (request.getMethod() != GET) return new JsonResponse(METHOD_NOT_ALLOWED, "Only GET is supported"); + + Path path = new Path(request.getUri()); + + return doHandle(request.getUri(), path, getConsumer(request)) + .orElse(new ErrorResponse(NOT_FOUND, "No content at given path")); + } + + private String getConsumer(HttpRequest request) { + return request.getProperty("consumer"); + } + + protected JsonResponse resourceListResponse(URI requestUri, List<String> resources) { + try { + return new JsonResponse(OK, resourceList(requestUri, resources)); + } catch (JSONException e) { + log.log(WARNING, "Bad JSON construction in generated resource list for " + requestUri.getPath(), e); + return new ErrorResponse(INTERNAL_SERVER_ERROR, + "An error occurred when generating the list of api resources."); + } + } + + // TODO: Use jackson with a "Resources" class instead of JSONObject + private static String resourceList(URI requestUri, List<String> resources) throws JSONException { + int port = requestUri.getPort(); + String host = requestUri.getHost(); + StringBuilder base = new StringBuilder("http://"); + base.append(host); + if (port >= 0) { + base.append(":").append(port); + } + String uriBase = base.toString(); + JSONArray linkList = new JSONArray(); + for (String api : resources) { + JSONObject resource = new JSONObject(); + resource.put("url", uriBase + api); + linkList.put(resource); + } + return new JSONObject().put("resources", linkList).toString(4); + } + +} diff --git a/container-core/src/main/java/com/yahoo/container/handler/metrics/JsonResponse.java b/container-core/src/main/java/com/yahoo/container/handler/metrics/JsonResponse.java new file mode 100644 index 00000000000..def06ce9de3 --- /dev/null +++ b/container-core/src/main/java/com/yahoo/container/handler/metrics/JsonResponse.java @@ -0,0 +1,30 @@ +// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.container.handler.metrics; + +import com.yahoo.container.jdisc.HttpResponse; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.Charset; + +/** + * @author gjoranv + */ +public class JsonResponse extends HttpResponse { + private final byte[] data; + + public JsonResponse(int code, String data) { + super(code); + this.data = data.getBytes(Charset.forName(DEFAULT_CHARACTER_ENCODING)); + } + + @Override + public String getContentType() { + return "application/json"; + } + + @Override + public void render(OutputStream outputStream) throws IOException { + outputStream.write(data); + } +} diff --git a/container-core/src/main/java/com/yahoo/container/handler/metrics/package-info.java b/container-core/src/main/java/com/yahoo/container/handler/metrics/package-info.java new file mode 100644 index 00000000000..031886afc94 --- /dev/null +++ b/container-core/src/main/java/com/yahoo/container/handler/metrics/package-info.java @@ -0,0 +1,6 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +/** Exported config package */ +@ExportPackage +package com.yahoo.container.handler.metrics; + +import com.yahoo.osgi.annotation.ExportPackage; diff --git a/container-core/src/test/java/com/yahoo/container/handler/metrics/ErrorResponseTest.java b/container-core/src/test/java/com/yahoo/container/handler/metrics/ErrorResponseTest.java new file mode 100644 index 00000000000..882f9044dce --- /dev/null +++ b/container-core/src/test/java/com/yahoo/container/handler/metrics/ErrorResponseTest.java @@ -0,0 +1,25 @@ +// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.container.handler.metrics; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author gjoranv + */ +public class ErrorResponseTest { + + @Test + public void error_message_is_wrapped_in_json_object() { + var json = ErrorResponse.asErrorJson("bad"); + assertEquals("{\"error\":\"bad\"}", json); + } + + @Test + public void quotes_are_escaped() { + var json = ErrorResponse.asErrorJson("Message \" with \" embedded quotes."); + assertEquals("{\"error\":\"Message \\\" with \\\" embedded quotes.\"}", json); + } + +} |