Problem/Motivation
The ContentNegotiation class is only used in the NegotiationMiddleware class. It is trivial in size and is not useful anywhere else. Let's simplify by just moving its functionality into the middleware.
Proposed resolution
* Move the getContentType() method from the ContentNegotiation class to NegotiationMiddleware and make it protected.
* Adapt NegotiationMiddleware to call the method on itself instead of on ContentNegotiation.
* Remove the dependency of NegotiationMiddleware on ContentNegotiation.
* Remove ContentNegotiation entirely (including from services.yml)
* Dance.
Remaining tasks
Do it.
User interface changes
none
API changes
nothing significant.
Beta phase evaluation
| Issue category | Task because it's just general cleanup |
|---|---|
| Issue priority | Normal because nothing's actual broken. This is mostly just tidiness, with maybe a micro-optimization benefit |
| Comment | File | Size | Author |
|---|---|---|---|
| #32 | remove-2506533-32.patch | 11.45 KB | Jaesin |
| #28 | remove-2506533-28.patch | 11.52 KB | neclimdul |
| #28 | 2506533-28.interdiff.txt | 4.62 KB | neclimdul |
| #24 | interdiff_2506533-24.txt | 2.73 KB | minnur |
| #24 | 2506533-24.patch | 7.51 KB | minnur |
Comments
Comment #1
Jaesin commentedI created a ContentNegotiationInterface interface and updated accept_header_routing_test to use a custom content negotiator instead of custom middleware. There still isn't web test coverage for this though.
Comment #2
Jaesin commentedUpdate motivation text to be more precise.
Comment #3
dawehnerIs there an actual usecase in replacing it? I mean its something you should actually not replace, given how hacky it is already. I'd honestly rather expected people to replace the middleware entirely.
Comment #4
neclimdulSeeing that error lazy me would have just extended the class and overrode the methods... Daniel is right though, if you really need to replace the functionality I'd error on replacing the middleware.
what is all this?
Comment #5
Jaesin commentedThat is the replacement for this code that is in the middleware.
@dawehner: I agree it is hacky and it would be great if content negotiation was pluggable but that has performance considerations. I think this is a compromise that feels less hacky than forcing an override of the middleware.
My use case. I have a requirement for custom REST endpoints that uses a .json extension and .json?_format=json is redundant.
Comment #6
dawehner@Jaesin
Do you mind removing the test code changes? I think a real accept header based middleware should be a middleware and not need that additional level of indirection.
Comment #7
Jaesin commentedSure. No Problem.
Comment #8
wim leersSo, regarding overriding the entire middleware (@dawehner + @neclimdul) versus just overriding the
ContentNegotiationservice:http_negotiation.format_negotiatorservice to be overridden: Add an interface to the service (i.e. the current patch).http_middleware.negotiationmiddleware service to be overridden: RemoveContentNegotiation's logic and move it intoNegotiationMiddleware. It seems they're tightly coupled anyway, and the complexity ofContentNegotiationis so small that it does actually make the overall logic simpler.Comment #9
Crell commentedRe #8: The reason no interface exists is because the ContentNegotiation class was never expected to live this long. :-) It was added in a hacky form 3 years ago and we've tried to kill it about 4 times. It's a tricky bugger. Opcache micro-optimization was never a consideration.
Given how trivial ContentNegotiation is in its current form, I'd be in favor of #8.2: Just kill it finally and move it into the middleware. We can probably just move the getContentType() method itself to the middleware class and be done with it.
Comment #10
dawehner+1 to do that. For me ContentNegotation is really just about helping the middleware, its kinda a private method.
Comment #11
wim leersYep, makes sense :)
Comment #12
wim leersComment #13
Crell commentedUpdating IS accordingly. Agreed that this is a good Novice candidate so giving a precise outline. Also, beta eval.
Comment #14
minnur commentedI made this update. Please review.
Comment #15
minnur commentedForgot to add my interdiff.txt file.
Comment #16
Jaesin commentedThere is a in space in there that should be removed.
Otherwise, given the consensus, I think this looks good. Thanks for porting the unit test. NegotiationMiddleware unit test coverage could be expanded but that is kinda outside this issue.
Comment #17
tim.plunkettThis issue needs a new title.
Comment #18
minnur commented@Jaesin: I removed spaces.
Comment #19
dawehnerLooks good in general.
This no longer needs to be public.
Comment #20
dawehner.
Comment #21
sdstyles commentedComment #22
sdstyles commentedComment #23
dawehnerLet's make it protected
Comment #24
minnur commentedComment #25
dawehnerThank you
Comment #26
alexpottSince this has been around for 3 years I guess we need a CR to tell people to just override the middleware in order to do their own content negotiation.
Comment #27
neclimdul???
Comment #28
neclimdulNM, I see. They where removed because the method wasn't public. re-adding tests. Also some more tests just because I'm a fan of test coverage.
Comment #29
neclimdulto the testbot. #26 still applies though.
Comment #30
Crell commentedMinor nit: handle(). Otherwise I kept reading "handle correctly" to mean that something else handled something correctly, which is totally not what we're saying here. :-)
We can use PHP 5.5 style class naming here now! Huzzah!
Here too.
Comment #31
dawehnerAdded one
Comment #32
Jaesin commentedNo interdiff because I manually edited the patch.
#30-1 Changed handle to handle()
#30-2 changed ''\Symfony\Component\HttpKernel\HttpKernelInterface'' to HttpKernelInterface::class
#30-2 changed '\Symfony\Component\HttpFoundation\Request' to Request::class (x2)
I am wondering how using ::class performs as opposed to using single quotes.
Comment #33
Crell commentedLet's do this!
(Side note: ::class is a constant, so it evaluates to the class name at compile time, not runtime. There shouldn't be any difference at runtime between a string literal and a constant, or if so it's so small that you wouldn't even notice.)
Comment #34
Jaesin commentedA quick little test:
Interesting result:
Comment #38
neclimdulCan't reproduce. Might be a rouge testbot.
Comment #40
neclimdulyeah, there was some problem with opcode caching something something. back to previous status.
Comment #41
dawehner+1 for the patch
Comment #42
alexpottThis makes sense - if you want to swap out the negotiation layer you'll need to swap out http_middleware.negotiation - the http_negotiation.format_negotiator is just noise. This patch is just followup from all the work in this area.
Committed f29f1e2 and pushed to 8.0.x. Thanks!
Thanks for adding the beta evaluation to the issue summary.
Comment #45
fabianx commentedPublished the change record.