Skip to content

Commit a4c4240

Browse files
authored
Send "Accept" request header to indicate RFC 9457 compliance (#1846)
Also evaluate RFC 9457 responses for PUT requests Ignore content-type attributes when checking for RFC 9457 responses. Add tests to check for proper "Accept" headers for GET/HEAD/PUT Add IT against Cloudflare provided RFC 9457 endpoints (https://blog.cloudflare.com/rfc-9457-agent-error-pages/#how-to-use-it) This closes #1845
1 parent 41fe1eb commit a4c4240

12 files changed

Lines changed: 313 additions & 51 deletions

File tree

maven-resolver-spi/src/main/java/org/eclipse/aether/spi/connector/transport/http/HttpConstants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ private HttpConstants() {}
3636

3737
public static final int PRECONDITION_FAILED = 412;
3838

39+
public static final String ACCEPT = "Accept";
40+
3941
public static final String ACCEPT_ENCODING = "Accept-Encoding";
4042

4143
public static final String CACHE_CONTROL = "Cache-Control";

maven-resolver-spi/src/main/java/org/eclipse/aether/spi/connector/transport/http/RFC9457/RFC9457Parser.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@
3030
import com.google.gson.JsonParseException;
3131

3232
public class RFC9457Parser {
33-
private static Gson gson = new GsonBuilder()
33+
private static final Gson GSON = new GsonBuilder()
3434
.registerTypeAdapter(RFC9457Payload.class, new RFC9457PayloadAdapter())
3535
.create();
3636

3737
public static RFC9457Payload parse(String data) {
38-
return gson.fromJson(data, RFC9457Payload.class);
38+
return GSON.fromJson(data, RFC9457Payload.class);
3939
}
4040

4141
private static class RFC9457PayloadAdapter implements JsonDeserializer<RFC9457Payload> {

maven-resolver-spi/src/main/java/org/eclipse/aether/spi/connector/transport/http/RFC9457/RFC9457Payload.java

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,24 @@ public URI getInstance() {
6868

6969
@Override
7070
public String toString() {
71-
return "RFC9457Payload {" + "type="
72-
+ type + ", status="
73-
+ status + ", title='"
74-
+ title + ", detail='"
75-
+ detail + ", instance="
76-
+ instance + '}';
71+
StringBuilder builder = new StringBuilder();
72+
builder.append("RFC9457Payload [");
73+
if (type != null) {
74+
builder.append("type=").append(type).append(", ");
75+
}
76+
if (status != null) {
77+
builder.append("status=").append(status).append(", ");
78+
}
79+
if (title != null) {
80+
builder.append("title=").append(title).append(", ");
81+
}
82+
if (detail != null) {
83+
builder.append("detail=").append(detail).append(", ");
84+
}
85+
if (instance != null) {
86+
builder.append("instance=").append(instance);
87+
}
88+
builder.append("]");
89+
return builder.toString();
7790
}
7891
}

maven-resolver-spi/src/main/java/org/eclipse/aether/spi/connector/transport/http/RFC9457/RFC9457Reporter.java

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,19 @@
2424
* A reporter for RFC 9457 messages.
2525
* RFC 9457 is a standard for reporting problems in HTTP responses as a JSON object.
2626
* There are members specified in the RFC but none of those appear to be required,
27-
* @see <a href=https://www.rfc-editor.org/rfc/rfc9457#section-3-7>rfc9457 section 3.7</a>
27+
* see <a href=https://www.rfc-editor.org/rfc/rfc9457#section-3-7>rfc9457 section 3.7</a>
2828
* Given the JSON fields are not mandatory, this reporter simply extracts the body of the
2929
* response without validation.
30-
* A RFC 9457 message is detected by the content type "application/problem+json".
30+
* A RFC 9457 message is detected by the content type {@value #CONTENT_TYPE_PROBLEM_DETAILS_JSON} in the response header.
3131
*
3232
* @param <T> The type of the response.
3333
* @param <E> The base exception type to throw if the response is not a RFC9457 message.
34+
* @param <R> The type of the request or request builder (which allows to modify headers)
35+
* @see <a href=https://www.rfc-editor.org/rfc/rfc9457#section-3-7>RFC 9457</a>
3436
*/
35-
public abstract class RFC9457Reporter<T, E extends Exception> {
37+
public abstract class RFC9457Reporter<T, E extends Exception, R> {
38+
public static final String CONTENT_TYPE_PROBLEM_DETAILS_JSON = "application/problem+json";
39+
3640
protected abstract boolean isRFC9457Message(T response);
3741

3842
protected abstract int getStatusCode(T response);
@@ -41,8 +45,24 @@ public abstract class RFC9457Reporter<T, E extends Exception> {
4145

4246
protected abstract String getBody(T response) throws IOException;
4347

48+
/**
49+
* Prepares the request to accept RFC 9457 responses.
50+
* This involves setting/updating the "Accept" header to include "application/problem+json".
51+
* @param request The request or request builder to prepare
52+
* @see <a href=https://www.rfc-editor.org/rfc/rfc9457#section-3-2>RFC 9457 section 3.2</a>
53+
*/
54+
public abstract void prepareRequest(R request);
55+
4456
protected boolean hasRFC9457ContentType(String contentType) {
45-
return "application/problem+json".equals(contentType);
57+
if (contentType == null) {
58+
return false;
59+
}
60+
// strip off parameters
61+
int idx = contentType.indexOf(';');
62+
if (idx > -1) {
63+
contentType = contentType.substring(0, idx);
64+
}
65+
return CONTENT_TYPE_PROBLEM_DETAILS_JSON.equals(contentType);
4666
}
4767

4868
/**
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.eclipse.aether.spi.connector.transport.http.RFC9457;
20+
21+
import org.junit.jupiter.api.Test;
22+
23+
import static org.junit.jupiter.api.Assertions.*;
24+
25+
class RFC9457ReporterTest {
26+
27+
@Test
28+
void hasRFC9457ContentType() {
29+
RFC9457Reporter<Object, Exception, Object> reporter = new RFC9457Reporter<Object, Exception, Object>() {
30+
@Override
31+
protected boolean isRFC9457Message(Object response) {
32+
return false;
33+
}
34+
35+
@Override
36+
protected int getStatusCode(Object response) {
37+
return 0;
38+
}
39+
40+
@Override
41+
protected String getReasonPhrase(Object response) {
42+
return null;
43+
}
44+
45+
@Override
46+
protected String getBody(Object response) {
47+
return null;
48+
}
49+
50+
@Override
51+
public void prepareRequest(Object request) {}
52+
};
53+
assertTrue(reporter.hasRFC9457ContentType("application/problem+json"));
54+
assertTrue(reporter.hasRFC9457ContentType("application/problem+json; charset=utf-8"));
55+
}
56+
}

0 commit comments

Comments
 (0)