Spring REST Docs: как заменить параметры

В моих модульных тестах мы находим

this.mockMvc
  .perform(post("/authenticate")
    .contentType(MediaType.APPLICATION_FORM_URLENCODED)
    .param("username", "[email protected]")
    .param("password", "superSecretPassword"))
  .andExpect(status().isOk())
  .andDo(document("preprocessed-request",
    preprocessRequest(replacePattern(Pattern.compile("superSecretPassword"), "XXX"))));

ср. Документация Spring REST Docs

Это генерирует build/generated-snippets/preprocessed-request/http-request.adoc с содержимым

[source,http]
----
POST /authenticate HTTP/1.1
Content-Type: application/x-www-form-urlencoded

username=user%40example.com&password=superSecretPassword
----

Но я ожидаю, что пароль будет замаскирован из-за replacePattern():

[source,http]
----
POST /authenticate HTTP/1.1
Content-Type: application/x-www-form-urlencoded

username=user%40example.com&password=XXX
----

Что я могу сделать?


person Johannes Flügel    schedule 22.10.2015    source источник


Ответы (1)


Замена шаблона не имеет никакого эффекта из-за досадного побочного эффекта того, как MockMvc обрабатывает параметры запроса. replacePattern воздействует на содержимое, т. е. на тело запроса, но MockMvc фактически не включает в тело параметры, закодированные в форме.

Spring REST Docs достаточно умен, чтобы справиться с этим при создании фрагментов, например. для запроса формы URL, закодированного POST, он просматривает параметры, чтобы выяснить, каким должно быть тело запроса. Он не применяет те же самые умные способности при применении replacePattern.

Вы по-прежнему можете замаскировать пароль, используя свой собственный OperationPreprocessor, который изменяет карту параметров. Например:

private OperationPreprocessor maskPassword() {
    return new PasswordMaskingPreprocessor();
}

private static class PasswordMaskingPreprocessor implements OperationPreprocessor {

    @Override
    public OperationRequest preprocess(OperationRequest request) {
        Parameters parameters = new Parameters();
        parameters.putAll(request.getParameters());
        parameters.set("password", "XXX");
        return new OperationRequestFactory().create(request.getUri(),
                request.getMethod(), request.getContent(), request.getHeaders(),
                parameters, request.getParts());
    }

    @Override
    public OperationResponse preprocess(OperationResponse response) {
        return response;
    }

}

Затем вы можете использовать этот новый препроцессор вместо replacePattern:

this.mockMvc
  .perform(post("/authenticate")
    .contentType(MediaType.APPLICATION_FORM_URLENCODED)
    .param("username", "[email protected]")
    .param("password", "superSecretPassword"))
  .andExpect(status().isOk())
  .andDo(document("preprocessed-request",
    preprocessRequest(maskPassword())));
person Andy Wilkinson    schedule 22.10.2015
comment
Я считаю очень полезным написать свои собственные OperationPreprocessors. Можно ли добавить его в документацию Spring REST Docs< /а>? - person Johannes Flügel; 23.10.2015