001/* 002 * Copyright © 2025 CUI-OpenSource-Software (info@cuioss.de) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package de.cuioss.http.client.handler; 017 018import lombok.Getter; 019import lombok.RequiredArgsConstructor; 020 021/** 022 * HTTP status code classification enum based on RFC 7231 status code families. 023 * 024 * <p>This enum provides a type-safe way to classify HTTP status codes into their standard 025 * families as defined by RFC 7231. It includes utility methods for checking status code 026 * categories and determining appropriate response handling strategies.</p> 027 * 028 * <h3>Design Principles</h3> 029 * <ul> 030 * <li><strong>RFC Compliance</strong> - Follows RFC 7231 HTTP status code definitions</li> 031 * <li><strong>Type Safety</strong> - Enum-based classification prevents invalid categories</li> 032 * <li><strong>Utility Methods</strong> - Convenient static methods for common checks</li> 033 * <li><strong>Range Validation</strong> - Validates status codes against standard ranges</li> 034 * </ul> 035 * 036 * <h3>Status Code Families</h3> 037 * <ul> 038 * <li><strong>1xx Informational</strong> - Request received, continuing process (100-199)</li> 039 * <li><strong>2xx Success</strong> - Action successfully received, understood, and accepted (200-299)</li> 040 * <li><strong>3xx Redirection</strong> - Further action must be taken to complete request (300-399)</li> 041 * <li><strong>4xx Client Error</strong> - Request contains bad syntax or cannot be fulfilled (400-499)</li> 042 * <li><strong>5xx Server Error</strong> - Server failed to fulfill apparently valid request (500-599)</li> 043 * <li><strong>Unknown</strong> - Status codes outside standard ranges or error conditions</li> 044 * </ul> 045 * 046 * <h3>Usage Examples</h3> 047 * <pre> 048 * // Classify status codes 049 * HttpStatusFamily family = HttpStatusFamily.fromStatusCode(200); 050 * assert family == HttpStatusFamily.SUCCESS; 051 * 052 * // Check for success 053 * if (HttpStatusFamily.isSuccess(response.statusCode())) { 054 * // Handle successful response 055 * } 056 * 057 * // Check for errors 058 * if (HttpStatusFamily.isClientError(response.statusCode())) { 059 * // Handle client error (4xx) 060 * } else if (HttpStatusFamily.isServerError(response.statusCode())) { 061 * // Handle server error (5xx) 062 * } 063 * 064 * // Validate status code range 065 * if (HttpStatusFamily.isValid(statusCode)) { 066 * // Process valid HTTP status code 067 * } 068 * 069 * // Family-specific checks 070 * HttpStatusFamily family = HttpStatusFamily.REDIRECTION; 071 * if (family.contains(302)) { 072 * // Handle redirection logic 073 * } 074 * </pre> 075 * 076 * <h3>Common Status Codes by Family</h3> 077 * <ul> 078 * <li><strong>2xx Success:</strong> 200 OK, 201 Created, 204 No Content</li> 079 * <li><strong>3xx Redirection:</strong> 301 Moved Permanently, 302 Found, 304 Not Modified</li> 080 * <li><strong>4xx Client Error:</strong> 400 Bad Request, 401 Unauthorized, 404 Not Found</li> 081 * <li><strong>5xx Server Error:</strong> 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable</li> 082 * </ul> 083 * 084 * @since 1.0 085 * @see HttpHandler 086 */ 087@RequiredArgsConstructor 088public enum HttpStatusFamily { 089 090 /** 091 * 1xx: Informational - Request received, a continuing process. 092 */ 093 INFORMATIONAL(100, 199, "Informational"), 094 095 /** 096 * 2xx: Success - The action was successfully received, understood, and accepted. 097 */ 098 SUCCESS(200, 299, "Success"), 099 100 /** 101 * 3xx: Redirection - Further action needs to be taken to complete the request. 102 */ 103 REDIRECTION(300, 399, "Redirection"), 104 105 /** 106 * 4xx: Client Error - The request contains bad syntax or cannot be fulfilled. 107 */ 108 CLIENT_ERROR(400, 499, "Client Error"), 109 110 /** 111 * 5xx: Server Error - The server failed to fulfill an apparently valid request. 112 */ 113 SERVER_ERROR(500, 599, "Server Error"), 114 115 /** 116 * Unknown - Used for status codes outside the standard ranges or for error conditions. 117 */ 118 UNKNOWN(-1, -1, "Unknown"); 119 120 @Getter private final int minCode; 121 @Getter private final int maxCode; 122 @Getter private final String description; 123 124 /** 125 * Checks if the given status code belongs to this family. 126 * 127 * @param statusCode the HTTP status code to check 128 * @return true if the status code belongs to this family, false otherwise 129 */ 130 public boolean contains(int statusCode) { 131 if (this == UNKNOWN) { 132 return statusCode < 100 || statusCode > 599; 133 } 134 return statusCode >= minCode && statusCode <= maxCode; 135 } 136 137 /** 138 * Gets the HTTP status code family for the given status code. 139 * 140 * @param statusCode the HTTP status code 141 * @return the corresponding HttpStatusFamily family 142 */ 143 public static HttpStatusFamily fromStatusCode(int statusCode) { 144 for (HttpStatusFamily family : values()) { 145 if (family.contains(statusCode)) { 146 return family; 147 } 148 } 149 return UNKNOWN; 150 } 151 152 /** 153 * Checks if the given status code indicates a successful response (2xx). 154 * 155 * @param statusCode the HTTP status code to check 156 * @return true if the status code indicates success, false otherwise 157 */ 158 public static boolean isSuccess(int statusCode) { 159 return SUCCESS.contains(statusCode); 160 } 161 162 /** 163 * Checks if the given status code indicates a client error (4xx). 164 * 165 * @param statusCode the HTTP status code to check 166 * @return true if the status code indicates a client error, false otherwise 167 */ 168 public static boolean isClientError(int statusCode) { 169 return CLIENT_ERROR.contains(statusCode); 170 } 171 172 /** 173 * Checks if the given status code indicates a server error (5xx). 174 * 175 * @param statusCode the HTTP status code to check 176 * @return true if the status code indicates a server error, false otherwise 177 */ 178 public static boolean isServerError(int statusCode) { 179 return SERVER_ERROR.contains(statusCode); 180 } 181 182 /** 183 * Checks if the given status code indicates a redirection (3xx). 184 * 185 * @param statusCode the HTTP status code to check 186 * @return true if the status code indicates a redirection, false otherwise 187 */ 188 public static boolean isRedirection(int statusCode) { 189 return REDIRECTION.contains(statusCode); 190 } 191 192 /** 193 * Checks if the given status code indicates an informational response (1xx). 194 * 195 * @param statusCode the HTTP status code to check 196 * @return true if the status code indicates an informational response, false otherwise 197 */ 198 public static boolean isInformational(int statusCode) { 199 return INFORMATIONAL.contains(statusCode); 200 } 201 202 /** 203 * Checks if the given status code is a valid HTTP status code (100-599). 204 * 205 * @param statusCode the HTTP status code to check 206 * @return true if the status code is valid, false otherwise 207 */ 208 public static boolean isValid(int statusCode) { 209 return statusCode >= 100 && statusCode <= 599; 210 } 211 212 @Override 213 public String toString() { 214 if (this == UNKNOWN) { 215 return description; 216 } 217 return "%s (%d-%d)".formatted(description, minCode, maxCode); 218 } 219}