{"id":15622460,"url":"https://github.com/ajb413/pfunc-rest-api-example","last_synced_at":"2025-06-25T08:03:20.370Z","repository":{"id":78009938,"uuid":"137143289","full_name":"ajb413/pfunc-rest-api-example","owner":"ajb413","description":"A series of examples for building a REST API with PubNub Functions","archived":false,"fork":false,"pushed_at":"2018-06-19T18:47:19.000Z","size":30,"stargazers_count":1,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-29T16:27:28.512Z","etag":null,"topics":["pubnub","pubnub-functions","rest-api","serverless","serverless-functions"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/ajb413.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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-06-13T00:47:49.000Z","updated_at":"2019-09-13T17:59:27.000Z","dependencies_parsed_at":null,"dependency_job_id":"5473fb58-b636-4958-898f-08d6dc04ec4e","html_url":"https://github.com/ajb413/pfunc-rest-api-example","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ajb413/pfunc-rest-api-example","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajb413%2Fpfunc-rest-api-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajb413%2Fpfunc-rest-api-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajb413%2Fpfunc-rest-api-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajb413%2Fpfunc-rest-api-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ajb413","download_url":"https://codeload.github.com/ajb413/pfunc-rest-api-example/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ajb413%2Fpfunc-rest-api-example/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259960481,"owners_count":22938072,"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":["pubnub","pubnub-functions","rest-api","serverless","serverless-functions"],"created_at":"2024-10-03T09:54:05.935Z","updated_at":"2025-06-15T10:34:06.090Z","avatar_url":"https://github.com/ajb413.png","language":"JavaScript","readme":"# Build a REST API in 5 minutes with PubNub\n\n**Step by step guide** [hosted here](https://www.pubnub.com/blog/build-a-rest-api-in-5-minutes-with-pubnub/?devrel_gh=adamb) on the PubNub blog. [PubNub](https://dashboard.pubnub.com/signup?devrel_gh=pfunc-rest-api-example) is forever free to try.\n\nPubNub Functions are JavaScript event handlers that can be executed on in-transit PubNub messages, or in the request/response style of a RESTful API over HTTPS.\n\nDeploying code can be done on the command line using the `pubnub-cli` on npm and also **via CI/CD** like [in this tutorial](https://www.pubnub.com/blog/ci-cd-deploy-pubnub-functions-cli/?devrel_gh=pfunc-rest-api-example).\n\nFor deploying using your command line, see [this tool](https://www.pubnub.com/docs/blocks/cli-api?devrel_gh=pfunc-rest-api-example).\n\nPubNub Functions are serverless, there is **no need to worry about deploying, maintaining, or scaling server infrastructure**. We have several points of presence around the world in which your code is **deployed simultaneously**. This ensures that your users have an **extremely low latency** experience, **regardless of their location**.\n\n## REST API\n\nYou can build a REST API with Functions and deploy it with 1 button click. **Create a forever free account [at PubNub](https://dashboard.pubnub.com/signup?devrel_gh=pfunc-rest-api-example)** and click the Functions tab in the dashboard. Create a module and an event handler with the type `on request`.\n\nPress the play button on the right and use the UI on the left for making test **GET, POST, PUT,** and **DELETE** requests.\n\n![PubNub Functions Test HTTP Request Button](https://i.imgur.com/XjrCSBD.png)\n\nThe **COPY URL** button on the left gives you the public URL that this API is hosted. The ending path can be adjusted but the URL itself is static and immutable.\n\n![PubNub Functions On Request Handler](https://i.imgur.com/do62Eii.png)\n\n## Examples\nThe event handler in this repo shows how to turn this event handler into an API. There is a `controllers` object that points to a JavaScript function for each `route` URL parameter based on the HTTP method used (like GET, POST, PUT, and DELETE).\n\n```javascript\nlet controllers = {\n    default: {}, \n    index: {},\n    account: {},\n    counter: {},\n    kitty: {}\n};\n```\n\nThe code at the very bottom selects the function to execute based on the **request method** and **URL parameters**. If there is not a route defined on the back end, a **404** is returned.\n\n```javascript\nconst route = request.params.route;\nconst method = request.method.toLowerCase();\n\nif (!route \u0026\u0026 method === 'get') {\n    return controllers.default.get();\n} else if (\n    method \u0026\u0026\n    route \u0026\u0026\n    controllers[route] \u0026\u0026\n    controllers[route][method]\n) {\n    return controllers[route][method]();\n} else {\n    return notFound();\n}\n```\n\n## CRUD methods for a REST API\n```javascript\n// Read an account object from the DB by its `id`.\ncontrollers.account.get = () =\u003e {\n    // TODO: Check that user is authorized and validate `params`.\n    const id = request.params.id;\n    return db.get(`account-${id}`).then((accountData) =\u003e {\n        response.status = 200;\n        return response.send({\n            account_data: accountData\n        });\n    });\n};\n\n// Creates an account object from the POST request body\ncontrollers.account.post = () =\u003e {\n    // TODO: Check that user is authorized and validate `body`.\n    const id = body.id;\n    const accountData = body.account_data;\n\n    // Set value with TTL of 7 days, 32KB max per entry.\n    return db.set(`account-${id}`, accountData, 10080)\n    .then(() =\u003e {\n        // Helper function defined earlier\n        return ok();\n    }).catch((error) =\u003e {\n        console.error(error);\n        return badRequest();\n    });\n};\n\n// Update the user name attribute of the account object\ncontrollers.account.put = () =\u003e {\n    // TODO: Check that user is authorized and validate `body`.\n    const id = body.id;\n    const userName = body.user_name;\n\n    // Get the existing account information for a user\n    return db.get(`account-${id}`)\n    .then((accountData) =\u003e {\n        accountData = accountData || {};\n\n        // Update the user name attribute of the account object\n        accountData.user_name = userName;\n\n        // Set value with TTL of 7 days, 32KB max per entry.\n        return db.set(`account-${id}`, accountData, 10080);\n    }).then(() =\u003e {\n        // Helper function defined earlier\n        return ok();\n    }).catch((error) =\u003e {\n        console.error(error);\n        return badRequest();\n    });\n};\n\n// Destroy an account object specified by `id`\ncontrollers.account.delete = () =\u003e {\n    // TODO: Check that user is authorized and validate `params`.\n    const id = request.params.id;\n\n    // Delete value by setting it to null.\n    return db.set(`account-${id}`, null)\n    .then(() =\u003e {\n        // Helper function defined earlier\n        return ok();\n    }).catch((error) =\u003e {\n        console.error(error);\n        return badRequest();\n    });\n};\n```\n\n## Return HTML\n```javascript\ncontrollers.index.get = () =\u003e {\n    response.status = 200;\n    response.headers['Content-Type'] = 'text/html; charset=utf-8';\n    return response.send('\u003chtml\u003eHello!!\u003c/html\u003e');\n};\n```\n\n## Proxy one or many external API requests\n\nUp to 3 `xhr` requests can be made in 1 event handler execution. They can be chained using JavaScript promises.\n\n```javascript\ncontrollers.kitty.get = () =\u003e {\n    const url = 'http://thecatapi.com/api/images/get?results_per_page=1';\n    return xhr.fetch(url).then((result) =\u003e {\n        response.status = 302;\n        response.headers['Location'] = result.url;\n        return response.send();\n    });\n}\n```\n\nAlso an API request that needs secret API keys can be properly implemented in Functions using [vault](https://www.pubnub.com/docs/blocks/vault-module?devrel_gh=pfunc-rest-api-example). Add secret keys to the module by clicking **MY SECRETS** in the event handler editor page.\n\n```javascript\nconst xhr = require('xhr');\nconst vault = require('vault');\n\nreturn vault.get(\"myApiKey\").then((apiKey) =\u003e {\n    const http_options = {\n        \"method\": \"GET\",\n        \"headers\": {\n            \"API_KEY\": apiKey\n        }\n    };\n    return xhr.fetch(\"https://httpbin.org/get\", http_options).then((resp) =\u003e {\n        console.log(resp);\n        return response.send(\"OK\");\n    });\n});\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fajb413%2Fpfunc-rest-api-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fajb413%2Fpfunc-rest-api-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fajb413%2Fpfunc-rest-api-example/lists"}