-
Notifications
You must be signed in to change notification settings - Fork 138
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Implement JSON Path replacement interceptor and associated tests Add `ReplaceInterceptor` class to handle JSON Path replacements in requests. Introduce necessary dependencies for JSON Path processing. Enhance unit tests for the interceptor, ensuring functionality with various JSON structures and scenarios. * Refactor ReplaceInterceptorTest to improve readability and maintainability - Rename instance variable to `replaceInterceptor` for clarity - Utilize `ObjectMapper` for JSON parsing in assertions - Format JSON strings for better readability in test cases * Add JavaDoc comments to setJsonPath and setReplacement methods in ReplaceInterceptor class * Update JSONPath dependency to version 2.9.0 and refactor ReplaceInterceptor class - Upgrade `json-path` dependency in `pom.xml`. - Change `ReplaceInterceptor` class annotation from `@MCElement(name="jsonPathReplacer")` to `@MCElement(name="replace")`. - Enhance `replaceWithJsonPath` method with logging and use a custom JSON provider. - Add example scripts for running the service proxy in both Bash and Batch formats. - Include a README with a sample curl command for testing the replacement functionality. * added test * requested changes * requested changes * requested changes * requested changes * Update README and proxies.xml to replace target API configuration with return directive
- Loading branch information
1 parent
1bd5a25
commit 46d078d
Showing
8 changed files
with
399 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 75 additions & 0 deletions
75
core/src/main/java/com/predic8/membrane/core/interceptor/json/ReplaceInterceptor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package com.predic8.membrane.core.interceptor.json; | ||
|
||
import com.jayway.jsonpath.Configuration; | ||
import com.jayway.jsonpath.JsonPath; | ||
import com.predic8.membrane.annot.MCAttribute; | ||
import com.predic8.membrane.annot.MCElement; | ||
import com.predic8.membrane.core.exchange.Exchange; | ||
import com.predic8.membrane.core.http.Message; | ||
import com.predic8.membrane.core.interceptor.AbstractInterceptor; | ||
import com.predic8.membrane.core.interceptor.Outcome; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import static com.predic8.membrane.core.http.MimeType.APPLICATION_JSON; | ||
import static com.predic8.membrane.core.interceptor.Outcome.CONTINUE; | ||
|
||
@SuppressWarnings("unused") | ||
@MCElement(name="replace") | ||
public class ReplaceInterceptor extends AbstractInterceptor { | ||
|
||
private static Logger log = LoggerFactory.getLogger(ReplaceInterceptor.class); | ||
|
||
private String jsonPath; | ||
|
||
private String with; | ||
|
||
@Override | ||
public Outcome handleRequest(Exchange exc) throws Exception { | ||
return handleInternal(exc.getRequestContentType(), exc.getRequest()); | ||
} | ||
|
||
@Override | ||
public Outcome handleResponse(Exchange exc) throws Exception { | ||
return handleInternal(exc.getResponseContentType(), exc.getResponse()); | ||
} | ||
|
||
private Outcome handleInternal(String contentType, Message msg) { | ||
if(contentType.equals(APPLICATION_JSON)) { | ||
msg.setBodyContent(replaceWithJsonPath(msg, jsonPath, with).getBytes()); | ||
} | ||
return CONTINUE; | ||
} | ||
|
||
String replaceWithJsonPath(Message msg, String jsonPath, String replacement) { | ||
Object document = Configuration.defaultConfiguration().jsonProvider().parse(msg.getBodyAsStringDecoded()); | ||
document = JsonPath.parse(document).set(jsonPath, replacement).json(); | ||
return Configuration.defaultConfiguration().jsonProvider().toJson(document); | ||
} | ||
|
||
/** | ||
* Sets the JSONPath expression to identify the target node in the JSON structure. | ||
* | ||
* @param jsonPath the JSONPath expression (e.g., "$.person.name"). | ||
*/ | ||
@MCAttribute | ||
public void setJsonPath(String jsonPath) { | ||
this.jsonPath = jsonPath; | ||
} | ||
|
||
/** | ||
* Sets the replacement value for the node specified by the JSONPath. | ||
* | ||
* @param with the new value to replace the existing one. | ||
*/ | ||
@MCAttribute | ||
public void setWith(String with) { | ||
this.with = with; | ||
} | ||
|
||
public String getJsonPath() {return jsonPath;} | ||
|
||
public String getWith() {return with;} | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
222 changes: 222 additions & 0 deletions
222
core/src/test/java/com/predic8/membrane/core/interceptor/json/ReplaceInterceptorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
package com.predic8.membrane.core.interceptor.json; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.predic8.membrane.core.exchange.Exchange; | ||
import com.predic8.membrane.core.http.Message; | ||
import com.predic8.membrane.core.http.Request; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.Arguments; | ||
import org.junit.jupiter.params.provider.MethodSource; | ||
|
||
import java.io.IOException; | ||
import java.net.URISyntaxException; | ||
import java.util.stream.Stream; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
|
||
public class ReplaceInterceptorTest { | ||
|
||
private ReplaceInterceptor replaceInterceptor; | ||
private Message msg; | ||
private static final ObjectMapper objectMapper = new ObjectMapper(); | ||
|
||
@BeforeEach | ||
void setUp() throws URISyntaxException { | ||
replaceInterceptor = new ReplaceInterceptor(); | ||
msg = Request.get("/foo").buildExchange().getRequest(); | ||
} | ||
|
||
@ParameterizedTest | ||
@MethodSource("jsonReplacementProvider") | ||
void testReplaceWithJsonPath(String originalJson, String jsonPath, String replacement, String expectedJson) throws IOException { | ||
msg.setBodyContent(originalJson.getBytes()); | ||
assertEquals( | ||
objectMapper.readTree(expectedJson), | ||
objectMapper.readTree(replaceInterceptor.replaceWithJsonPath( | ||
msg, | ||
jsonPath, | ||
replacement) | ||
) | ||
); | ||
} | ||
|
||
private static Stream<Arguments> jsonReplacementProvider() { | ||
return Stream.of( | ||
Arguments.of( | ||
""" | ||
{ | ||
"name": "John", | ||
"age": 30 | ||
} | ||
""", | ||
"$.name", | ||
"Jane", | ||
""" | ||
{ | ||
"name": "Jane", | ||
"age": 30 | ||
} | ||
""" | ||
), | ||
Arguments.of( | ||
""" | ||
{ | ||
"person": { | ||
"name": "John", | ||
"age": 30 | ||
} | ||
} | ||
""", | ||
"$.person.name", | ||
"Jane", | ||
""" | ||
{ | ||
"person": { | ||
"name": "Jane", | ||
"age": 30 | ||
} | ||
} | ||
""" | ||
), | ||
Arguments.of( | ||
""" | ||
{ | ||
"people": [ | ||
{ | ||
"name": "John" | ||
}, | ||
{ | ||
"name": "Doe" | ||
} | ||
] | ||
} | ||
""", | ||
"$.people[0].name", | ||
"Jane", | ||
""" | ||
{ | ||
"people": [ | ||
{ | ||
"name": "Jane" | ||
}, | ||
{ | ||
"name": "Doe" | ||
} | ||
] | ||
} | ||
""" | ||
), | ||
Arguments.of( | ||
""" | ||
{ | ||
"family": { | ||
"parents": [ | ||
{ | ||
"name": "John" | ||
}, | ||
{ | ||
"name": "Doe" | ||
} | ||
] | ||
} | ||
} | ||
""", | ||
"$.family.parents[1].name", | ||
"Jane", | ||
""" | ||
{ | ||
"family": { | ||
"parents": [ | ||
{ | ||
"name": "John" | ||
}, | ||
{ | ||
"name": "Jane" | ||
} | ||
] | ||
} | ||
} | ||
""" | ||
), | ||
Arguments.of( | ||
""" | ||
{ | ||
"employees": [ | ||
{ | ||
"name": "John", | ||
"role": "Manager" | ||
}, | ||
{ | ||
"name": "Doe", | ||
"role": "Developer" | ||
} | ||
] | ||
} | ||
""", | ||
"$.employees[*].name", | ||
"Jane", | ||
""" | ||
{ | ||
"employees": [ | ||
{ | ||
"name": "Jane", | ||
"role": "Manager" | ||
}, | ||
{ | ||
"name": "Jane", | ||
"role": "Developer" | ||
} | ||
] | ||
} | ||
""" | ||
), | ||
Arguments.of( | ||
""" | ||
{ | ||
"company": { | ||
"employees": [ | ||
{ | ||
"name": "John", | ||
"department": { | ||
"name": "HR" | ||
} | ||
}, | ||
{ | ||
"name": "Doe", | ||
"department": { | ||
"name": "IT" | ||
} | ||
} | ||
] | ||
} | ||
} | ||
""", | ||
"$.company.employees[*].department.name", | ||
"Operations", | ||
""" | ||
{ | ||
"company": { | ||
"employees": [ | ||
{ | ||
"name": "John", | ||
"department": { | ||
"name": "Operations" | ||
} | ||
}, | ||
{ | ||
"name": "Doe", | ||
"department": { | ||
"name": "Operations" | ||
} | ||
} | ||
] | ||
} | ||
} | ||
""" | ||
) | ||
); | ||
} | ||
|
||
|
||
} |
27 changes: 27 additions & 0 deletions
27
distribution/examples/message-transformation/replace/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Replace Plugin | ||
|
||
The `Replace`plugin allows you to modify values in your JSON by using a `jsonPath` expression to target specific fields for replacement. | ||
## Running the Example | ||
|
||
1. Run `service-proxy.bat` or `service-proxy.sh` | ||
2. Send a request using `curl`: | ||
|
||
```shell | ||
curl localhost:2000 \ | ||
-H "Content-Type: application/json" \ | ||
-d '{"user": {"name": "Alice", "age": 22}}' | ||
``` | ||
and take a look at the output: | ||
```json | ||
{"user":{"name":"Bob","age":22}} | ||
``` | ||
|
||
## Configuration | ||
|
||
This configuration sets up an API that replaces the value of the `name` field under the `shop object` in the JSON body with "foo", before forwarding the request to a target service running on localhost at port 3000. | ||
```xml | ||
<api port="2000"> | ||
<replace jsonPath="$.user.name" with="Bob" /> | ||
<return /> | ||
</api> | ||
``` |
16 changes: 16 additions & 0 deletions
16
distribution/examples/message-transformation/replace/proxies.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<spring:beans xmlns:spring="http://www.springframework.org/schema/beans" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xmlns="http://membrane-soa.org/proxies/1/" | ||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd | ||
http://membrane-soa.org/proxies/1/ http://membrane-soa.org/schemas/proxies-1.xsd"> | ||
|
||
<router> | ||
|
||
<api port="2000"> | ||
<replace jsonPath="$.user.name" with="Bob" /> | ||
<return /> | ||
</api> | ||
|
||
</router> | ||
|
||
</spring:beans> |
18 changes: 18 additions & 0 deletions
18
distribution/examples/message-transformation/replace/service-proxy.bat
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
@echo off | ||
if not "%MEMBRANE_HOME%" == "" goto homeSet | ||
set "MEMBRANE_HOME=%cd%\..\..\.." | ||
echo "%MEMBRANE_HOME%" | ||
if exist "%MEMBRANE_HOME%\service-proxy.bat" goto homeOk | ||
|
||
:homeSet | ||
if exist "%MEMBRANE_HOME%\service-proxy.bat" goto homeOk | ||
echo Please set the MEMBRANE_HOME environment variable to point to | ||
echo the directory where you have extracted the Membrane software. | ||
exit | ||
|
||
:homeOk | ||
set "CLASSPATH=%MEMBRANE_HOME%" | ||
set "CLASSPATH=%MEMBRANE_HOME%/conf" | ||
set "CLASSPATH=%CLASSPATH%;%MEMBRANE_HOME%/starter.jar" | ||
echo Membrane Router running... | ||
java -classpath "%CLASSPATH%" com.predic8.membrane.core.Starter -c proxies.xml |
Oops, something went wrong.