001/* 002 * Copyright 2002-2020 the original author or authors. 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 * https://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 */ 016 017package org.springframework.web.server; 018 019import java.util.Collection; 020import java.util.Collections; 021import java.util.LinkedHashSet; 022import java.util.Map; 023import java.util.Set; 024 025import org.springframework.http.HttpHeaders; 026import org.springframework.http.HttpMethod; 027import org.springframework.http.HttpStatus; 028import org.springframework.lang.Nullable; 029import org.springframework.util.Assert; 030import org.springframework.util.CollectionUtils; 031 032/** 033 * Exception for errors that fit response status 405 (method not allowed). 034 * 035 * @author Rossen Stoyanchev 036 * @since 5.0 037 */ 038@SuppressWarnings("serial") 039public class MethodNotAllowedException extends ResponseStatusException { 040 041 private final String method; 042 043 private final Set<HttpMethod> httpMethods; 044 045 046 public MethodNotAllowedException(HttpMethod method, Collection<HttpMethod> supportedMethods) { 047 this(method.name(), supportedMethods); 048 } 049 050 public MethodNotAllowedException(String method, @Nullable Collection<HttpMethod> supportedMethods) { 051 super(HttpStatus.METHOD_NOT_ALLOWED, "Request method '" + method + "' not supported"); 052 Assert.notNull(method, "'method' is required"); 053 if (supportedMethods == null) { 054 supportedMethods = Collections.emptySet(); 055 } 056 this.method = method; 057 this.httpMethods = Collections.unmodifiableSet(new LinkedHashSet<>(supportedMethods)); 058 } 059 060 061 /** 062 * Return a Map with an "Allow" header. 063 * @since 5.1.11 064 */ 065 @SuppressWarnings("deprecation") 066 @Override 067 public Map<String, String> getHeaders() { 068 return getResponseHeaders().toSingleValueMap(); 069 } 070 071 /** 072 * Return HttpHeaders with an "Allow" header. 073 * @since 5.1.13 074 */ 075 @Override 076 public HttpHeaders getResponseHeaders() { 077 if (CollectionUtils.isEmpty(this.httpMethods)) { 078 return HttpHeaders.EMPTY; 079 } 080 HttpHeaders headers = new HttpHeaders(); 081 headers.setAllow(this.httpMethods); 082 return headers; 083 } 084 085 /** 086 * Return the HTTP method for the failed request. 087 */ 088 public String getHttpMethod() { 089 return this.method; 090 } 091 092 /** 093 * Return the list of supported HTTP methods. 094 */ 095 public Set<HttpMethod> getSupportedMethods() { 096 return this.httpMethods; 097 } 098 099}