Spring에서 Jetty를 사용자 정의하는 방법 - 사용자 정의 오류 핸들러

10904 단어 javawebspringjetty
지난 주에 우리는 어떤 경우에 우리 애플리케이션이 오류에 대한 중복 데이터(예: stacktrace)를 표시하고 있음을 발견했습니다. Jetty인 애플리케이션 컨테이너에 의해 처리되는 오류가 있을 때 발생합니다. 예를 들어 X-FORWARDED-PORT: some-not-numeric-value와 같은 헤더를 보내면 NumberFormatException가 발생하고 전체 스택 추적이 표시됩니다.

문서를 살펴보고 기본 오류 처리기에서 스택 추적을 숨길 수 있음을 확인했습니다. 그 대신 커스텀으로 교체하기로 했습니다. 이를 통해 추가 로깅 논리를 추가하고 출력을 사용자 지정할 수 있습니다. 그리고 이것은 그것을하는 방법에 대한 간단한 설명입니다. ;-)

사용자 지정 오류 처리기를 구현하기 위해 메서드를 확장org.eclipse.jetty.server.handler.AbstractHandler하고 재정의handle할 수 있습니다. 아래 코드 스니펫에는 예제 핸들러가 있습니다. 명확성을 위해 코드, 오류 메시지 및 URL이 사용된 간단한 텍스트(content-type text/plain )를 항상 반환합니다.

클라이언트의 헤더, 추가 로깅 등에 기반한 다른 응답과 같은 추가 논리를 추가하여 이를 확장할 수 있습니다. :-)

package pl.net.banach.customizeJetty;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.io.ByteBufferOutputStream;
import org.eclipse.jetty.server.Dispatcher;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.StringUtil;

public class CustomJettyErrorHandler extends AbstractHandler {

    @Override
    public void handle(String target, Request baseRequest, 
                       HttpServletRequest request,
                       HttpServletResponse response) 
                       throws IOException, ServletException {


        try {
            // Get error message, sanitize it, just in case.
            String message = StringUtil.sanitizeXmlString(
                (String) request.getAttribute(Dispatcher.ERROR_MESSAGE)
            );

            // Get error code that will returned
            int code = response.getStatus();

            var charset = StandardCharsets.UTF_8;

            // Get writer used
            var buffer = baseRequest.getResponse().getHttpOutput().getBuffer();
            var out = new ByteBufferOutputStream(buffer);
            var writer = new PrintWriter(new OutputStreamWriter(out, charset));

            // Set content type, encoding and write response
            response.setContentType(MimeTypes.Type.TEXT_PLAIN.asString());
            response.setCharacterEncoding(charset.name());
            writer.print("HTTP ERROR ");
            writer.print(code);
            writer.print("\nMessage: ");
            writer.print(message);
            writer.print("\nURI: ");
            writer.print(request.getRequestURI());


            writer.flush();
        } catch (BufferOverflowException e) {
            baseRequest.getResponse().resetContent();
        }

        baseRequest.getHttpChannel().sendResponseAndComplete();
    }
}


오류 처리기가 준비되면 등록하기 쉽습니다. 이를 위해 WebServerFactoryCustomizer 주석이 있는 @Configuration를 구현하는 사용자 지정 구성을 만듭니다. customize 메서드에서 사용자 지정 프로그램을 만들고 새로 만든 오류 처리기를 추가합니다.

간단해 보이지만 Spring@ComponentScan 주석으로 스캔되는 패키지에 이 구성 클래스를 반드시 넣어야 합니다!

package pl.net.banach.customizeJetty;

import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JettyConfiguration
            implements WebServerFactoryCustomizer<JettyServletWebServerFactory> {

    @Override
    public void customize(JettyServletWebServerFactory factory) {
        JettyServerCustomizer customizer = server -> {
            server.setErrorHandler(new CustomJettyErrorHandler());
        };
        factory.addServerCustomizers(customizer);
    }
}


그게 전부입니다. 지금부터 Jetty(응용 프로그램 서버)로 이동하는 모든 오류는 사용자 지정 처리기에 의해 처리됩니다. :-)

좋은 웹페이지 즐겨찾기