feat(gateway-vertx) Use policy failure and error writers. Reenable corresponding tests.
MODIFY
gateway/engine/core/src/main/java/io/apiman/gateway/engine/IPolicyFailureWriter.java
gateway/engine/core/src/main/java/io/apiman/gateway/engine/IPolicyFailureWriter.java
@@ -28,9 +28,9 @@ public interface IPolicyFailureWriter {
/**
* Formats the given policy failure.
- * @param request
- * @param failure
- * @param response
+ * @param request the API request
+ * @param failure the policy failure
+ * @param response the client response
*/
public void write(ApiRequest request, PolicyFailure failure, IApiClientResponse response);

MODIFY
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/http/HttpPolicyAdapter.java
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/http/HttpPolicyAdapter.java
*/
package io.apiman.gateway.platforms.vertx3.http;
-import io.apiman.common.util.MediaType;
+import io.apiman.gateway.engine.IApiClientResponse;
import io.apiman.gateway.engine.IApiRequestExecutor;
import io.apiman.gateway.engine.IEngine;
import io.apiman.gateway.engine.IEngineResult;
+import io.apiman.gateway.engine.IPolicyErrorWriter;
+import io.apiman.gateway.engine.IPolicyFailureWriter;
import io.apiman.gateway.engine.beans.ApiRequest;
import io.apiman.gateway.engine.beans.ApiResponse;
-import io.apiman.gateway.engine.beans.EngineErrorResponse;
import io.apiman.gateway.engine.beans.PolicyFailure;
import io.apiman.gateway.platforms.vertx3.io.VertxApimanBuffer;
-import io.netty.handler.codec.http.HttpResponseStatus;
import io.vertx.core.buffer.Buffer;
-import io.vertx.core.http.HttpHeaders;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
-import io.vertx.core.json.Json;
import io.vertx.core.logging.Logger;
import io.vertx.core.logging.LoggerFactory;
-import java.util.Map;
-
/**
* @author Marc Savy {@literal <msavy@redhat.com>}
*/
public class HttpPolicyAdapter {
private final HttpServerRequest vertxRequest;
private final HttpServerResponse vertxResponse;
+ private final IPolicyFailureWriter policyFailureWriter;
+ private final IPolicyErrorWriter policyErrorWriter;
private final IEngine engine;
private final Logger log = LoggerFactory.getLogger(HttpPolicyAdapter.class);
private final boolean isTls;
public HttpPolicyAdapter(HttpServerRequest req,
+ IPolicyFailureWriter policyFailureWriter,
+ IPolicyErrorWriter policyErrorWriter,
IEngine engine,
boolean isTls) {
this.vertxRequest = req;
+ this.policyFailureWriter = policyFailureWriter;
+ this.policyErrorWriter = policyErrorWriter;
this.engine = engine;
this.isTls = isTls;
this.vertxResponse = req.response();
@@ -58,7 +60,7 @@ public class HttpPolicyAdapter {
try {
_execute();
} catch (Exception ex) {
- handleError(vertxResponse, ex);
+ handleError(new ApiRequest(), ex, vertxResponse);
}
}
@@ -73,16 +75,16 @@ public class HttpPolicyAdapter {
// Exception
vertxRequest.exceptionHandler(ex -> {
- handleError(vertxResponse, ex);
+ handleError(request, ex, vertxResponse);
}); // TODO: Should probably log error also.
// Set up executor to run conversation through apiman's policy engine.
IApiRequestExecutor executor = engine.executor(request, result -> {
if (result.isSuccess()) {
- handleEngineResult(result.getResult());
+ handleEngineResult(request, result.getResult());
} else {
// An unexpected problem occurred somewhere.
- handleError(vertxResponse, result.getError());
+ handleError(request, result.getError(), vertxResponse);
}
});
@@ -110,7 +112,7 @@ public class HttpPolicyAdapter {
executor.execute();
}
- private void handleEngineResult(IEngineResult engineResult) {
+ private void handleEngineResult(ApiRequest request, IEngineResult engineResult) {
// Everything worked
if (engineResult.isResponse()) {
ApiResponse response = engineResult.getApiResponse();
@@ -127,55 +129,69 @@ public class HttpPolicyAdapter {
engineResult.endHandler(end -> vertxResponse.end());
} else { // Policy failure (i.e. denial - it's not an exception).
log.debug(String.format("Failed with policy failure (denial): %s", engineResult.getPolicyFailure())); //$NON-NLS-1$
- handlePolicyFailure(vertxResponse, engineResult.getPolicyFailure());
+ handlePolicyFailure(request, engineResult.getPolicyFailure(), vertxResponse);
+ }
}
+
+ private void handleError(ApiRequest apimanRequest, Throwable error, HttpServerResponse vertxResponse) {
+ vertxResponse.setChunked(true);
+ policyErrorWriter.write(apimanRequest, error, new IApiClientResponse() {
+
+ @Override
+ public void write(StringBuffer buffer) {
+ vertxResponse.end(buffer.toString());
+ }
+
+ @Override
+ public void write(StringBuilder builder) {
+ vertxResponse.end(builder.toString());
+ }
+
+ @Override
+ public void write(String body) {
+ vertxResponse.end(body);
}
- private static void handleError(HttpServerResponse response, Throwable error) {
- response.setStatusCode(HttpResponseStatus.INTERNAL_SERVER_ERROR.code());
- response.setStatusMessage(HttpResponseStatus.INTERNAL_SERVER_ERROR.reasonPhrase());
- response.headers().add("X-Gateway-Error", String.valueOf(error.getMessage())); //$NON-NLS-1$
- response.headers().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
+ @Override
+ public void setStatusCode(int code) {
+ vertxResponse.setStatusCode(code);
+ }
- EngineErrorResponse errorResponse = new EngineErrorResponse();
- errorResponse.setResponseCode(HttpResponseStatus.INTERNAL_SERVER_ERROR.code());
- errorResponse.setMessage(error.getMessage());
- errorResponse.setTrace(error);
- response.setChunked(true);
- response.write(Json.encode(errorResponse));
- response.end();
+ @Override
+ public void setHeader(String headerName, String headerValue) {
+ vertxResponse.putHeader(headerName, headerValue);
+ }
+ });
}
- private static void handlePolicyFailure(HttpServerResponse response, PolicyFailure failure) {
- response.headers().add("X-Policy-Failure-Type", String.valueOf(failure.getType())); //$NON-NLS-1$
- response.headers().add("X-Policy-Failure-Message", failure.getMessage()); //$NON-NLS-1$
- response.headers().add("X-Policy-Failure-Code", String.valueOf(failure.getFailureCode())); //$NON-NLS-1$
- response.headers().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
+ private void handlePolicyFailure(ApiRequest apimanRequest, PolicyFailure policyFailure, HttpServerResponse vertxResponse) {
+ vertxResponse.setChunked(true);
+ policyFailureWriter.write(apimanRequest, policyFailure, new IApiClientResponse() {
- int code = HttpResponseStatus.INTERNAL_SERVER_ERROR.code();
+ @Override
+ public void write(StringBuffer buffer) {
+ vertxResponse.end(buffer.toString());
+ }
- switch (failure.getType()) {
- case Authentication:
- code = HttpResponseStatus.UNAUTHORIZED.code();
- break;
- case Authorization:
- code = HttpResponseStatus.FORBIDDEN.code();
- break;
- case NotFound:
- code = HttpResponseStatus.NOT_FOUND.code();
- break;
- case Other:
- code = failure.getResponseCode();
- break;
+ @Override
+ public void write(StringBuilder builder) {
+ vertxResponse.end(builder.toString());
}
- response.setStatusCode(code);
- response.setStatusMessage(failure.getMessage());
+ @Override
+ public void write(String body) {
+ vertxResponse.end(body);
+ }
+
+ @Override
+ public void setStatusCode(int code) {
+ vertxResponse.setStatusCode(code);
+ }
- for (Map.Entry<String, String> entry : failure.getHeaders()) {
- response.headers().add(entry.getKey(), entry.getValue());
+ @Override
+ public void setHeader(String headerName, String headerValue) {
+ vertxResponse.putHeader(headerName, headerValue);
}
- response.setChunked(true);
- response.end(Json.encode(failure));
+ });
}
}

MODIFY
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/verticles/ApimanVerticleWithEngine.java
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/verticles/ApimanVerticleWithEngine.java
package io.apiman.gateway.platforms.vertx3.verticles;
import io.apiman.gateway.engine.IEngine;
+import io.apiman.gateway.engine.IPolicyErrorWriter;
+import io.apiman.gateway.engine.IPolicyFailureWriter;
+import io.apiman.gateway.engine.impl.ConfigDrivenEngineFactory;
import io.apiman.gateway.platforms.vertx3.engine.VertxConfigDrivenEngineFactory;
import io.vertx.core.Future;
+import java.util.Map;
+
/**
* A base for those verticles that require an instantiated engine.
*
@@ -27,6 +32,8 @@ import io.vertx.core.Future;
public abstract class ApimanVerticleWithEngine extends ApimanVerticleBase {
protected IEngine engine;
+ protected IPolicyFailureWriter policyFailureWriter;
+ protected IPolicyErrorWriter policyErrorWriter;
@Override
public void start(Future<Void> startFuture) {
@@ -40,7 +47,20 @@ public abstract class ApimanVerticleWithEngine extends ApimanVerticleBase {
}
}).createEngine();
- engine.getRegistry(); // this should help avoid slow first-time loads.
+ policyFailureWriter = initPolicyFailureWriter();
+ policyErrorWriter = initPolicyErrorWriter();
+ }
+
+ private IPolicyFailureWriter initPolicyFailureWriter() {
+ Class<? extends IPolicyFailureWriter> clazz = apimanConfig.getPolicyFailureWriterClass(engine.getPluginRegistry());
+ Map<String, String> conf = apimanConfig.getPolicyFailureWriterConfig();
+ return ConfigDrivenEngineFactory.instantiate(clazz, conf);
+ }
+
+ private IPolicyErrorWriter initPolicyErrorWriter() {
+ Class<? extends IPolicyErrorWriter> clazz = apimanConfig.getPolicyErrorWriterClass(engine.getPluginRegistry());
+ Map<String, String> conf = apimanConfig.getPolicyErrorWriterConfig();
+ return ConfigDrivenEngineFactory.instantiate(clazz, conf);
}
protected IEngine engine() {

MODIFY
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/verticles/HttpGatewayVerticle.java
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/verticles/HttpGatewayVerticle.java
@@ -45,7 +45,7 @@ public class HttpGatewayVerticle extends ApimanVerticleWithEngine {
}
private void requestHandler(HttpServerRequest req) {
- new HttpPolicyAdapter(req, engine, false).execute();
+ new HttpPolicyAdapter(req, policyFailureWriter, policyErrorWriter, engine, false).execute();
}
@Override

MODIFY
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/verticles/HttpsGatewayVerticle.java
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/verticles/HttpsGatewayVerticle.java
@@ -57,7 +57,7 @@ public class HttpsGatewayVerticle extends ApimanVerticleWithEngine {
}
private void requestHandler(HttpServerRequest req) {
- new HttpPolicyAdapter(req, engine, true).execute();
+ new HttpPolicyAdapter(req, policyFailureWriter, policyErrorWriter, engine, true).execute();
}
@Override

MODIFY
gateway/test/src/test/java/io/apiman/gateway/test/Policy_IgnoredResourcesXmlTest.java
gateway/test/src/test/java/io/apiman/gateway/test/Policy_IgnoredResourcesXmlTest.java
@@ -18,7 +18,6 @@ package io.apiman.gateway.test;
import io.apiman.gateway.test.junit.GatewayRestTestPlan;
import io.apiman.gateway.test.junit.GatewayRestTester;
-import org.junit.Ignore;
import org.junit.runner.RunWith;
/**
@@ -28,7 +27,6 @@ import org.junit.runner.RunWith;
*/
@RunWith(GatewayRestTester.class)
@GatewayRestTestPlan("test-plans/policies/ignored-resources-xml-testPlan.xml")
-@Ignore
public class Policy_IgnoredResourcesXmlTest {
}

MODIFY
gateway/test/src/test/java/io/apiman/gateway/test/SimplePayloadPolicyTest.java
gateway/test/src/test/java/io/apiman/gateway/test/SimplePayloadPolicyTest.java
@@ -20,7 +20,6 @@ import io.apiman.gateway.test.junit.GatewayRestTestPlan;
import io.apiman.gateway.test.junit.GatewayRestTestSystemProperties;
import io.apiman.gateway.test.junit.GatewayRestTester;
-import org.junit.Ignore;
import org.junit.runner.RunWith;
/**
@@ -34,7 +33,6 @@ import org.junit.runner.RunWith;
GatewayConfigProperties.MAX_PAYLOAD_BUFFER_SIZE, "4096",
GatewayConfigProperties.ERROR_WRITER_CLASS, "io.apiman.gateway.engine.impl.TracePolicyErrorWriter"
})
-@Ignore
public class SimplePayloadPolicyTest {
}

MODIFY
gateway/test/src/test/resources/test-plan-data/policies/ignored-resources-xml/003-success.resttest
gateway/test/src/test/resources/test-plan-data/policies/ignored-resources-xml/003-success.resttest
@@ -34,6 +34,10 @@ Content-Type: application/xml
<key>Accept-Encoding</key>
<value>*</value>
</entry>
+ <entry>
+ <key>Content-Length</key>
+ <value>*</value>
+ </entry>
</headers>
<method>GET</method>
<resource>/invoices</resource>

feat(gateway-vertx) Use policy failure and error writers. Reenable corresponding tests.