From dc6684d51f459d06c3344e074aef6ad5c2c3e175 Mon Sep 17 00:00:00 2001 From: Martin Polden Date: Thu, 19 Sep 2019 15:24:08 +0200 Subject: Move general REST API classes to com.yahoo.restapi --- container-core/abi-spec.json | 110 ++++++++++++++++++++- .../main/java/com/yahoo/restapi/ErrorResponse.java | 66 +++++++++++++ .../java/com/yahoo/restapi/MessageResponse.java | 31 ++++++ .../java/com/yahoo/restapi/ResourceResponse.java | 42 ++++++++ .../java/com/yahoo/restapi/SlimeJsonResponse.java | 38 +++++++ .../java/com/yahoo/restapi/StringResponse.java | 27 +++++ .../src/main/java/com/yahoo/restapi/Uri.java | 64 ++++++++++++ 7 files changed, 377 insertions(+), 1 deletion(-) create mode 100644 container-core/src/main/java/com/yahoo/restapi/ErrorResponse.java create mode 100644 container-core/src/main/java/com/yahoo/restapi/MessageResponse.java create mode 100644 container-core/src/main/java/com/yahoo/restapi/ResourceResponse.java create mode 100644 container-core/src/main/java/com/yahoo/restapi/SlimeJsonResponse.java create mode 100644 container-core/src/main/java/com/yahoo/restapi/StringResponse.java create mode 100644 container-core/src/main/java/com/yahoo/restapi/Uri.java (limited to 'container-core') diff --git a/container-core/abi-spec.json b/container-core/abi-spec.json index 81af58b6681..9292db89eb5 100644 --- a/container-core/abi-spec.json +++ b/container-core/abi-spec.json @@ -854,6 +854,57 @@ ], "fields": [] }, + "com.yahoo.restapi.ErrorResponse$errorCodes": { + "superClass": "java.lang.Enum", + "interfaces": [], + "attributes": [ + "public", + "final", + "enum" + ], + "methods": [ + "public static com.yahoo.restapi.ErrorResponse$errorCodes[] values()", + "public static com.yahoo.restapi.ErrorResponse$errorCodes valueOf(java.lang.String)" + ], + "fields": [ + "public static final enum com.yahoo.restapi.ErrorResponse$errorCodes NOT_FOUND", + "public static final enum com.yahoo.restapi.ErrorResponse$errorCodes BAD_REQUEST", + "public static final enum com.yahoo.restapi.ErrorResponse$errorCodes FORBIDDEN", + "public static final enum com.yahoo.restapi.ErrorResponse$errorCodes METHOD_NOT_ALLOWED", + "public static final enum com.yahoo.restapi.ErrorResponse$errorCodes INTERNAL_SERVER_ERROR", + "public static final enum com.yahoo.restapi.ErrorResponse$errorCodes UNAUTHORIZED" + ] + }, + "com.yahoo.restapi.ErrorResponse": { + "superClass": "com.yahoo.restapi.SlimeJsonResponse", + "interfaces": [], + "attributes": [ + "public" + ], + "methods": [ + "public void (int, java.lang.String, java.lang.String)", + "public static com.yahoo.restapi.ErrorResponse notFoundError(java.lang.String)", + "public static com.yahoo.restapi.ErrorResponse internalServerError(java.lang.String)", + "public static com.yahoo.restapi.ErrorResponse badRequest(java.lang.String)", + "public static com.yahoo.restapi.ErrorResponse forbidden(java.lang.String)", + "public static com.yahoo.restapi.ErrorResponse unauthorized(java.lang.String)", + "public static com.yahoo.restapi.ErrorResponse methodNotAllowed(java.lang.String)" + ], + "fields": [] + }, + "com.yahoo.restapi.MessageResponse": { + "superClass": "com.yahoo.container.jdisc.HttpResponse", + "interfaces": [], + "attributes": [ + "public" + ], + "methods": [ + "public void (java.lang.String)", + "public void render(java.io.OutputStream)", + "public java.lang.String getContentType()" + ], + "fields": [] + }, "com.yahoo.restapi.Path": { "superClass": "java.lang.Object", "interfaces": [], @@ -872,5 +923,62 @@ "public java.lang.String toString()" ], "fields": [] + }, + "com.yahoo.restapi.ResourceResponse": { + "superClass": "com.yahoo.container.jdisc.HttpResponse", + "interfaces": [], + "attributes": [ + "public" + ], + "methods": [ + "public varargs void (com.yahoo.container.jdisc.HttpRequest, java.lang.String[])", + "public void render(java.io.OutputStream)", + "public java.lang.String getContentType()" + ], + "fields": [] + }, + "com.yahoo.restapi.SlimeJsonResponse": { + "superClass": "com.yahoo.container.jdisc.HttpResponse", + "interfaces": [], + "attributes": [ + "public" + ], + "methods": [ + "public void (com.yahoo.slime.Slime)", + "public void (int, com.yahoo.slime.Slime)", + "public void render(java.io.OutputStream)", + "public java.lang.String getContentType()" + ], + "fields": [] + }, + "com.yahoo.restapi.StringResponse": { + "superClass": "com.yahoo.container.jdisc.HttpResponse", + "interfaces": [], + "attributes": [ + "public" + ], + "methods": [ + "public void (java.lang.String)", + "public void render(java.io.OutputStream)" + ], + "fields": [] + }, + "com.yahoo.restapi.Uri": { + "superClass": "java.lang.Object", + "interfaces": [], + "attributes": [ + "public" + ], + "methods": [ + "public void (java.net.URI)", + "public void (java.lang.String)", + "public com.yahoo.restapi.Uri append(java.lang.String)", + "public com.yahoo.restapi.Uri withoutParameters()", + "public com.yahoo.restapi.Uri withPath(java.lang.String)", + "public com.yahoo.restapi.Uri withTrailingSlash()", + "public java.net.URI toURI()", + "public java.lang.String toString()" + ], + "fields": [] } -} +} \ No newline at end of file diff --git a/container-core/src/main/java/com/yahoo/restapi/ErrorResponse.java b/container-core/src/main/java/com/yahoo/restapi/ErrorResponse.java new file mode 100644 index 00000000000..d3e81a10720 --- /dev/null +++ b/container-core/src/main/java/com/yahoo/restapi/ErrorResponse.java @@ -0,0 +1,66 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.restapi; + +import com.yahoo.slime.Cursor; +import com.yahoo.slime.Slime; + +import static com.yahoo.jdisc.Response.Status.BAD_REQUEST; +import static com.yahoo.jdisc.Response.Status.FORBIDDEN; +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.UNAUTHORIZED; + +/** + * A HTTP JSON response containing an error code and a message + * + * @author bratseth + */ +public class ErrorResponse extends SlimeJsonResponse { + + public enum errorCodes { + NOT_FOUND, + BAD_REQUEST, + FORBIDDEN, + METHOD_NOT_ALLOWED, + INTERNAL_SERVER_ERROR, + UNAUTHORIZED + } + + public ErrorResponse(int statusCode, String errorType, String message) { + super(statusCode, asSlimeMessage(errorType, message)); + } + + private static Slime asSlimeMessage(String errorType, String message) { + Slime slime = new Slime(); + Cursor root = slime.setObject(); + root.setString("error-code", errorType); + root.setString("message", message); + return slime; + } + + public static ErrorResponse notFoundError(String message) { + return new ErrorResponse(NOT_FOUND, errorCodes.NOT_FOUND.name(), message); + } + + public static ErrorResponse internalServerError(String message) { + return new ErrorResponse(INTERNAL_SERVER_ERROR, errorCodes.INTERNAL_SERVER_ERROR.name(), message); + } + + public static ErrorResponse badRequest(String message) { + return new ErrorResponse(BAD_REQUEST, errorCodes.BAD_REQUEST.name(), message); + } + + public static ErrorResponse forbidden(String message) { + return new ErrorResponse(FORBIDDEN, errorCodes.FORBIDDEN.name(), message); + } + + public static ErrorResponse unauthorized(String message) { + return new ErrorResponse(UNAUTHORIZED, errorCodes.UNAUTHORIZED.name(), message); + } + + public static ErrorResponse methodNotAllowed(String message) { + return new ErrorResponse(METHOD_NOT_ALLOWED, errorCodes.METHOD_NOT_ALLOWED.name(), message); + } + +} diff --git a/container-core/src/main/java/com/yahoo/restapi/MessageResponse.java b/container-core/src/main/java/com/yahoo/restapi/MessageResponse.java new file mode 100644 index 00000000000..8669d4f9b0c --- /dev/null +++ b/container-core/src/main/java/com/yahoo/restapi/MessageResponse.java @@ -0,0 +1,31 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.restapi; + +import com.yahoo.container.jdisc.HttpResponse; +import com.yahoo.slime.JsonFormat; +import com.yahoo.slime.Slime; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * @author bratseth + */ +public class MessageResponse extends HttpResponse { + + private final Slime slime = new Slime(); + + public MessageResponse(String message) { + super(200); + slime.setObject().setString("message", message); + } + + @Override + public void render(OutputStream stream) throws IOException { + new JsonFormat(true).encode(stream, slime); + } + + @Override + public String getContentType() { return "application/json"; } + +} diff --git a/container-core/src/main/java/com/yahoo/restapi/ResourceResponse.java b/container-core/src/main/java/com/yahoo/restapi/ResourceResponse.java new file mode 100644 index 00000000000..4852bfafa60 --- /dev/null +++ b/container-core/src/main/java/com/yahoo/restapi/ResourceResponse.java @@ -0,0 +1,42 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.restapi; + +import com.yahoo.container.jdisc.HttpRequest; +import com.yahoo.container.jdisc.HttpResponse; +import com.yahoo.slime.Cursor; +import com.yahoo.slime.JsonFormat; +import com.yahoo.slime.Slime; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * Returns a response containing an array of links to sub-resources + * + * @author bratseth + */ +public class ResourceResponse extends HttpResponse { + + private final Slime slime = new Slime(); + + public ResourceResponse(HttpRequest request, String ... subResources) { + super(200); + Cursor resourceArray = slime.setObject().setArray("resources"); + for (String subResource : subResources) { + Cursor resourceEntry = resourceArray.addObject(); + resourceEntry.setString("url", new Uri(request.getUri()) + .append(subResource) + .withTrailingSlash() + .toString()); + } + } + + @Override + public void render(OutputStream stream) throws IOException { + new JsonFormat(true).encode(stream, slime); + } + + @Override + public String getContentType() { return "application/json"; } + +} diff --git a/container-core/src/main/java/com/yahoo/restapi/SlimeJsonResponse.java b/container-core/src/main/java/com/yahoo/restapi/SlimeJsonResponse.java new file mode 100644 index 00000000000..2473da3578d --- /dev/null +++ b/container-core/src/main/java/com/yahoo/restapi/SlimeJsonResponse.java @@ -0,0 +1,38 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.restapi; + +import com.yahoo.container.jdisc.HttpResponse; +import com.yahoo.slime.JsonFormat; +import com.yahoo.slime.Slime; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * A generic Json response using Slime for JSON encoding + * + * @author bratseth + */ +public class SlimeJsonResponse extends HttpResponse { + + private final Slime slime; + + public SlimeJsonResponse(Slime slime) { + super(200); + this.slime = slime; + } + + public SlimeJsonResponse(int statusCode, Slime slime) { + super(statusCode); + this.slime = slime; + } + + @Override + public void render(OutputStream stream) throws IOException { + new JsonFormat(true).encode(stream, slime); + } + + @Override + public String getContentType() { return "application/json"; } + +} diff --git a/container-core/src/main/java/com/yahoo/restapi/StringResponse.java b/container-core/src/main/java/com/yahoo/restapi/StringResponse.java new file mode 100644 index 00000000000..55ea22880de --- /dev/null +++ b/container-core/src/main/java/com/yahoo/restapi/StringResponse.java @@ -0,0 +1,27 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.restapi; + +import com.yahoo.container.jdisc.HttpResponse; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +/** + * @author bratseth + */ +public class StringResponse extends HttpResponse { + + private final String message; + + public StringResponse(String message) { + super(200); + this.message = message; + } + + @Override + public void render(OutputStream stream) throws IOException { + stream.write(message.getBytes(StandardCharsets.UTF_8)); + } + +} diff --git a/container-core/src/main/java/com/yahoo/restapi/Uri.java b/container-core/src/main/java/com/yahoo/restapi/Uri.java new file mode 100644 index 00000000000..c1b0d19eb3e --- /dev/null +++ b/container-core/src/main/java/com/yahoo/restapi/Uri.java @@ -0,0 +1,64 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.restapi; + +import java.net.URI; +import java.net.URISyntaxException; + +/** + * A Uri which provides convenience methods for creating various manipulated copies. + * This is immutable. + * + * @author bratseth + */ +public class Uri { + + /** The URI instance wrapped by this */ + private final URI uri; + + public Uri(URI uri) { + this.uri = uri; + } + + public Uri(String uri) { + try { + this.uri = new URI(uri); + } + catch (URISyntaxException e) { + throw new IllegalArgumentException("Invalid URI", e); + } + } + + /** Returns a uri with the given path appended and all parameters removed */ + public Uri append(String pathElement) { + return new Uri(withoutParameters().withTrailingSlash() + pathElement); + } + + public Uri withoutParameters() { + int parameterStart = uri.toString().indexOf("?"); + if (parameterStart < 0) + return new Uri(uri.toString()); + else + return new Uri(uri.toString().substring(0, parameterStart)); + } + + public Uri withPath(String path) { + try { + return new Uri(new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), + uri.getPort(), path, uri.getQuery(), uri.getFragment())); + } + catch (URISyntaxException e) { + throw new IllegalArgumentException("Could not add path '" + path + "' to " + this); + } + } + + public Uri withTrailingSlash() { + if (toString().endsWith("/")) return this; + return new Uri(toString() + "/"); + } + + public URI toURI() { return uri; } + + @Override + public String toString() { return uri.toString(); } + +} -- cgit v1.2.3