From 4b160303cfcc32f723a713f9bbd8fde728a28b61 Mon Sep 17 00:00:00 2001 From: Jason Dobry Date: Fri, 13 Nov 2015 13:47:57 -0800 Subject: [PATCH] Cleaned up memcached example and added tests. --- .travis.yml | 1 + README.md | 3 + appengine/express-memcached-session/README.md | 132 +++++++++++------- appengine/express-memcached-session/app.yaml | 1 - .../express-memcached-session/package.json | 16 ++- appengine/express-memcached-session/server.js | 45 +++--- package.json | 1 + test/appengine/all.test.js | 23 +-- .../express-memcached-session.test.js | 26 ++++ 9 files changed, 161 insertions(+), 87 deletions(-) create mode 100644 test/appengine/express-memcached-session.test.js diff --git a/.travis.yml b/.travis.yml index 7c015d2c48..a1c131dc71 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,6 +34,7 @@ cache: services: - redis-server + - memcached - docker env: diff --git a/README.md b/README.md index 9d0e8df248..1cd61e4950 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ and applications on [Google App Engine](http://cloud.google.com/nodejs). ### Frameworks - Express.js - [Source code][express_1] | [App Engine Tutorial][express_2] | [Live demo][express_3] | [Documentation][express_4] + - Express.js + Memcached Sessions - [Source code][express_5] | [Documentation][express_6] - Geddy.js - [Source code][geddy_1] | [App Engine Tutorial][geddy_2] | [Live demo][geddy_3] | [Documentation][geddy_4] - Hapi.js - [Source code][hapi_1] | [App Engine Tutorial][hapi_2] | [Live demo][hapi_3] | [Documentation][hapi_4] - Loopback.js - [Source code][loopback_1] | [App Engine Tutorial][loopback_2] | [Live demo][loopback_3] | [Documentation][loopback_4] @@ -68,6 +69,8 @@ See [LICENSE](https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/ma [express_2]: https://cloud.google.com/nodejs/resources/frameworks/express [express_3]: http://express-dot-nodejs-docs-samples.appspot.com [express_4]: http://expressjs.com/ +[express_5]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/appengine/express-memcached-session +[express_6]: https://github.com/balor/connect-memcached [geddy_1]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/appengine/geddy [geddy_2]: https://cloud.google.com/nodejs/resources/frameworks/geddy diff --git a/appengine/express-memcached-session/README.md b/appengine/express-memcached-session/README.md index c3107c8f6a..66ee94eac4 100644 --- a/appengine/express-memcached-session/README.md +++ b/appengine/express-memcached-session/README.md @@ -1,65 +1,93 @@ -# Express + Memcached Sessions -> Google App Engine +## Express.js + Memcached Sessions on Google App Engine -This is a simple guide to using memcached for session state while running [expressjs](http://expressjs.com/) on Google App Engine. Each Google App Engine application comes with a memcached service instance, which can be reached with a standard memcached driver at `memcache:11211`. +This is a simple guide to using memcached for session state while running +[Express.js](http://expressjs.com/) on Google App Engine. Each Google App Engine +application comes with a memcached service instance, which can be reached with a +standard memcached driver at `memcache:11211`. This sample uses the +[connect-memcached](https://github.com/balor/connect-memcached) module to store +session data in memcached. -1. [Create a new Express app](http://expressjs.com/starter/generator.html) +## Clone the Express.js + Memcached Sessions app -2. Create an `app.yaml` in the root of your application with the following contents: +If you haven't already, copy the repository to your local machine by entering +the following command in your terminal window: - ```yaml - runtime: nodejs - vm: true - env_variables: - PORT: 8080 - MEMCACHE_URL: memcache:11211 - ``` +``` +$ git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git +$ cd nodejs-docs-samples/appengine/express-memcached-session +``` + +Alternatively, you can [download the sample][download] as a zip and extract it. + +## Run the app on your local computer + +1. Install dependencies. Enter the following command: - Notice the MEMCACHE_URL environment variable - this is where you can reach your standard memcached cluster across instances. - -3. Use the [connect-memcached](https://github.com/balor/connect-memcached) module. Run `npm install --save connect-memcached`, and add the following to your server.js or app.js: - - ```js - var MemcachedStore = require('connect-memcached')(session); - ... - app.use(session({ - secret: 'appengineFTW', - key: 'test', - proxy: 'true', - store: new MemcachedStore({ - hosts: [process.env.MEMCACHE_URL || '127.0.0.1:11211'] - }) - })); ``` -4. In your express route handlers, you can now safely use `req.session.*` across multiple nodejs instances: - - ```js - app.get('/', function(req, res){ - publicIp.v4(function (err, ip) { - res.write("
" + ip + "
"); - if(req.session.views) { - ++req.session.views; - } else { - req.session.views = 1; - } - res.end('Viewed ' + req.session.views + ' times.'); - }); - }); + $ npm install ``` -5. To test the sample locally, you can install memcached. - - OSX + [Brew](http://brew.sh/): `brew install memcached` - - Windows + [Chocolatey](https://chocolatey.org/packages/memcached): `choco install memcached` +2. Run the start script. - Run memcached on localhost:11211 by running `memcached` - + ```` + $ npm start + ``` -6. Deploy your app. For convenience, you can use an npm script to run the command. Modify your `package.json` to include: +3. In your web browser, enter the following address: - ```js - "scripts": { - "start": "node server.js", - "deploy": "gcloud preview app deploy app.yaml --set-default --project [project id]" - } ``` + $ http://localhost:8080 + ``` + +You can see the sample app displayed in the page. This page was delivered by the +Express.js web server running on your computer. + +In your terminal window, press Ctrl+C to exit the web server. + +## Deploy the app to Google Cloud Platform + +In your terminal window, enter the following command to deploy the sample: + +``` +$ gcloud preview app deploy app.yaml --promote +``` + +### See the app run in the cloud + +In your web browser, enter the following address: + +``` +https://.appspot.com +``` + +For convenience, you can use an npm script to run the gcloud command. Add these lines to your package.json file: + +``` +"scripts": { + "start": "node server.js", + "deploy": "gcloud preview app deploy app.yaml --promote --project " +} +``` + +At the terminal you can now run the following command to deploy your application: + +``` +$ npm run deploy +``` + +## Configuration + +Every Managed VMs application requires an app.yaml file to describe its deployment configuration. + +```yaml +runtime: nodejs +vm: true +env_variables: + PORT: 8080 + MEMCACHE_URL: memcache:11211 +``` + +Notice the `MEMCACHE_URL` environment variable–this is where you can reach your +standard memcached cluster across instances. -At the terminal you can now run `npm run deploy` to deploy your application. +[download]: https://github.com/GoogleCloudPlatform/nodejs-docs-samples/archive/master.zip diff --git a/appengine/express-memcached-session/app.yaml b/appengine/express-memcached-session/app.yaml index ef57b97784..74bdf41675 100644 --- a/appengine/express-memcached-session/app.yaml +++ b/appengine/express-memcached-session/app.yaml @@ -12,7 +12,6 @@ # limitations under the License. runtime: nodejs -api_version: 1 vm: true env_variables: PORT: 8080 diff --git a/appengine/express-memcached-session/package.json b/appengine/express-memcached-session/package.json index 1f1bd274b6..3defb6f7fa 100644 --- a/appengine/express-memcached-session/package.json +++ b/appengine/express-memcached-session/package.json @@ -1,14 +1,20 @@ { - "name": "express-memcached-session-demo", - "version": "1.0.0", + "name": "appengine-express-memcached-session", + "description": "An example of using memcached for sessions in Express.js on Google App Engine.", + "version": "0.0.1", "private": true, + "license": "Apache Version 2.0", + "engines": { + "node": "~0.12.7" + }, "scripts": { - "deploy": "gcloud preview app deploy app.yaml --set-default --project express-memcached-demo" + "start": "node server.js", + "deploy": "gcloud preview app deploy app.yaml" }, "dependencies": { "connect-memcached": "^0.1.0", - "cookie-parser": "~1.3.5", - "express": "~4.12.4", + "cookie-parser": "^1.3.5", + "express": "^4.12.4", "express-session": "^1.11.3", "public-ip": "^1.1.0" } diff --git a/appengine/express-memcached-session/server.js b/appengine/express-memcached-session/server.js index 855b500c10..e9827248a8 100644 --- a/appengine/express-memcached-session/server.js +++ b/appengine/express-memcached-session/server.js @@ -16,7 +16,6 @@ var express = require('express'); var session = require('express-session'); var cookieParser = require('cookie-parser'); -var http = require('http'); var MemcachedStore = require('connect-memcached')(session); var publicIp = require('public-ip'); @@ -24,29 +23,33 @@ var app = express(); app.use(cookieParser()); app.use(session({ - secret: 'appengineFTW', - key: 'test', - proxy: 'true', - store: new MemcachedStore({ - hosts: [process.env.MEMCACHE_URL || '127.0.0.1:11211'] - }) + secret: 'your-secret-here', + key: 'view:count', + proxy: 'true', + store: new MemcachedStore({ + hosts: [process.env.MEMCACHE_URL || '127.0.0.1:11211'] + }) })); app.get('/', function(req, res){ - publicIp.v4(function (err, ip) { - - // This shows the IP for each - res.write('
' + ip + '
'); - - if(req.session.views) { - ++req.session.views; - } else { - req.session.views = 1; - } - res.end('Viewed ' + req.session.views + ' times.'); - }); + publicIp.v4(function (err, ip) { + + // This shows the IP for each + res.write('
' + ip + '
'); + + if(req.session.views) { + ++req.session.views; + } else { + req.session.views = 1; + } + res.end('Viewed ' + req.session.views + ' times.'); + }); }); -http.createServer(app).listen(process.env.PORT || 8080, function() { +if (module === require.main) { + app.listen(process.env.PORT || 8080, function() { console.log('Listening on %d', this.address().port); -}); \ No newline at end of file + }); +} + +module.exports = app; diff --git a/package.json b/package.json index d7a3ca9b3e..ca8a8dc7de 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "cover": "istanbul cover --hook-run-in-context node_modules/mocha/bin/_mocha -- --timeout 10000 --recursive", "coveralls": "cat ./coverage/lcov.info | node_modules/.bin/coveralls", "pretest_express": "cd appengine/express && npm install && cd ../..", + "pretest_memcached": "cd appengine/express-memcached-session && npm install && cd ../..", "pretest_geddy": "cd appengine/geddy && npm install geddy; GEDDY_SECRET=config/secrets.json; [[ -f $GEDDY_SECRET ]] || echo '{}' > $GEDDY_SECRET && node node_modules/.bin/geddy gen secret; cd ../..;", "pretest": "npm run pretest_express && npm run pretest_geddy", "test": "npm run jshint && npm run cover" diff --git a/test/appengine/all.test.js b/test/appengine/all.test.js index f8e7e995d9..bb13f2426f 100644 --- a/test/appengine/all.test.js +++ b/test/appengine/all.test.js @@ -34,6 +34,13 @@ var sampleTests = [ msg: 'Hello World! Express.js on Google App Engine.', TRAVIS_NODE_VERSION: '0.10' }, + { + dir: 'express-memcached-session', + cmd: 'node', + args: ['server.js'], + msg: 'Viewed', + TRAVIS_NODE_VERSION: '0.10' + }, { dir: 'geddy', deploy: true, @@ -82,12 +89,12 @@ var sampleTests = [ args: ['app.js'], msg: 'Express.js + Mailgun on Google App Engine.' }, - // { - // dir: 'redis', - // cmd: 'node', - // args: ['server.js'], - // msg: '127.0.0.1' - // }, + { + dir: 'redis', + cmd: 'node', + args: ['server.js'], + msg: '127.0.0.1' + }, { dir: 'restify', deploy: true, @@ -112,7 +119,7 @@ if (process.env.TRAVIS_NODE_VERSION === '0.10') { }); } -//if (process.env.TRAVIS_NODE_VERSION === 'stable') { +if (process.env.TRAVIS_NODE_VERSION === 'stable') { // For some reason the "npm install" step for the Sails sample doesn't work on // Travis when using Node.js stable. It works locally, however. sampleTests.push({ @@ -123,7 +130,7 @@ if (process.env.TRAVIS_NODE_VERSION === '0.10') { msg: 'Hello World! Koa.js on Google App Engine.', TRAVIS_NODE_VERSION: 'stable' }); -//} +} // Send a request to the given url and test that the response body has the // expected value diff --git a/test/appengine/express-memcached-session.test.js b/test/appengine/express-memcached-session.test.js new file mode 100644 index 0000000000..6508023084 --- /dev/null +++ b/test/appengine/express-memcached-session.test.js @@ -0,0 +1,26 @@ +// Copyright 2015, Google, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +var request = require('supertest'); +var app = require('../../appengine/express-memcached-session/server.js'); + +describe('express-memcached-session', function () { + it('should return 200', function (done) { + request(app) + .get('/') + .expect(200) + .end(done); + }); +});