Earlier in the Drupal 8 life cycle, up until 8.0.0-beta12, Drupal supported the use of the Accept header instead of the _format parameter. Unfortunately, there were issues with external caches. Drupal was serving HTML and other formats on the same path, only using different Accept headers. CDNs and reverse proxies do not invalidate cache based on this header alone. The only solution to prevent cache poisoning on these external caches, such as Varnish, was to ensure the implementation of the Vary: Accept header. There were, however, too many issues regarding CDNs and variance of implementation, so the _format parameter was introduced instead of appending extensions (.json and .xml) to paths.
A detail of the problem can be found on the following core issues:
- Refer to external caches mix up response formats on URLs where content negotiation is in use at https://www.drupal.org/node/2364011
- Check how to implement query parameter-based content negotiation as an alternative to extensions at https://www.drupal.org/node/2481453