{"id":13737037,"url":"https://github.com/subsetpark/nim-stomp","last_synced_at":"2025-04-14T22:00:05.993Z","repository":{"id":77775682,"uuid":"128261206","full_name":"subsetpark/nim-stomp","owner":"subsetpark","description":"A fork of Mahlon Smith's nim-stomp.","archived":false,"fork":false,"pushed_at":"2018-04-06T21:38:56.000Z","size":24,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-06T13:49:54.445Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://bitbucket.org/mahlon/nim-stomp","language":"Nim","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/subsetpark.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-04-05T20:33:51.000Z","updated_at":"2018-04-06T21:38:56.000Z","dependencies_parsed_at":"2023-04-12T23:32:19.956Z","dependency_job_id":null,"html_url":"https://github.com/subsetpark/nim-stomp","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/subsetpark%2Fnim-stomp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/subsetpark%2Fnim-stomp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/subsetpark%2Fnim-stomp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/subsetpark%2Fnim-stomp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/subsetpark","download_url":"https://codeload.github.com/subsetpark/nim-stomp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248968745,"owners_count":21191158,"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-08-03T03:01:33.995Z","updated_at":"2025-04-14T22:00:05.973Z","avatar_url":"https://github.com/subsetpark.png","language":"Nim","funding_links":[],"categories":["Web"],"sub_categories":["Protocols"],"readme":"# README #\n\n## Overview ##\n\nThis is a pure-nim client library for interacting with Stomp\ncompliant messaging brokers.\n\nhttps://stomp.github.io/\n\nStomp is a simple protocol for message passing between clients, using a central\nbroker.  It is a subset of other more elaborate protocols (like AMQP), supporting\nonly the most used features of common brokers.\n\nBecause this library is pure-nim, there are no external dependencies.  If you\ncan compile a nim binary, you can participate in advanced messaging between processes.\n\nA list of broker support for Stomp can be found here:\nhttps://stomp.github.io/implementations.html.\n\nThis library has been tested with recent versions of RabbitMQ.  If it\nworks for you with another broker, please let the author know.\n\n### Installation ###\n\nThe easiest way to install this module is via the nimble package manager, \nby simply running 'nimble install stomp'.\n\nAlternatively, you can fetch the 'stomp.nim' file yourself, and put it\nin a place of your choosing.\n\n\n### Protocol support ###\n\nThis library supports (almost) the entirety of the Stomp 1.2 spec,\nwith the exception of client to server heartbeat.  Server to client\nheartbeat is fully supported, which should normally be sufficient to\nkeep firewall state tables open and sockets alive.\n\n\n### Callbacks ###\n\nBecause a client can receive frames at any time, most of the behavior\nof this module is implemented via callback procs.\n\nBy default, most every event is a no-op.  You can override various\nbehaviors with the following callbacks:\n\n* **connected_callback**:  Called when the Stomp library makes a successful\n connection to the broker.\n\n* **error_callback**: Called if there was a **ERROR** frame in the stream. By default,\n this raises a **StompError** exception with the error message.\n\n* **heartbeat_callback**: Called when a server heartbeat is received.\n\n* **message_callback**: Called when a **MESSAGE** frame is received.\n\n* **missed_heartbeat_callback**: Called when the Stomp socket is idle longer than\n the specified heartbeat time -- usually an indication of a problem.  The default behavior\n raises a **StompError** exception.\n\n* **receipt_callback**: Called when a **RECEIPT** frame is received.\n\n\n### Custom headers ###\n\nDepending on the broker, you may be able to add addtional features to outgoing messages\nby adding specific headers.  You can also add \"x-headers\" that are carried between messages.\n\nAnother use is to issue \"receipts\" on sends or subscriptions, to ensure the broker has\nprocessed your request.  Here's an example of how to perform receipt processing:\n\n```\n#!nimrod\nproc accept_receipt( c: StompClient, r: StompResponse ) =\n   var receipt = r[ \"receipt-id\" ]\n   # ... match this receipt up to the request that generated it\n\nvar client = newStompClient( socket, \"...\" )\n\nclient.receipt_callback = accept_receipt\nclient.connect\n\nvar headers = seq[ tuple[name:string, value:string] ]\nheaders.add( (\"x-breakfast\", \"tequila\") )\nheaders.add( (\"receipt\", \"special-identifier\") )\n\nclient.send( \"/destination\", \"message!\", \"text/plain\", headers )\n```\n\n\n### Transactions ###\n\nThis library has full support for transactions.  Once entering a\ntransaction, any messages or acknowledgments attached to it must be\ncommitted before the broker will release them.\n\nWith one open transaction, messages are automatically attached to it.\nIf you have multiple open transactions, you'll need to add which one\nyou want a message to be part of via the custom headers.\n\n```\n#!nimrod\n# Single transaction\n#\nclient.begin( \"trans-1\" )\nclient.send( \"/destination\", \"hi\" ) # Part of \"trans-1\"\nclient.send( \"/destination\", \"yo\" ) # Part of \"trans-1\"\nclient.send( \"/destination\", \"whaddup\" ) # Part of \"trans-1\"\nclient.commit # or client.abort\n\n# Multiple simultaneous transactions\n#\nclient.begin( \"trans-1\" )\nclient.begin( \"trans-2\" )\nclient.begin( \"trans-3\" )\n\nvar headers = seq[ tuple[name:string, value:string] ]\nheaders.add( (\"transaction\", \"trans-1\") )\nclient.send( \"/destination\", \"hi\", nil, headers ) # Part of \"trans-1\"\n\nheaders = @[]\nheaders.add( (\"transaction\", \"trans-2\") )\nclient.send( \"/destination\", \"hi\", nil, headers ) # Part of \"trans-2\"\nclient.ack( \"some-ack-id\", \"trans-2\" ) # Part of \"trans-2\"\n\nheaders = @[]\nheaders.add( (\"transaction\", \"trans-3\") )\nclient.send( \"/destination\", \"hi\", nil, headers ) # Part of \"trans-3\"\nclient.ack( \"some-ack-id\", \"trans-3\" ) # Part of \"trans-3\"\n\nclient.abort( \"trans-1\" )  # anything \"trans-1\" never happened\nclient.commit( \"trans-2\" ) # \"trans-2\" messages and acks are released\nclient.abort( \"trans-3\" )  # anything \"trans-3\" never happened\n```\n\n### Example ###\n\nThis is a complete client that does the following:\n\n* Connect to an AMQP server at **mq.example.com** via SSL as the **test** user,\n  in the **/example** vhost.\n* Request heartbeats every **5** seconds.\n* Subscribe to a topic exchange **events** with the key of **user.create**, requiring message\n  acknowledgement.\n* Accept incoming messages, parsing the JSON payloads.\n* If parsing was successful, ACK the message and emit a new message to the exchange\n  with JSON results to the **user.created** key -- presumably to be picked up by another\n  process elsewhere.\n\n```\n#!nimrod\n# (This should be compiled with -d:ssl)\n\nimport\n   json,\n   net,\n   stomp\n\nlet\n   socket = newSocket()\n   sslContext = newContext( verifyMode = CVerifyNone )\n\nsslContext.wrapSocket( socket )\nvar client = newStompClient( socket, \"stomp+ssl://test:test@mq.example.com/%2Fexample?heartbeat=5\" )\n\n# Announce when we're connected.\nproc connected( c: StompClient, r: StompResponse ) =\n   echo \"Connected to a \", c[\"server\"], \" server.\"\n\n# Echo to screen when we see a heartbeat.\nproc heartbeat( c: StompClient, r: StompResponse ) =\n   echo \"Heartbeat at: \",  c.last_msgtime\n\n# Parse JSON, perform work, send success message.\nproc message( c: StompClient, r: StompResponse ) =\n   let id = r[ \"ack\" ]\n\n   if r[ \"content-type\" ] != \"application/json\":\n\t   echo \"I expect JSON payloads.\"\n\t   c.nack( id )\n\t   return\n\n   try:\n\t   var json = r.payload.parse_json\n\n\t   # ... do the heavy lifting with the parsed data.\n\t   # ... and assuming is was successful, ack and emit!\n\t   \n\t   c.ack( id )\n\n\t   var message = %*{ \"user\": json[\"user\"].getStr, \"otherstuff\": true }\n\t   c.send( \"/exchange/events/user.created\", $message, \"application/json\" )\n\n   except JsonParsingError:\n\t   echo \"Couldn't parse JSON! \", r.payload\n\t   c.nack( id )\n\n# Attach callbacks\nclient.connected_callback = connected\nclient.message_callback = message\nclient.heartbeat_callback = heartbeat\n\n# Open a session with the broker\nclient.connect\n\n# Subscribe to a topic key, requiring acknowledgements.\nclient.subscribe( \"/exchange/events/user.create\", \"client-individual\" )\n\n# Enter message loop.\nclient.wait_for_messages\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsubsetpark%2Fnim-stomp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsubsetpark%2Fnim-stomp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsubsetpark%2Fnim-stomp/lists"}