{"action":"created","issue":{"url":"https://api.github.com/repos/laravel/framework/issues/13653","repository_url":"https://api.github.com/repos/laravel/framework","labels_url":"https://api.github.com/repos/laravel/framework/issues/13653/labels{/name}","comments_url":"https://api.github.com/repos/laravel/framework/issues/13653/comments","events_url":"https://api.github.com/repos/laravel/framework/issues/13653/events","html_url":"https://github.com/laravel/framework/pull/13653","id":156170641,"number":13653,"title":"[5.3] Broadcasting Improvements","user":{"login":"leemason","id":1238646,"avatar_url":"https://avatars.githubusercontent.com/u/1238646?v=3","gravatar_id":"","url":"https://api.github.com/users/leemason","html_url":"https://github.com/leemason","followers_url":"https://api.github.com/users/leemason/followers","following_url":"https://api.github.com/users/leemason/following{/other_user}","gists_url":"https://api.github.com/users/leemason/gists{/gist_id}","starred_url":"https://api.github.com/users/leemason/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/leemason/subscriptions","organizations_url":"https://api.github.com/users/leemason/orgs","repos_url":"https://api.github.com/users/leemason/repos","events_url":"https://api.github.com/users/leemason/events{/privacy}","received_events_url":"https://api.github.com/users/leemason/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":22,"created_at":"2016-05-22T20:20:31Z","updated_at":"2016-05-28T16:06:30Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/laravel/framework/pulls/13653","html_url":"https://github.com/laravel/framework/pull/13653","diff_url":"https://github.com/laravel/framework/pull/13653.diff","patch_url":"https://github.com/laravel/framework/pull/13653.patch"},"body":"The PR contains the following changes:\r\n\r\n**1. \"de-vendors\" and enhances the new broadcast authentication features of 5.3.**\r\n\r\n1.1. Cached socket/session ids are changed from `pusher:socket:$id` to `broadcast:socket:$id`.\r\n\r\n1.2. Common broadcast driver functions are refactored into an external abstract class, namely auth(), check(), extractAuthParameters(), rememberSocket() and validAuthenticationResponse().\r\n\r\n1.2.1. Specific drivers need only override validAuthenticationResponse() and/or rememberSocket() as the others are pretty general (but provided in the abstract class to prevent method not found issues, for example when testing). If not overwritten a default json response will be returned with status => success, user_id and user_info.\r\n\r\n1.2.2 All drivers extending the abstract class (all existing core drivers) have been updated to require a container instance in there constructor, this is due to the abstract classes ability to ioc resolve classes mentioned in the next point.\r\n\r\nThis function returns the \"member info\" and anything else needed by a specific driver implementation. Pusher for example doesnt return anything, it does an api call, whereas Rebound (discussed further down) expects a response with the member info. Allowing this to be overwritten allows for different implementations without much hassle.\r\n\r\n1.3. The auth('channel', function(){}) functionality has been extended to allow declaration just like other areas of laravel with the ```class@method``` syntax, or a callable. This gives the developer the choice to inject required classes via the class constructor (as it uses the ioc container to resolve the class before calling the \"check\" method.\r\n\r\n1.3.1. Where just a class name is provided the class is expected to have an authenticate() method.\r\n\r\n1.4. A new Illuminate\\Foundation\\Support\\Providers\\BroadcastServiceProvider has been created with the same functionality signature as the EventServiceProvider.\r\n\r\n1.4.1 This provider is extended within laravel/laravel via another pull request: https://github.com/laravel/laravel/pull/3784 and in addition to using auth('channel', function(){}); you can now declare channel_name => [AuthClass::class] for auth callbacks. This will be familiar to users as it exists with the EventServiceProvider.\r\n\r\n~~2. A new core broadcast driver has been added, called Rebound. This is a package i have developed in response to Laravel Echo and the authentication features coming in 5.3.~~\r\n\r\n~~Rebound is NOT built ontop of socket.io. it is a package built ontop engine.io.~~\r\n\r\n~~For those who dont know engine.io is the work horse of socket.io. engine.io is responsible for the transport upgrading, sending messages, reconnections, etc. Socket.io provides the namespaces, rooms, etc functionality.~~\r\n\r\nThe default responses added are to allow a generic api to using the broadcasting routes, namely for a socket client i built, detailed below. As they are \"default\" responses unless overwritten by a specific driver they could be used by any client following the same conventions.\r\n\r\nI chose to build Rebound to have an open source alternative to Pusher, that shares the same API as Laravel Echo.\r\n\r\nThe way pusher has \"channels\" and socket.io has namespaces/rooms just didnt make sense when trying to build a unified api.\r\n\r\nRebound works by adding messages to a redis db, which are handled by a node rebound-server proccess, and pushed out to all the connected sockets. (similar to socket.io and redis in 5.2).\r\n\r\nThe rebound-client has the same API as laravel echo, just a different engine underneath.\r\n\r\nFor example echo:\r\n\r\n```\r\nvar socket = new Echo('api', {\r\n....options\r\n});\r\n\r\nvar channel = socket.channel('name');\r\nchannel.on('Event', function(data){\r\n//..\r\n});\r\n\r\nvar channel = socket.private('name');\r\nchannel.on('Event', function(data){\r\n//..\r\n});\r\n\r\nvar channel = socket.presence('name');\r\nchannel.here(function(members){\r\n//..\r\n});\r\n```\r\n\r\nand Rebound:\r\n\r\n```\r\nvar socket = new rebound.Socket('domain:port', {\r\n....options\r\n});\r\n\r\nvar channel = socket.channel('name');\r\nchannel.on('Event', function(data){\r\n//..\r\n});\r\n\r\nvar channel = socket.private('name');\r\nchannel.on('Event', function(data){\r\n//..\r\n});\r\n\r\nvar channel = socket.presence('name');\r\nchannel.here(function(members){\r\n//..\r\n});\r\n```\r\n\r\nWhen a socket connects the server sends a post request to /broadcasting/socket just like pusher does to \"remember\" the socket against the session.\r\n\r\nThe way rebound authenticates channels is very similar to pusher. The node server gets a request from a browser socket to join. the node server then sends a post request to the laravel app (on the same urls used for pusher /broadcasting/auth). this is where the auth('channel', function(){}); functions take over and either return data, or throw a 403 error. \r\n\r\nif no error is thrown and data returned, the node server puts the socket into a \"channel\" group. If an error is thrown they dont get added, this is important.\r\n\r\nThe node server also caches the responses in redis to prevent multiple post requests on every page load (its configurable for expiry).\r\n\r\nWhen a message comes in via redis, the channel name is collected.\r\n\r\nThe node server then loops through all the browser sockets within the channel group of the same name and sends them the event.\r\n\r\nwhats key here is sockets that requested access to that channel have to be validated by laravel before they get put into the node servers channel group. Then when events on that channel get fired **we only send to sockets in that channel group**. there is no way for the client to bypass this check.\r\n\r\nThe client api will be mainatined along with Laravel echo, and the server is pretty opinionated so doesnt need a public api at present, so both are stable as we speak (active development still happening, but nothing is likley to need changing).\r\n\r\nThe \"server\" can be found here: https://github.com/leemason/rebound-server\r\n\r\nAnd the \"client\" here: https://github.com/leemason/rebound-server\r\n\r\nMore docs to come with time."},"comment":{"url":"https://api.github.com/repos/laravel/framework/issues/comments/222315956","html_url":"https://github.com/laravel/framework/pull/13653#issuecomment-222315956","issue_url":"https://api.github.com/repos/laravel/framework/issues/13653","id":222315956,"user":{"login":"leemason","id":1238646,"avatar_url":"https://avatars.githubusercontent.com/u/1238646?v=3","gravatar_id":"","url":"https://api.github.com/users/leemason","html_url":"https://github.com/leemason","followers_url":"https://api.github.com/users/leemason/followers","following_url":"https://api.github.com/users/leemason/following{/other_user}","gists_url":"https://api.github.com/users/leemason/gists{/gist_id}","starred_url":"https://api.github.com/users/leemason/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/leemason/subscriptions","organizations_url":"https://api.github.com/users/leemason/orgs","repos_url":"https://api.github.com/users/leemason/repos","events_url":"https://api.github.com/users/leemason/events{/privacy}","received_events_url":"https://api.github.com/users/leemason/received_events","type":"User","site_admin":false},"created_at":"2016-05-28T16:06:30Z","updated_at":"2016-05-28T16:06:30Z","body":"Talking about that, i think we also need to update the docs on events returning their own data structure.\r\n\r\nAs if they do the socket property wont get sent unless explicitly declared in the broadcastWith() method."}}
{"actor":{"display_login":"leemason"}}