web/Spring

Spring Webflux url length 제한 413 에러 해결 방법

위들 wedul 2020. 12. 26. 23:04
반응형

프로젝트에서 사용되는 특정 api에 request param의 길이가 길어지는 api가 현재 구조상 어쩔 수 없이 존재하게 되었다.

 

그렇게 조심스럽게 운영하다가 request param의 길이가 너무 길어져서 api에서 413에러를 내뱉으면서 결과를 반환 받지 못하는 문제가 생겼다.

우선 nginx에 있는 request param 길이 관련 설정이 문제를 유발하는지 확인해봤다.

 

 

우선 테스트를 위한 api를 하나 만들었다. 단순하게 요청을 받고 바로 반환하는 api

package com.wedul.reactivetest;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

@RestController
public class TestController {

    @RequestMapping("/heavy")
    public Mono<String> exract(String param) {
        return Mono.just(param);
    }

}

 

Nginx 설정

nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size

nginx 설정에 있는 client_max_body_size 값을 수정하려고 했으나 실질적으로 넘어오는 request가 4kb만 넘어도 에러가 발생하는 상황이라 기본값이 1m인 이 설정은 의미가 없었다.

Syntax:	client_max_body_size size;
Default:	
client_max_body_size 1m;

 

 

 

그럼 실제로 application에서 오류가 발생한 것인지 확인하기 위해 nginx 없이 직접 application에 요청을 날려보았다.

 

실제 에러를 뱉고 있는 부분은 spring application 이었다.

webflux에서 사용하고 있는 netty 설정의 어느 부분을 수정해야하는지 netty 설정을 확인해봤다.

 

 

 

Netty 기본값 설정 변경

Netty에서 제공하고 있는 Http request Decoder 설정정보들을 확인해봤다.

protected int maxInitialLineLength = DEFAULT_MAX_INITIAL_LINE_LENGTH;
protected int maxHeaderSize        = DEFAULT_MAX_HEADER_SIZE;
protected int maxChunkSize         = DEFAULT_MAX_CHUNK_SIZE;
protected boolean validateHeaders  = DEFAULT_VALIDATE_HEADERS;
protected int initialBufferSize    = DEFAULT_INITIAL_BUFFER_SIZE;

여러 기본 설정들이 있었는데 이중 가장 연관성이 있어보이는 주석을 발견했다.

 

/**
* Configure the maximum length that can be decoded for the HTTP request's initial
* line. Defaults to {@link #DEFAULT_MAX_INITIAL_LINE_LENGTH}.
*

DEFAULT_MAX_INITIAL_LINE_LENGTH 이 변수에 기본값을확인해보니 4096이었다.! 

public static final int DEFAULT_MAX_INITIAL_LINE_LENGTH = 4096;

 

4kb만 넘어도 되지 않던 이슈와 유사했고 이 수치를 변경해주기 위해서 spring boot embeded netty 쪽을 확인해봤고 netty web server를 만드는 NettyReactiveWebServerFactory의 내용을 customize해줘야 한다고 한다.

 

 

이 내용을 customize 해주기 위해서는 WebServerFactoryCustomizer 인터페이스를 구현하여 customize 메소드 내부에서 boot에서 실행되는 embeded netty 서버 설정을 바꾸면 적용이 된다고 한다.

 

그래서 간단하게 적용해봤다.

package com.wedul.reactivetest;

import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;

@Component
public class WebConfiguration implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory> {

    @Override
    public void customize(NettyReactiveWebServerFactory serverFactory) {
        serverFactory.addServerCustomizers(httpServer -> httpServer.httpRequestDecoder(
            httpRequestDecoderSpec -> httpRequestDecoderSpec
                .maxInitialLineLength(80960)
        ));
    }
}

 

 

그리고 다시 한번 테스트를 해봤다.

결과는 성공적!

 

 

projectreactor.io/docs/netty/release/reference/index.html#_http_request_decoder

 

Reactor Netty Reference Guide

./../../reactor-netty-examples/src/main/java/reactor/netty/examples/documentation/http/server/clientaddress/CustomForwardedHeaderHandlerApplication.java import java.net.InetSocketAddress; import reactor.core.publisher.Mono; import reactor.netty.DisposableS

projectreactor.io

github.com/weduls/reactive_programming

 

weduls/reactive_programming

spring reactive study. Contribute to weduls/reactive_programming development by creating an account on GitHub.

github.com

 

반응형
1 2 3 4 5 6 7 8 9 ··· 645