Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using different Header, Body and Query filters for requests/responses #413

Closed
paulopossas opened this issue Jan 23, 2019 · 4 comments
Closed

Comments

@paulopossas
Copy link

Hi,first of all, thanks for this amazing library.
I've been using the same group of Header, Body and Query filters when logging requests and responses. Now I want to have one singular group of these filters for requests and another for responses. Is it possible to do this?
I've tried to achieve this by creating a custom RequestFilter and ResponseFilter but it's not working. The attributes I'm hiding from the requests/responses aren't visible to the rest of my application. If the Request/Response Filter is the correct approach for this issue, where can I find an example of a custom filter?
Thanks in advance.

@whiskeysierra
Copy link
Collaborator

whiskeysierra commented Jan 23, 2019 via email

@paulopossas
Copy link
Author

paulopossas commented Jan 23, 2019

I tried to make one that simply masked the Authorization header, it looked like this:

@Bean
    public RequestFilter requestFilter() {
        return request -> {
            request.getHeaders().replace("Authorization", Collections.singletonList("XXX"));
            return request;
        };
    }

@paulopossas
Copy link
Author

A quick update:
I've tried to return a FilteredHttpRequest in my request filter but that classes' constructor is package private.
Here is my code so far:

@Bean
    public RequestFilter requestFilter() {
        return request -> new FilteredHttpRequest(request, queryFilter(), headerFilter(), bodyFilter());
    }

    /**
     * Overrides LogBook autoconfiguration bean with a custom
     * set of strings to be masked in message body, when logged.
     *
     * <p>Custom strings can be added via logging configuration.
     *
     * @return a BodyFilter bean.
     */
    @Bean
    public BodyFilter bodyFilter() {
        final LogbookProperties.Write write = logbookProperties.getWrite();
        final int maxBodySize = write.getMaxBodySize();

        if (!loggingConfiguration.getMask().isEnabled()) {
            return BodyFilter.none();
        }

        if (maxBodySize < 0) {
            Set<String> properties = new HashSet<>(loggingConfiguration.getMask().getBodyOptions().getBodyStrings());
            return replaceJsonStringProperty(properties, "XXX");
        }

        return BodyFilter.merge(truncate(maxBodySize), defaultValue());
    }

    /**
     * Overrides LogBook autoconfiguration bean with a custom
     * set of strings to be masked in message header, when logged.
     *
     * <p>Custom strings can be added via logging configuration.
     *
     * @return a HeaderFilter bean.
     */
    @Bean
    public HeaderFilter headerFilter() {
        List<String> headers = loggingConfiguration.getMask().getHeadersOptions().getHeaders();

        if (!loggingConfiguration.getMask().isEnabled()) {
            return HeaderFilter.none();
        }

        return headers.stream()
                      .map(header -> HeaderFilters.replaceHeaders(header::equalsIgnoreCase, "XXX"))
                      .collect(toList()).stream()
                      .reduce(HeaderFilter::merge)
                      .orElseGet(HeaderFilter::none);
    }

    /**
     * Overrides LogBook autoconfiguration bean with a custom
     * set of strings to be masked in message query url, when logged.
     *
     * <p>Custom strings can be added via logging configuration.
     *
     * @return a QueryFilter bean.
     */
    @Bean
    public QueryFilter queryFilter() {
        final List<String> parameters = loggingConfiguration.getMask().getParameterOptions().getParameters();

        if (!loggingConfiguration.getMask().isEnabled()) {
            return QueryFilter.none();
        }

        return parameters.stream()
                         .map(parameter -> QueryFilters.replaceQuery(parameter, "XXX"))
                         .collect(toList()).stream()
                         .reduce(QueryFilter::merge)
                         .orElseGet(QueryFilter::none);
    }

@paulopossas
Copy link
Author

Hi, after more thinking, I found a solution. I'll post the code here for posterity. I used the query filter on the filtered body on form-urlencoded because the query params were being added to the body.

@Bean
    public RequestFilter requestFilter() {
        return new RequestFilter() {
            Map<String, List<String>> filteredHeaders = new HashMap<>();
            String filteredQuery;
            String filteredBody;

            @Override
            public HttpRequest filter(HttpRequest request) {
                filteredHeaders = headerFilter().filter(request.getHeaders());
                filteredQuery = queryFilter().filter(request.getQuery());
                try {
                    if (ContentType.APPLICATION_FORM_URLENCODED.getMimeType().equalsIgnoreCase(request.getContentType())) {
                        filteredBody = bodyFilter(true).filter(request.getContentType(), request.getBodyAsString());
                        filteredBody = queryFilter().filter(filteredBody);   
                    } else {
                        filteredBody = bodyFilter(false).filter(request.getContentType(), request.getBodyAsString());
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }

                return new HttpRequest() {
                    @Override public String getRemote() {
                        return request.getRemote();
                    }

                    @Override public String getMethod() {
                        return request.getMethod();
                    }

                    @Override public String getScheme() {
                        return request.getScheme();
                    }

                    @Override public String getHost() {
                        return request.getHost();
                    }

                    @Override public Optional<Integer> getPort() {
                        return request.getPort();
                    }

                    @Override public String getPath() {
                        return request.getPath();
                    }

                    @Override public String getQuery() {
                        return filteredQuery;
                    }

                    @Override public byte[] getBody() throws IOException {
                        return filteredBody.getBytes();
                    }

                    @Override public String getProtocolVersion() {
                        return request.getProtocolVersion();
                    }

                    @Override public Origin getOrigin() {
                        return request.getOrigin();
                    }

                    @Override public Map<String, List<String>> getHeaders() {
                        return filteredHeaders;
                    }

                    @Nullable @Override public String getContentType() {
                        return request.getContentType();
                    }

                    @Override public Charset getCharset() {
                        return request.getCharset();
                    }
                };
            }
        };
    }

    /**
     * Overrides LogBook autoconfiguration bean with a custom
     * set of strings to be masked in message body, when logged.
     *
     * <p>Custom strings can be added via logging configuration.
     *
     * @return a BodyFilter bean.
     */
    public BodyFilter bodyFilter(boolean isForm) {
        final LogbookProperties.Write write = logbookProperties.getWrite();
        final int maxBodySize = write.getMaxBodySize();
        if (!loggingConfiguration.getMask().isEnabled()) {
            return BodyFilter.none();
        }
        if (maxBodySize < 0) {
            Set<String> properties = new HashSet<>(loggingConfiguration.getMask().getBodyOptions().getBodyStrings());
            if (isForm) {
                return BodyFilter.merge(defaultValue(), replaceFormUrlEncodedProperty(properties, "XXX"));
            }
            return BodyFilter.merge(defaultValue(), replaceJsonStringProperty(properties, "XXX"));
        }
        return BodyFilter.merge(truncate(maxBodySize), defaultValue());
    }

    /**
     * Overrides LogBook autoconfiguration bean with a custom
     * set of strings to be masked in message header, when logged.
     *
     * <p>Custom strings can be added via logging configuration.
     *
     * @return a HeaderFilter bean.
     */
    public HeaderFilter headerFilter() {
        List<String> headers = loggingConfiguration.getMask().getHeadersOptions().getHeaders();

        if (!loggingConfiguration.getMask().isEnabled()) {
            return HeaderFilter.none();
        }

        return headers.stream()
                      .map(header -> HeaderFilters.replaceHeaders(header::equalsIgnoreCase, "XXX"))
                      .collect(toList()).stream()
                      .reduce(HeaderFilter::merge)
                      .orElseGet(HeaderFilter::none);
    }

    /**
     * Overrides LogBook autoconfiguration bean with a custom
     * set of strings to be masked in message query url, when logged.
     *
     * <p>Custom strings can be added via logging configuration.
     *
     * @return a QueryFilter bean.
     */
    public QueryFilter queryFilter() {
        final List<String> parameters = loggingConfiguration.getMask().getParameterOptions().getParameters();

        if (!loggingConfiguration.getMask().isEnabled()) {
            return QueryFilter.none();
        }

        return parameters.stream()
                         .map(parameter -> QueryFilters.replaceQuery(parameter, "XXX"))
                         .collect(toList()).stream()
                         .reduce(QueryFilter::merge)
                         .orElseGet(QueryFilter::none);
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants