Spring boot - POST method not allowed

25,198

Solution 1

So the problem was that one of the parameter was null. It has been solved adding required=null at the request parameter annotation, like that:

@RequestParam(value = "yourParamName", required = false)

this cause a 405, as defined here:

6.5.5.  405 Method Not Allowed

The 405 (Method Not Allowed) status code indicates that the method
received in the request-line is known by the origin server but not
supported by the target resource.  The origin server MUST generate an
Allow header field in a 405 response containing a list of the target
resource's currently supported methods.

A 405 response is cacheable by default; i.e., unless otherwise
indicated by the method definition or explicit cache controls (see
Section 4.2.2 of [RFC7234]).

when the "target resource" are defined here:

Solution 2

In my case the endpoint had ssl on i.e. it was https

In Postman I by mistake was using http

http will work fine for GETs but for POSTs it returns a 405 method not allowed. It has to be https if your endpoint expects it to be.

If you have request and response logging turned on in Spring the POST endpoint in the above situation will log as follows:

[2021-02-26T10:40:07+02:00] (my-app/fffffa343226e) 2021-02-26T08:40:07,915Z (UTC+0) [http-nio-80-exec-6] DEBUG o.s.w.f.CommonsRequestLoggingFilter - Before request [GET /api/v1/my-app, client=1.2.3.4, user=aUser]
[2021-02-26T10:40:07+02:00] (my-app/fffffa343226e) 2021-02-26T08:40:07,915Z (UTC+0) [http-nio-80-exec-6] WARN  o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported]
[2021-02-26T10:40:07+02:00] (my-app/fffffa343226e) 2021-02-26T08:40:07,916Z (UTC+0) [http-nio-80-exec-6] DEBUG o.s.w.f.CommonsRequestLoggingFilter - After request [GET /api/v1/my-app, client=1.2.3.4, user=aUser]

Share:
25,198
MarioC
Author by

MarioC

Updated on February 26, 2021

Comments

  • MarioC
    MarioC about 3 years

    I'm dwelling with this problem... I have a Spring Boot application wit a S2S communication. I have a @RestController method which should accept POST request.

    This is the controller

    @RestController
    public class PaymentRestController {
    
    @PostMapping("/util/paymentResponse")
        public void savePaymentResponse(@RequestParam boolean transaction_status, @RequestParam String usedToken,
                @RequestParam String transaction_message, @RequestParam String authCode,
                @RequestParam String transactionCode, @RequestParam String orderId, HttpServletRequest request) {
    //business logic
    }
    
    }
    

    If i hit this link i get a 405 error, method not allowed

    At first time i found that the request was blocked by the CSFR Filter which is enabled on the web application, so I have configured my security in this way

    @Configuration
    @ComponentScan("it.besmart")
    @EnableWebSecurity
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
    
        @Autowired
        @Qualifier("customUserDetailsService")
        UserDetailsService userDetailsService;
    
        @Autowired
        CustomSuccessHandler customSuccessHandler;
    
        @Autowired
        CustomAuthenticationFailureHandler customAuthenticationFailureHandler;
    
        @Autowired
        DataSource dataSource;
    
        private final static Logger logger = LoggerFactory.getLogger(SecurityConfiguration.class);
    
        @Autowired
        public void configureGlobalService(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    
        }
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    
        @Bean
        public SwitchUserFilter switchUserFilter() {
            SwitchUserFilter filter = new SwitchUserFilter();
            filter.setUserDetailsService(userDetailsService);
            filter.setSuccessHandler(customSuccessHandler);
            filter.setFailureHandler(customAuthenticationFailureHandler);
            return filter;
        }
    
            protected void configure(HttpSecurity http) throws Exception {
                logger.debug("Webapp security configured");
    
    
                http
    
                .authorizeRequests()
                        .antMatchers("/",  "/home", "/contacts", "/faq", "/privacy", "/register", "/registrationConfirm", "/util/**", "/resendRegistrationToken","/park**", "/oauth/authorize", "/error")
                        .permitAll()
                        .antMatchers("/profile**", "/edit**","/payment**", "/plate**","/notification**", "/addPaymentMethod**", "/logout/impersonate**")
                        .access("hasRole('USER') or hasRole('NOPAYMENT')")
                        .antMatchers("/book**", "/manage**")
                        .access("hasRole('USER')")
                        .antMatchers("/admin**", "/login/impersonate**").access("hasRole('ADMIN')")
                        .antMatchers("/updatePassword").hasAuthority("CHANGE_PASSWORD_PRIVILEGE")
    
                        .and().formLogin().loginPage("/?login=login").loginProcessingUrl("/")                   .successHandler(customSuccessHandler).failureHandler(customAuthenticationFailureHandler).usernameParameter("email").passwordParameter("password").and().rememberMe().rememberMeParameter("remember-me").tokenRepository(persistentTokenRepository()).tokenValiditySeconds(86400).and().exceptionHandling().accessDeniedPage("/accessDenied")
    
                        .and().csrf().ignoringAntMatchers( "/util**")
                        .and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                        .logoutSuccessUrl("/?logout=true").permitAll()
    
    
                        .and().addFilterAfter(switchUserFilter(), FilterSecurityInterceptor.class);
    
            }
    

    In this way i'm not getting the CSRF token exception, but still getting the 405 error. It's not even a problem of POST because if i change to GET the request and the mapping, i still take the 405 error... And if i try to send a POST, i see in the header response that the Allowed method is POST, if i send it in GET i see allowed method POST... weird

    I don't know where to see...