001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.eclipse.aether.spi.connector.transport.http.RFC9457; 020 021import java.io.IOException; 022 023/** 024 * A reporter for RFC 9457 messages. 025 * RFC 9457 is a standard for reporting problems in HTTP responses as a JSON object. 026 * There are members specified in the RFC but none of those appear to be required, 027 * @see <a href=https://www.rfc-editor.org/rfc/rfc9457#section-3-7>rfc9457 section 3.7</a> 028 * Given the JSON fields are not mandatory, this reporter simply extracts the body of the 029 * response without validation. 030 * A RFC 9457 message is detected by the content type "application/problem+json". 031 * 032 * @param <T> The type of the response. 033 * @param <E> The base exception type to throw if the response is not a RFC9457 message. 034 */ 035public abstract class RFC9457Reporter<T, E extends Exception> { 036 protected abstract boolean isRFC9457Message(T response); 037 038 protected abstract int getStatusCode(T response); 039 040 protected abstract String getReasonPhrase(T response); 041 042 protected abstract String getBody(T response) throws IOException; 043 044 protected boolean hasRFC9457ContentType(String contentType) { 045 return "application/problem+json".equals(contentType); 046 } 047 048 /** 049 * Generates a {@link HttpRFC9457Exception} if the response type is a RFC 9457 message. 050 * Otherwise, it throws the base exception 051 * 052 * @param response The response to check for RFC 9457 messages. 053 * @param baseException The base exception to throw if the response is not a RFC 9457 message. 054 */ 055 public void generateException(T response, BiConsumerChecked<Integer, String, E> baseException) 056 throws E, HttpRFC9457Exception { 057 int statusCode = getStatusCode(response); 058 String reasonPhrase = getReasonPhrase(response); 059 060 if (isRFC9457Message(response)) { 061 String body; 062 try { 063 body = getBody(response); 064 } catch (IOException ignore) { 065 // No body found but it is representing a RFC 9457 message due to the content type. 066 throw new HttpRFC9457Exception(statusCode, reasonPhrase, RFC9457Payload.INSTANCE); 067 } 068 069 if (body != null && !body.isEmpty()) { 070 RFC9457Payload rfc9457Payload = RFC9457Parser.parse(body); 071 throw new HttpRFC9457Exception(statusCode, reasonPhrase, rfc9457Payload); 072 } 073 throw new HttpRFC9457Exception(statusCode, reasonPhrase, RFC9457Payload.INSTANCE); 074 } 075 baseException.accept(statusCode, reasonPhrase); 076 } 077}