{"action":"created","issue":{"url":"https://api.github.com/repos/http-interop/http-middleware/issues/37","repository_url":"https://api.github.com/repos/http-interop/http-middleware","labels_url":"https://api.github.com/repos/http-interop/http-middleware/issues/37/labels{/name}","comments_url":"https://api.github.com/repos/http-interop/http-middleware/issues/37/comments","events_url":"https://api.github.com/repos/http-interop/http-middleware/issues/37/events","html_url":"https://github.com/http-interop/http-middleware/issues/37","id":191310911,"number":37,"title":"Callable delegates","user":{"login":"mindplay-dk","id":103348,"avatar_url":"https://avatars.githubusercontent.com/u/103348?v=3","gravatar_id":"","url":"https://api.github.com/users/mindplay-dk","html_url":"https://github.com/mindplay-dk","followers_url":"https://api.github.com/users/mindplay-dk/followers","following_url":"https://api.github.com/users/mindplay-dk/following{/other_user}","gists_url":"https://api.github.com/users/mindplay-dk/gists{/gist_id}","starred_url":"https://api.github.com/users/mindplay-dk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mindplay-dk/subscriptions","organizations_url":"https://api.github.com/users/mindplay-dk/orgs","repos_url":"https://api.github.com/users/mindplay-dk/repos","events_url":"https://api.github.com/users/mindplay-dk/events{/privacy}","received_events_url":"https://api.github.com/users/mindplay-dk/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":52,"created_at":"2016-11-23T15:53:38Z","updated_at":"2016-12-01T14:52:44Z","closed_at":null,"body":"I hate to bring this up again, but...\r\n\r\nA lot of people have expressed a dislike for the single-method DelegateInterface and want to be able to to just `return $next($request)` in their middleware implementations. That's not a big deal for me, but several people seemed annoyed, and wanted to put `__invoke()` in the interface because of that, etc.\r\n\r\nIn `mindplay/middleman`, I have this silly implementation of `DelegateInterface` that simply wraps a `callable`, which is also completely redundant and wasteful - creating a meaningless extra object wrapper for every middleware that gets dispatched, for *perceived* type-safety (and, okay, yes, stricter static analysis) but it's really just moving the point of failure one layer away from the middleware itself if it passes a non-request to the delegate.\r\n\r\nWell, that's two issues, but then I just ran into another one.\r\n\r\nI have a case where I'd like to call [this middleware](https://github.com/middlewares/client-ip), which does client IP detection, but from outside the context of a middleware stack.\r\n\r\nIn other words, I want to just run a single middleware component.\r\n\r\nWith a `callable` delegate, that was really simple - I might just do:\r\n\r\n```php\r\n$client_ip = new ClientIp();\r\n\r\n$ip = $client_ip->process($request, function ($r) { return $r; })->getAttribute(\"client-ip\");\r\n```\r\n\r\nBut I can't do that.\r\n\r\nI need an actual implementation of `DelegateInterface` and I have to either implement and create an instance of that, or import and instanciate an entire middleware stack - for no real reason, other than to satisfy the type-hint.\r\n\r\nThis is not an odd case - I've had plenty of cases in the past, where I compose middleware out of several other internal middleware components, for example, conditionally dispatching different middleware instances, etc.\r\n\r\nIn the light of all these issue, I have to bring up this subject again - sorry.\r\n\r\nWhat I keep coming back to, is that `callable` for delegates, in de-facto standard PSR-7 middleware, *worked fine* - it wasn't causing anyone any real headaches, and I think the problem that stricter type-hinting solves in this case is really mostly theoretical.\r\n\r\nThe `DelegateInterface`, on the other hand, seems to have rubbed several people the wrong way, and seems to breed other problems and complexities that wouldn't exist with a plain `callable`.\r\n\r\nWho are we supposedly helping with this extra abstraction around delegates?\r\n\r\nMaybe the reason this interface (and it's method) was so hard to name, is because it's really honestly serving no real purpose beyond stricter type-hinting - in a place that wasn't really being reported as a problematic pain point by anyone in the first place.\r\n\r\nAre we *absolutely freakin' sure* that this is the right approach?\r\n"},"comment":{"url":"https://api.github.com/repos/http-interop/http-middleware/issues/comments/264192809","html_url":"https://github.com/http-interop/http-middleware/issues/37#issuecomment-264192809","issue_url":"https://api.github.com/repos/http-interop/http-middleware/issues/37","id":264192809,"user":{"login":"schnittstabil","id":6059032,"avatar_url":"https://avatars.githubusercontent.com/u/6059032?v=3","gravatar_id":"","url":"https://api.github.com/users/schnittstabil","html_url":"https://github.com/schnittstabil","followers_url":"https://api.github.com/users/schnittstabil/followers","following_url":"https://api.github.com/users/schnittstabil/following{/other_user}","gists_url":"https://api.github.com/users/schnittstabil/gists{/gist_id}","starred_url":"https://api.github.com/users/schnittstabil/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/schnittstabil/subscriptions","organizations_url":"https://api.github.com/users/schnittstabil/orgs","repos_url":"https://api.github.com/users/schnittstabil/repos","events_url":"https://api.github.com/users/schnittstabil/events{/privacy}","received_events_url":"https://api.github.com/users/schnittstabil/received_events","type":"User","site_admin":false},"created_at":"2016-12-01T14:52:44Z","updated_at":"2016-12-01T14:52:44Z","body":"Lets say we have 2 middlewares and a stack:\r\n* middleware A requires `\"psr/http-middleware\": \"^1.0\"`\r\n* middleware B requires `\"psr/http-middleware\": \"^2.0\"`\r\n* the stack requires `\"psr/http-middleware\": \"^1.0|^2.0\"`\r\n\r\nIf you want to use A and B with the stack, composer must install:\r\n`\"psr/http-middleware\": \"^1.0\"` **or** `\"psr/http-middleware\": \"^2.0\"`\r\n\r\nBut it cannot install both :unamused: "}}
{"actor":{"display_login":"schnittstabil"}}