Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#841 added StatusWrapper interface #859

Merged
merged 1 commit into from
Dec 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions handler/src/main/java/com/networknt/handler/LightHttpHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
import com.networknt.config.Config;
import com.networknt.handler.config.HandlerConfig;
import com.networknt.httpstring.AttachmentConstants;
import com.networknt.service.SingletonServiceFactory;
import com.networknt.status.Status;
import com.networknt.status.StatusWrapper;
import com.networknt.utility.Constants;

import io.undertow.server.HttpHandler;
Expand Down Expand Up @@ -76,6 +78,15 @@ default void setExchangeStatus(HttpServerExchange exchange, String code, final O
* @param status error status
*/
default void setExchangeStatus(HttpServerExchange exchange, Status status) {
// Wrap default status into custom status if the implementation of StatusWrapper was provided
StatusWrapper statusWrapper;
try {
statusWrapper = SingletonServiceFactory.getBean(StatusWrapper.class);
} catch (NoClassDefFoundError e) {
statusWrapper = null;
}
status = statusWrapper == null ? status : statusWrapper.wrap(status, exchange);

exchange.setStatusCode(status.getStatusCode());
exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/json");
status.setDescription(status.getDescription().replaceAll("\\\\", "\\\\\\\\"));
Expand Down
4 changes: 4 additions & 0 deletions status/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-core</artifactId>
</dependency>
</dependencies>

</project>
24 changes: 24 additions & 0 deletions status/src/main/java/com/networknt/status/StatusWrapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.networknt.status;

import io.undertow.server.HttpServerExchange;

/**
* Interface to allow custom Status and then inject the customized status into framework through SingletonFactory
* <p>
* Implement the interface and configure in service.yml
* - com.networknt.status.StatusWrapper
* - custom implementation
*
* @author Jiachen Sun
*/

public interface StatusWrapper {
/**
* Encapsulate the default status of the framework as a custom status
*
* @param status The status to be wrapped
* @param exchange The source of custom info used to wrap status
* @return the custom status
*/
Status wrap(Status status, HttpServerExchange exchange);
}
66 changes: 66 additions & 0 deletions status/src/test/java/com/networknt/status/StatusWrapperTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.networknt.status;

import com.networknt.config.Config;
import com.networknt.service.SingletonServiceFactory;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RunWith(SeparateClassloaderTestRunner.class)
public class StatusWrapperTest {
private static Config config = null;
private static final String homeDir = System.getProperty("user.home");

@BeforeClass
public static void setUp() throws Exception {
config = Config.getInstance();

// write a config file into the user home directory.
List<String> implementationList = new ArrayList<>();
implementationList.add("com.networknt.status.TestStatusWrapper");
Map<String, List<String>> implementationMap = new HashMap<>();
implementationMap.put("com.networknt.status.StatusWrapper", implementationList);
List<Map<String, List<String>>> interfaceList = new ArrayList<>();
interfaceList.add(implementationMap);
Map<String, Object> singletons = new HashMap<>();
singletons.put("singletons", interfaceList);
config.getMapper().writeValue(new File(homeDir + "/service.json"), singletons);

// Add home directory to the classpath of the system class loader.
AppURLClassLoader classLoader = new AppURLClassLoader(new URL[0], ClassLoader.getSystemClassLoader());
classLoader.addURL(new File(homeDir).toURI().toURL());
config.setClassLoader(classLoader);
}

@AfterClass
public static void tearDown() {
// Remove the service.yml from home directory
File test = new File(homeDir + "/service.json");
test.delete();
}

@Test
public void testStatusWrap() {
StatusWrapper statusWrapper = SingletonServiceFactory.getBean(StatusWrapper.class);
Status status = new Status("ERR10001");
status = statusWrapper.wrap(status, null);
Assert.assertEquals("{\"error\":{\"statusCode\":401,\"code\":\"ERR10001\",\"message\":\"AUTH_TOKEN_EXPIRED\",\"description\":\"Jwt token in authorization header expired\",\"customInfo\":\"custom_info\",\"severity\":\"ERROR\"}}", status.toString());
}

@Test
public void testStatusWrapWithArgs() {
StatusWrapper statusWrapper = SingletonServiceFactory.getBean(StatusWrapper.class);
Status status = new Status("ERR11000","arg1", "arg2");
status = statusWrapper.wrap(status, null);
Assert.assertEquals("{\"error\":{\"statusCode\":400,\"code\":\"ERR11000\",\"message\":\"VALIDATOR_REQUEST_PARAMETER_QUERY_MISSING\",\"description\":\"Query parameter arg1 is required on path arg2 but not found in request.\",\"customInfo\":\"custom_info\",\"severity\":\"ERROR\"}}", status.toString());
}
}
42 changes: 42 additions & 0 deletions status/src/test/java/com/networknt/status/TestStatusWrapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.networknt.status;

import io.undertow.server.HttpServerExchange;

public class TestStatusWrapper implements StatusWrapper {
@Override
public Status wrap(Status status, HttpServerExchange exchange) {
return new TestStatus(status, exchange);
}

private class TestStatus extends Status {
private String customInfo;

public TestStatus(Status status, HttpServerExchange exchange) {
this.setStatusCode(status.getStatusCode());
this.setCode(status.getCode());
this.setDescription(status.getDescription());
this.setMessage(status.getMessage());
this.setSeverity(status.getSeverity());
this.setCustomInfo("custom_info");
}

public String getCustomInfo() {
return customInfo;
}

public void setCustomInfo(String customInfo) {
this.customInfo = customInfo;
}

@Override
public String toString() {
String message = "{\"error\":" + "{\"statusCode\":" + getStatusCode()
+ ",\"code\":\"" + getCode()
+ "\",\"message\":\"" + getMessage()
+ "\",\"description\":\"" + getDescription()
+ "\",\"customInfo\":\"" + getCustomInfo()
+ "\",\"severity\":\"" + getSeverity() + "\"}" + "}";
return message;
}
}
}