{"id":37166326,"url":"https://github.com/kafkaesque-io/pulsar-beam","last_synced_at":"2026-01-14T19:42:41.948Z","repository":{"id":41125007,"uuid":"226555831","full_name":"kafkaesque-io/pulsar-beam","owner":"kafkaesque-io","description":"Pulsar Beam is a streaming service via HTTP built on Apache Pulsar.","archived":false,"fork":false,"pushed_at":"2022-07-13T07:13:49.000Z","size":323,"stargazers_count":58,"open_issues_count":13,"forks_count":14,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-11-14T20:54:54.396Z","etag":null,"topics":["apache-pulsar","go","golang","http","queueing","sse","streaming","webhook"],"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/kafkaesque-io.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":"2019-12-07T18:06:36.000Z","updated_at":"2024-03-02T18:44:12.000Z","dependencies_parsed_at":"2022-09-06T05:10:46.312Z","dependency_job_id":null,"html_url":"https://github.com/kafkaesque-io/pulsar-beam","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/kafkaesque-io/pulsar-beam","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kafkaesque-io%2Fpulsar-beam","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kafkaesque-io%2Fpulsar-beam/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kafkaesque-io%2Fpulsar-beam/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kafkaesque-io%2Fpulsar-beam/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kafkaesque-io","download_url":"https://codeload.github.com/kafkaesque-io/pulsar-beam/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kafkaesque-io%2Fpulsar-beam/sbom","scorecard":{"id":547311,"data":{"date":"2025-08-11","repo":{"name":"github.com/kafkaesque-io/pulsar-beam","commit":"1a2f11041e1ec44d693d77a66fbe16ee494a7549"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.6,"checks":[{"name":"Code-Review","score":1,"reason":"Found 5/30 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/go.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact 1.0.0 not signed: https://api.github.com/repos/kafkaesque-io/pulsar-beam/releases/30442388","Warn: release artifact 1.0.0 does not have provenance: https://api.github.com/repos/kafkaesque-io/pulsar-beam/releases/30442388"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/kafkaesque-io/pulsar-beam/go.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/kafkaesque-io/pulsar-beam/go.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:36: update your workflow using https://app.stepsecurity.io/secureworkflow/kafkaesque-io/pulsar-beam/go.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:48: update your workflow using https://app.stepsecurity.io/secureworkflow/kafkaesque-io/pulsar-beam/go.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/kafkaesque-io/pulsar-beam/go.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/go.yml:58: update your workflow using https://app.stepsecurity.io/secureworkflow/kafkaesque-io/pulsar-beam/go.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/go.yml:103: update your workflow using https://app.stepsecurity.io/secureworkflow/kafkaesque-io/pulsar-beam/go.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:120: update your workflow using https://app.stepsecurity.io/secureworkflow/kafkaesque-io/pulsar-beam/go.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/go.yml:130: update your workflow using https://app.stepsecurity.io/secureworkflow/kafkaesque-io/pulsar-beam/go.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:154: update your workflow using https://app.stepsecurity.io/secureworkflow/kafkaesque-io/pulsar-beam/go.yml/master?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:4","Warn: containerImage not pinned by hash: Dockerfile:19: pin your Docker image by updating alpine to alpine@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1","Warn: goCommand not pinned by hash: Dockerfile:12","Warn: goCommand not pinned by hash: .github/workflows/go.yml:32","Info:   0 out of   7 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned","Info:   0 out of   2 containerImage dependencies pinned","Info:   0 out of   2 goCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Vulnerabilities","score":0,"reason":"20 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2023-2409 / GHSA-6294-6rgp-fr7r / GHSA-mhpq-9638-x6pw","Warn: Project is vulnerable to: GO-2025-3553 / GHSA-mh63-6h87-95cp","Warn: Project is vulnerable to: GO-2024-2947 / GHSA-v6v8-xj6m-xwqh","Warn: Project is vulnerable to: GO-2023-2402 / GHSA-45x7-px36-x8w8","Warn: Project is vulnerable to: GO-2024-3321 / GHSA-v778-237x-gjrc","Warn: Project is vulnerable to: GO-2025-3487 / GHSA-hcg3-q754-cr77","Warn: Project is vulnerable to: GO-2022-0969 / GHSA-69cg-p879-7622","Warn: Project is vulnerable to: GO-2023-1495 / GHSA-fxg5-wq6x-vr4w","Warn: Project is vulnerable to: GO-2022-1144 / GHSA-xrjj-mj9h-534m","Warn: Project is vulnerable to: GO-2023-1571 / GHSA-vvpx-j8f3-3w6h","Warn: Project is vulnerable to: GO-2023-1988 / GHSA-2wrh-6pvc-2jm9","Warn: Project is vulnerable to: GO-2023-2102 / GHSA-4374-p667-p6c8","Warn: Project is vulnerable to: GHSA-qppj-fm5r-hxr3","Warn: Project is vulnerable to: GO-2024-2687 / GHSA-4v7x-pqxf-cx7m","Warn: Project is vulnerable to: GO-2024-3333","Warn: Project is vulnerable to: GO-2025-3503 / GHSA-qxp5-gwg8-xv66","Warn: Project is vulnerable to: GO-2025-3595 / GHSA-vvgc-356p-c3xw","Warn: Project is vulnerable to: GO-2025-3488 / GHSA-6v2p-p543-phr9","Warn: Project is vulnerable to: GO-2022-1059 / GHSA-69ch-w2m2-3vjp","Warn: Project is vulnerable to: GO-2024-2611 / GHSA-8r3f-844c-mc37"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 24 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-20T09:52:14.744Z","repository_id":41125007,"created_at":"2025-08-20T09:52:14.744Z","updated_at":"2025-08-20T09:52:14.744Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28432680,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T18:57:19.464Z","status":"ssl_error","status_checked_at":"2026-01-14T18:52:48.501Z","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":["apache-pulsar","go","golang","http","queueing","sse","streaming","webhook"],"created_at":"2026-01-14T19:42:41.088Z","updated_at":"2026-01-14T19:42:41.939Z","avatar_url":"https://github.com/kafkaesque-io.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"[![Join the chat at https://gitter.im/FaradayRF/Lobby](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/kafkaesque-io/community?utm_source=badge\u0026utm_medium=badge\u0026utm_content=badge)\n[![Go Report Card](https://goreportcard.com/badge/github.com/kafkaesque-io/pulsar-beam)](https://goreportcard.com/report/github.com/kafkaesque-io/pulsar-beam)\n[![CI Build](https://github.com/kafkaesque-io/pulsar-beam/workflows/ci/badge.svg\n)](https://github.com/kafkaesque-io/pulsar-beam/actions)\n[![Language](https://img.shields.io/badge/Language-Go-blue.svg)](https://golang.org/)\n[![codecov](https://codecov.io/gh/kafkaesque-io/pulsar-beam/branch/master/graph/badge.svg)](https://codecov.io/gh/kafkaesque-io/pulsar-beam)\n[![Docker image](https://shields.beevelop.com/docker/image/image-size/kafkaesqueio/pulsar-beam/0.22.svg?style=round-square)](https://hub.docker.com/r/kafkaesqueio/pulsar-beam/)\n[![LICENSE](https://img.shields.io/hexpm/l/pulsar.svg)](https://github.com/kafkaesque-io/pulsar-beam/blob/master/LICENSE)\n\n# Pulsar Beam\n\nBeam is an http based streaming and queueing system backed up by Apache Pulsar.\n\n- [x] A message can be sent to Pulsar via an HTTP POST method as a producer.\n- [x] A message can be pushed to a webhook or Cloud Function for consumption.\n- [x] A webhook or Cloud Function receives a message, process it and reply another message, in a response body, back to another Pulsar topic via Pulsar Beam.\n- [x] Messages can be streamed via HTTP Sever Sent Event, [SSE](https://www.html5rocks.com/en/tutorials/eventsource/basics/)\n- [x] Support HTTP polling of batch messages\n\nOpening an issue and PR are welcomed! Please email `contact@kafkaesque.io` for any inquiry or demo.\n\n## Advantages\n1. Since Beam speaks http, it is language and OS independent. You can take advantage of powerhouse of Apache Pulsar without limitation of client library and OS.\n\nImmediately, Pulsar can be supported on Windows and any languages with HTTP support.\n\n2. It has a very small footprint with a 15MB docker image size.\n\n3. Supports HTTP SSE streaming\n\n## Interface\n\nREST API and endpoint swagger document is published at [this link](https://kafkaesque-io.github.io/pulsar-beam-swagger/)\n\n### Endpoint to send messages\nThis is the endpoint to `POST` a message to Pulsar. \n\n```\n/v2/firehose/{persistent}/{tenant}/{namespace}/{topic}\n```\nValid values of {persistent} are `p`, `persistent`, `np`, `nonpersistent`\n\nThese HTTP headers may be required to map to Pulsar topic.\n1. Authorization -\u003e Bearer token as Pulsar token\n2. PulsarUrl -\u003e *optional* a fully qualified pulsar or pulsar+ssl URL where the message should be sent to. It is optional. The message will be sent to Pulsar URL specified under `PulsarBrokerURL` in the pulsar-beam.yml file if it is absent.\n\n### Endpoint to stream HTTP Server Sent Event\nThis is the endpoint to `GET` messages from Pulsar as a consumer subscription\n```\n/v2/sse/{persistent}/{tenant}/{namespace}/{topic}\n```\nValid values of {persistent} are `p`, `persistent`, `np`, `nonpersistent`\n\nThese HTTP headers may be required to map to Pulsar topic.\n1. Authorization -\u003e Bearer token as Pulsar token\n2. PulsarUrl -\u003e *optional* a fully qualified pulsar or pulsar+ssl URL where the message should be sent to. It is optional. The message will be sent to Pulsar URL specified under `PulsarBrokerURL` in the pulsar-beam.yml file if it is absent.\n\nQuery parameters\n1. SubscriptionType -\u003e Supported type strings are `exclusive` as default, `shared`, and `failover`\n2. SubscriptionInitialPosition -\u003e supported type are `latest` as default and `earliest`\n3. SubscriptionName -\u003e the length must be 5 characters or longer. An auto-generated name will be provided in absence. Only the auto-generated subscription will be unsubscribed.\n\n### Endpoint to poll batch messages\nPolls a batch of messages always from the earliest subscription position from a topic.\n```\n/v2/poll/{persistent}/{tenant}/{namespace}/{topic}\n```\nThese HTTP headers may be required to map to Pulsar topic.\n1. Authorization -\u003e Bearer token as Pulsar token\n2. PulsarUrl -\u003e *optional* a fully qualified pulsar or pulsar+ssl URL where the message should be sent to. It is optional. The message will be sent to Pulsar URL specified under `PulsarBrokerURL` in the pulsar-beam.yml file if it is absent.\n\nQuery parameters\n1. SubscriptionType -\u003e Supported type strings are `exclusive` as default, `shared`, and `failover`\n2. SubscriptionName -\u003e the length must be 5 characters or longer. An auto-generated name will be provided in absence. Only the auto-generated subscription will be unsubscribed.\n3. batchSize -\u003e Replies to a client when the batch size limit is reached. The default is 10 messages per batch. \n4. perMessageTimeoutMs -\u003e is a time out to wait for the next message's arrival from a Pulsar topic. It is in milliseconds per message. The default is 300ms.\n\n### Webhook registration\nWebhook registration is done via REST API backed by a database of your choice, such as MongoDB, in momery cache, and Pulsar itself. Yes, you can use a compacted Pulsar topic as a database table to perform CRUD. The configuration parameter is `\"PbDbType\": \"inmemory\",` in the `pulsar_beam.yml` file or the env variable `PbDbType`.\n\n#### Webhook or Cloud function management API\nThe management REAT API has this endpoint. Here is [the swagger document](https://kafkaesque-io.github.io/pulsar-beam-swagger/#/Create-or-Update-Topic)\n```\n/v2/topic\n```\n\n#### Bearer Token Authentication\nPulsar Beam can decode and authenticate JWT generated by Pulsar. Webhook management requires a subject in JWT that matches the tenant name in the topic full name. `pulsar-admin token` can be used to generate such token.\n\nPulsar Beam requires the same public and private keys to generate and verify JWT. These public and private key should be specified in the config to be loaded.\n\nTo disable JWT authentication, set the paramater `HTTPAuthImpl` in the config file or env variable to `noauth`.\n\n### Sink source\n\nIf a webhook's response contains a body and three headers including `Authorization` for Pulsar JWT, `TopicFn` for a topic fully qualified name, and `PulsarUrl`, the beam server will send the body as a new message to the Pulsar's topic specified as in TopicFn and PulsarUrl.\n\n### Server configuration\n\nBoth [json](./config/pulsar_beam.json) and [yml format](./config/pulsar_beam.yml) are supported as configuration file. The configuration paramters are specified by [config.go](https://github.com/kafkaesque-io/pulsar-beam/blob/master/src/util/config.go#L25). Every parameter can be overridden by an environment variable with the same name.\n\n#### Server Mode\nIn order to offer high performance and division of responsiblity, webhook and receiver endpoint can run independently `-mode broker` or `-mode receiver`. By default, the server runs in a hybrid mode with all features running in the same process.\n\n\n### Docker image and Docker builds\nThe docker image can be pulled from dockerhub.io.\n```\n$ sudo docker pull kafkaesqueio/pulsar-beam\n```\n\nHere are steps to build docker image and run docker container in a file based configuration.\n\n1. Build docker image\n```\n$ sudo docker build -t pulsar-beam .\n```\n\n2. Run docker\nThis is an example of a default configurations using in-memory database. Customized `pulsar_beam.yml` and private and public key files can be mounted and passed in as an env variable `PULSAR_BEAM_CONFIG`. The certificate is required to connect to Pulsar with TLS enabled.\n\n```\n$ sudo docker run -d -it -v /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem:/etc/ssl/certs/ca-bundle.crt -p 8085:8085 --name=pbeam-server pulsar-beam\n```\n\n`gops` is built in the docker image for troubleshooting purpose.\n\n### Pulsar Kubernetes cluster deployment\n\nPulsar Beam can be deployed within the same cluster as Pulsar. This [helm chart](https://github.com/kafkaesque-io/pulsar-helm-chart/blob/master/helm-chart-sources/pulsar/templates/beamwh-deployment.yaml) deploys a webhook broker in its own pod. The rest of HTTP receiver endpoint and REST API are deployed as a container within the [Pulsar proxy pod](https://github.com/kafkaesque-io/pulsar-helm-chart), that offers scalability with multiple replicas.\n\n\n## Dev set up\nClone the repo at your gopath src/github.com/kafkaesque-io/pulsar-beam folder.\n\n### Linting\nInstall golint.\n```bash\n$ go install github.com/golang/lint\n```\n\n```bash\n$ cd src\n$ golint ./...\n```\n\nThere are two scripts used for CI. You might want to run them in the local environment before submitting a PR.\nThis [CI script](./scripts/ci.sh) does linting, go vet and go build.\nThe [code coverage script](./scripts/test_coverage.sh) runs unit test and tallies up the code coverage.\n\n### How to run \nThe steps how to start the web server.\n```bash\n$ cd src\n$ go run main.go\n```\n\n### Local CI, unit test and end to end test\nThere are scripts under `./scripts` folder to run code analysis, vetting, compilation, unit test, and code coverage manually as all of these are part of CI checks by Github Actions.\n\nOne end to end test is under `./src/e2e/e2etest.go`, that performs the following steps in order:\n1. Create a topic and its webhook via RESTful API. The webhook URL can be an HTTP triggered Cloud Function. CI process uses a GCP \n2. Send a message to Pulsar Beam's v1 injestion endpoint\n3. Waiting on the sink topic where the first message will be sent to a GCP Cloud Function (in CI) and in turn reply to Pulsar Beam to forward to the second sink topic\n4. Verify the replied message on the sink topic\n5. Delete the topic and its webhook document via RESTful API\n\nSince the set up is non-trivial involving Pulsar Beam, a Cloud function or webhook, the test tool, and Pulsar itself with SSL, we recommend to take advantage of [the free plan at kesque.com](https://kesque.com) as the Pulsar server and a Cloud Function that we have verified GCP Fcuntion, Azure Function or AWS Lambda will suffice in the e2e flow.\n\n Step to perform unit test\n```bash\n$ cd src/unit-test\n$ go test -v .\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkafkaesque-io%2Fpulsar-beam","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkafkaesque-io%2Fpulsar-beam","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkafkaesque-io%2Fpulsar-beam/lists"}