Completed
Pull Request — dev (#265)
by Konstantin
02:32
created

postHandle(HttpServletRequest,HttpServletResponse,Object,ModelAndView)   B

Complexity

Conditions 5

Size

Total Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
c 1
b 0
f 0
dl 0
loc 38
rs 8.5013
1
package easytests.swagger;
2
3
import com.atlassian.oai.validator.model.Request;
4
import com.atlassian.oai.validator.model.Response;
5
import com.atlassian.oai.validator.report.ValidationReport;
6
import java.io.IOException;
7
import javax.servlet.http.HttpServletRequest;
8
import javax.servlet.http.HttpServletResponse;
9
import org.slf4j.Logger;
10
import org.slf4j.LoggerFactory;
11
import org.springframework.core.io.support.EncodedResource;
12
import org.springframework.lang.Nullable;
13
import org.springframework.web.servlet.ModelAndView;
14
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
15
import org.springframework.web.util.ContentCachingResponseWrapper;
16
17
18
/**
19
 * @author atlassian
20
 * An Interceptor which validates incoming requests against the defined swagger interface.
21
 */
22
@SuppressWarnings("checkstyle:MultipleStringLiterals")
23
public class SwaggerValidationInterceptor extends HandlerInterceptorAdapter {
24
25
    private static final Logger LOG = LoggerFactory.getLogger(SwaggerValidationInterceptor.class);
26
27
    private final SwaggerRequestValidationService swaggerRequestValidationService;
28
29
    public SwaggerValidationInterceptor(final EncodedResource swaggerInterface) throws IOException {
30
        this(new SwaggerRequestValidationService(swaggerInterface));
31
    }
32
33
    SwaggerValidationInterceptor(final SwaggerRequestValidationService swaggerRequestValidationService) {
34
        this.swaggerRequestValidationService = swaggerRequestValidationService;
35
    }
36
37
    /**
38
     * Validates the given requests. If a request is defined but invalid against the Swagger schema
39
     * an {@link InvalidRequestException} will be thrown leading to an error response.
40
     * <p>
41
     * Only {@link ResettableRequestServletWrapper} can be validated. Wrapping is done within the
42
     * {@link SwaggerValidationFilter}.
43
     *
44
     * @param servletRequest  the {@link HttpServletRequest} to validate
45
     * @param servletResponse the servlet response
46
     * @param handler         a handler
47
     * @return {@code true} if the request is valid against or not defined in the Swagger schema or
48
     * the servlet is not a {@link ResettableRequestServletWrapper}
49
     * @throws Exception if the request is invalid against the Swagger schema or the requests body
50
     *                   can't be read
51
     */
52
    @Override
53
    public boolean preHandle(
54
            final HttpServletRequest servletRequest,
55
            final HttpServletResponse servletResponse,
56
            final Object handler) throws Exception {
57
        // only wrapped servlet requests can be validated - see: SwaggerValidationFilter
58
        if (!(servletRequest instanceof ResettableRequestServletWrapper)) {
59
            return true;
60
        }
61
62
        // validate the request
63
        final ResettableRequestServletWrapper resettableRequest = (ResettableRequestServletWrapper) servletRequest;
64
        final String requestLoggingKey = servletRequest.getMethod() + "#" + servletRequest.getRequestURI();
65
        LOG.debug("Swagger request validation: {}", requestLoggingKey);
66
67
        final Request request = swaggerRequestValidationService.buildRequest(resettableRequest);
68
        final ValidationReport validationReport = swaggerRequestValidationService.validateRequest(request);
69
        if (!validationReport.hasErrors()) {
70
            LOG.debug("Swagger validation: {} - The request is valid.", requestLoggingKey);
71
        } else if (!swaggerRequestValidationService.isDefinedSwaggerRequest(validationReport)) {
72
            LOG.info("Swagger validation: {} - The request is not defined in the Swagger schema. Ignoring it.",
73
                    requestLoggingKey);
74
        } else {
75
            final InvalidRequestException invalidRequestException = new InvalidRequestException(validationReport);
76
            LOG.info("Swagger validation: {} - The REST request is invalid: {}", requestLoggingKey,
77
                    invalidRequestException.getMessage());
78
            throw invalidRequestException;
79
        }
80
81
        // reset the requests servlet input stream after reading it on former step
82
        resettableRequest.resetInputStream();
83
        return true;
84
    }
85
86
    @Override
87
    public void postHandle(
88
            HttpServletRequest servletRequest,
89
            HttpServletResponse servletResponse,
90
            Object handler,
91
            @Nullable ModelAndView modelAndView) throws Exception {
92
        // only wrapped servlet requests can be validated - see: SwaggerValidationFilter
93
        if (!(servletRequest instanceof ResettableRequestServletWrapper)
94
                || !(servletResponse instanceof ContentCachingResponseWrapper)) {
95
            return;
96
        }
97
98
        // validate the request
99
        final ResettableRequestServletWrapper resettableRequest = (ResettableRequestServletWrapper) servletRequest;
100
        final ContentCachingResponseWrapper cachingResponse = (ContentCachingResponseWrapper) servletResponse;
101
102
        final Request request = swaggerRequestValidationService.buildRequest(resettableRequest);
103
        final Response response = swaggerRequestValidationService.buildResponse(cachingResponse);
104
105
        final String requestLoggingKey = servletRequest.getMethod() + "#" + servletRequest.getRequestURI()
106
                + "#" + response.getStatus();
107
        LOG.info("Swagger response validation: {}", requestLoggingKey);
108
109
        final ValidationReport validationReport = swaggerRequestValidationService.validateResponse(
110
                request.getPath(),
111
                request.getMethod(),
112
                response
113
        );
114
        if (!validationReport.hasErrors()) {
115
            LOG.debug("Swagger validation: {} - The response is valid.", requestLoggingKey);
116
        } else if (!swaggerRequestValidationService.isDefinedSwaggerRequest(validationReport)) {
117
            LOG.info("Swagger validation: {} - The request/response is not defined in the Swagger schema. Ignoring it.",
118
                    requestLoggingKey);
119
        } else {
120
            final InvalidResponseException invalidReponseException = new InvalidResponseException(validationReport);
121
            LOG.warn("Swagger validation: {} - The REST response is invalid: {}", requestLoggingKey,
122
                    invalidReponseException.getMessage());
123
            throw invalidReponseException;
124
        }
125
    }
126
}
127