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 b8813c2dbe..9716a4b3a3 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);
+ });
+});