Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -230,18 +230,18 @@ private LoginContext buildLoginContext() throws LoginException {
}

@Override
protected final <T> T doExecute(final URI url, final @Nullable String uriTemplate,
protected final <T> @Nullable T doExecute(final URI url, final @Nullable String uriTemplate,
final @Nullable HttpMethod method, final @Nullable RequestCallback requestCallback,
final @Nullable ResponseExtractor<T> responseExtractor) throws RestClientException {

try {
LoginContext lc = buildLoginContext();
lc.login();
Subject serviceSubject = lc.getSubject();
return Subject.doAs(serviceSubject, new PrivilegedAction<T>() {
return Subject.doAs(serviceSubject, new PrivilegedAction<@Nullable T>() {

@Override
public T run() {
public @Nullable T run() {
return KerberosRestTemplate.this.doExecuteSubject(url, uriTemplate, method, requestCallback,
responseExtractor);
}
Expand All @@ -256,14 +256,14 @@ public T run() {
}
}

private <T> T doExecuteSubject(URI url, @Nullable String uriTemplate, @Nullable HttpMethod method,
private <T> @Nullable T doExecuteSubject(URI url, @Nullable String uriTemplate, @Nullable HttpMethod method,
@Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor)
throws RestClientException {
T result = super.doExecute(url, uriTemplate, method, requestCallback, responseExtractor);
if (result == null) {
throw new RestClientException("doExecute returned null");
}
return result;
// RestTemplate.doExecute() legitimately returns null, e.g. when there is
// no ResponseExtractor (delete(), put()) or when the extractor maps a
// response such as 204 No Content to null. Let the null pass through
// instead of failing a successful request.
return super.doExecute(url, uriTemplate, method, requestCallback, responseExtractor);
}

private static final class ClientLoginConfig extends Configuration {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ void throwsOriginalException() {
.isThrownBy(() -> this.restTemplate.getForObject(this.baseUrl + "/notfound", String.class));
}

@Test
void deleteWithNoContentSucceeds() {
// gh-19935: RestTemplate.doExecute() legitimately returns null for delete();
// a successful 204 must not surface as RestClientException.
this.restTemplate.delete(this.baseUrl + "/delete");
}

private void setUpClient() {
Map<String, Object> loginOptions = new HashMap<>();
loginOptions.put("refreshKrb5Config", "true");
Expand Down Expand Up @@ -136,6 +143,16 @@ else if (header.startsWith("Negotiate ")) {
return getRequest(request, helloWorldBytes, textContentType.toString());
}
}
if (request.getPath().equals("/delete")) {
String header = request.getHeader(HttpHeaders.AUTHORIZATION);
if (header == null) {
return new MockResponse().setResponseCode(401)
.addHeader(HttpHeaders.WWW_AUTHENTICATE, "Negotiate");
}
else if (header.startsWith("Negotiate ")) {
return new MockResponse().setResponseCode(204);
}
}
return new MockResponse().setResponseCode(404);
}
catch (Throwable ex) {
Expand Down