egov4.0 spring cloud gateway 사용중 data 후처리를 위해
ServerHttpResponseDecorator 이용한 response body 수정
@Override
public GatewayFilter apply(Config config) {
return new OrderedGatewayFilter((exchange, chain) -> {
//data 변환 조건
if(true) {
DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory();
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(response) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (body instanceof Flux) {
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
DefaultDataBuffer joinedBuffers = new DefaultDataBufferFactory().join(dataBuffers);
byte[] content = new byte[joinedBuffers.readableByteCount()];
joinedBuffers.read(content);
//
String responseBody = new String(content, StandardCharsets.UTF_8);
try {
/*
///////////////////////////////////////////////////
// (byte[] type) content 원하는 양식으로 변경 후 재주입
///////////////////////////////////////////////////
*/
return bufferFactory.wrap(content);
} catch (Exception e) {
// data 수정 없이 return
return joinedBuffers;
}
}));
}
return super.writeWith(body);
}
};
//new builded response
return chain.filter(exchange.mutate().response(decoratedResponse).build());
}
// 기존 return
else{
return chain.filter(exchange);
}
// filter 우선 적용 (-2 >= x) or Ordered.HIGHEST_PRECEDENCE
}, -2);
}
json 형태의 response body data
CSV 파일 형태로 출력
//Custon filter
@Component
@Slf4j
public class ApiCsvConvertFilter extends AbstractGatewayFilterFactory<ApiCsvConvertFilter.Config> {
@Autowired
private final AuthMapper authMapper;
ApiCsvConvertFilter(AuthMapper authMapper) {
super(ApiCsvConvertFilter.Config.class);
this.authMapper = authMapper;
}
@Override
public GatewayFilter apply(Config config) {
return new OrderedGatewayFilter((exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
//권한 확인
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("actionUrl", request.getURI().getPath().substring(4));
HashMap<String, Object> actionCheckMap = authMapper.checkActionUrlByUrl(map);
//data 변환 조건
if((exchange.getRequest().getQueryParams().containsKey("type")
? exchange.getRequest().getQueryParams().get("type").get(0).equals("csv")
: false)
&& actionCheckMap != null) {
DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory();
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(response) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (body instanceof Flux) {
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
DefaultDataBuffer joinedBuffers = new DefaultDataBufferFactory().join(dataBuffers);
byte[] content = new byte[joinedBuffers.readableByteCount()];
joinedBuffers.read(content);
//
String responseBody = new String(content, StandardCharsets.UTF_8);
CsvSchema.Builder csvSchemaBuilder = CsvSchema.builder();
ObjectMapper objectMapper = new ObjectMapper();
try {
JsonNode jsonTree1 = objectMapper.readTree(responseBody);
JsonNode jsonTree = objectMapper.readTree(content);
JsonNode firstObject = jsonTree1.elements().next();
firstObject.fieldNames().forEachRemaining(csvSchemaBuilder::addColumn);
CsvSchema csvSchema = csvSchemaBuilder.build().withHeader();
CsvMapper csvMapper = new CsvMapper();
//
return bufferFactory.wrap(csvMapper.writerFor(JsonNode.class).with(csvSchema).writeValueAsBytes(jsonTree1));
} catch (Exception e) {
log.error("Exception : {}", e.fillInStackTrace());
//
return joinedBuffers;
}
}));
}
return super.writeWith(body);
}
};
try{
List<String> header = request.getHeaders().get("User-Agent");
String browser = "";
if(header.get(0).indexOf("MSIE") > -1){
browser = "MSIE";
}
else if(header.get(0).indexOf("Chrome") > -1){
browser = "Chrome";
}
else if(header.get(0).indexOf("Opera") > -1){
browser = "Opera";
}
else if(header.get(0).indexOf("Firefox") > -1){
browser = "Firefox";
}
else if(header.get(0).indexOf("Mozilla") > -1){
if(header.get(0).indexOf("Firefox") > -1){
browser = "Firefox";
}
else{
browser = "MSIE";
}
}
else{
browser = "MSIE";
}
String fileName = (String) actionCheckMap.get("api_name") + ".csv";
String encodedFilename = "";
if (browser.equals("MSIE")) {
encodedFilename = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
}
else if(browser.equals("Firefox")) {
encodedFilename = "\""
+ new String(fileName.getBytes("UTF-8"), "8859_1") + "\"";
}
else if (browser.equals("Opera")) {
encodedFilename = "\""
+ new String(fileName.getBytes("UTF-8"), "8859_1") + "\"";
}
else if(browser.equals("Chrome")) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < fileName.length(); i++) {
char c = fileName.charAt(i);
if (c > '~') {
sb.append(URLEncoder.encode("" + c, "UTF-8"));
} else {
sb.append(c);
}
}
encodedFilename = sb.toString();
}
else {
log.error("Exception : Not supported browser");
}
//response header content type 수정
decoratedResponse.getHeaders().set("Set-Cookie", "fileDownload=true; path=/");
decoratedResponse.getHeaders().set("Content-Disposition", "attachment; filename=" + encodedFilename);
if("Opera".equals(browser)){
decoratedResponse.getHeaders().setContentType(MediaType.APPLICATION_OCTET_STREAM);
}
} catch (Exception e) {
log.error("Exception : {}", e.fillInStackTrace());
decoratedResponse.getHeaders().set("Set-Cookie", "fileDownload=true; path=/");
}
//new builded response
return chain.filter(exchange.mutate().response(decoratedResponse).build());
}
// 기존 return
else{
return chain.filter(exchange);
}
// filter 우선 적용 (-2 >= x) or Ordered.HIGHEST_PRECEDENCE
}, -2);
}
public static class Config {}
}