{"id":37891419,"url":"https://github.com/go-openapi/swaggersocket","last_synced_at":"2026-01-16T16:56:41.076Z","repository":{"id":57525027,"uuid":"76589534","full_name":"go-openapi/swaggersocket","owner":"go-openapi","description":"ReST over websocket, so you can serve swagger apis over websocket","archived":false,"fork":false,"pushed_at":"2017-02-21T05:55:52.000Z","size":211,"stargazers_count":17,"open_issues_count":3,"forks_count":14,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-06-20T15:03:30.624Z","etag":null,"topics":["golang","rest","swagger","websocket"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/go-openapi.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":"2016-12-15T19:29:59.000Z","updated_at":"2023-11-23T15:52:02.000Z","dependencies_parsed_at":"2022-08-26T03:43:18.333Z","dependency_job_id":null,"html_url":"https://github.com/go-openapi/swaggersocket","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/go-openapi/swaggersocket","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-openapi%2Fswaggersocket","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-openapi%2Fswaggersocket/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-openapi%2Fswaggersocket/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-openapi%2Fswaggersocket/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/go-openapi","download_url":"https://codeload.github.com/go-openapi/swaggersocket/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-openapi%2Fswaggersocket/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28480081,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","response_time":107,"last_error":"SSL_read: 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":["golang","rest","swagger","websocket"],"created_at":"2026-01-16T16:56:40.282Z","updated_at":"2026-01-16T16:56:41.068Z","avatar_url":"https://github.com/go-openapi.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SwaggerSocket [![Build Status](https://travis-ci.org/go-openapi/swaggersocket.svg?branch=master)](https://travis-ci.org/go-openapi/swaggersocket) [![codecov](https://codecov.io/gh/go-openapi/swaggersocket/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/swaggersocket) [![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)\n\n[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/swaggersocket/master/LICENSE) [![GoDoc](https://godoc.org/github.com/go-openapi/swaggersocket?status.svg)](http://godoc.org/github.com/go-openapi/swaggersocket)\n\nReST over websocket, so you can serve swagger apis over websocket\n\n## Websocket Server\n\n### How to create a websocket server\nA websocket server can be created using the `NewWebSocketServer` function\n```go\nfunc NewWebSocketServer(opts SocketServerOpts) *WebsocketServer\n```\n The above function creates a websocket server based on the options structure passed to the constructor function\n\n ```go\n type SocketServerOpts struct {\n\tAddr      string\n\tKeepAlive bool\n\tPingHdlr  func(string) error\n\tPongHdlr  func(string) error\n\tAppData   []byte\n\tLog       Logger\n}\n```\n\n`Addr` the ip address and port the websocket server is listening to\n`KeepAlive` activates the heartbeat mechanism at the server side\n`PingHdlr` A custom function to websocket ping messages (default is to send back a pong message)\n`PongHdlr` a custom function to a websocket pong message (default is nothing)\n`AppData` optional application-level data passed with the heartbeat messages\n`Log` custom logger\n\n### The Websocket Server Event Stream\nAfter creating a websocket server, the user will probably need to listen the events happening on the websocket server.\n\nTo listen to the event stream of the websocket server\n```go\nfunc (ss *WebsocketServer) EventStream() (\u003c-chan ConnectionEvent, error)\n```\nThe `EventStream` method returs a channel that carries `ConnectionEvent` instances\n\n```go\ntype ConnectionEvent struct {\n\tEventType    EvtType\n\tConnectionId string\n}\n```\n\nThere are three types of connection events:\n- ConnectionReceived\n- ConnectionClosed\n- ConnectionFailure\n\nThe `ConnectionEvent` also has the `ConnectionId` field which is the ID of the connection associated with the event.\n\n## Websocket Client\nA websocket client can be created using the `NewWebSocketServer` function\n```go\nfunc NewWebSocketClient(opts SocketClientOpts) *WebsocketClient\n```\n This creates a websocket client based on the `SocketClientOpts`\n\n ```go\n type SocketClientOpts struct {\n\tURL       *url.URL\n\tKeepAlive bool\n\tPingHdlr  func(string) error\n\tPongHdlr  func(string) error\n\tAppData   []byte\n\tLogger    Logger\n}\n```\n\nThe `URL` is the url of the websocket server\nA `KeepAlive` set to true will activate the heartbeat mechanism from the client side and on connection failure, will attempt to reconnect to the websocket server with an exponential backoff.\n\n## Server-Client Handshake\nThis is a three-way handshake in the beginning of the connection. The purpose of this handshake is:\n\n- agree on a unique id `ConnectionId` for the connection\n- allowing the websocket client to store some connection metadata at the websocket server side\n\nIn particular, this is the sequence of events:\n\n1. The websocket Client sends an initial message to the websocket server with the connection metadata (if any)\n2. The websocket server stores the metadata for the connection and responds with a unique connection id\n3. The client confirms the reception of the connection id\n\n## The Heartbeat\nThe Heartbeat is the mechanism by which connection failures can be detected. The Heartbeat simply utilizes the underlying websocket ping/pong messages to send periodic heartbeat messages to check the health of the connection. Heartbeat messages can be activated at the websocket client and/or server sides by setting the `KeepAlive` field.\n\n## Swagger API Server\nWebsocket connections are bidirectional. This means the API server can be attached to either the websocket client or the websocket server.\n\nIf the api server is attached to the websocket client, the websocket server will act as the api client (issue requests to the websocket client and receive ap response)\n\nAfter a connection has been established between the websocket server and the websocket client, the api server can be attached to any by hooking up the swagger api handler.\n\n### Attaching the Swagger API handler to the websocket server\n```go\nwsServer := NewWebSocketServer(opts)\nch, err := wsServer.EventStream()\n// the following loop is safe to run in a separate go-routine\nfor {\n\t\t\tselect {\n\t\t\tcase event := \u003c-ch:\n\t\t\t\tif event.EventType == ConnectionReceived {\n\t\t\t\t\tconn := wsServer.connectionFromConnID(event.ConnectionId)\n\t\t\t\t\tconn.Serve(context.Background(), SwaggerAPIHandler)\n\t\t\t\t}\n\n\t\t\tcase \u003c-done:\n\t\t\t\treturn\n\t\t\t}\n}\n```\n### Attaching the swagger api handler to the websocket client\n```go\n// create a websocket client\nwsClient := swaggersocket.NewWebSocketClient(clientOpts).WithMetaData(\"dummy connection metadata\")\n// connect to the websocket server\nif err := wsClient.Connect(); err != nil {\n\t\tpanic(err)\n}\n///////////////////\n// some code goes here\n//////////////////\n// serve the swagger api on the websocket client\nwsClient.Connection().Serve(context.Background(), SwaggerAPIHandler)\n```\n## Swagger API Client\n`SocketConnection` implements the RoundTripper interface. This means that the swagger client requires no modifications except for changing the RoundTripper of the runtime\n\nFor example, assuming that we are hooking the swagger client to the websocket client:\n\n```go\n// create a websocket client\nwsClient := swaggersocket.NewWebSocketClient(clientOpts).WithMetaData(\"dummy connection metadata\")\n// connect to the websocket server\nif err := wsClient.Connect(); err != nil {\n\t\tpanic(err)\n}\n///////////////////\n// some code goes here\n//////////////////\n// runtime is the go-openapi runtime\nrt := runtime.New(\"localhost\", \"/\", []string{\"https\"})\nrt.Transport = wsClient.Connection()\n// client is the swagger http client\ncli := client.New(rt, nil)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-openapi%2Fswaggersocket","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgo-openapi%2Fswaggersocket","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-openapi%2Fswaggersocket/lists"}