Spring Cloud Gateway (3) response body 수정

ljft183·2022년 12월 12일
0

Spring_Cloud_Gateway

목록 보기
3/3

response body 수정

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);
    }

CsvSchema 이용한 json data 변환 적용

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 {}
}

0개의 댓글