Support non-JSON content types and fix multi-placeholder replacement #12
@@ -135,11 +135,21 @@ public class MockRequestInterceptor implements HandlerInterceptor {
|
|||||||
// Replace placeholders in the mock response body with path/global values
|
// Replace placeholders in the mock response body with path/global values
|
||||||
Object body = mockService.replacePlaceholders(selected.body(), pathVars);
|
Object body = mockService.replacePlaceholders(selected.body(), pathVars);
|
||||||
|
|
||||||
// Write the mock response: headers, status, and JSON body
|
// Write the mock response: headers, status, and body
|
||||||
selected.headers().forEach(response::setHeader);
|
selected.headers().forEach(response::setHeader);
|
||||||
response.setStatus(selected.status());
|
response.setStatus(selected.status());
|
||||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
|
||||||
|
// Respect Content-Type from YAML headers; default to application/json
|
||||||
|
String contentType = selected.headers().getOrDefault("Content-Type",
|
||||||
|
MediaType.APPLICATION_JSON_VALUE);
|
||||||
|
response.setContentType(contentType);
|
||||||
|
|
||||||
|
// For non-JSON content types with a string body, write the raw string directly
|
||||||
|
if (!contentType.contains("json") && body instanceof String rawBody) {
|
||||||
|
response.getWriter().write(rawBody);
|
||||||
|
} else {
|
||||||
response.getWriter().write(mockService.toJson(body));
|
response.getWriter().write(mockService.toJson(body));
|
||||||
|
}
|
||||||
|
|
||||||
return false; // Request has been fully handled
|
return false; // Request has been fully handled
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -215,28 +215,24 @@ public class MockService {
|
|||||||
String result = input;
|
String result = input;
|
||||||
|
|
||||||
// Process datetime with offset (e.g., {datetime+2d4h30m} or {datetime+2d4h30m:rfc3339})
|
// Process datetime with offset (e.g., {datetime+2d4h30m} or {datetime+2d4h30m:rfc3339})
|
||||||
Matcher dateTimeOffsetMatcher = DATETIME_OFFSET_PATTERN.matcher(result);
|
result = replaceAllMatches(result, DATETIME_OFFSET_PATTERN, matcher -> {
|
||||||
if (dateTimeOffsetMatcher.find()) {
|
String sign = matcher.group("sign");
|
||||||
String sign = dateTimeOffsetMatcher.group("sign");
|
String daysStr = matcher.group("days");
|
||||||
String daysStr = dateTimeOffsetMatcher.group("days");
|
String hoursStr = matcher.group("hours");
|
||||||
String hoursStr = dateTimeOffsetMatcher.group("hours");
|
String minutesStr = matcher.group("minutes");
|
||||||
String minutesStr = dateTimeOffsetMatcher.group("minutes");
|
String format = matcher.group("format");
|
||||||
String format = dateTimeOffsetMatcher.group("format");
|
|
||||||
|
|
||||||
LocalDateTime now = LocalDateTime.now();
|
LocalDateTime now = LocalDateTime.now();
|
||||||
LocalDateTime target = calculateDateTimeWithOffset(now, sign, daysStr, hoursStr, minutesStr);
|
LocalDateTime target = calculateDateTimeWithOffset(now, sign, daysStr, hoursStr, minutesStr);
|
||||||
|
return formatDateTime(target, format);
|
||||||
String replacement = formatDateTime(target, format);
|
});
|
||||||
result = dateTimeOffsetMatcher.replaceFirst(replacement);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process datetime with days at specific time (e.g., {datetime+2d@13:00} or {datetime+2d@13:00:rfc3339})
|
// Process datetime with days at specific time (e.g., {datetime+2d@13:00} or {datetime+2d@13:00:rfc3339})
|
||||||
Matcher dateTimeAtTimeMatcher = DATETIME_AT_TIME_PATTERN.matcher(result);
|
result = replaceAllMatches(result, DATETIME_AT_TIME_PATTERN, matcher -> {
|
||||||
if (dateTimeAtTimeMatcher.find()) {
|
String sign = matcher.group("sign");
|
||||||
String sign = dateTimeAtTimeMatcher.group("sign");
|
int days = Integer.parseInt(matcher.group("days"));
|
||||||
int days = Integer.parseInt(dateTimeAtTimeMatcher.group("days"));
|
String timeStr = matcher.group("time");
|
||||||
String timeStr = dateTimeAtTimeMatcher.group("time");
|
String format = matcher.group("format");
|
||||||
String format = dateTimeAtTimeMatcher.group("format");
|
|
||||||
|
|
||||||
LocalDate targetDate = LocalDate.now();
|
LocalDate targetDate = LocalDate.now();
|
||||||
if ("+".equals(sign)) {
|
if ("+".equals(sign)) {
|
||||||
@@ -247,17 +243,14 @@ public class MockService {
|
|||||||
|
|
||||||
LocalTime time = LocalTime.parse(timeStr);
|
LocalTime time = LocalTime.parse(timeStr);
|
||||||
LocalDateTime target = LocalDateTime.of(targetDate, time);
|
LocalDateTime target = LocalDateTime.of(targetDate, time);
|
||||||
|
return formatDateTime(target, format);
|
||||||
String replacement = formatDateTime(target, format);
|
});
|
||||||
result = dateTimeAtTimeMatcher.replaceFirst(replacement);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process date with offset (e.g., {date-4d} or {date-4d:MMM dd, yyyy})
|
// Process date with offset (e.g., {date-4d} or {date-4d:MMM dd, yyyy})
|
||||||
Matcher dateOffsetMatcher = DATE_OFFSET_PATTERN.matcher(result);
|
result = replaceAllMatches(result, DATE_OFFSET_PATTERN, matcher -> {
|
||||||
if (dateOffsetMatcher.find()) {
|
String sign = matcher.group("sign");
|
||||||
String sign = dateOffsetMatcher.group("sign");
|
int days = Integer.parseInt(matcher.group("days"));
|
||||||
int days = Integer.parseInt(dateOffsetMatcher.group("days"));
|
String format = matcher.group("format");
|
||||||
String format = dateOffsetMatcher.group("format");
|
|
||||||
|
|
||||||
LocalDate target = LocalDate.now();
|
LocalDate target = LocalDate.now();
|
||||||
if ("+".equals(sign)) {
|
if ("+".equals(sign)) {
|
||||||
@@ -265,14 +258,29 @@ public class MockService {
|
|||||||
} else {
|
} else {
|
||||||
target = target.minusDays(days);
|
target = target.minusDays(days);
|
||||||
}
|
}
|
||||||
|
return formatDate(target, format);
|
||||||
String replacement = formatDate(target, format);
|
});
|
||||||
result = dateOffsetMatcher.replaceFirst(replacement);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces all matches of a pattern in the input string, using a function
|
||||||
|
* to compute the replacement for each match.
|
||||||
|
*/
|
||||||
|
private String replaceAllMatches(String input, Pattern pattern,
|
||||||
|
java.util.function.Function<Matcher, String> replacer)
|
||||||
|
{
|
||||||
|
Matcher matcher = pattern.matcher(input);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
while (matcher.find()) {
|
||||||
|
String replacement = replacer.apply(matcher);
|
||||||
|
matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
|
||||||
|
}
|
||||||
|
matcher.appendTail(sb);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates a LocalDateTime with the given offset components.
|
* Calculates a LocalDateTime with the given offset components.
|
||||||
* @param base the base datetime to start from
|
* @param base the base datetime to start from
|
||||||
|
|||||||
Reference in New Issue
Block a user