{"id":15557690,"url":"https://github.com/fgasper/p5-net-websocket","last_synced_at":"2025-06-18T18:35:12.426Z","repository":{"id":56831503,"uuid":"83241680","full_name":"FGasper/p5-Net-WebSocket","owner":"FGasper","description":"CPAN’s Net::WebSocket","archived":false,"fork":false,"pushed_at":"2021-10-19T10:44:15.000Z","size":1280,"stargazers_count":5,"open_issues_count":0,"forks_count":3,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-23T21:08:09.529Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FGasper.png","metadata":{"files":{"readme":"README.md","changelog":"Changes","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":"2017-02-26T21:23:09.000Z","updated_at":"2023-12-19T13:39:32.000Z","dependencies_parsed_at":"2022-08-28T20:10:50.266Z","dependency_job_id":null,"html_url":"https://github.com/FGasper/p5-Net-WebSocket","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/FGasper/p5-Net-WebSocket","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FGasper%2Fp5-Net-WebSocket","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FGasper%2Fp5-Net-WebSocket/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FGasper%2Fp5-Net-WebSocket/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FGasper%2Fp5-Net-WebSocket/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FGasper","download_url":"https://codeload.github.com/FGasper/p5-Net-WebSocket/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FGasper%2Fp5-Net-WebSocket/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260610141,"owners_count":23036071,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-10-02T15:20:22.972Z","updated_at":"2025-06-18T18:35:07.412Z","avatar_url":"https://github.com/FGasper.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NAME\n\nNet::WebSocket - WebSocket in Perl\n\n# SYNOPSIS\n\n    use Net::WebSocket::Handshake::Client ();\n    use Net::WebSocket::HTTP_R ();\n\n    my $handshake = Net::WebSocket::Handshake::Client-\u003enew(\n        uri =\u003e $uri,\n    );\n\n    syswrite $inet, $handshake-\u003eto_string() or die $!;\n\n    #You can parse HTTP headers however you want;\n    #Net::WebSocket makes no assumptions about this.\n    my $resp = HTTP::Response-\u003eparse($hdrs_txt);\n\n    #If you use an interface that’s compatible with HTTP::Response,\n    #then you can take advantage of this convenience function;\n    #otherwise you’ll need to do a bit more work.\n    Net::WebSocket::HTTP_R::handshake_parse_response( $handshake, $resp );\n\n    #See below about IO::Framed\n    my $iof = IO::Framed-\u003enew($inet);\n\n    my $parser = Net::WebSocket::Parser-\u003enew($iof);\n\n    my $ept = Net::WebSocket::Endpoint::Client-\u003enew(\n        parser =\u003e $parser,\n        out =\u003e $iof,\n    );\n\n    $iof-\u003ewrite(\n        $ept-\u003ecreate_message( 'text', 'Hello, world' )-\u003eto_bytes()\n    );\n\n    #Determine that $inet can be read from …\n\n    my $msg = $ept-\u003eget_next_message();\n\n    #… or, if we timeout while waiting for $inet to be ready for reading:\n\n    $ept-\u003echeck_heartbeat();\n    exit if $ept-\u003eis_closed();\n\n# BETA QUALITY\n\nThis is a beta release. It should be safe for production, but there could\nstill be small changes to the API. Please check the changelog before\nupgrading.\n\n# DESCRIPTION\n\nThis distribution provides a set of fundamental tools for communicating via\n[WebSocket](https://tools.ietf.org/html/rfc6455).\nIt is only concerned with the protocol itself;\nthe underlying transport mechanism is up to you: it could be a file,\na UNIX socket, ordinary TCP/IP, some funky `tie()`d object, or whatever.\n\nNet::WebSocket also “has no opinions” about how you should do I/O or HTTP\nheaders. There are too many different ways to accomplish HTTP header\nmanagement in particular for it to be sensible for a WebSocket library to\nimpose any one approach. As a result of this, Net::WebSocket can probably\nfit your project with minimal overhead. There are some examples\nof how you might write complete applications (client or server)\nin the distribution’s `demo/` directory.\n\nNet::WebSocket emphasizes flexibility and lightness rather than the more\nmonolithic approach in modules like [Mojolicious](https://metacpan.org/pod/Mojolicious).\nNet::WebSocket should support anything\nthat the WebSocket protocol itself can do, as lightly as possible and without\nprejudice as to how you want to do it: extensions, streaming, blocking or\nnon-blocking I/O, arbitrary HTTP headers, etc. The end result should be a\nclean, light implementation that will grow (or shrink!) as your needs\ndictate.\n\n# OVERVIEW\n\nHere are the main modules:\n\n- [Net::WebSocket::Handshake::Server](https://metacpan.org/pod/Net::WebSocket::Handshake::Server)\n- [Net::WebSocket::Handshake::Client](https://metacpan.org/pod/Net::WebSocket::Handshake::Client)\n\n    Logic for handshakes. Every application needs one of these.\n    This handles all headers and can also negotiate\n    subprotocols and extensions for you.\n\n- [Net::WebSocket::HTTP\\_R](https://metacpan.org/pod/Net::WebSocket::HTTP_R)\n\n    A thin convenience wrapper for [HTTP::Request](https://metacpan.org/pod/HTTP::Request) and [HTTP::Response](https://metacpan.org/pod/HTTP::Response),\n    CPAN’s “standard” classes to represent HTTP requests and responses.\n    Net::WebSocket::HTTP\\_R should also work with other classes whose\n    interfaces are compatible with these “standard” ones.\n\n- [Net::WebSocket::Endpoint::Server](https://metacpan.org/pod/Net::WebSocket::Endpoint::Server)\n- [Net::WebSocket::Endpoint::Client](https://metacpan.org/pod/Net::WebSocket::Endpoint::Client)\n\n    A high-level abstraction to parse input\n    and respond to control frames and timeouts. You can use this to receive\n    streamed (i.e., fragmented) transmissions as well. You don’t have to use\n    this module, but it will make your life easier.\n\n- [Net::WebSocket::Parser](https://metacpan.org/pod/Net::WebSocket::Parser)\n\n    Translate WebSocket frames out of a filehandle into useful data for\n    your application.\n\n- [Net::WebSocket::Streamer::Server](https://metacpan.org/pod/Net::WebSocket::Streamer::Server)\n- [Net::WebSocket::Streamer::Client](https://metacpan.org/pod/Net::WebSocket::Streamer::Client)\n\n    Useful for sending streamed (fragmented) data rather than\n    a full message in a single frame.\n\n- Net::WebSocket::Frame::\\*\n\n    Useful for creating raw frames. You probably shouldn’t call these\n    classes directly; instead, use Endpoint’s `create_message()` method.\n    But if you want to dig deeply, these will be your bread and butter.\n    See [Net::WebSocket::Frame::text](https://metacpan.org/pod/Net::WebSocket::Frame::text) for sample usage.\n\n# IMPLEMENTATION NOTES\n\n## Handshakes\n\nWebSocket uses regular HTTP headers for its handshakes. Because there are\nmany different solutions around for parsing HTTP headers, Net::WebSocket\nis “agnostic” about how that’s done. The advantage is that if you’ve got\na custom solution for parsing headers then Net::WebSocket can fit into\nthat quite easily.\n\nThe liability of this is that you, the library user, must give headers\ndirectly to your Handshake object. (NB: [Net::WebSocket::HTTP\\_R](https://metacpan.org/pod/Net::WebSocket::HTTP_R) might\nbe able to do this for you.)\n\n## Masking\n\nAs per [the specification](https://tools.ietf.org/html/rfc6455#section-5.1),\nclient serializers “MUST” mask the data randomly, whereas server serializers\n“MUST NOT” do this. Net::WebSocket does this for you automatically,\nbut you need to distinguish\nbetween client serializers—which mask their payloads—and server serializers,\nwhich don’t mask.\n\nThis module used to do this with [Bytes::Random::Secure::Tiny](https://metacpan.org/pod/Bytes::Random::Secure::Tiny), but\nthat seems like overkill given that the masking is only there to accommodate\npeculiarities of certain proxies. Moreover, TLS is widely available and\n[free now besides](https://letsencrypt.org), and it will randomize the data\nstream anyway. So, nowadays we just use Perl’s `rand()` built-in.\n\n## Text vs. Binary\n\nRecall that in some languages—like JavaScript!—the difference between\n“text” and “binary” is much more significant than for us in Perl.\n\n## Use of [IO::Framed](https://metacpan.org/pod/IO::Framed)\n\nCPAN’s [IO::Framed](https://metacpan.org/pod/IO::Framed) provides a straightforward interface for chunking up\ndata from byte streams into frames. It also provides a write buffer for\nnon-blocking writes, and it (by default) retries on EINTR. You don’t have to\nuse it (which is why it’s not listed as a requirement), but you’ll need to\nprovide a compatible interface if you don’t.\n\nSee the demo scripts that use [IO::Framed](https://metacpan.org/pod/IO::Framed) for an example of when you may\nneed a different solution here.\n\n# EXTENSION SUPPORT\n\nThe WebSocket specification describes several methods of extending the\nprotocol, all of which Net::WebSocket supports:\n\n- The three reserved bits in each frame’s header.\n(See [Net::WebSocket::Frame](https://metacpan.org/pod/Net::WebSocket::Frame).) This is used, e.g., in the\n[permessage-deflate extension](https://tools.ietf.org/html/rfc7692).\n(See below for its implementation in Net::WebSocket.)\n- Additional opcodes: 3-7 and 11-15. You’ll need to subclass\n[Net::WebSocket::Frame](https://metacpan.org/pod/Net::WebSocket::Frame) for this, and you will likely want to subclass\n[Net::WebSocket::Parser](https://metacpan.org/pod/Net::WebSocket::Parser).\nIf you’re using the custom classes for streaming, then you can\nalso subclass [Net::WebSocket::Streamer](https://metacpan.org/pod/Net::WebSocket::Streamer). See each of those modules for\nmore information on doing this.\n\n    **THIS IS NOT WELL TESTED.** Proceed with caution, and please file bug\n    reports as needed. (I personally don’t know of any applications that\n    actually use this.)\n\n- Apportion part of the payload data for the extension. This you\ncan do in your application.\n\n## permessage-deflate\n\nNet::WebSocket fully supports the permessage-deflate (compression) extension.\nSee [Net::WebSocket::PMCE::deflate](https://metacpan.org/pod/Net::WebSocket::PMCE::deflate) for details.\n\n# TODO\n\nAt this point Net::WebSocket seems to support everything the WebSocket\nprotocol can (usefully) do, including compression. Please file bug reports\nfor any issues that may crop up.\n\n- Add more tests.\n\n# SEE ALSO\n\n[Mojolicious](https://metacpan.org/pod/Mojolicious) has a WebSocket implementation. It’s not as complete as\nNet::WebSocket, but if you’re using Mojolicious, you might try this first.\n\n[Protocol::WebSocket](https://metacpan.org/pod/Protocol::WebSocket) is an older module that supports\npre-standard versions of the WebSocket protocol. It’s similar to this one\nin that it gives you just the protocol itself, but it doesn’t give you\nthings like automatic ping/pong/close, classes for each message type, etc.\n\n[Net::WebSocket::Server](https://metacpan.org/pod/Net::WebSocket::Server) implements only server behaviors and\ngives you more automation than P::WS.\n\n[Net::WebSocket::EV](https://metacpan.org/pod/Net::WebSocket::EV) uses XS to call [wslay](http://wslay.sourceforge.net).\nAs of this writing it lacks support for handshake logic.\n\n# REPOSITORY\n\n[https://github.com/FGasper/p5-Net-WebSocket](https://github.com/FGasper/p5-Net-WebSocket)\n\n# AUTHOR\n\nFelipe Gasper (FELIPE)\n\n# COPYRIGHT\n\nCopyright 2018-2019 by [Gasper Software Consulting](http://gaspersoftware.com)\n\n# LICENSE\n\nThis distribution is released under the same license as Perl.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffgasper%2Fp5-net-websocket","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffgasper%2Fp5-net-websocket","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffgasper%2Fp5-net-websocket/lists"}