{"id":45292593,"url":"https://github.com/piecehealth/actioncable","last_synced_at":"2026-02-21T03:27:06.759Z","repository":{"id":57694631,"uuid":"487576911","full_name":"piecehealth/actioncable","owner":"piecehealth","description":"A golang websocket framework, a server implementation of rails/actioncable (https://github.com/rails/rails/tree/main/actioncable)","archived":false,"fork":false,"pushed_at":"2022-05-02T06:22:09.000Z","size":22,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-31T22:49:38.905Z","etag":null,"topics":["actioncable","golang","webscoket"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/piecehealth.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-05-01T15:47:42.000Z","updated_at":"2025-06-04T02:45:04.000Z","dependencies_parsed_at":"2022-09-26T21:01:37.688Z","dependency_job_id":null,"html_url":"https://github.com/piecehealth/actioncable","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/piecehealth/actioncable","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piecehealth%2Factioncable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piecehealth%2Factioncable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piecehealth%2Factioncable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piecehealth%2Factioncable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/piecehealth","download_url":"https://codeload.github.com/piecehealth/actioncable/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piecehealth%2Factioncable/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29672704,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T03:11:15.450Z","status":"ssl_error","status_checked_at":"2026-02-21T03:10:34.920Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["actioncable","golang","webscoket"],"created_at":"2026-02-21T03:27:06.217Z","updated_at":"2026-02-21T03:27:06.745Z","avatar_url":"https://github.com/piecehealth.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# actioncable\n\nA golang websocket framework, a server implementation of [rails/actioncable](https://github.com/rails/rails/tree/main/actioncable)\n\n[Full-Stack Examples](https://github.com/piecehealth/actioncable-examples)\n\n## Client library\n* [Javascript](https://www.npmjs.com/package/@rails/actioncable)\n* [Client-Server Interaction](https://guides.rubyonrails.org/action_cable_overview.html#client-server-interaction)\n\n## Basic Usage\n\n### Setup cable\n\n```golang\npackage main\n\nimport (\n  \"...\"\n  \"github.com/piecehealth/actioncable\"\n)\n\nvar cable *actioncable.Cable\n\nfunc main() {\n  cbCfg := actioncable.NewConfig() // actioncable default config\n\n  // use redis for the PubSub service if your application run on multiple nodes.\n  // cbCfg = cbCfg.WithRedisPubSub(\u0026redis.Options{Addr: \"localhost:6379\"})\n\n  // Config how to authenticate client connection.\n  // You can fetch user information by cookies or URL parameters.\n  //\n  // The first return value is the identifier of the connection. Common identifier\n  // is currentUser, but could be anything.\n  //\n  // If the second return value is false, the server would reject the connection.\n  cbCfg = cbCfg.WithAuthenticator(func(h *http.Request) (any, bool) {\n    name, err := h.Cookie(\"userName\")\n\n    if err != nil {\n      return nil, false\n    }\n\n    id, _ := url.QueryUnescape(name.Value)\n\n    if id == \"the unwelcome user\" {\n      return nil, false\n    } else {\n      return id, true\n    }\n  })\n\n  // Initialize cable.\n  cable = actioncable.NewActionCable(cbCfg)\n\n  // Use GIN as example.\n  router := gin.Default()\n\n  // Handle websocket connection/request. The default endpoint is \"/cable\".\n  router.GET(\"/cable\", func(c *gin.Context) {\n    cable.Handle(c.Writer, c.Request)\n  })\n}\n```\n\n### Define Channel\n```golang\nvar getRoomId = func(params json.RawMessage) string {\n  p := struct {\n    Id string `json:\"id\"`\n  }{}\n\n  json.Unmarshal(params, \u0026p)\n\n  return fmt.Sprintf(\"room_%s\", p.Id)\n}\n\nvar roomChannel = \u0026actioncable.ChannelDescription{\n  Name: \"RoomChannel\",\n  // Called once a consumer has become a subscriber of the channel.\n  Subscribed: func(c *actioncable.Channel) {\n    roomId := getRoomId(c.Params)\n    currentUser := fmt.Sprintf(\"%v\", c.ConnIdentifier)\n\n    if roomId == \"forbidden_room\" {\n      // reject Subscription.\n      c.Reject()\n      return\n    }\n\n    // Start streaming from `RoomChannel#room_\u003cid\u003e`\n    c.StreamFrom(roomId)\n  },\n  // handle messages from client socket.\n  PerformAction: func(c *actioncable.Channel, jsonData string) {\n    d := struct {\n      Action  string `json:\"action\"` // the action would be set by the client library.\n      Message string `json:\"message\"`\n    }{}\n\n    json.Unmarshal([]byte(jsonData), \u0026d)\n\n    roomId := getRoomId(c.Params)\n\n    switch d.Action {\n    case \"send_message\":\n      currentUser := fmt.Sprintf(\"%v\", c.ConnIdentifier)\n\n      m := map[string]string{\n        \"send_by\": currentUser,\n        \"message\": d.Message,\n      }\n\n      // Broadcast the message to all the subscribers.\n      c.Broadcast(roomId, m)\n    default:\n      log.Printf(\"Unable to process RoomChannel#%s\", d.Action)\n    }\n  },\n  // Called once a consumer has cut its cable connection.\n  Unsubscribed: func(c *actioncable.Channel) {\n    // ...\n  }\n}\n\n// Register the channel to the cable.\ncable.RegisterChannel(roomChannel)\n\n// Broadcast message by cable.\nmsg := struct{\n  Message string `json:\"message\"`\n  SendBy  string `json:\"send_by\"`\n}{\n  Message: \"Hello ActionCable\",\n  SendBy:  \"SYSTEM\",\n}\ncable.Broadcast(\"RoomChannel\", \"room_1\", msg)\n```\n\n\n## [Full-Stack Example](https://github.com/piecehealth/actioncable-examples)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiecehealth%2Factioncable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpiecehealth%2Factioncable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiecehealth%2Factioncable/lists"}