{"id":21065055,"url":"https://github.com/prolificinteractive/behalf","last_synced_at":"2025-09-09T15:44:44.374Z","repository":{"id":35853233,"uuid":"40137707","full_name":"prolificinteractive/behalf","owner":"prolificinteractive","description":"Emulate the way browsers make requests and manage cookies.","archived":false,"fork":false,"pushed_at":"2018-01-24T15:44:02.000Z","size":130,"stargazers_count":3,"open_issues_count":3,"forks_count":2,"subscribers_count":30,"default_branch":"master","last_synced_at":"2025-04-03T19:11:13.668Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/prolificinteractive.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-08-03T17:14:48.000Z","updated_at":"2016-11-23T19:04:16.000Z","dependencies_parsed_at":"2022-09-08T17:30:11.279Z","dependency_job_id":null,"html_url":"https://github.com/prolificinteractive/behalf","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prolificinteractive%2Fbehalf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prolificinteractive%2Fbehalf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prolificinteractive%2Fbehalf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/prolificinteractive%2Fbehalf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/prolificinteractive","download_url":"https://codeload.github.com/prolificinteractive/behalf/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254456231,"owners_count":22074131,"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-11-19T17:53:18.848Z","updated_at":"2025-05-16T02:32:57.577Z","avatar_url":"https://github.com/prolificinteractive.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Behalf](behalf.jpg)\n\n## Installation\n\n`npm install behalf --save`\n\n## Summary\n\nBehalf mimics the way browsers make requests and manage cookies. It provides session objects that automatically send and store cookies with each request, as well as Express middleware that allows you to automatically load sessions within requests.\n\n## Example\n\n```javascript\nvar session = behalf.createSession({ host: 'amazon.com' });\n\nsession\n  .requestSecure({\n    method: 'POST',\n    uri: '/login',\n    form: {\n      email: 'blitz@prolificinteractive.com',\n      password: 'dogtreats'\n    }\n  })\n  .then(function () {\n    return session.requestSecure('/wishlist'); // Session automatically sends cookies along\n  })\n  .get('body')\n  .done(doStuffWithWishlistPage);\n```\n\n## Contents\n\n[API](#api)\n - [behalf.createSession](#behalfcreatesessionoptions-or-new-behalfsessionoptions)\n - [behalf.Session.import](#sessionimportexportobject)\n - [session.export](#sessionexport-id-string-host-string-useragent-string-jar-object)\n - [session.request](#sessionrequestrequestoptions-callback-responsepromise)\n - [session.requestSecure](#sessionrequestsecurerequestoptions-callback-responsepromise)\n - [session.requestJson](#sessionrequestjsonrequestoptions-callback-responsepromise)\n - [session.requestJsonSecure](#sessionrequestjsonsecurerequestoptions-callback-responsepromise)\n\n[Middleware](#middleware)\n - [behalf.middleware.sessionManager](#behalfmiddlewaresessionmanageroptions)\n - [behalf.middleware.generateSession](#behalfmiddlewaregeneratesession)\n - [behalf.middleware.requireSession](#behalfmiddlewarerequiresession)\n\n[Session Stores](#session-stores)\n - [behalf.stores.Redis](#new-behalfstoresredisoptions)\n - [behalf.stores.Memory](#new-behalfstoresmemory)\n - [Rolling Your Own](#rolling-your-own-session-store)\n\n[Contributing](#contributing)\n\n## API\n\n### `behalf.createSession(options)` or `new behalf.Session(options)`\n\n - `jar` - A cookie jar either made with `request` library's `request.jar()` method or a `tough-cookie` jar object. Creates a new one by default.  \n - `id` - A uuid. Automatically generated by default.  \n - `userAgent` - A user agent string to send along in the header of each request.  \n - `host` - Sets a host so that we don't have to repeat it for every request.  \n\n### `Session.import(exportObject)`\n\nCreates a behalf session object from an exported object.\n\n### `session.export() -\u003e { id: String, host: String, userAgent: String, jar: Object }`\n\nReturns an object containing the session's `id` and cookie jar. Useful for serializing and persisting to a database.\n\n### `session.request(requestOptions, [callback]) -\u003e responsePromise`\n\nMakes a request using the [request library](https://github.com/request/request), automatically using the stored `jar`, `host`, and `userAgent`. Supports both promises and callbacks, with a response object as the return value.\n\nBy default, Behalf will manually follow redirects so that it can consume any cookies that are sent back along the way. To disable this, simply set `followRedirect: true` in `requestOptions`.\n\n### `session.requestSecure(requestOptions, [callback]) -\u003e responsePromise`\n\nSame as `session.request`, except using `https` protocol.\n\n### `session.requestJson(requestOptions, [callback]) -\u003e responsePromise`\n\nSets the `Content-Type` header to \"application/json\" and adds a `json` key to the response object, which contains the parsed body.\n\n### `session.requestJsonSecure(requestOptions, [callback]) -\u003e responsePromise`\n\nSame as `session.requestJson` but with HTTPS as the protocol.\n\n## Express Middleware\n\nThe library also includes a set of Express middleware to manage the automatic loading and saving of sessions, which is very useful for applications that wrap around websites (see examples/ folder).\n\n### `behalf.middleware.sessionManager(options)`\n\nThis middleware extracts a session key from the request, then loads a session. Example:\n\n```javascript\nvar sessions = new behalf.middleware.sessionManager(\n  store: new behalf.stores.Redis(),\n  ttl: 3600000, //1 hour\n  getKey: function (req) {\n    return req.headers['session-key'];\n  }\n);\n\napp.use(sessions);\n```\n\nOptions:\n - `store` - An instance of a session store. Behalf comes with two: `behalf.stores.Memory` and `behalf.stores.Redis`. See [\"Session Stores\"](#session-stores) to learn more.\n - `ttl` - TTL in milliseconds. Defaults to indefinite TTL.\n - `getKey` - A function that extracts and returns the session key from the Express request object.\n\nNow you'll get an object attached to the Express request object under the `behalf` property that contains the session context. It has these properties:\n - `key` - The session key, or `null`, extracted with the `getKey` function.\n - `session` - The loaded `behalf.Session` instance, or `null`.\n\nIn this example, we proxy Amazon's homepage. If the user has logged in using a Behalf session request, the cookies will trigger the site to serve that user's personalized homepage rather than the generic one:\n\n```javascript\napp.get('/', function (req, resp, next) {\n  req.behalf.session\n    .request('http://amazon.com')\n    .done(resp.send.bind(resp), next);\n});\n```\n\n### `behalf.middleware.requireSession()`\n\nThis middleware ensures that there will be a session, or throws an error. If no session key is found in the request, it will return a `499` status code. If a key is found but can't be retrieved from the store, a `498` status code is returned.\n\nExample:\n```javascript\napp.get('/wishlist', behalf.middleware.requireSession(), function (req, resp, next) {\n  req.behalf.session\n    .request('http://amazon.com/account/wishlist')\n    .done(resp.send.bind(resp), next);\n});\n```\n\n### `behalf.middleware.generateSession()`\n\nCreates a new session. This is useful for providing an endpoint that grants session keys:\n\n```javascript\napp.get('/sessions/new', [\n  behalf.middleware.generateSession(),\n  function (req, resp) {\n    resp.send({\n      sessionId: req.behalf.session.id\n    });\n  }\n]);\n```\n\n## Session Stores\n\nBehalf includes two session stores, one in-memory and one for Redis.\n\n### `new behalf.stores.Redis(options)`\n\nOptions:\n - `config` - _Optional_. Redis configuration, passed into the `redis.createClient` constructor.\n - `keyPrefix` - _Optional_. Prepended to every Redis key that sessions are stored against. Default: \"sessions:\"\n\n### `new behalf.stores.Memory()`\n\nStores sessions within the memory of the running process. Recommended for development use only.\n\n### Rolling Your Own Session Store\n\nIf you want to use a different kind of database, the interface for a store is very simple. There are 3 required methods: `save`, `load`, and `destroy`.\n\n#### .save\n\nThe save method takes a `behalf.Session` instance and an optional TTL, and should return a promise. The promise shouldn't resolve with a value. You should always use the `session.export` method to serialize the session instance. Here's a pseudo-example:\n\n```javascript\nMyStore.prototype.save = function (session, ttl) {\n  var exportObj = session.export();\n\n  exportObj.jar = JSON.stringify(exportObj.jar);\n\n  return this.db\n    .insert('sessions', exportObj)\n    .then(function () {\n      if (ttl) {\n        return messageQueue.cancel('destroySession', { id: session.id });\n      }\n    })\n    .then(function () {\n      return messageQueue.push('destroySession', { id: session.id }, ttl);\n    })\n    .return();\n}\n```\n\n#### .load\n\nThe load method takes a session ID string as an argument and returns a promise that resolves to a `behalf.Session` instance. Use `behalf.Session.import` to deserialize the exported object.\n\n```javascript\nMyStore.prototype.load = function (sessionId) {\n  return this.db\n    .select('sessions', sessionId)\n    .tap(function (exportObj) {\n      exportObj.jar = JSON.parse(exportObj.jar);\n    })\n    .then(behalf.Session.import);\n}\n```\n\n#### .destroy\n\nTakes a session ID string as an argument and returns a promise that resolves with no value:\n\n```javascript\nMyStore.prototype.destroy = function (sessionId) {\n  return this.db\n    .delete('sessions', sessionId)\n    .return();\n}\n```\n\n#### Testing Your Session Store\n\nTest your interface by using the test suite:\n\n```javascript\nrequire('behalf/test/session-store-test')(new MyStore(), 'MyStore');\n```\n\n## Contributing\n\nRun tests using `npm test`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprolificinteractive%2Fbehalf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprolificinteractive%2Fbehalf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprolificinteractive%2Fbehalf/lists"}