Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarify how to avoid favoring path extensions as well as deprecation warnings #24642

Closed
pgrisafi opened this issue Mar 4, 2020 · 9 comments
Closed
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: documentation A documentation task
Milestone

Comments

@pgrisafi
Copy link

pgrisafi commented Mar 4, 2020

Affects: 5.2.4.RELEASE

According to 24179 favorPathExtension is deprecated, and we should all use the Accept header, which is perfect for me, since I always use favorPathExtension = false

The setter in ContentNegotiationManagerFactoryBean is Deprecated, but the field value is true (line 108) , so as far as I understand, the use of path seems in fact encouraged, since is the default value and the only way to set as false is Deprecated

Am I getting something wrong?

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Mar 4, 2020
@rstoyanchev rstoyanchev self-assigned this Mar 13, 2020
@rstoyanchev
Copy link
Contributor

No, you're not.

This is very long standing behavior and changing the default can cause significant disruption but maintenance releases are intended to be trouble free so you can take advantage of fixes including security issues, if any.

The purpose of the deprecation and #24179 is:

  1. Provide an advance warning for a change to come in the next minor release 5.3, see Deprecate use of path extensions in request mapping and content negotiation #24179.
  2. Provide all options necessary to actually make the switch, which required a number of changes as you can see from the commits linked to Deprecate use of path extensions in request mapping and content negotiation #24179.

Note that even in 5.3 we will turn off automatic matching to all extensions, but continue to match explicitly registered extensions by default and so favorPathExtension will remain true. In the next minor or major release after that we'll consider completely removing path extension support. So it is a very phased approach.

@rstoyanchev rstoyanchev added in: web Issues in web modules (web, webmvc, webflux, websocket) and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Mar 13, 2020
@pgrisafi
Copy link
Author

I'm not quite sure I understand, please correct me if I'm wrong.

I used to have an url like
/something/{email}
And expect a json back. In order to make it work with
/something/data@gmail.com
I needed to set up
configurer.favorPathExtension(false);

Now in order to do that I need to call a deprecated method.

In the future, I will not need to call any method, since this is going to be the default behaibour

@rstoyanchev rstoyanchev reopened this Mar 31, 2020
@rstoyanchev
Copy link
Contributor

That's a very good point but switching the default would likewise defeat the goal of a gradual migration through advance warning and deprecation.

It means we need to explain how to be configured which is:

// 1)
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { 
    configurer.useRegisteredExtensionsOnly(true);
    configurer.replaceMediaTypes(Collections.emptyMap());
}

// 2)
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
    // the below will become the default values in 5.3
    configurer.useSuffixPatternMatch(false);
    configurer.useRegisteredExtensionsOnly(true);
}
  1. Causes a path extension to never be resolved to a MediaType
  2. Suppresses the use suffix pattern matching and tries registered extensions only of which there should be none.

@rstoyanchev rstoyanchev added the type: documentation A documentation task label Mar 31, 2020
@rstoyanchev rstoyanchev changed the title favorPathExtension seems to be preferred in 5.2.4.RELEASE Clarify how to avoid favoring path extensions as well as deprecation warnings Mar 31, 2020
@rstoyanchev rstoyanchev added this to the 5.2.6 milestone Mar 31, 2020
@kev22257
Copy link

kev22257 commented Apr 15, 2020

That's a very good point but switching the default would likewise defeat the goal of a gradual migration through advance warning and deprecation.

It means we need to explain how to be configured which is:

// 1)
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { 
    configurer.useRegisteredExtensionsOnly(true);
    configurer.replaceMediaTypes(Collections.emptyMap());
}

// 2)
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
    // the below will become the default values in 5.3
    configurer.useSuffixPatternMatch(false);
    configurer.useRegisteredExtensionsOnly(true);
}
  1. Causes a path extension to never be resolved to a MediaType
  2. Suppresses the use suffix pattern matching and tries registered extensions only of which there should be none.

I originally asked this same question on #24179, but I see you started to answer it here. Unfortunately with Spring 5.2.5 I cannot get 2) of your recommendation to work: there is no useSuffixPatternMatch or useRegisteredExtensionsOnly method in org.springframework.web.servlet.config.annotation.PathMatchConfigurer; I do see the old deprecated "set" versions of those methods, but I thought the suggestion here was how to get around the warnings before 5.3 is released.

@rstoyanchev
Copy link
Contributor

rstoyanchev commented Apr 15, 2020

I cannot get 2) of your recommendation to work: there is no useSuffixPatternMatch or useRegisteredExtensionsOnly method in org.springframework.web.servlet.config.annotation.PathMatchConfigurer

Indeed my bad.

Technically the proper thing to do would be to deprecate them in 5.3 when the defaults values will change and those methods can be avoided altogether.

That said I'd really like to keep the deprecations in 5.2 to maximize advance warning and provide extra time to adapt. Therefore in 5.2 applications will have to use these deprecated methods but as long as they are used to turn off suffix pattern matching, it's okay to suppress the deprecation warnings. Then in 5.3 we will change the default values (but not yet remove the config options), and at that applications can remove their use.

This is what I'll have to update the docs with.

@kev22257
Copy link

kev22257 commented Apr 15, 2020

Great, thanks. Here is what I have then.

    @Override
    public void configureContentNegotiation(
            ContentNegotiationConfigurer configurer) {
        configurer.useRegisteredExtensionsOnly(true);
        configurer.replaceMediaTypes(Collections.emptyMap());
    }

    @Override
    @SuppressWarnings("deprecation")
    public void configurePathMatch(PathMatchConfigurer configurer) {
        // The below will become the default values in 5.3
        // Safe to use in 5.2 as long as disabling pattern match
        configurer.setUseSuffixPatternMatch(Boolean.FALSE);
        configurer.setUseRegisteredSuffixPatternMatch(Boolean.TRUE);
    }

@kev22257
Copy link

kev22257 commented Apr 15, 2020

Also, I'm not sure if you saw my comment in #24179, but I had also suggested, to bridge the gap between 5.2.4+ and 5.3, adding a disableUseSuffixPatternMatch() method to be deprecated in 5.3 that disables the functionality (same as above). This would allow a non-deprecated method to set the 5.3 functionality while still allowing the to-be-removed methods to be deprecated in 5.2.4+.

@rstoyanchev
Copy link
Contributor

I thought about that but I don't see how it helps since that method will also need to be removed together with the rest and therefore would also need to be deprecated.

@ahezzati
Copy link

ahezzati commented Aug 5, 2020

Just for completeness, this solution worked for my production code but my unit testing with MockMvc it did not.

What worked for me (not sure if there is another way) is to use MockMvcBuilders.standaloneSetup(your controller).setContentNegotiationManager(new ContentNegotiationManager(List.of(new HeaderContentNegotiationStrategy()))).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: documentation A documentation task
Projects
None yet
Development

No branches or pull requests

5 participants