├── .gitignore
├── LICENSE
├── README.md
├── hapi-16
├── 404-route-and-handler
│ ├── base
│ │ ├── handler.js
│ │ ├── index.js
│ │ └── routes.js
│ ├── server.js
│ └── views
│ │ ├── 404.html
│ │ ├── index.html
│ │ └── layout.html
├── authenticate-with-github
│ ├── authentication
│ │ └── index.js
│ ├── connect-with-github
│ │ ├── handler.js
│ │ ├── index.js
│ │ └── routes.js
│ ├── server.js
│ └── views
│ │ ├── authenticated.html
│ │ ├── index.html
│ │ └── layout.html
├── authenticate-with-gitlab
│ ├── authentication
│ │ └── index.js
│ ├── connect-with-gitlab
│ │ ├── handler.js
│ │ ├── index.js
│ │ └── routes.js
│ ├── server.js
│ └── views
│ │ ├── authenticated.html
│ │ ├── index.html
│ │ └── layout.html
├── basic-auth
│ ├── basic-routes.js
│ ├── server.js
│ └── views
│ │ ├── index.html
│ │ ├── layout.html
│ │ └── success.html
├── bell-custom-oauth
│ ├── authentication
│ │ └── index.js
│ ├── connect-with-your-server
│ │ ├── handler.js
│ │ ├── index.js
│ │ └── routes.js
│ ├── server.js
│ └── views
│ │ ├── authenticated.html
│ │ ├── index.html
│ │ └── layout.html
├── cookie-auth
│ ├── cookie-routes.js
│ ├── server.js
│ ├── users-db.js
│ └── views
│ │ ├── index.html
│ │ ├── layout.html
│ │ └── profile.html
├── cookies-store-and-read
│ ├── base-route.js
│ └── server.js
├── default-auth-strategy
│ ├── routes.js
│ ├── server.js
│ └── users-db.js
├── different-default-handlebars-layouts
│ ├── index
│ │ ├── handler.js
│ │ ├── index.js
│ │ └── routes.js
│ ├── server.js
│ └── views
│ │ ├── index.html
│ │ ├── layout.html
│ │ └── second-layout.html
├── extend-hapi-with-plugins
│ └── server.js
├── getting-started
│ └── server.js
├── hapi-vue-ssr-basic
│ ├── base
│ │ ├── handler.js
│ │ ├── index.js
│ │ └── routes.js
│ ├── server.js
│ └── views
│ │ ├── about.html
│ │ ├── index.html
│ │ └── layout.html
├── ignore-trailing-slash-on-paths
│ ├── base-route.js
│ └── server.js
├── multiple-auth-strategies-for-routes
│ ├── routes.js
│ ├── server.js
│ ├── users-db.js
│ └── views
│ │ ├── index.html
│ │ ├── layout.html
│ │ └── profile.html
├── multiple-server-instances
│ ├── backend-route.js
│ ├── frontend-route.js
│ └── server.js
├── optional-path-params
│ ├── base-route.js
│ └── server.js
├── package.json
├── path-params-of-same-name
│ ├── base-route.js
│ └── server.js
├── query-params
│ ├── base-route.js
│ └── server.js
├── redirect-to-previous-page-after-login
│ ├── authentication
│ │ └── index.js
│ ├── implementation
│ │ ├── handler.js
│ │ ├── index.js
│ │ └── routes.js
│ ├── server.js
│ ├── users-db.js
│ └── views
│ │ ├── index.html
│ │ ├── layout.html
│ │ ├── login.html
│ │ ├── private.html
│ │ └── profile.html
├── render-handlebars-views
│ ├── server.js
│ └── views
│ │ ├── index.html
│ │ └── layout.html
├── reply-json
│ ├── base-route.js
│ └── server.js
├── request-headers
│ ├── base-route.js
│ └── server.js
├── request-payload
│ ├── base-route.js
│ └── server.js
├── response-status-codes
│ ├── base-route.js
│ └── server.js
├── restrict-access-with-scopes
│ ├── base-routes.js
│ ├── server.js
│ ├── users-db.js
│ └── views
│ │ ├── admin.html
│ │ ├── index.html
│ │ ├── layout.html
│ │ └── profile.html
├── routing
│ ├── base-route.js
│ └── server.js
├── serve-static-files
│ ├── base-route.js
│ ├── files
│ │ ├── js
│ │ │ └── test.js
│ │ └── main.js
│ └── server.js
├── show-error-stacktrace-in-browser
│ ├── base
│ │ ├── handler.js
│ │ ├── index.js
│ │ └── routes.js
│ ├── server.js
│ ├── show-error-stacktrace
│ │ ├── error.html
│ │ └── index.js
│ └── views
│ │ ├── 404.html
│ │ ├── error.html
│ │ ├── index.html
│ │ └── layout.html
├── testing-inject-requests
│ ├── .eslintignore
│ ├── .eslintrc.js
│ ├── base
│ │ ├── handler.js
│ │ ├── index.js
│ │ └── routes.js
│ ├── package.json
│ ├── server.js
│ └── test
│ │ ├── before-and-after-test-actions.js
│ │ ├── inject-payload-headers-params.js
│ │ └── plugin-index-responds-with-json.js
├── upload-files
│ ├── base-route.js
│ └── server.js
├── validation-parameters-and-payload
│ ├── base-route.js
│ └── server.js
├── validation-path-parameter
│ ├── base-route.js
│ └── server.js
├── validation-payload
│ ├── base-route.js
│ └── server.js
├── validation-query-parameter
│ ├── base-route.js
│ └── server.js
├── validation-request-headers
│ ├── base-route.js
│ └── server.js
├── validation-return-all-errors
│ ├── base-route.js
│ └── server.js
├── vuejs-and-handlebars
│ ├── index
│ │ ├── handler.js
│ │ ├── index.js
│ │ └── routes.js
│ ├── server.js
│ └── views
│ │ ├── index.html
│ │ └── layout.html
├── wildcard-path-params
│ ├── base-route.js
│ └── server.js
└── write-your-own-plugin
│ ├── base-route.js
│ └── server.js
└── hapi-18
├── .eslintrc.json
├── package.json
└── redirect-including-request-payload
└── redirect-including-request-payload.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # ignore premium Tutorials
2 | premium
3 |
4 |
5 | # Logs
6 | logs
7 | *.log
8 |
9 | # Runtime data
10 | pids
11 | *.pid
12 | *.seed
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21 | .grunt
22 |
23 | # node-waf configuration
24 | .lock-wscript
25 |
26 | # Compiled binary addons (http://nodejs.org/api/addons.html)
27 | build/Release
28 |
29 | # Dependency directory
30 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
31 | node_modules
32 | package-lock.json
33 |
34 | # Vagrant
35 | .vagrant
36 |
37 | # IDEA (Webstorm)
38 | .idea
39 |
40 | # Visual Studio Code
41 | .vscode
42 |
43 | # bcrypt windows
44 | build
45 | src
46 | binding.gyp
47 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016-2019 Future Studio
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # hapi Tutorial Series
2 | This repository contains code examples for the [hapi tutorial series with **100+ tutorials**](https://futurestud.io/tutorials/hapi-get-your-server-up-and-running). The hapi tutorial series is published within the Future Studio University.
3 |
4 |
5 |
6 |
7 |
8 |
9 | ## YouTube Playlist
10 | Find a [playlist on YouTube with videos on the individual tutorials](https://www.youtube.com/watch?v=-o6IxDy3pIk&list=PLpUMhvC6l7AMXP2bWhHF6UTZGseIkWUG_). Each video is related to a tutorial and walks you through the implementation of an individual feature. It’s all practical, watch me live code :)
11 |
12 |
13 | ------
14 |
15 |
This hapi tutorial series is sponsored by Future Studio University 🚀
16 |
17 | Join the Future Studio University and Skyrocket in Node.js
18 |
19 |
20 | ------
21 |
22 |
23 | ## Dependencies
24 | You need the following tools installed on your machine to actually run the individual examples:
25 |
26 | - Node.js v4+
27 | - NPM
28 |
29 |
30 | ## Setup
31 | To set up the required environment, just clone this repository to your local machine and install the NPM dependencies.
32 |
33 | ```
34 | $ git clone git@github.com:fs-opensource/nodejs-tutorials-hapi.git
35 | $ cd nodejs-tutorials-hapi
36 | $ npm i
37 | ```
38 |
39 |
40 | ## Run Examples
41 | Every example code contains its own hapi server that kicks off at `localhost:3000`.
42 |
43 | ```
44 | $ cd examples
45 | $ cd
46 | $ node server
47 | ```
48 |
49 | Many examples allow you to check them out within the browser. Navigate your browser to the url `localhost:3000` with a running example server in the background.
50 |
51 |
52 | ## Do you wanna see a specific example?
53 | Don't worry, just let us know :) You can file an idea within our [university-ping](https://github.com/fs-opensource/university-ping/issues/new) repository and let us know about anything you're interested to see!
54 |
55 | Enjoy coding & make it rock!
56 |
--------------------------------------------------------------------------------
/hapi-16/404-route-and-handler/base/handler.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Boom = require('boom')
4 |
5 | const Handler = {
6 | index: {
7 | handler: (request, reply) => {
8 | reply.view('index')
9 | }
10 | },
11 |
12 | missing: {
13 | handler: (request, reply) => {
14 | const accept = request.raw.req.headers.accept
15 |
16 | // take priority: check header if there’s a JSON REST request
17 | if (accept && accept.match(/json/)) {
18 | return reply(Boom.notFound('Fuckity fuck, this resource isn’t available.'))
19 | }
20 |
21 | reply.view('404').code(404)
22 | }
23 | }
24 | }
25 |
26 | module.exports = Handler
27 |
--------------------------------------------------------------------------------
/hapi-16/404-route-and-handler/base/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Routes = require('./routes')
4 |
5 | exports.register = (server, options, next) => {
6 | server.dependency([ 'vision' ])
7 |
8 | server.route(Routes)
9 | server.log('info', 'Plugin registered: 404 handler')
10 |
11 | next()
12 | }
13 |
14 | exports.register.attributes = {
15 | name: '404-handler',
16 | version: '1.0.0'
17 | }
18 |
--------------------------------------------------------------------------------
/hapi-16/404-route-and-handler/base/routes.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Handler = require('./handler')
4 |
5 | const Routes = [
6 | {
7 | method: 'GET',
8 | path: '/',
9 | config: Handler.index
10 | },
11 | {
12 | method: [ 'GET', 'POST' ],
13 | path: '/{path*}',
14 | config: Handler.missing
15 | }
16 | ]
17 |
18 | module.exports = Routes
19 |
--------------------------------------------------------------------------------
/hapi-16/404-route-and-handler/server.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hapi = require('hapi')
4 |
5 | // create new server instance
6 | const server = new Hapi.Server()
7 |
8 | // add server’s connection information
9 | server.connection({
10 | host: 'localhost',
11 | port: 3000
12 | })
13 |
14 | // register plugins to server instance
15 | server.register([
16 | {
17 | register: require('vision')
18 | },
19 | {
20 | register: require('./base')
21 | }
22 | ], err => {
23 | if (err) {
24 | throw err
25 | }
26 |
27 | server.views({
28 | engines: {
29 | html: require('handlebars')
30 | },
31 | path: __dirname + '/views',
32 | layout: 'layout',
33 | context: {
34 | title: '404 — Nothing here'
35 | }
36 | })
37 |
38 | // start your server
39 | server.start(err => {
40 |
41 | if (err) {
42 | throw err
43 | }
44 |
45 | console.log('Server running at: ' + server.info.uri)
46 | })
47 | })
48 |
--------------------------------------------------------------------------------
/hapi-16/404-route-and-handler/views/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
404!
5 |
6 | Uh, shit. Fuckity fuck! This resource isn’t available.
7 |
8 |
9 |
10 |
11 |
12 | Better go back to safe lands, like the
13 | startpage
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/hapi-16/404-route-and-handler/views/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Hello!
5 |
6 |
7 | Go anywhere, you’ll see the 404 :)
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/hapi-16/404-route-and-handler/views/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{title}}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{{ content }}}
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/hapi-16/authenticate-with-github/authentication/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hoek = require('hoek')
4 |
5 | exports.register = function (server, options, next) {
6 | // declare dependency to hapi-auth-cookie and bell
7 | server.register([
8 | {
9 | register: require('hapi-auth-cookie')
10 | },
11 | {
12 | register: require('bell')
13 | }
14 | ], err => {
15 | Hoek.assert(!err, 'Cannot register authentication plugin')
16 |
17 | /**
18 | * Register session based auth strategy to store
19 | * credentials received from GitHub and keep
20 | * the user logged in
21 | */
22 | server.auth.strategy('session', 'cookie', {
23 | password: 'ThisIsASecretPasswordForTheAuthCookie',
24 | redirectTo: '/',
25 | isSecure: process.env.NODE_ENV === 'production'
26 | })
27 |
28 | /**
29 | * Register 'github' authentication strategy
30 | */
31 | server.auth.strategy('github', 'bell', {
32 | provider: 'github',
33 | password: 'ThisIsASecretCookiePasswordForGitHub',
34 | clientId: 'aee4fc96cc87416273cd',
35 | clientSecret: '5a0885bd00510c16931102459aea74063ea7c505',
36 | isSecure: process.env.NODE_ENV === 'production'
37 | })
38 |
39 | server.log('info', 'Plugin registered: bell authentication with strategy »github«')
40 |
41 | next()
42 | })
43 | }
44 |
45 | exports.register.attributes = {
46 | name: 'authentication',
47 | version: '1.0.0',
48 | once: true
49 | }
50 |
--------------------------------------------------------------------------------
/hapi-16/authenticate-with-github/connect-with-github/handler.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Handler = {
4 | index: {
5 | auth: {
6 | mode: 'try',
7 | strategy: 'session'
8 | },
9 | plugins: {
10 | 'hapi-auth-cookie': {
11 | redirectTo: false
12 | }
13 | },
14 | handler: function (request, reply) {
15 | if (request.auth.isAuthenticated) {
16 | return reply.view('authenticated', request.auth.credentials)
17 | }
18 |
19 | reply.view('index')
20 | }
21 | },
22 |
23 | /**
24 | * used to authenticate
25 | */
26 | connect: {
27 | auth: 'github',
28 | handler: function (request, reply) {
29 | if (request.auth.isAuthenticated) {
30 | const user = request.auth.credentials.profile
31 | const data = {
32 | name: user.displayName,
33 | username: user.username,
34 | avatar: user.raw.avatar_url
35 | }
36 |
37 | request.cookieAuth.set(data)
38 | return reply.view('authenticated', data)
39 | }
40 |
41 | reply.view('index', {
42 | error: 'There was an issue with the GitHub authentication.'
43 | }).code(400)
44 | }
45 | },
46 |
47 | logout: {
48 | auth: 'session',
49 | handler: function (request, reply) {
50 | request.cookieAuth.clear()
51 | reply.view('index')
52 | }
53 | }
54 | }
55 |
56 | module.exports = Handler
57 |
--------------------------------------------------------------------------------
/hapi-16/authenticate-with-github/connect-with-github/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Routes = require('./routes')
4 |
5 | exports.register = (server, options, next) => {
6 | server.register([
7 | {
8 | register: require('vision')
9 | },
10 | {
11 | register: require('./../authentication')
12 | }
13 | ], err => {
14 | if (err) {
15 | throw err
16 | }
17 |
18 | server.route(Routes)
19 | server.log('info', 'Plugin registered: connect to GitHub')
20 |
21 | next()
22 | })
23 | }
24 |
25 | exports.register.attributes = {
26 | name: 'connect-to-github',
27 | version: '1.0.0'
28 | }
29 |
--------------------------------------------------------------------------------
/hapi-16/authenticate-with-github/connect-with-github/routes.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Handler = require('./handler')
4 |
5 | const Routes = [
6 | {
7 | method: 'GET',
8 | path: '/',
9 | config: Handler.index
10 | },
11 | {
12 | method: 'GET',
13 | path: '/auth/github',
14 | config: Handler.connect
15 | },
16 | {
17 | method: 'GET',
18 | path: '/logout',
19 | config: Handler.logout
20 | }
21 | ]
22 |
23 | module.exports = Routes
24 |
--------------------------------------------------------------------------------
/hapi-16/authenticate-with-github/server.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hapi = require('hapi')
4 |
5 | // create new server instance
6 | const server = new Hapi.Server()
7 |
8 | // add server’s connection information
9 | server.connection({
10 | host: 'localhost',
11 | port: 3000
12 | })
13 |
14 | // register plugins to server instance
15 | server.register([
16 | {
17 | register: require('./connect-with-github')
18 | }
19 | ], function (err) {
20 | if (err) {
21 | throw err
22 | }
23 |
24 | server.views({
25 | engines: {
26 | html: require('handlebars')
27 | },
28 | path: __dirname + '/views',
29 | layout: 'layout'
30 | })
31 |
32 | // start your server
33 | server.start(function (err) {
34 |
35 | if (err) {
36 | throw err
37 | }
38 |
39 | console.log('Server running at: ' + server.info.uri)
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/hapi-16/authenticate-with-github/views/authenticated.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Signed in!
4 |
5 |
6 |
7 |
8 | Hi {{name}}, great to see you!
9 |
10 |
11 | Logout
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/hapi-16/authenticate-with-github/views/index.html:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/hapi-16/authenticate-with-github/views/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{title}}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{{ content }}}
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/hapi-16/authenticate-with-gitlab/authentication/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hoek = require('hoek')
4 |
5 | exports.register = function (server, options, next) {
6 | // declare dependency to hapi-auth-cookie and bell
7 | server.register([
8 | {
9 | register: require('hapi-auth-cookie')
10 | },
11 | {
12 | register: require('bell')
13 | }
14 | ], err => {
15 | Hoek.assert(!err, 'Cannot register authentication plugin')
16 |
17 | /**
18 | * Register session based auth strategy to store
19 | * credentials received from GitLab and keep
20 | * the user logged in
21 | */
22 | server.auth.strategy('session', 'cookie', {
23 | password: 'ThisIsASecretPasswordForTheAuthCookie',
24 | redirectTo: '/',
25 | isSecure: process.env.NODE_ENV === 'production'
26 | })
27 |
28 | /**
29 | * Register 'gitlab' authentication strategy
30 | */
31 | server.auth.strategy('gitlab', 'bell', {
32 | provider: 'gitlab',
33 | password: 'ThisIsASecretCookiePasswordForGitLab',
34 | clientId: '281d2b423e8715a8d8bd1d2c60ab7b3218feb6346a89913bfe4a868a837cc5d8',
35 | clientSecret: '47c184bcd3e13096e1500d9f7c16d58b19ba6a4e55939cd1a8e33472e2d268e4',
36 | isSecure: process.env.NODE_ENV === 'production'
37 | })
38 |
39 | server.log('info', 'Plugin registered: bell authentication with strategy »gitlab«')
40 |
41 | next()
42 | })
43 | }
44 |
45 | exports.register.attributes = {
46 | name: 'authentication',
47 | version: '1.0.0'
48 | }
49 |
--------------------------------------------------------------------------------
/hapi-16/authenticate-with-gitlab/connect-with-gitlab/handler.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Handler = {
4 | index: {
5 | auth: {
6 | mode: 'try',
7 | strategy: 'session'
8 | },
9 | plugins: {
10 | 'hapi-auth-cookie': {
11 | redirectTo: false
12 | }
13 | },
14 | handler: function (request, reply) {
15 | if (request.auth.isAuthenticated) {
16 | return reply.view('authenticated', request.auth.credentials)
17 | }
18 |
19 | reply.view('index')
20 | }
21 | },
22 |
23 | /**
24 | * used to authenticate
25 | */
26 | connect: {
27 | auth: 'gitlab',
28 | handler: function (request, reply) {
29 | if (request.auth.isAuthenticated) {
30 | const user = request.auth.credentials.profile
31 | const data = {
32 | name: user.name,
33 | username: user.username,
34 | avatar: user.avatar_url
35 | }
36 |
37 | request.cookieAuth.set(data)
38 | return reply.view('authenticated', data)
39 | }
40 |
41 | reply.view('index', {
42 | error: 'There was an issue with GitLab authentication.'
43 | }).code(400)
44 | }
45 | },
46 |
47 | logout: {
48 | auth: 'session',
49 | handler: function (request, reply) {
50 | request.cookieAuth.clear()
51 | reply.view('index')
52 | }
53 | }
54 | }
55 |
56 | module.exports = Handler
57 |
--------------------------------------------------------------------------------
/hapi-16/authenticate-with-gitlab/connect-with-gitlab/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Routes = require('./routes')
4 |
5 | exports.register = (server, options, next) => {
6 | server.dependency([ 'authentication', 'vision' ])
7 |
8 | server.route(Routes)
9 | server.log('info', 'Plugin registered: connect to GitLab')
10 |
11 | next()
12 | }
13 |
14 | exports.register.attributes = {
15 | name: 'connect-to-gitlab',
16 | version: '1.0.0'
17 | }
18 |
--------------------------------------------------------------------------------
/hapi-16/authenticate-with-gitlab/connect-with-gitlab/routes.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Handler = require('./handler')
4 |
5 | const Routes = [
6 | {
7 | method: 'GET',
8 | path: '/',
9 | config: Handler.index
10 | },
11 | {
12 | method: 'GET',
13 | path: '/auth/gitlab',
14 | config: Handler.connect
15 | },
16 | {
17 | method: 'GET',
18 | path: '/logout',
19 | config: Handler.logout
20 | }
21 | ]
22 |
23 | module.exports = Routes
24 |
--------------------------------------------------------------------------------
/hapi-16/authenticate-with-gitlab/server.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hapi = require('hapi')
4 |
5 | // create new server instance
6 | const server = new Hapi.Server()
7 |
8 | // add server’s connection information
9 | server.connection({
10 | host: 'localhost',
11 | port: 3000
12 | })
13 |
14 | // register plugins to server instance
15 | server.register([
16 | {
17 | register: require('./authentication')
18 | },
19 | {
20 | register: require('vision')
21 | },
22 | {
23 | register: require('./connect-with-gitlab')
24 | }
25 | ], function (err) {
26 | if (err) {
27 | throw err
28 | }
29 |
30 | server.views({
31 | engines: {
32 | html: require('handlebars')
33 | },
34 | path: __dirname + '/views',
35 | layout: 'layout'
36 | })
37 |
38 | // start your server
39 | server.start(function (err) {
40 |
41 | if (err) {
42 | throw err
43 | }
44 |
45 | console.log('Server running at: ' + server.info.uri)
46 | })
47 | })
48 |
--------------------------------------------------------------------------------
/hapi-16/authenticate-with-gitlab/views/authenticated.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Signed in!
4 |
5 |
6 |
7 |
8 | Hi {{name}}, great to see you!
9 |
10 |
11 | Logout
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/hapi-16/authenticate-with-gitlab/views/index.html:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/hapi-16/authenticate-with-gitlab/views/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{title}}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{{ content }}}
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/hapi-16/basic-auth/basic-routes.js:
--------------------------------------------------------------------------------
1 | var routes = [
2 | {
3 | method: 'GET',
4 | path: '/',
5 | handler: function (request, reply) {
6 | var data = {
7 | message: 'Check the route that requires auth at /basic'
8 | }
9 |
10 | reply.view('index', data)
11 | }
12 | },
13 | {
14 | method: 'GET',
15 | path: '/basic',
16 | config: {
17 | auth: 'basic',
18 | handler: function (request, reply) {
19 | reply.view('success')
20 | }
21 | }
22 | }
23 | ]
24 |
25 | module.exports = routes
--------------------------------------------------------------------------------
/hapi-16/basic-auth/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 | var Bcrypt = require('bcrypt')
4 | var Vision = require('vision')
5 | var Handlebars = require('handlebars')
6 | var BasicAuth = require('hapi-auth-basic')
7 |
8 | // create new server instance
9 | var server = new Hapi.Server()
10 |
11 | // add server’s connection information
12 | server.connection({
13 | host: 'localhost',
14 | port: 3000
15 | })
16 |
17 | // register plugins to server instance
18 | server.register([
19 | {
20 | register: Vision
21 | },
22 | {
23 | register: Good,
24 | options: {
25 | ops: {
26 | interval: 10000
27 | },
28 | reporters: {
29 | console: [
30 | {
31 | module: 'good-squeeze',
32 | name: 'Squeeze',
33 | args: [ { log: '*', response: '*', request: '*' } ]
34 | },
35 | {
36 | module: 'good-console'
37 | },
38 | 'stdout'
39 | ]
40 | }
41 | }
42 | },
43 | {
44 | register: BasicAuth
45 | }
46 | ], function (err) {
47 | if (err) {
48 | server.log('error', 'failed to install plugins')
49 |
50 | throw err
51 | }
52 |
53 | server.log('info', 'Plugins registered')
54 |
55 | /**
56 | * view configuration
57 | */
58 | server.views({
59 | engines: {
60 | html: Handlebars
61 | },
62 | path: __dirname + '/views',
63 | layout: true
64 | })
65 | server.log('info', 'View configuration completed')
66 |
67 | // hardcoded users object … just for illustration purposes
68 | var users = {
69 | future: {
70 | username: 'future',
71 | password: '$2a$04$YPy8WdAtWswed8b9MfKixebJkVUhEZxQCrExQaxzhcdR2xMmpSJiG', // 'studio'
72 | name: 'Future Studio',
73 | id: '1'
74 | }
75 | }
76 |
77 | // validation function used for hapi-auth-basic
78 | var basicValidation = function (request, username, password, callback) {
79 | var user = users[ username ]
80 |
81 | if (!user) {
82 | return callback(null, false)
83 | }
84 |
85 | Bcrypt.compare(password, user.password, function (err, isValid) {
86 | server.log('info', 'user authentication successful')
87 | callback(err, isValid, { id: user.id, name: user.name })
88 | })
89 | }
90 |
91 | server.auth.strategy('basic', 'basic', { validateFunc: basicValidation })
92 | server.log('info', 'Registered auth strategy: basic auth')
93 |
94 | var routes = require('./basic-routes')
95 | server.route(routes)
96 | server.log('info', 'Routes registered')
97 |
98 |
99 |
100 | // start your server after plugin registration
101 | server.start(function (err) {
102 | if (err) {
103 | server.log('error', 'failed to start server')
104 | server.log('error', err)
105 |
106 | throw err
107 | }
108 |
109 | server.log('info', 'Server running at: ' + server.info.uri)
110 | })
111 | })
112 |
--------------------------------------------------------------------------------
/hapi-16/basic-auth/views/index.html:
--------------------------------------------------------------------------------
1 |
2 |
Hapi Basic Authentication
3 |
authenticate
4 |
5 | Username: future
6 | Password: studio
7 |
8 |
--------------------------------------------------------------------------------
/hapi-16/basic-auth/views/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hapi — Basic Authentication
5 |
6 |
7 |
8 | {{{ content }}}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/hapi-16/basic-auth/views/success.html:
--------------------------------------------------------------------------------
1 |
2 |
Yeah, you made it! This view is only visible after successful authentication.
3 |
--------------------------------------------------------------------------------
/hapi-16/bell-custom-oauth/authentication/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | exports.register = function (server, options, next) {
4 | // declare dependency to hapi-auth-cookie and bell
5 | server.dependency([ 'hapi-auth-cookie', 'bell' ])
6 |
7 | /**
8 | * Register session based auth strategy to store
9 | * credentials received from GitHub and keep
10 | * the user logged in
11 | */
12 | server.auth.strategy('session', 'cookie', {
13 | password: 'ThisIsASecretPasswordForTheAuthCookie',
14 | redirectTo: '/',
15 | isSecure: process.env.NODE_ENV === 'production'
16 | })
17 |
18 | /**
19 | * Register 'digitalocean' authentication strategy
20 | */
21 | const doUrl = 'https://cloud.digitalocean.com/v1/oauth'
22 | const doUserUrl = 'https://api.digitalocean.com/v2/account'
23 |
24 | server.auth.strategy('digitalocean', 'bell', {
25 | //provider: 'github', // <-- instead of this, we do this ->
26 | provider: {
27 | protocol: 'oauth2',
28 | auth: doUrl + '/authorize',
29 | token: doUrl + '/token',
30 | scope: [ 'read write' ],
31 | profile: function (credentials, params, get, callback) {
32 | get(doUserUrl, null, (profile) => {
33 | const account = profile.account
34 |
35 | credentials.profile = {
36 | email: account.email,
37 | status: account.status,
38 | dropletLimit: account.droplet_limit,
39 | raw: account
40 | }
41 |
42 | return callback()
43 | })
44 | }
45 | },
46 | password: 'ThisIsASecretCookiePasswordForDigitalOcean',
47 | clientId: '499d5ba6f00cdc7f4d2c9213c837b5f219a647e377352187087654d2e5804937',
48 | clientSecret: '1f05d6ad0cbcc74f064300bb3bb8344b93a4d48808439d7cce6dcc79a54de068',
49 | isSecure: process.env.NODE_ENV === 'production'
50 | })
51 |
52 | server.log('info', 'Plugin registered: bell authentication with strategy »digitalocean«')
53 |
54 | next()
55 | }
56 |
57 | exports.register.attributes = {
58 | name: 'authentication',
59 | version: '1.0.0'
60 | }
61 |
--------------------------------------------------------------------------------
/hapi-16/bell-custom-oauth/connect-with-your-server/handler.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Handler = {
4 | index: {
5 | auth: {
6 | mode: 'try',
7 | strategy: 'session'
8 | },
9 | plugins: {
10 | 'hapi-auth-cookie': {
11 | redirectTo: false
12 | }
13 | },
14 | handler: function (request, reply) {
15 | if (request.auth.isAuthenticated) {
16 | return reply.view('authenticated', request.auth.credentials)
17 | }
18 |
19 | reply.view('index')
20 | }
21 | },
22 |
23 | /**
24 | * used to authenticate
25 | */
26 | connect: {
27 | auth: 'digitalocean',
28 | handler: function (request, reply) {
29 | if (request.auth.isAuthenticated) {
30 | const user = request.auth.credentials.profile
31 | const data = {
32 | email: user.email,
33 | }
34 |
35 | request.cookieAuth.set(data)
36 | return reply.view('authenticated', data)
37 | }
38 |
39 | reply.view('index', {
40 | error: 'There was an issue with the GitHub authentication.'
41 | }).code(400)
42 | }
43 | },
44 |
45 | logout: {
46 | auth: 'session',
47 | handler: function (request, reply) {
48 | request.cookieAuth.clear()
49 | reply.view('index')
50 | }
51 | }
52 | }
53 |
54 | module.exports = Handler
55 |
--------------------------------------------------------------------------------
/hapi-16/bell-custom-oauth/connect-with-your-server/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Routes = require('./routes')
4 |
5 | exports.register = (server, options, next) => {
6 | server.dependency([ 'authentication', 'vision' ])
7 |
8 | server.route(Routes)
9 | server.log('info', 'Plugin registered: connect to GitHub')
10 |
11 | next()
12 | }
13 |
14 | exports.register.attributes = {
15 | name: 'connect-to-custom-auth-provider',
16 | version: '1.0.0'
17 | }
18 |
--------------------------------------------------------------------------------
/hapi-16/bell-custom-oauth/connect-with-your-server/routes.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Handler = require('./handler')
4 |
5 | const Routes = [
6 | {
7 | method: 'GET',
8 | path: '/',
9 | config: Handler.index
10 | },
11 | {
12 | method: 'GET',
13 | path: '/auth/digitalocean',
14 | config: Handler.connect
15 | },
16 | {
17 | method: 'GET',
18 | path: '/logout',
19 | config: Handler.logout
20 | }
21 | ]
22 |
23 | module.exports = Routes
24 |
--------------------------------------------------------------------------------
/hapi-16/bell-custom-oauth/server.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hapi = require('hapi')
4 | const server = new Hapi.Server()
5 |
6 | // add server’s connection information
7 | server.connection({
8 | host: 'localhost',
9 | port: 3000
10 | })
11 |
12 | // register plugins to server instance
13 | server.register([
14 | {
15 | register: require('hapi-auth-cookie')
16 | },
17 | {
18 | register: require('bell')
19 | },
20 | {
21 | register: require('./authentication')
22 | },
23 | {
24 | register: require('vision')
25 | },
26 | {
27 | register: require('./connect-with-your-server')
28 | }
29 | ], function (err) {
30 | if (err) {
31 | throw err
32 | }
33 |
34 | server.views({
35 | engines: {
36 | html: require('handlebars')
37 | },
38 | path: __dirname + '/views',
39 | layout: 'layout'
40 | })
41 |
42 | // start your server
43 | server.start(function (err) {
44 |
45 | if (err) {
46 | throw err
47 | }
48 |
49 | console.log('Server running at: ' + server.info.uri)
50 | })
51 | })
52 |
--------------------------------------------------------------------------------
/hapi-16/bell-custom-oauth/views/authenticated.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Signed in!
5 |
6 | {{#if avatar}}
7 |
8 |
9 |
10 | {{/if}}
11 |
12 |
13 | Hi {{email}}, great to see you!
14 |
15 |
16 | Logout
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/hapi-16/bell-custom-oauth/views/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Sign in with OAuth
5 | {{!--
6 |
7 | Hi Buddy, authenticate with any OAuth Provider .
8 |
9 |
10 |
11 |
12 | Authenticate with your Provider
13 |
14 |
15 |
16 |
17 |
18 | --}}
19 |
20 | To illustrate the hapi configuration for a custom OAuth provider,
21 | let’s go with DigitalOcean and manually do the setup. You can apply
22 | the configuration to your provider.
23 |
24 |
25 |
26 |
27 | Authenticate with DigitalOcean
28 |
29 |
30 | {{!
31 | Sorry DigitalOcean for the wrong logo, Font Awesome doesn’t have
32 | the correct one yet :-/
33 |
34 | }}
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/hapi-16/bell-custom-oauth/views/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{title}}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{{ content }}}
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/hapi-16/cookie-auth/cookie-routes.js:
--------------------------------------------------------------------------------
1 | var Boom = require('boom')
2 | var Bcrypt = require('bcrypt')
3 | var Users = require('./users-db')
4 |
5 | var routes = [
6 | {
7 | method: 'GET',
8 | path: '/',
9 | config: {
10 | auth: {
11 | mode: 'try',
12 | strategy: 'session'
13 | },
14 | plugins: {
15 | 'hapi-auth-cookie': {
16 | redirectTo: false
17 | }
18 | },
19 | handler: function (request, reply) {
20 | if (request.auth.isAuthenticated) {
21 | return reply.view('profile')
22 | }
23 |
24 | reply.view('index')
25 | }
26 | }
27 | },
28 | {
29 | method: 'POST',
30 | path: '/',
31 | config: {
32 | auth: {
33 | mode: 'try'
34 | },
35 | plugins: {
36 | 'hapi-auth-cookie': {
37 | redirectTo: false
38 | }
39 | },
40 | handler: function (request, reply) {
41 | if (request.auth.isAuthenticated) {
42 | return reply.view('Profile')
43 | }
44 |
45 | var username = request.payload.username
46 | var user = Users[ username ]
47 |
48 | if (!user) {
49 | return reply(Boom.notFound('No user registered with given credentials'))
50 | }
51 |
52 | var password = request.payload.password
53 |
54 | return Bcrypt.compare(password, user.password, function (err, isValid) {
55 | if (isValid) {
56 | request.server.log('info', 'user authentication successful')
57 | request.cookieAuth.set(user);
58 | return reply.view('profile')
59 | }
60 |
61 | return reply.view('index')
62 | })
63 | }
64 | }
65 | },
66 | {
67 | method: 'GET',
68 | path: '/logout',
69 | config: {
70 | auth: 'session',
71 | handler: function (request, reply) {
72 | request.cookieAuth.clear();
73 | reply.view('index')
74 | }
75 | }
76 | }
77 | ]
78 |
79 | module.exports = routes
--------------------------------------------------------------------------------
/hapi-16/cookie-auth/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 | var Vision = require('vision')
4 | var Users = require('./users-db')
5 | var Handlebars = require('handlebars')
6 | var CookieAuth = require('hapi-auth-cookie')
7 |
8 | // create new server instance
9 | var server = new Hapi.Server()
10 |
11 | // add server’s connection information
12 | server.connection({
13 | host: 'localhost',
14 | port: 3000
15 | })
16 |
17 | // register plugins to server instance
18 | server.register([
19 | {
20 | register: Vision
21 | },
22 | {
23 | register: Good,
24 | options: {
25 | ops: {
26 | interval: 10000
27 | },
28 | reporters: {
29 | console: [
30 | {
31 | module: 'good-squeeze',
32 | name: 'Squeeze',
33 | args: [ { log: '*', response: '*', request: '*' } ]
34 | },
35 | {
36 | module: 'good-console'
37 | },
38 | 'stdout'
39 | ]
40 | }
41 | }
42 | },
43 | {
44 | register: CookieAuth
45 | }
46 | ], function (err) {
47 | if (err) {
48 | server.log('error', 'failed to install plugins')
49 |
50 | throw err
51 | }
52 |
53 | server.log('info', 'Plugins registered')
54 |
55 | /**
56 | * view configuration
57 | */
58 | server.views({
59 | engines: {
60 | html: Handlebars
61 | },
62 | path: __dirname + '/views',
63 | layout: true
64 | })
65 | server.log('info', 'View configuration completed')
66 |
67 | // validation function used for hapi-auth-cookie: optional and checks if the user is still existing
68 | var validation = function (request, session, callback) {
69 | var username = session.username
70 | var user = Users[ username ]
71 |
72 | if (!user) {
73 | return callback(null, false)
74 | }
75 |
76 | server.log('info', 'user authenticated')
77 | callback(err, true, user)
78 | }
79 |
80 | server.auth.strategy('session', 'cookie', true, {
81 | password: 'm!*"2/),p4:xDs%KEgVr7;e#85Ah^WYC',
82 | cookie: 'future-studio-hapi-tutorials-cookie-auth-example',
83 | redirectTo: '/',
84 | isSecure: false,
85 | validateFunc: validation
86 | })
87 |
88 | server.log('info', 'Registered auth strategy: cookie auth')
89 |
90 | var routes = require('./cookie-routes')
91 | server.route(routes)
92 | server.log('info', 'Routes registered')
93 |
94 | // start your server after plugin registration
95 | server.start(function (err) {
96 | if (err) {
97 | server.log('error', 'failed to start server')
98 | server.log('error', err)
99 |
100 | throw err
101 | }
102 |
103 | server.log('info', 'Server running at: ' + server.info.uri)
104 | })
105 | })
106 |
--------------------------------------------------------------------------------
/hapi-16/cookie-auth/users-db.js:
--------------------------------------------------------------------------------
1 | // hardcoded users object … just for illustration purposes
2 | var users = {
3 | future: {
4 | username: 'future',
5 | password: '$2a$04$YPy8WdAtWswed8b9MfKixebJkVUhEZxQCrExQaxzhcdR2xMmpSJiG', // 'studio'
6 | name: 'Future Studio',
7 | id: '1'
8 | }
9 | }
10 |
11 | module.exports = users
--------------------------------------------------------------------------------
/hapi-16/cookie-auth/views/index.html:
--------------------------------------------------------------------------------
1 |
2 |
Hapi Cookie Authentication
3 |
4 | Use the following credentials to log in.
5 |
6 |
7 | Username: future
8 | Password: studio
9 |
10 |
11 |
20 |
--------------------------------------------------------------------------------
/hapi-16/cookie-auth/views/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hapi — Basic Authentication
5 |
6 |
7 |
8 | {{{ content }}}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/hapi-16/cookie-auth/views/profile.html:
--------------------------------------------------------------------------------
1 |
2 |
Your Profile
3 |
4 | logout
5 |
6 |
--------------------------------------------------------------------------------
/hapi-16/cookies-store-and-read/base-route.js:
--------------------------------------------------------------------------------
1 | var util = require('util')
2 |
3 | var baseRoutes = {
4 | register: function (server, options, next) {
5 | server.state('session', {
6 | ttl: 1000 * 60 * 60 * 24,
7 | encoding: 'base64json'
8 | })
9 |
10 | server.state('email', {
11 | ttl: 1000 * 60 * 60 * 24 * 7
12 | })
13 |
14 | var routes = [
15 | {
16 | method: 'GET',
17 | path: '/',
18 | config: {
19 | handler: function (request, reply) {
20 | var email = request.state.email
21 | if (!email) {
22 | email = 'info@futurestud.io'
23 | }
24 |
25 | var session = request.state.session
26 | if (!session) {
27 | session = {
28 | username: 'futurestudio',
29 | firstvisit: false
30 | }
31 | }
32 |
33 | cookie.lastVisit = Date.now()
34 |
35 | return reply('Hello Future Studio')
36 | .state('session', session)
37 | .state('email', email)
38 | }
39 | }
40 | }
41 | ]
42 |
43 | // add defined routes to hapi
44 | server.route(routes)
45 | next()
46 | }
47 | }
48 |
49 | baseRoutes.register.attributes = {
50 | name: 'response-status',
51 | version: '1.0.0'
52 | }
53 |
54 | module.exports = baseRoutes
55 |
--------------------------------------------------------------------------------
/hapi-16/cookies-store-and-read/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 |
4 | // create new server instance
5 | var server = new Hapi.Server()
6 |
7 | // add server’s connection information
8 | server.connection({
9 | host: 'localhost',
10 | port: 3000
11 | })
12 |
13 | // register plugins to server instance
14 | server.register([
15 | {
16 | register: Good,
17 | options: {
18 | ops: {
19 | interval: 10000
20 | },
21 | reporters: {
22 | console: [
23 | {
24 | module: 'good-squeeze',
25 | name: 'Squeeze',
26 | args: [ { log: '*', response: '*', request: '*' } ]
27 | },
28 | {
29 | module: 'good-console'
30 | },
31 | 'stdout'
32 | ]
33 | }
34 | }
35 | },
36 | {
37 | register: require('./base-route')
38 | }
39 | ], function (err) {
40 | if (err) {
41 | throw err
42 | }
43 |
44 | // start your server after plugin registration
45 | server.start(function (err) {
46 | if (err) {
47 | throw err
48 | }
49 |
50 | server.log('info', 'Server running at: ' + server.info.uri)
51 | })
52 | })
53 |
--------------------------------------------------------------------------------
/hapi-16/default-auth-strategy/routes.js:
--------------------------------------------------------------------------------
1 | var routes = [
2 | {
3 | method: 'GET',
4 | path: '/',
5 | config: {
6 | handler: function (request, reply) {
7 | if (request.auth.isAuthenticated) {
8 | return reply('Authenticated')
9 | }
10 |
11 | reply('Not Authenticated')
12 | }
13 | }
14 | },
15 | {
16 | method: 'GET',
17 | path: '/not-authenticated',
18 | config: {
19 | handler: function (request, reply) {
20 | if (request.auth.isAuthenticated) {
21 | return reply('Authenticated')
22 | }
23 |
24 | reply('Not Authenticated')
25 | }
26 | }
27 | }
28 | ]
29 |
30 | module.exports = routes
--------------------------------------------------------------------------------
/hapi-16/default-auth-strategy/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 | var Vision = require('vision')
4 | var Bcrypt = require('bcrypt')
5 | var Users = require('./users-db')
6 | var BasicAuth = require('hapi-auth-basic')
7 |
8 | // create new server instance
9 | var server = new Hapi.Server()
10 |
11 | // add server’s connection information
12 | server.connection({
13 | host: 'localhost',
14 | port: 3000
15 | })
16 |
17 | // register plugins to server instance
18 | server.register([
19 | {
20 | register: Good,
21 | options: {
22 | ops: {
23 | interval: 10000
24 | },
25 | reporters: {
26 | console: [
27 | {
28 | module: 'good-squeeze',
29 | name: 'Squeeze',
30 | args: [ { log: '*', response: '*', request: '*' } ]
31 | },
32 | {
33 | module: 'good-console'
34 | },
35 | 'stdout'
36 | ]
37 | }
38 | }
39 | },
40 | {
41 | register: BasicAuth
42 | }
43 | ], function (err) {
44 | if (err) {
45 | server.log('error', 'failed to install plugins')
46 |
47 | throw err
48 | }
49 |
50 | server.log('info', 'Plugins registered')
51 |
52 | var basicValidation = function (request, username, password, callback) {
53 | var user = Users[ username ]
54 |
55 | if (!user) {
56 | return callback(null, false)
57 | }
58 |
59 | Bcrypt.compare(password, user.password, function (err, isValid) {
60 | server.log('info', 'user authentication successful')
61 | callback(err, isValid, user)
62 | })
63 | }
64 |
65 | // Create auth strategy:
66 | // 1. without setting it as default
67 | server.auth.strategy('basic', 'basic', { validateFunc: basicValidation })
68 | // set default auth strategy separately
69 | // all routes added afterwards will follow the default, required auth strategy
70 | server.auth.default('basic')
71 |
72 | // 2. set it as default
73 | // all routes will automatically require and follow the default strategy
74 | // server.auth.strategy('basic', 'basic', true, { validateFunc: basicValidation })
75 |
76 | server.log('info', 'Registered auth strategy: basic auth')
77 |
78 | var routes = require('./routes')
79 | server.route(routes)
80 | server.log('info', 'Routes registered')
81 |
82 | // start your server after plugin registration
83 | server.start(function (err) {
84 | if (err) {
85 | server.log('error', 'failed to start server')
86 | server.log('error', err)
87 |
88 | throw err
89 | }
90 |
91 | server.log('info', 'Server running at: ' + server.info.uri)
92 | })
93 | })
94 |
--------------------------------------------------------------------------------
/hapi-16/default-auth-strategy/users-db.js:
--------------------------------------------------------------------------------
1 | // hardcoded users object … just for illustration purposes
2 | var users = {
3 | future: {
4 | username: 'future',
5 | password: '$2a$04$YPy8WdAtWswed8b9MfKixebJkVUhEZxQCrExQaxzhcdR2xMmpSJiG', // 'studio'
6 | name: 'Future Studio',
7 | id: '1'
8 | }
9 | }
10 |
11 | module.exports = users
--------------------------------------------------------------------------------
/hapi-16/different-default-handlebars-layouts/index/handler.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Handler = {
4 | index: {
5 | handler: function (request, reply) {
6 | reply.view('index')
7 | }
8 | },
9 |
10 | second: {
11 | handler: function (request, reply) {
12 | reply.view('index', null, { layout: 'second-layout' })
13 | }
14 | }
15 | }
16 |
17 | module.exports = Handler
18 |
--------------------------------------------------------------------------------
/hapi-16/different-default-handlebars-layouts/index/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Routes = require('./routes')
4 |
5 | exports.register = (server, options, next) => {
6 | server.dependency([ 'vision' ])
7 |
8 | server.route(Routes)
9 | server.log('info', 'Plugin registered: use Vue.js with Handlebars in hapi')
10 |
11 | next()
12 | }
13 |
14 | exports.register.attributes = {
15 | name: 'vue-and-handlebars',
16 | version: '1.0.0'
17 | }
18 |
--------------------------------------------------------------------------------
/hapi-16/different-default-handlebars-layouts/index/routes.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Handler = require('./handler')
4 |
5 | const Routes = [
6 | {
7 | method: 'GET',
8 | path: '/',
9 | config: Handler.index
10 | },
11 | {
12 | method: 'GET',
13 | path: '/second',
14 | config: Handler.second
15 | }
16 | ]
17 |
18 | module.exports = Routes
19 |
--------------------------------------------------------------------------------
/hapi-16/different-default-handlebars-layouts/server.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hapi = require('hapi')
4 | const Path = require('path')
5 |
6 | // create new server instance
7 | const server = new Hapi.Server()
8 |
9 | // add server’s connection information
10 | server.connection({
11 | host: 'localhost',
12 | port: 3000
13 | })
14 |
15 | // register plugins to server instance
16 | server.register([
17 | {
18 | register: require('vision')
19 | },
20 | {
21 | register: require('./index')
22 | }
23 | ], function (err) {
24 | if (err) {
25 | throw err
26 | }
27 |
28 | server.views({
29 | engines: {
30 | html: require('handlebars')
31 | },
32 | layout: 'my-layout',
33 | path: Path.resolve('views')
34 | })
35 |
36 | // start your server
37 | server.start(function (err) {
38 | if (err) {
39 | throw err
40 | }
41 |
42 | console.log('Server running at: ' + server.info.uri)
43 | })
44 | })
45 |
--------------------------------------------------------------------------------
/hapi-16/different-default-handlebars-layouts/views/index.html:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
22 |
--------------------------------------------------------------------------------
/hapi-16/different-default-handlebars-layouts/views/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Multiple Handlebars Layouts
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | {{{ content }}}
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/hapi-16/different-default-handlebars-layouts/views/second-layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Vue.js and Handlebars in hapi
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | Second Layout, without Fontawesome Integration
17 |
18 |
19 |
20 |
21 | {{{ content }}}
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/hapi-16/extend-hapi-with-plugins/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 |
4 | // create new server instance
5 | var server = new Hapi.Server()
6 |
7 | // add server’s connection information
8 | server.connection({
9 | host: 'localhost',
10 | port: 3000
11 | })
12 |
13 | // add “hello world” route
14 | server.route({
15 | method: 'GET',
16 | path: '/',
17 | handler: function (request, reply) {
18 | reply('Hello Future Studio!')
19 | }
20 | })
21 |
22 | // register plugins to server instance
23 | server.register({
24 | register: Good,
25 | options: {
26 | ops: {
27 | interval: 10000
28 | },
29 | reporters: {
30 | console: [
31 | {
32 | module: 'good-squeeze',
33 | name: 'Squeeze',
34 | args: [ { log: '*', response: '*', request: '*' } ]
35 | },
36 | {
37 | module: 'good-console'
38 | },
39 | 'stdout'
40 | ]
41 | }
42 | }
43 | })
44 |
45 | // start your server
46 | server.start(function (err) {
47 | if (err) {
48 | throw err
49 | }
50 |
51 | server.log('info', 'Server running at: ' + server.info.uri)
52 | })
53 |
--------------------------------------------------------------------------------
/hapi-16/getting-started/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 |
3 | // create new server instance
4 | var server = new Hapi.Server()
5 |
6 | // add server’s connection information
7 | server.connection({
8 | host: 'localhost',
9 | port: 3000
10 | })
11 |
12 | // add “hello world” route
13 | server.route({
14 | method: 'GET',
15 | path: '/',
16 | handler: function (request, reply) {
17 | reply('Hello Future Studio!')
18 | }
19 | })
20 |
21 | // start your server
22 | server.start(function (err) {
23 | if (err) {
24 | throw err
25 | }
26 |
27 | console.log('Server running at: ' + server.info.uri)
28 | })
29 |
--------------------------------------------------------------------------------
/hapi-16/hapi-vue-ssr-basic/base/handler.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Fs = require('fs')
4 | const Vue = require('vue')
5 | const Boom = require('boom')
6 | const Path = require('path')
7 |
8 | // initialize Renderer with default template layout
9 | const LayoutPath = Path.resolve(__dirname, '..', 'views', 'layout.html')
10 | const Renderer = require('vue-server-renderer').createRenderer({
11 | template: Fs.readFileSync(LayoutPath, 'utf-8'),
12 | data: {
13 | title: 'Welcome to hapi-vue-ssr'
14 | }
15 | })
16 |
17 | function renderAndReply (template, context, reply) {
18 | const TemplatePath = Path.resolve(__dirname, '..', 'views', `${template}.html`)
19 | const app = new Vue({
20 | data: context,
21 | template: Fs.readFileSync(TemplatePath, 'utf-8')
22 | })
23 |
24 | return Renderer.renderToString(app, (err, html) => {
25 | if (err) {
26 | console.log(err)
27 | return reply(Boom.boomify(err, { statusCode: 500 }))
28 | }
29 |
30 | return reply(html)
31 | })
32 | }
33 |
34 | const Handler = {
35 | index: {
36 | handler: (request, reply) => {
37 | renderAndReply('index', null, reply)
38 | }
39 | },
40 |
41 | missing: {
42 | handler: (request, reply) => {
43 | renderAndReply('about', { url: request.url.path }, reply)
44 | }
45 | }
46 | }
47 |
48 | module.exports = Handler
49 |
--------------------------------------------------------------------------------
/hapi-16/hapi-vue-ssr-basic/base/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Routes = require('./routes')
4 |
5 | exports.register = (server, options, next) => {
6 | server.route(Routes)
7 | server.log('info', 'Plugin registered: 404 handler')
8 |
9 | next()
10 | }
11 |
12 | exports.register.attributes = {
13 | name: '404-handler',
14 | version: '1.0.0'
15 | }
16 |
--------------------------------------------------------------------------------
/hapi-16/hapi-vue-ssr-basic/base/routes.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Handler = require('./handler')
4 |
5 | const Routes = [
6 | {
7 | method: 'GET',
8 | path: '/',
9 | config: Handler.index
10 | },
11 | {
12 | method: [ 'GET', 'POST' ],
13 | path: '/{path*}',
14 | config: Handler.missing
15 | }
16 | ]
17 |
18 | module.exports = Routes
19 |
--------------------------------------------------------------------------------
/hapi-16/hapi-vue-ssr-basic/server.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hapi = require('hapi')
4 |
5 | // create new server instance
6 | const server = new Hapi.Server()
7 |
8 | // add server’s connection information
9 | server.connection({
10 | host: 'localhost',
11 | port: 3000
12 | })
13 |
14 | // register plugins to server instance
15 | server.register([
16 | {
17 | register: require('inert')
18 | },
19 | {
20 | register: require('./base')
21 | }
22 | ]).then(() => {
23 | server.start()
24 | }).then(() => {
25 | console.log('Server running at: ' + server.info.uri)
26 | }).catch(err => {
27 | throw err
28 | })
29 |
--------------------------------------------------------------------------------
/hapi-16/hapi-vue-ssr-basic/views/about.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Hey there 😘
5 |
6 | Future Studio is helping 5,000+ users daily to solve
7 | Android and Node.js problems with 350+ written tutorials
8 | and videos. We’re on a mission to provide new in-depth
9 | content every week.
10 |
11 |
12 |
13 |
14 |
15 | Take me back to the
16 | startpage
17 |
18 |
19 |
20 |
21 |
22 | You’re here: {{ url }}
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/hapi-16/hapi-vue-ssr-basic/views/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Hello!
5 |
6 |
7 | This page is rendered with Vue.js on the server 🤘😃
8 |
9 |
10 | Go anywhere, you’ll see the another SSR page
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/hapi-16/hapi-vue-ssr-basic/views/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | hapi & Vue SSR
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/hapi-16/ignore-trailing-slash-on-paths/base-route.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const baseRoutes = {
4 | register: function (server, options, next) {
5 | // add defined route to hapi server
6 | server.route([
7 | {
8 | method: 'GET',
9 | path: '/',
10 | handler: function (request, reply) {
11 | reply('Did the work :)')
12 | }
13 | },
14 | {
15 | method: 'GET',
16 | path: '/slash',
17 | handler: function (request, reply) {
18 | reply('Called the /slash or /slash/ route')
19 | }
20 | },
21 | {
22 | method: 'GET',
23 | path: '/slash/{name}',
24 | handler: function (request, reply) {
25 | reply('Called route with slash at the end: ' + request.params.name)
26 | }
27 | }
28 | ])
29 |
30 | next()
31 | }
32 | }
33 |
34 | baseRoutes.register.attributes = {
35 | name: 'base-routes',
36 | version: '1.0.0'
37 | }
38 |
39 | module.exports = baseRoutes
--------------------------------------------------------------------------------
/hapi-16/ignore-trailing-slash-on-paths/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 |
4 | // create new server instance
5 | var server = new Hapi.Server()
6 |
7 | // add server’s connection information
8 | server.connection({
9 | host: 'localhost',
10 | port: 3000,
11 | router: {
12 | stripTrailingSlash: true
13 | }
14 | })
15 |
16 | // register plugins to server instance
17 | server.register([
18 | {
19 | register: Good,
20 | options: {
21 | reporters: {
22 | console: [
23 | { module: 'good-squeeze', name: 'Squeeze', args: [ { log: '*', response: '*', request: '*' } ] },
24 | { module: 'good-console' },
25 | 'stdout'
26 | ]
27 | }
28 | }
29 | },
30 | {
31 | register: require('./base-route')
32 | }
33 | ], function (err) {
34 | if (err) {
35 | throw err
36 | }
37 |
38 | server.log('info', 'Registered plugins')
39 |
40 | // start your server after plugin registration
41 | server.start(function (err) {
42 | if (err) {
43 | throw err
44 | }
45 |
46 | server.log('info', 'Server running at: ' + server.info.uri)
47 | })
48 | })
49 |
--------------------------------------------------------------------------------
/hapi-16/multiple-auth-strategies-for-routes/routes.js:
--------------------------------------------------------------------------------
1 | var Boom = require('boom')
2 | var Bcrypt = require('bcrypt')
3 | var Users = require('./users-db')
4 |
5 | var routes = [
6 | {
7 | method: 'GET',
8 | path: '/profile',
9 | config: {
10 | auth: {
11 | strategies: ['simple', 'session']
12 | },
13 | handler: function (request, reply) {
14 | return reply.view('profile')
15 | }
16 | }
17 | },
18 | {
19 | method: 'GET',
20 | path: '/',
21 | config: {
22 | auth: {
23 | mode: 'try',
24 | strategy: 'session'
25 | },
26 | plugins: {
27 | 'hapi-auth-cookie': {
28 | redirectTo: false
29 | }
30 | },
31 | handler: function (request, reply) {
32 | if (request.auth.isAuthenticated) {
33 | return reply.view('profile')
34 | }
35 |
36 | reply.view('index')
37 | }
38 | }
39 | },
40 | {
41 | method: 'POST',
42 | path: '/',
43 | config: {
44 | // auth: 'session',
45 | auth: {
46 | mode: 'try'
47 | },
48 | plugins: {
49 | 'hapi-auth-cookie': {
50 | redirectTo: false
51 | }
52 | },
53 | handler: function (request, reply) {
54 | if (request.auth.isAuthenticated) {
55 | return reply.view('Profile')
56 | }
57 |
58 | var username = request.payload.username
59 | var user = Users[ username ]
60 |
61 | if (!user) {
62 | return reply(Boom.notFound('No user registered with given credentials'))
63 | }
64 |
65 | var password = request.payload.password
66 |
67 | return Bcrypt.compare(password, user.password, function (err, isValid) {
68 | if (isValid) {
69 | request.server.log('info', 'user authentication successful')
70 | request.cookieAuth.set(user);
71 | return reply.view('profile')
72 | }
73 |
74 | return reply.view('index')
75 | })
76 | }
77 | }
78 | },
79 | {
80 | method: 'GET',
81 | path: '/logout',
82 | config: {
83 | auth: 'session',
84 | handler: function (request, reply) {
85 | request.cookieAuth.clear();
86 | reply.view('index')
87 | }
88 | }
89 | }
90 | ]
91 |
92 | module.exports = routes
--------------------------------------------------------------------------------
/hapi-16/multiple-auth-strategies-for-routes/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 | var Vision = require('vision')
4 | var Bcrypt = require('bcrypt')
5 | var Users = require('./users-db')
6 | var Handlebars = require('handlebars')
7 | var BasicAuth = require('hapi-auth-basic')
8 | var CookieAuth = require('hapi-auth-cookie')
9 |
10 | // create new server instance
11 | var server = new Hapi.Server()
12 |
13 | // add server’s connection information
14 | server.connection({
15 | host: 'localhost',
16 | port: 3000
17 | })
18 |
19 | // register plugins to server instance
20 | server.register([ Vision, BasicAuth, CookieAuth,
21 | {
22 | register: Good,
23 | options: {
24 | ops: {
25 | interval: 10000
26 | },
27 | reporters: {
28 | console: [
29 | {
30 | module: 'good-squeeze',
31 | name: 'Squeeze',
32 | args: [ { log: '*', response: '*', request: '*' } ]
33 | },
34 | {
35 | module: 'good-console'
36 | },
37 | 'stdout'
38 | ]
39 | }
40 | }
41 | }
42 | ], function (err) {
43 | if (err) {
44 | server.log('error', 'failed to install plugins')
45 |
46 | throw err
47 | }
48 |
49 | server.log('info', 'Plugins registered')
50 |
51 | /**
52 | * view configuration
53 | */
54 | server.views({
55 | engines: {
56 | html: Handlebars
57 | },
58 | path: __dirname + '/views',
59 | layout: true
60 | })
61 | server.log('info', 'View configuration completed')
62 |
63 | // validation function used for hapi-auth-basic
64 | var basicValidation = function (request, username, password, callback) {
65 | var user = Users[ username ]
66 |
67 | if (!user) {
68 | return callback(null, false)
69 | }
70 |
71 | Bcrypt.compare(password, user.password, function (err, isValid) {
72 | server.log('info', 'user authentication successful')
73 | callback(err, isValid, { id: user.id, name: user.name })
74 | })
75 | }
76 |
77 | server.auth.strategy('simple', 'basic', { validateFunc: basicValidation })
78 | server.log('info', 'Registered auth strategy: basic auth')
79 |
80 | // validation function used for hapi-auth-cookie: optional and checks if the user is still existing
81 | var cookieValidation = function (request, session, callback) {
82 | var username = session.username
83 | var user = Users[ username ]
84 |
85 | if (!user) {
86 | return callback(null, false)
87 | }
88 |
89 | server.log('info', 'user authenticated')
90 | callback(err, true, user)
91 | }
92 |
93 | server.auth.strategy('session', 'cookie', {
94 | password: 'm!*"2/),p4:xDs%KEgVr7;e#85Ah^WYC',
95 | cookie: 'future-studio-hapi-tutorials-cookie-auth-example',
96 | redirectTo: false,
97 | isSecure: false,
98 | validateFunc: cookieValidation
99 | })
100 | server.log('info', 'Registered auth strategy: cookie auth')
101 |
102 | // default auth strategy avoids server crash for routes that doesn’t specify auth config
103 | server.auth.default('simple')
104 |
105 | var routes = require('./routes')
106 | server.route(routes)
107 | server.log('info', 'Routes registered')
108 |
109 | // start your server after plugin registration
110 | server.start(function (err) {
111 | if (err) {
112 | server.log('error', 'failed to start server')
113 | server.log('error', err)
114 |
115 | throw err
116 | }
117 |
118 | server.log('info', 'Server running at: ' + server.info.uri)
119 | })
120 | })
121 |
--------------------------------------------------------------------------------
/hapi-16/multiple-auth-strategies-for-routes/users-db.js:
--------------------------------------------------------------------------------
1 | // hardcoded users object … just for illustration purposes
2 | var users = {
3 | future: {
4 | username: 'future',
5 | password: '$2a$04$YPy8WdAtWswed8b9MfKixebJkVUhEZxQCrExQaxzhcdR2xMmpSJiG', // 'studio'
6 | name: 'Future Studio',
7 | id: '1'
8 | }
9 | }
10 |
11 | module.exports = users
--------------------------------------------------------------------------------
/hapi-16/multiple-auth-strategies-for-routes/views/index.html:
--------------------------------------------------------------------------------
1 |
2 |
Hapi Cookie Authentication
3 |
4 | Use the following credentials to log in.
5 |
6 |
7 | Username: future
8 | Password: studio
9 |
10 |
11 |
20 |
--------------------------------------------------------------------------------
/hapi-16/multiple-auth-strategies-for-routes/views/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hapi — Basic Authentication
5 |
6 |
7 |
8 | {{{ content }}}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/hapi-16/multiple-auth-strategies-for-routes/views/profile.html:
--------------------------------------------------------------------------------
1 |
2 |
Your Profile
3 |
4 | logout
5 |
6 |
--------------------------------------------------------------------------------
/hapi-16/multiple-server-instances/backend-route.js:
--------------------------------------------------------------------------------
1 | var plugin = {
2 | register: function (server, options, next) {
3 | server.route({
4 | method: 'GET',
5 | path: '/',
6 | handler: function (request, reply) {
7 | reply('Backend is ok')
8 | }
9 | })
10 |
11 | next()
12 | }
13 | }
14 |
15 | plugin.register.attributes = {
16 | name: 'multiple-server-instances-backend-routes',
17 | version: '1.0.0'
18 | }
19 |
20 | module.exports = plugin
21 |
--------------------------------------------------------------------------------
/hapi-16/multiple-server-instances/frontend-route.js:
--------------------------------------------------------------------------------
1 | var plugin = {
2 | register: function (server, options, next) {
3 | server.route({
4 | method: 'GET',
5 | path: '/',
6 | handler: function (request, reply) {
7 | reply('Frontend is totally fine')
8 | }
9 | })
10 |
11 | next()
12 | }
13 | }
14 |
15 | plugin.register.attributes = {
16 | name: 'multiple-server-instances-frontend-routes',
17 | version: '1.0.0'
18 | }
19 |
20 | module.exports = plugin
21 |
--------------------------------------------------------------------------------
/hapi-16/multiple-server-instances/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var _ = require('lodash')
3 | var port = 3000
4 |
5 | // create new server instance
6 | var server = new Hapi.Server()
7 |
8 | // add server’s connection information
9 | var frontend = server.connection({
10 | host: 'localhost',
11 | port: process.env.PORT || port,
12 | labels: 'frontend'
13 | })
14 |
15 | frontend.register({
16 | register: require('./frontend-route')
17 | })
18 |
19 |
20 | // add another server connection
21 | var backend = server.connection({
22 | host: 'localhost',
23 | port: process.env.PORT + 1 || port + 1,
24 | labels: 'backend'
25 | })
26 |
27 | backend.register({
28 | register: require('./backend-route')
29 | })
30 |
31 |
32 | // start your server after plugin registration
33 | server.start(function (err) {
34 | if (err) {
35 | throw err
36 | }
37 |
38 | _.forEach(server.connections, function(connection) {
39 | console.log('Server started at: ' + connection.info.uri)
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/hapi-16/optional-path-params/base-route.js:
--------------------------------------------------------------------------------
1 | var plugin = {
2 | register: function (server, options, next) {
3 | var routes = [
4 | {
5 | method: 'GET',
6 | path: '/{param?}',
7 | handler: function (request, reply) {
8 | var params = request.params
9 |
10 | server.log('info', params)
11 |
12 | reply(params)
13 | }
14 | }
15 | ]
16 |
17 | // add defined routes to hapi
18 | server.route(routes)
19 |
20 | next()
21 | }
22 | }
23 |
24 | plugin.register.attributes = {
25 | name: 'optional-path-params',
26 | version: '1.0.0'
27 | }
28 |
29 | module.exports = plugin
--------------------------------------------------------------------------------
/hapi-16/optional-path-params/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 |
4 | // create new server instance
5 | var server = new Hapi.Server()
6 |
7 | // add server’s connection information
8 | server.connection({
9 | host: 'localhost',
10 | port: 3000
11 | })
12 |
13 | // register plugins to server instance
14 | server.register([
15 | {
16 | register: require('./base-route')
17 | },
18 | {
19 | register: Good,
20 | options: {
21 | ops: {
22 | interval: 10000
23 | },
24 | reporters: {
25 | console: [
26 | {
27 | module: 'good-squeeze',
28 | name: 'Squeeze',
29 | args: [ { log: '*', response: '*', request: '*' } ]
30 | },
31 | {
32 | module: 'good-console'
33 | },
34 | 'stdout'
35 | ]
36 | }
37 | }
38 | }
39 | ], function (err) {
40 | if (err) {
41 | throw err
42 | }
43 |
44 | // start your server after plugin registration
45 | server.start(function (err) {
46 | if (err) {
47 | throw err
48 | }
49 |
50 | server.log('info', 'Server running at: ' + server.info.uri)
51 | })
52 | })
53 |
--------------------------------------------------------------------------------
/hapi-16/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nodejs-tutorials-hapi",
3 | "description": "Example code related to an extensive hapi series on Future Studio (https://futurestud.io)",
4 | "version": "1.0.0",
5 | "author": "Future Studio ",
6 | "bugs": "https://github.com/fs-opensource/nodejs-tutorials-hapi/issues",
7 | "contributors": [
8 | {
9 | "name": "Marcus Poehls",
10 | "email": "marcus@futurestud.io"
11 | }
12 | ],
13 | "dependencies": {
14 | "bcrypt": "~1.0.3",
15 | "bell": "~8.8.0",
16 | "boom": "~5.2.0",
17 | "good": "~7.3.0",
18 | "good-console": "~6.4.0",
19 | "good-file": "~6.0.1",
20 | "good-squeeze": "~5.0.2",
21 | "handlebars": "~4.5.3",
22 | "hapi": "~16.6.2",
23 | "hapi-auth-basic": "~4.2.0",
24 | "hapi-auth-cookie": "~7.0.0",
25 | "hapi-dev-errors": "~1.3.2",
26 | "hoek": "~6.1.3",
27 | "inert": "~4.2.1",
28 | "joi": "~10.5.2",
29 | "lodash": "~4.17.4",
30 | "pug": "~2.0.0-rc.4",
31 | "vision": "~4.1.1",
32 | "vue": "~2.5.2",
33 | "vue-server-renderer": "~2.5.2",
34 | "when": "~3.7.8"
35 | },
36 | "devDependencies": {
37 | "eslint": "~4.9.0",
38 | "code": "~4.1.0",
39 | "lab": "~14.3.1",
40 | "eslint-config-standard": "~10.2.1",
41 | "eslint-plugin-import": "~2.8.0",
42 | "eslint-plugin-node": "~5.2.0",
43 | "eslint-plugin-promise": "~3.6.0",
44 | "eslint-plugin-standard": "~3.0.1"
45 | },
46 | "engines": {
47 | "node": ">=4.0.0"
48 | },
49 | "homepage": "https://futurestud.io/tutorials/hapi-get-your-server-up-and-running",
50 | "keywords": [
51 | "hapi",
52 | "node.js",
53 | "tutorials"
54 | ],
55 | "license": "MIT",
56 | "repository": "https://github.com/fs-opensource/nodejs-tutorials-hapi",
57 | "scripts": {
58 | "test": "echo \"Error: no test specified\" && exit 1"
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/hapi-16/path-params-of-same-name/base-route.js:
--------------------------------------------------------------------------------
1 | var plugin = {
2 | register: function (server, options, next) {
3 | var routes = [
4 | {
5 | method: 'GET',
6 | path: '/filter/{type}',
7 | handler: function (request, reply) {
8 | var params = request.params
9 |
10 | server.log('info', params)
11 |
12 | reply(params)
13 | }
14 | }
15 | ]
16 |
17 | // add defined routes to hapi
18 | server.route(routes)
19 |
20 | next()
21 | }
22 | }
23 |
24 | plugin.register.attributes = {
25 | name: 'path-params-optional-wildcard',
26 | version: '1.0.0'
27 | }
28 |
29 | module.exports = plugin
--------------------------------------------------------------------------------
/hapi-16/path-params-of-same-name/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 |
4 | // create new server instance
5 | var server = new Hapi.Server()
6 |
7 | // add server’s connection information
8 | server.connection({
9 | host: 'localhost',
10 | port: 3000
11 | })
12 |
13 | // register plugins to server instance
14 | server.register([
15 | {
16 | register: require('./base-route')
17 | },
18 | {
19 | register: Good,
20 | options: {
21 | ops: {
22 | interval: 10000
23 | },
24 | reporters: {
25 | console: [
26 | {
27 | module: 'good-squeeze',
28 | name: 'Squeeze',
29 | args: [ { log: '*', response: '*', request: '*' } ]
30 | },
31 | {
32 | module: 'good-console'
33 | },
34 | 'stdout'
35 | ]
36 | }
37 | }
38 | }
39 | ], function (err) {
40 | if (err) {
41 | throw err
42 | }
43 |
44 | // start your server after plugin registration
45 | server.start(function (err) {
46 | if (err) {
47 | throw err
48 | }
49 |
50 | server.log('info', 'Server running at: ' + server.info.uri)
51 | })
52 | })
53 |
--------------------------------------------------------------------------------
/hapi-16/query-params/base-route.js:
--------------------------------------------------------------------------------
1 | var plugin = {
2 | register: function (server, options, next) {
3 | var routes = [
4 | {
5 | method: 'GET',
6 | path: '/',
7 | handler: function (request, reply) {
8 | var params = request.query
9 |
10 | server.log('info', params)
11 |
12 | reply(params)
13 | }
14 | }
15 | ]
16 |
17 | // add defined routes to hapi
18 | server.route(routes)
19 |
20 | next()
21 | }
22 | }
23 |
24 | plugin.register.attributes = {
25 | name: 'query-param-routes',
26 | version: '1.0.0'
27 | }
28 |
29 | module.exports = plugin
--------------------------------------------------------------------------------
/hapi-16/query-params/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 |
4 | // create new server instance
5 | var server = new Hapi.Server()
6 |
7 | // add server’s connection information
8 | server.connection({
9 | host: 'localhost',
10 | port: 3000
11 | })
12 |
13 | // register plugins to server instance
14 | server.register([
15 | {
16 | register: require('./base-route')
17 | },
18 | {
19 | register: Good,
20 | options: {
21 | ops: {
22 | interval: 10000
23 | },
24 | reporters: {
25 | console: [
26 | {
27 | module: 'good-squeeze',
28 | name: 'Squeeze',
29 | args: [ { log: '*', response: '*', request: '*' } ]
30 | },
31 | {
32 | module: 'good-console'
33 | },
34 | 'stdout'
35 | ]
36 | }
37 | }
38 | }
39 | ], function (err) {
40 | if (err) {
41 | throw err
42 | }
43 |
44 | // start your server after plugin registration
45 | server.start(function (err) {
46 | if (err) {
47 | throw err
48 | }
49 |
50 | server.log('info', 'Server running at: ' + server.info.uri)
51 | })
52 | })
53 |
--------------------------------------------------------------------------------
/hapi-16/redirect-to-previous-page-after-login/authentication/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Users = require('../users-db')
4 | const Hoek = require('hoek')
5 |
6 | exports.register = function (server, options, next) {
7 | // declare dependency to hapi-auth-cookie and bell
8 | server.register([
9 | {
10 | register: require('hapi-auth-cookie')
11 | }
12 | ], err => {
13 | Hoek.assert(!err, 'Cannot register authentication plugin')
14 |
15 | /**
16 | * Register session based auth strategy to store
17 | * and validate the session cookie received with
18 | * the user’s requests
19 | */
20 | server.auth.strategy('session', 'cookie', {
21 | password: 'ThisIsASecretPasswordForTheAuthCookie',
22 | redirectTo: '/login',
23 | appendNext: true, // appends the current URL to the query param "next". Set to a string to use a different query param name
24 | isSecure: process.env.NODE_ENV === 'production',
25 | validateFunc: (request, session, callback) => {
26 | // validate the existing session
27 | // this simple example checks the “users db” for an entry
28 | const username = session.username
29 | const user = Users[ username ]
30 |
31 | if (!user) {
32 | return callback(null, false)
33 | }
34 |
35 | callback(err, true, user)
36 | }
37 | })
38 |
39 | next()
40 | })
41 | }
42 |
43 | exports.register.attributes = {
44 | name: 'authentication',
45 | version: '1.0.0'
46 | }
47 |
--------------------------------------------------------------------------------
/hapi-16/redirect-to-previous-page-after-login/implementation/handler.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Bcrypt = require('bcrypt')
4 | const Users = require('../users-db')
5 |
6 | const Handler = {
7 | index: {
8 | auth: {
9 | mode: 'try',
10 | strategy: 'session'
11 | },
12 | plugins: {
13 | 'hapi-auth-cookie': {
14 | redirectTo: false
15 | }
16 | },
17 | handler: function (request, reply) {
18 | reply.view('index')
19 | }
20 | },
21 |
22 | showLogin: {
23 | auth: {
24 | mode: 'try',
25 | strategy: 'session'
26 | },
27 | plugins: {
28 | 'hapi-auth-cookie': {
29 | redirectTo: false
30 | }
31 | },
32 | handler: function (request, reply) {
33 | if (request.auth.isAuthenticated) {
34 | return reply.redirect(request.query.next)
35 | }
36 |
37 | reply.view('login')
38 | }
39 | },
40 |
41 | login: {
42 | auth: {
43 | mode: 'try',
44 | strategy: 'session'
45 | },
46 | plugins: {
47 | 'hapi-auth-cookie': {
48 | redirectTo: false
49 | }
50 | },
51 | handler: (request, reply) => {
52 | if (request.auth.isAuthenticated) {
53 | return reply.redirect(request.query.next)
54 | }
55 |
56 | const username = request.payload.username
57 | const user = Users[ username ]
58 |
59 | if (!user) {
60 | // no user found with given username
61 | return reply.view('login', {
62 | username,
63 | errormessage: 'No user registered with given credentials'
64 | }).code(404)
65 | }
66 |
67 | const password = request.payload.password
68 |
69 | return Bcrypt.compare(password, user.password, (err, isValid) => {
70 | if (isValid) {
71 | request.cookieAuth.set(user)
72 |
73 | // check whether there’s a value for "next" query param
74 | // if not, define the default "/"
75 | const next = request.query.next ? request.query.next : '/'
76 |
77 | // redirect the user to the previous page
78 | return reply.redirect(next)
79 | }
80 |
81 | // given password doesn’t match the stored one
82 | return reply.view('login', {
83 | username,
84 | errormessage: 'No user registered with given credentials'
85 | }).code(404)
86 | })
87 | }
88 | },
89 |
90 | private: {
91 | auth: 'session',
92 | handler: function (request, reply) {
93 | reply.view('private')
94 | }
95 | },
96 |
97 | profile: {
98 | auth: 'session',
99 | handler: function (request, reply) {
100 | reply.view('profile')
101 | }
102 | },
103 |
104 | logout: {
105 | auth: 'session',
106 | handler: function (request, reply) {
107 | request.cookieAuth.clear()
108 | reply.view('index')
109 | }
110 | }
111 | }
112 |
113 | module.exports = Handler
114 |
--------------------------------------------------------------------------------
/hapi-16/redirect-to-previous-page-after-login/implementation/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Routes = require('./routes')
4 |
5 | exports.register = (server, options, next) => {
6 | server.dependency([ 'authentication', 'vision' ])
7 |
8 | server.route(Routes)
9 | server.log('info', 'Plugin registered: redirect to previous page')
10 |
11 | next()
12 | }
13 |
14 | exports.register.attributes = {
15 | name: 'redirect-to-previous-page',
16 | version: '1.0.0'
17 | }
18 |
--------------------------------------------------------------------------------
/hapi-16/redirect-to-previous-page-after-login/implementation/routes.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Handler = require('./handler')
4 |
5 | const Routes = [
6 | {
7 | method: 'GET',
8 | path: '/',
9 | config: Handler.index
10 | },
11 | {
12 | method: 'GET',
13 | path: '/login',
14 | config: Handler.showLogin
15 | },
16 | {
17 | method: 'POST',
18 | path: '/login',
19 | config: Handler.login
20 | },
21 | {
22 | method: 'GET',
23 | path: '/private',
24 | config: Handler.private
25 | },
26 | {
27 | method: 'GET',
28 | path: '/profile',
29 | config: Handler.profile
30 | },
31 | {
32 | method: 'GET',
33 | path: '/logout',
34 | config: Handler.logout
35 | }
36 | ]
37 |
38 | module.exports = Routes
39 |
--------------------------------------------------------------------------------
/hapi-16/redirect-to-previous-page-after-login/server.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hapi = require('hapi')
4 |
5 | // create new server instance
6 | const server = new Hapi.Server()
7 |
8 | // add server’s connection information
9 | server.connection({
10 | host: 'localhost',
11 | port: 3000
12 | })
13 |
14 | // register plugins to server instance
15 | server.register([
16 | {
17 | register: require('./authentication')
18 | },
19 | {
20 | register: require('vision')
21 | },
22 | {
23 | register: require('./implementation')
24 | }
25 | ], err => {
26 | if (err) {
27 | throw err
28 | }
29 |
30 | server.views({
31 | engines: {
32 | html: require('handlebars')
33 | },
34 | path: __dirname + '/views',
35 | layout: 'layout'
36 | })
37 |
38 | // start your server
39 | server.start(err => {
40 |
41 | if (err) {
42 | throw err
43 | }
44 |
45 | console.log('Server running at: ' + server.info.uri)
46 | })
47 | })
48 |
--------------------------------------------------------------------------------
/hapi-16/redirect-to-previous-page-after-login/users-db.js:
--------------------------------------------------------------------------------
1 | // hardcoded users object … just for illustration purposes
2 | const users = {
3 | future: {
4 | username: 'future',
5 | password: '$2a$04$YPy8WdAtWswed8b9MfKixebJkVUhEZxQCrExQaxzhcdR2xMmpSJiG', // 'studio'
6 | name: 'Future Studio',
7 | id: '1'
8 | }
9 | }
10 |
11 | module.exports = users
--------------------------------------------------------------------------------
/hapi-16/redirect-to-previous-page-after-login/views/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Hello!
5 |
6 |
7 | Both of the links below require authentication and
8 | you’ll be redirected to the actual page after login.
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/hapi-16/redirect-to-previous-page-after-login/views/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{title}}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{{ content }}}
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/hapi-16/redirect-to-previous-page-after-login/views/login.html:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
Login
11 |
12 | Hi buddy, log in with username future and password studio :
13 |
14 |
15 | Back to the startpage
16 |
17 |
18 | {{#if errormessage}}
19 |
20 |
21 | {{errormessage}}
22 |
23 | {{/if}}
24 |
25 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/hapi-16/redirect-to-previous-page-after-login/views/private.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Private. Shhh!
5 |
6 | You’re the only one who can see this private view :)
7 |
8 |
9 |
10 | Back to the startpage
11 |
12 |
13 |
14 | Logout
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/hapi-16/redirect-to-previous-page-after-login/views/profile.html:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/hapi-16/render-handlebars-views/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 | var Vision = require('vision')
4 | var Handlebars = require('handlebars')
5 |
6 |
7 | // create new server instance
8 | var server = new Hapi.Server()
9 |
10 | // add server’s connection information
11 | server.connection({
12 | host: 'localhost',
13 | port: 3000
14 | })
15 |
16 | // register plugins to server instance
17 | server.register([
18 | {
19 | register: Vision
20 | },
21 | {
22 | register: Good,
23 | options: {
24 | ops: {
25 | interval: 10000
26 | },
27 | reporters: {
28 | console: [
29 | {
30 | module: 'good-squeeze',
31 | name: 'Squeeze',
32 | args: [ { log: '*', response: '*', request: '*' } ]
33 | },
34 | {
35 | module: 'good-console'
36 | },
37 | 'stdout'
38 | ]
39 | }
40 | }
41 | }
42 | ], function (err) {
43 | if (err) {
44 | server.log('error', 'failed to install plugins')
45 |
46 | throw err
47 | }
48 |
49 | server.log('info', 'Plugins registered')
50 |
51 | /**
52 | * view configuration
53 | */
54 | server.views({
55 | engines: {
56 | html: Handlebars
57 | },
58 | path: __dirname + '/views',
59 | layout: true
60 | })
61 | server.log('info', 'View configuration completed')
62 |
63 |
64 | server.route({
65 | method: 'GET',
66 | path: '/',
67 | handler: function(request, reply) {
68 | var data = {
69 | title: 'Hapi Render Views',
70 | message: 'Wohoo \\o/ Your view has been rendered successfully!'
71 | }
72 |
73 | reply.view('index', data)
74 | }
75 | })
76 | server.log('info', 'Route registered')
77 |
78 | // start your server after plugin registration
79 | server.start(function (err) {
80 | if (err) {
81 | server.log('error', 'failed to start server')
82 | server.log('error', err)
83 |
84 | throw err
85 | }
86 |
87 | server.log('info', 'Server running at: ' + server.info.uri)
88 | })
89 | })
90 |
--------------------------------------------------------------------------------
/hapi-16/render-handlebars-views/views/index.html:
--------------------------------------------------------------------------------
1 |
2 |
{{message}}
3 |
--------------------------------------------------------------------------------
/hapi-16/render-handlebars-views/views/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{title}}
5 |
6 |
7 |
8 | {{{ content }}}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/hapi-16/reply-json/base-route.js:
--------------------------------------------------------------------------------
1 | var baseRoutes = {
2 | register: function (server, options, next) {
3 | var routes = [
4 | {
5 | method: 'GET',
6 | path: '/',
7 | handler: function (request, reply) {
8 | var data = {
9 | key: 'value',
10 | another: false,
11 | number: 10,
12 | func: function() {
13 | return this.number * 10
14 | }
15 | }
16 |
17 | reply(data)
18 | }
19 | }
20 | ]
21 |
22 | // add defined routes to hapi
23 | server.route(routes)
24 | next()
25 | }
26 | }
27 |
28 | baseRoutes.register.attributes = {
29 | name: 'base-routes',
30 | version: '1.0.0'
31 | }
32 |
33 | module.exports = baseRoutes
--------------------------------------------------------------------------------
/hapi-16/reply-json/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 |
4 | // create new server instance
5 | var server = new Hapi.Server()
6 |
7 | // add server’s connection information
8 | server.connection({
9 | host: 'localhost',
10 | port: 3000
11 | })
12 |
13 | // register plugins to server instance
14 | server.register([
15 | {
16 | register: require('./base-route')
17 | },
18 | {
19 | register: Good,
20 | options: {
21 | ops: {
22 | interval: 10000
23 | },
24 | reporters: {
25 | console: [
26 | {
27 | module: 'good-squeeze',
28 | name: 'Squeeze',
29 | args: [ { log: '*', response: '*', request: '*' } ]
30 | },
31 | {
32 | module: 'good-console'
33 | },
34 | 'stdout'
35 | ]
36 | }
37 | }
38 | }
39 | ], function (err) {
40 | if (err) {
41 | throw err
42 | }
43 |
44 | // start your server after plugin registration
45 | server.start(function (err) {
46 | if (err) {
47 | throw err
48 | }
49 |
50 | server.log('info', 'Server running at: ' + server.info.uri)
51 | })
52 | })
53 |
--------------------------------------------------------------------------------
/hapi-16/request-headers/base-route.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const plugin = {
4 | register: function (server, options, next) {
5 | server.route({
6 | method: 'GET',
7 | path: '/',
8 | handler: function (request, reply) {
9 | const headers = request.headers
10 |
11 | server.log('info', headers)
12 |
13 | reply(headers)
14 | }
15 | })
16 |
17 | next()
18 | }
19 | }
20 |
21 | plugin.register.attributes = {
22 | name: 'request-headers',
23 | version: '1.0.0'
24 | }
25 |
26 | module.exports = plugin
--------------------------------------------------------------------------------
/hapi-16/request-headers/server.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hapi = require('hapi')
4 | const Good = require('good')
5 |
6 | // create new server instance
7 | let server = new Hapi.Server()
8 |
9 | // add server’s connection information
10 | server.connection({
11 | host: 'localhost',
12 | port: 3000
13 | })
14 |
15 | // register plugins to server instance
16 | server.register([
17 | {
18 | register: require('./base-route')
19 | },
20 | {
21 | register: Good,
22 | options: {
23 | ops: {
24 | interval: 10000
25 | },
26 | reporters: {
27 | console: [
28 | {
29 | module: 'good-squeeze',
30 | name: 'Squeeze',
31 | args: [ { log: '*', response: '*', request: '*' } ]
32 | },
33 | {
34 | module: 'good-console'
35 | },
36 | 'stdout'
37 | ]
38 | }
39 | }
40 | }
41 | ], function (err) {
42 | if (err) {
43 | throw err
44 | }
45 |
46 | // start your server after plugin registration
47 | server.start(function (err) {
48 | if (err) {
49 | throw err
50 | }
51 |
52 | server.log('info', 'Server running at: ' + server.info.uri)
53 | })
54 | })
55 |
--------------------------------------------------------------------------------
/hapi-16/request-payload/base-route.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const plugin = {
4 | register: function (server, options, next) {
5 | server.route({
6 | method: 'POST',
7 | path: '/',
8 | handler: function (request, reply) {
9 | const payload = request.payload;
10 |
11 | server.log('info', payload)
12 |
13 | reply(payload)
14 | }
15 | })
16 |
17 | next()
18 | }
19 | }
20 |
21 | plugin.register.attributes = {
22 | name: 'wildcard-path-params',
23 | version: '1.0.0'
24 | }
25 |
26 | module.exports = plugin
--------------------------------------------------------------------------------
/hapi-16/request-payload/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 |
4 | // create new server instance
5 | var server = new Hapi.Server()
6 |
7 | // add server’s connection information
8 | server.connection({
9 | host: 'localhost',
10 | port: 3000
11 | })
12 |
13 | // register plugins to server instance
14 | server.register([
15 | {
16 | register: require('./base-route')
17 | },
18 | {
19 | register: Good,
20 | options: {
21 | ops: {
22 | interval: 10000
23 | },
24 | reporters: {
25 | console: [
26 | {
27 | module: 'good-squeeze',
28 | name: 'Squeeze',
29 | args: [ { log: '*', response: '*', request: '*' } ]
30 | },
31 | {
32 | module: 'good-console'
33 | },
34 | 'stdout'
35 | ]
36 | }
37 | }
38 | }
39 | ], function (err) {
40 | if (err) {
41 | throw err
42 | }
43 |
44 | // start your server after plugin registration
45 | server.start(function (err) {
46 | if (err) {
47 | throw err
48 | }
49 |
50 | server.log('info', 'Server running at: ' + server.info.uri)
51 | })
52 | })
53 |
--------------------------------------------------------------------------------
/hapi-16/response-status-codes/base-route.js:
--------------------------------------------------------------------------------
1 | var Boom = require('boom')
2 |
3 | var baseRoutes = {
4 | register: function (server, options, next) {
5 | var routes = [
6 | {
7 | method: 'GET',
8 | path: '/',
9 | handler: function (request, reply) {
10 | var data = {
11 | key: 'value'
12 | }
13 |
14 | reply(data).code(201)
15 | }
16 | },
17 | {
18 | method: 'GET',
19 | path: '/error',
20 | handler: function (request, reply) {
21 | var error = Boom.notFound('Cannot find the requested page')
22 | reply(error)
23 | }
24 | },
25 | {
26 | method: 'GET',
27 | path: '/empty',
28 | config: {
29 | response: {
30 | emptyStatusCode: 204
31 | },
32 | handler: function (request, reply) {
33 | reply()
34 | }
35 | }
36 | }
37 | ]
38 |
39 | // add defined routes to hapi
40 | server.route(routes)
41 | next()
42 | }
43 | }
44 |
45 | baseRoutes.register.attributes = {
46 | name: 'response-status',
47 | version: '1.0.0'
48 | }
49 |
50 | module.exports = baseRoutes
51 |
--------------------------------------------------------------------------------
/hapi-16/response-status-codes/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 |
4 | // create new server instance
5 | var server = new Hapi.Server()
6 |
7 | // add server’s connection information
8 | server.connection({
9 | host: 'localhost',
10 | port: 3000
11 | })
12 |
13 | // register plugins to server instance
14 | server.register([
15 | {
16 | register: require('./base-route')
17 | },
18 | {
19 | register: Good,
20 | options: {
21 | ops: {
22 | interval: 10000
23 | },
24 | reporters: {
25 | console: [
26 | {
27 | module: 'good-squeeze',
28 | name: 'Squeeze',
29 | args: [ { log: '*', response: '*', request: '*' } ]
30 | },
31 | {
32 | module: 'good-console'
33 | },
34 | 'stdout'
35 | ]
36 | }
37 | }
38 | }
39 | ], function (err) {
40 | if (err) {
41 | throw err
42 | }
43 |
44 | // start your server after plugin registration
45 | server.start(function (err) {
46 | if (err) {
47 | throw err
48 | }
49 |
50 | server.log('info', 'Server running at: ' + server.info.uri)
51 | })
52 | })
53 |
--------------------------------------------------------------------------------
/hapi-16/restrict-access-with-scopes/base-routes.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Boom = require('boom')
4 | const Bcrypt = require('bcrypt')
5 | const Users = require('./users-db')
6 |
7 | const routes = [
8 | {
9 | method: 'GET',
10 | path: '/',
11 | config: {
12 | auth: {
13 | mode: 'try',
14 | strategy: 'session'
15 | },
16 | plugins: {
17 | 'hapi-auth-cookie': {
18 | redirectTo: false
19 | }
20 | },
21 | handler: function (request, reply) {
22 | if (request.auth.isAuthenticated) {
23 | return reply.view('profile')
24 | }
25 |
26 | reply.view('index')
27 | }
28 | }
29 | },
30 | {
31 | method: 'GET',
32 | path: '/admin',
33 | config: {
34 | auth: {
35 | strategy: 'session',
36 | scope: 'admin'
37 | },
38 | handler: function (request, reply) {
39 | reply.view('admin')
40 | }
41 | }
42 | },
43 | {
44 | method: 'POST',
45 | path: '/',
46 | config: {
47 | // auth: 'session',
48 | auth: {
49 | mode: 'try'
50 | },
51 | plugins: {
52 | 'hapi-auth-cookie': {
53 | redirectTo: false
54 | }
55 | },
56 | handler: function (request, reply) {
57 | if (request.auth.isAuthenticated) {
58 | return reply.view('Profile')
59 | }
60 |
61 | const username = request.payload.username
62 | let user = Users[ username ]
63 |
64 | if (!user) {
65 | return reply(Boom.notFound('No user registered with given credentials'))
66 | }
67 |
68 | const password = request.payload.password
69 |
70 | return Bcrypt.compare(password, user.password, function (err, isValid) {
71 | if (isValid) {
72 | request.server.log('info', 'user authentication successful')
73 | request.cookieAuth.set(user)
74 | return reply.view('profile')
75 | }
76 |
77 | return reply.view('index')
78 | })
79 | }
80 | }
81 | },
82 | {
83 | method: 'GET',
84 | path: '/logout',
85 | config: {
86 | auth: 'session',
87 | handler: function (request, reply) {
88 | request.cookieAuth.clear()
89 | reply.view('index')
90 | }
91 | }
92 | }
93 | ]
94 |
95 | module.exports = routes
--------------------------------------------------------------------------------
/hapi-16/restrict-access-with-scopes/server.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hapi = require('hapi')
4 | const Good = require('good')
5 | const Vision = require('vision')
6 | const Users = require('./users-db')
7 | const Handlebars = require('handlebars')
8 | const CookieAuth = require('hapi-auth-cookie')
9 |
10 | // create new server instance
11 | const server = new Hapi.Server()
12 |
13 | // add server’s connection information
14 | server.connection({
15 | host: 'localhost',
16 | port: 3000
17 | })
18 |
19 | // register plugins to server instance
20 | server.register([
21 | {
22 | register: Vision
23 | },
24 | {
25 | register: Good,
26 | options: {
27 | ops: {
28 | interval: 10000
29 | },
30 | reporters: {
31 | console: [
32 | {
33 | module: 'good-squeeze',
34 | name: 'Squeeze',
35 | args: [ { log: '*', response: '*', request: '*' } ]
36 | },
37 | {
38 | module: 'good-console'
39 | },
40 | 'stdout'
41 | ]
42 | }
43 | }
44 | },
45 | {
46 | register: CookieAuth
47 | }
48 | ], function (err) {
49 | if (err) {
50 | server.log('error', 'failed to install plugins')
51 |
52 | throw err
53 | }
54 |
55 | server.log('info', 'Plugins registered')
56 |
57 | /**
58 | * view configuration
59 | */
60 | server.views({
61 | engines: {
62 | html: Handlebars
63 | },
64 | path: __dirname + '/views',
65 | layout: true
66 | })
67 | server.log('info', 'View configuration completed')
68 |
69 | // validation function used for hapi-auth-cookie: optional and checks if the user is still existing
70 | const validation = function (request, session, callback) {
71 | const username = session.username
72 | let user = Users[ username ]
73 |
74 | if (!user) {
75 | return callback(null, false)
76 | }
77 |
78 | server.log('info', 'user authenticated')
79 | callback(err, true, user)
80 | }
81 |
82 | server.auth.strategy('session', 'cookie', true, {
83 | password: 'm!*"2/),p4:xDs%KEgVr7;e#85Ah^WYC',
84 | cookie: 'future-studio-hapi-tutorials-cookie-auth-example',
85 | redirectTo: '/',
86 | isSecure: false,
87 | validateFunc: validation
88 | })
89 |
90 | server.log('info', 'Registered auth strategy: cookie auth')
91 |
92 | const routes = require('./base-routes')
93 | server.route(routes)
94 | server.log('info', 'Routes registered')
95 |
96 | // start your server after plugin registration
97 | server.start(function (err) {
98 | if (err) {
99 | server.log('error', 'failed to start server')
100 | server.log('error', err)
101 |
102 | throw err
103 | }
104 |
105 | server.log('info', 'Server running at: ' + server.info.uri)
106 | })
107 | })
108 |
--------------------------------------------------------------------------------
/hapi-16/restrict-access-with-scopes/users-db.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | // hardcoded users object … just for illustration purposes
4 | const users = {
5 | future: {
6 | username: 'future',
7 | password: '$2a$04$YPy8WdAtWswed8b9MfKixebJkVUhEZxQCrExQaxzhcdR2xMmpSJiG', // 'studio'
8 | name: 'Future Studio',
9 | scope: [ 'user' ],
10 | id: '1'
11 | },
12 | admin: {
13 | username: 'admin',
14 | password: '$2a$04$YPy8WdAtWswed8b9MfKixebJkVUhEZxQCrExQaxzhcdR2xMmpSJiG', // 'studio'
15 | name: 'Future Studio Admin',
16 | scope: [ 'admin', 'user' ],
17 | id: '2'
18 | }
19 | }
20 |
21 | module.exports = users
--------------------------------------------------------------------------------
/hapi-16/restrict-access-with-scopes/views/admin.html:
--------------------------------------------------------------------------------
1 |
2 |
Admin Panel
3 |
4 |
5 | This view is only reachable and visible for admins!
6 |
7 |
8 |
9 | logout
10 |
11 |
--------------------------------------------------------------------------------
/hapi-16/restrict-access-with-scopes/views/index.html:
--------------------------------------------------------------------------------
1 |
2 |
Hapi Cookie Authentication
3 |
4 | Use the following credentials to log in.
5 |
6 |
7 | Username: future
8 | Password: studio
9 |
10 |
11 |
20 |
--------------------------------------------------------------------------------
/hapi-16/restrict-access-with-scopes/views/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hapi — Basic Authentication
5 |
6 |
7 |
8 | {{{ content }}}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/hapi-16/restrict-access-with-scopes/views/profile.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/hapi-16/routing/base-route.js:
--------------------------------------------------------------------------------
1 | var baseRoutes = {
2 | register: function (server, options, next) {
3 | var routes = [
4 | // optional parameter
5 | {
6 | method: 'GET',
7 | path: '/{identifier?}',
8 | handler: function (request, reply) {
9 | reply('Hello Future Studio! You requested data for ' + encodeURIComponent(request.params.identifier))
10 | }
11 | },
12 | // add exemplary POST route
13 | {
14 | method: [ 'POST', 'PUT' ],
15 | path: '/',
16 | handler: function (request, reply) {
17 | reply('Hey Bro, awesome to see you around!')
18 | }
19 | },
20 | {
21 | method: 'GET',
22 | path: '/page/{page*}',
23 | handler: function (request, reply) {
24 | var page = request.params.page || 1
25 | reply('Greetings from page: ' + encodeURIComponent(page))
26 | }
27 | }
28 | ]
29 |
30 | // add defined routes to hapi
31 | server.route(routes)
32 | next()
33 | }
34 | }
35 |
36 | baseRoutes.register.attributes = {
37 | name: 'base-routes',
38 | version: '1.0.0'
39 | }
40 |
41 | module.exports = baseRoutes
--------------------------------------------------------------------------------
/hapi-16/routing/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 |
4 | // create new server instance
5 | var server = new Hapi.Server()
6 |
7 | // add server’s connection information
8 | server.connection({
9 | host: 'localhost',
10 | port: 3000
11 | })
12 |
13 | // register plugins to server instance
14 | server.register([
15 | {
16 | register: require('./base-route')
17 | },
18 | {
19 | register: Good,
20 | options: {
21 | ops: {
22 | interval: 10000
23 | },
24 | reporters: {
25 | console: [
26 | {
27 | module: 'good-squeeze',
28 | name: 'Squeeze',
29 | args: [ { log: '*', response: '*', request: '*' } ]
30 | },
31 | {
32 | module: 'good-console'
33 | },
34 | 'stdout'
35 | ]
36 | }
37 | }
38 | }
39 | ], function (err) {
40 | // start your server after plugin registration
41 | server.start(function (err) {
42 | if (err) {
43 | throw err
44 | }
45 |
46 | server.log('info', 'Server running at: ' + server.info.uri)
47 | })
48 | })
49 |
--------------------------------------------------------------------------------
/hapi-16/serve-static-files/base-route.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const baseRoutes = {
4 | register: function (server, options, next) {
5 | const routes = [
6 | {
7 | method: 'GET',
8 | path: '/directory/{file}',
9 | handler: {
10 | directory: {
11 | path: './files'
12 | }
13 | }
14 | },
15 | {
16 | method: 'GET',
17 | path: '/sub-directory/{file*}',
18 | handler: {
19 | directory: {
20 | path: './files'
21 | }
22 | }
23 | },
24 | {
25 | method: 'GET',
26 | path: '/file/{file*}',
27 | handler: function (request, reply) {
28 | const file = request.params.file
29 |
30 | console.log(file)
31 |
32 | reply.file('files/' + file)
33 | }
34 | }
35 | ]
36 |
37 | // add defined routes to hapi
38 | server.route(routes)
39 | next()
40 | }
41 | }
42 |
43 | baseRoutes.register.attributes = {
44 | name: 'serve-static-files',
45 | version: '1.0.0'
46 | }
47 |
48 | module.exports = baseRoutes
49 |
--------------------------------------------------------------------------------
/hapi-16/serve-static-files/files/js/test.js:
--------------------------------------------------------------------------------
1 | console.log('This log is from the test.js file')
--------------------------------------------------------------------------------
/hapi-16/serve-static-files/files/main.js:
--------------------------------------------------------------------------------
1 | 'Hello'
--------------------------------------------------------------------------------
/hapi-16/serve-static-files/server.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hapi = require('hapi')
4 | const Good = require('good')
5 | const Inert = require('inert')
6 |
7 | // create new server instance
8 | const server = new Hapi.Server()
9 |
10 | // add server’s connection information
11 | server.connection({
12 | host: 'localhost',
13 | port: 3000
14 | })
15 |
16 | // register plugins to server instance
17 | server.register([
18 | {
19 | register: Inert
20 | },
21 | {
22 | register: require('./base-route')
23 | },
24 | {
25 | register: Good,
26 | options: {
27 | ops: {
28 | interval: 10000
29 | },
30 | reporters: {
31 | console: [
32 | {
33 | module: 'good-squeeze',
34 | name: 'Squeeze',
35 | args: [ { log: '*', response: '*', request: '*' } ]
36 | },
37 | {
38 | module: 'good-console'
39 | },
40 | 'stdout'
41 | ]
42 | }
43 | }
44 | }
45 | ], function (err) {
46 | // start your server after plugin registration
47 | server.start(function (err) {
48 | if (err) {
49 | throw err
50 | }
51 |
52 | server.log('info', 'Server running at: ' + server.info.uri)
53 | })
54 | })
55 |
--------------------------------------------------------------------------------
/hapi-16/show-error-stacktrace-in-browser/base/handler.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Handler = {
4 | index: {
5 | handler: function (request, reply) {
6 | reply.view('index').test()
7 | }
8 | },
9 |
10 | missing: {
11 | handler: function (request, reply) {
12 | reply.view('404').code(404)
13 | }
14 | }
15 | }
16 |
17 | module.exports = Handler
18 |
--------------------------------------------------------------------------------
/hapi-16/show-error-stacktrace-in-browser/base/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Routes = require('./routes')
4 |
5 | exports.register = (server, options, next) => {
6 | server.dependency([ 'vision' ])
7 |
8 | server.route(Routes)
9 | server.log('info', 'Plugin registered: 404 handler')
10 |
11 | next()
12 | }
13 |
14 | exports.register.attributes = {
15 | name: '404-handler',
16 | version: '1.0.0'
17 | }
18 |
--------------------------------------------------------------------------------
/hapi-16/show-error-stacktrace-in-browser/base/routes.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Handler = require('./handler')
4 |
5 | const Routes = [
6 | {
7 | method: 'GET',
8 | path: '/',
9 | config: Handler.index
10 | },
11 | {
12 | method: 'GET',
13 | path: '/{path*}',
14 | config: Handler.missing
15 | }
16 | ]
17 |
18 | module.exports = Routes
19 |
--------------------------------------------------------------------------------
/hapi-16/show-error-stacktrace-in-browser/server.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hapi = require('hapi')
4 |
5 | // create new server instance
6 | const server = new Hapi.Server()
7 |
8 | // add server’s connection information
9 | server.connection({
10 | host: 'localhost',
11 | port: 3000
12 | })
13 |
14 | // register plugins to server instance
15 | server.register([
16 | {
17 | register: require('vision')
18 | },
19 | {
20 | register: require('./base')
21 | },
22 | {
23 | register: require('hapi-dev-errors'),
24 | options: {
25 | //template: 'error',
26 | showErrors: process.env.NODE_ENV !== 'production'
27 | }
28 | }
29 | ], err => {
30 | if (err) {
31 | throw err
32 | }
33 |
34 | server.views({
35 | engines: {
36 | html: require('handlebars')
37 | },
38 | path: __dirname + '/views',
39 | layout: 'layout'
40 | })
41 |
42 | // start your server
43 | server.start(err => {
44 |
45 | if (err) {
46 | throw err
47 | }
48 |
49 | console.log('Server running at: ' + server.info.uri)
50 | })
51 | })
52 |
--------------------------------------------------------------------------------
/hapi-16/show-error-stacktrace-in-browser/show-error-stacktrace/error.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | %title% (%statusCode%)
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
%title% (%statusCode%)
18 |
%message%
19 |
20 |
21 | %stacktrace%
22 |
23 |
24 |
25 | Called URL
26 |
27 |
28 | %method% %url%
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/hapi-16/show-error-stacktrace-in-browser/show-error-stacktrace/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Fs = require('fs')
4 | const Path = require('path')
5 | const TemplatePath = Path.join(__dirname, './error.html')
6 |
7 | exports.register = (server, options, next) => {
8 |
9 | // default option values
10 | const defaults = {
11 | showErrors: false
12 | }
13 |
14 | const config = Object.assign(defaults, options)
15 |
16 | // want to render specific template? Better make sure `vision` is available :)
17 | if (config.template) {
18 | server.dependency([ 'vision' ])
19 | }
20 |
21 | // read and keep the default error template
22 | const errorTemplate = Fs.readFileSync(TemplatePath, 'utf8')
23 |
24 | // extend the request lifecycle at `onPreResponse`
25 | // to change the default error handling behavior (if enabled)
26 | server.ext('onPreResponse', (request, reply) => {
27 | if (!config.showErrors) {
28 | return reply.continue()
29 | }
30 |
31 | // response shortcut
32 | const response = request.response
33 |
34 | // only show "bad implementation" developer errors, status code 500
35 | if (response.isDeveloperError) {
36 | const accept = request.raw.req.headers.accept
37 | const statusCode = response.output.payload.statusCode
38 |
39 | const errorResponse = {
40 | title: response.output.payload.error,
41 | statusCode: statusCode,
42 | message: response.message,
43 | method: request.raw.req.method,
44 | url: request.url.path,
45 | payload: request.raw.req.method !== 'GET' ? request.payload : '',
46 | stacktrace: response.stack
47 | }
48 |
49 | // take priority: check header if there's a JSON REST request
50 | if (accept && accept.match(/json/)) {
51 | return reply(errorResponse).code(statusCode)
52 | }
53 |
54 | // did the user explicitly specify an error template
55 | if (options.template) {
56 | return reply.view(options.template, errorResponse).code(statusCode)
57 | }
58 |
59 | // prepare the error template and replace %placeholder% with error specific details
60 | const output = errorTemplate.replace(/%(\w+)%/g, (full, token) => {
61 | return errorResponse[ token ] || ''
62 | })
63 |
64 | return reply(output).code(statusCode)
65 | }
66 |
67 | // go ahead with the response, no developer error detected
68 | return reply.continue()
69 | })
70 |
71 | // server.log('info', 'Plugin registered: show error stacktrace')
72 |
73 | next()
74 | }
75 |
76 | exports.register.attributes = {
77 | name: 'show-error-stacktrace',
78 | version: '1.0.0'
79 | }
80 |
--------------------------------------------------------------------------------
/hapi-16/show-error-stacktrace-in-browser/views/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
404!
5 |
6 | Sorry buddy, this resouce isn’t available.
7 |
8 |
9 |
10 | Back home
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/hapi-16/show-error-stacktrace-in-browser/views/error.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{title}} ({{statusCode}})
5 |
6 | Called URL
7 |
8 |
9 | {{method}} {{url}}
10 |
11 |
12 |
13 |
14 | Error Details
15 |
16 | {{message}}
17 |
18 |
19 | {{#if stacktrace}}
20 |
21 |
22 | {{~ stacktrace ~}}
23 |
24 |
25 | {{/if}}
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/hapi-16/show-error-stacktrace-in-browser/views/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Hello!
5 |
6 |
7 | Go anywhere, you’ll see the 404 :)
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/hapi-16/show-error-stacktrace-in-browser/views/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Better hapi errors in dev
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{{ content }}}
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/hapi-16/testing-inject-requests/.eslintignore:
--------------------------------------------------------------------------------
1 | package.json
--------------------------------------------------------------------------------
/hapi-16/testing-inject-requests/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: 'standard'
3 | }
4 |
--------------------------------------------------------------------------------
/hapi-16/testing-inject-requests/base/handler.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Handler = {
4 | index: {
5 | handler: (request, reply) => {
6 | reply({ name: 'Marcus', isDeveloper: true })
7 | }
8 | },
9 |
10 | injectData: {
11 | handler: (request, reply) => {
12 | const data = Object.assign({}, request.params, request.query, request.payload, request.headers)
13 |
14 | // if you’re with Node.js v8.6 or later, the spread operator is for you :)
15 | // const data = { ...request.params, ...request.query, ...request.payload, ...request.headers }
16 |
17 | reply(data)
18 | }
19 | }
20 | }
21 |
22 | module.exports = Handler
23 |
--------------------------------------------------------------------------------
/hapi-16/testing-inject-requests/base/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Routes = require('./routes')
4 |
5 | exports.register = (server, options, next) => {
6 | server.route(Routes)
7 | server.log('info', 'Plugin registered: test hapi handles by injecting requests')
8 |
9 | next()
10 | }
11 |
12 | exports.register.attributes = {
13 | name: 'hapi-testing-1',
14 | version: '1.0.0'
15 | }
16 |
--------------------------------------------------------------------------------
/hapi-16/testing-inject-requests/base/routes.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Handler = require('./handler')
4 |
5 | const Routes = [
6 | {
7 | method: 'GET',
8 | path: '/',
9 | config: Handler.index
10 | },
11 |
12 | {
13 | method: 'POST',
14 | path: '/inject-data/{page}',
15 | config: Handler.injectData
16 | }
17 | ]
18 |
19 | module.exports = Routes
20 |
--------------------------------------------------------------------------------
/hapi-16/testing-inject-requests/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nodejs-tutorials-hapi-testing",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "test": "./../../node_modules/lab/bin/lab --assert code --leaks --coverage",
6 | "test-lint": "./../../node_modules/lab/bin/lab --assert code --leaks --coverage --lint",
7 | "test-lint-format":
8 | "./../../node_modules/eslint/bin/eslint.js --fix ./* && ./../../node_modules/lab/bin/lab --assert code --leaks --coverage --lint"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/hapi-16/testing-inject-requests/server.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hapi = require('hapi')
4 |
5 | // create new server instance
6 | const server = new Hapi.Server()
7 |
8 | // add server’s connection information
9 | server.connection({
10 | host: 'localhost',
11 | port: 3000
12 | })
13 |
14 | // register plugins to server instance
15 | server.register([
16 | {
17 | register: require('vision')
18 | },
19 | {
20 | register: require('./base')
21 | }
22 | ]).then(() => {
23 | // start your server
24 | server.start(function (err) {
25 | if (err) {
26 | throw err
27 | }
28 |
29 | console.log('Server running at: ' + server.info.uri)
30 | })
31 | }).catch(err => {
32 | throw err
33 | })
34 |
--------------------------------------------------------------------------------
/hapi-16/testing-inject-requests/test/before-and-after-test-actions.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Lab = require('lab')
4 | const Hapi = require('hapi')
5 | const Path = require('path')
6 |
7 | let server
8 |
9 | const lab = (exports.lab = Lab.script())
10 | const experiment = lab.experiment
11 | const test = lab.test
12 |
13 | experiment('hapi-tutorials run actions before and after tests', () => {
14 | // use lab.before if you need to execute code before the tests are executed
15 | // this is beneficial for asynchronous operations and initializations
16 | lab.before(done => {
17 | // run before test
18 | done()
19 | })
20 |
21 | // with lab.beforeEach you can run code that is executed before every single test
22 | // like with lab.before, this is helpful for async operations
23 | lab.beforeEach(done => {
24 | // run before every single test
25 | server = new Hapi.Server()
26 | server.connection({ port: 3000 })
27 | server
28 | .register({
29 | register: require(Path.resolve(__dirname, '..', 'base'))
30 | })
31 | .then(() => {
32 | done()
33 | })
34 | .catch(err => {
35 | done(err)
36 | })
37 | })
38 |
39 | // please have a look at the comments on lab.before and lab.beforeEach ;-)
40 | lab.after(done => {
41 | done()
42 | })
43 |
44 | // please have a look at the comments on lab.before and lab.beforeEach ;-)
45 | lab.afterEach(done => {
46 | // run after every single test
47 | done()
48 | })
49 |
50 | test('resolves already', done => {
51 | done()
52 | })
53 | })
54 |
--------------------------------------------------------------------------------
/hapi-16/testing-inject-requests/test/inject-payload-headers-params.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Lab = require('lab')
4 | const Code = require('code')
5 | const Hapi = require('hapi')
6 | const Path = require('path')
7 | const Qs = require('querystring')
8 |
9 | const server = new Hapi.Server()
10 | server.connection({ port: 3000 })
11 | server
12 | .register({
13 | register: require(Path.resolve(__dirname, '..', 'base'))
14 | })
15 | .catch(err => {
16 | throw err
17 | })
18 |
19 | const lab = (exports.lab = Lab.script())
20 | const experiment = lab.experiment
21 | const test = lab.test
22 |
23 | experiment('hapi-tutorials base plugin', () => {
24 | test('test if the plugin returns JSON by default', done => {
25 | const query = Qs.stringify({ name: 'Marcus' })
26 | const page = 1
27 |
28 | const options = {
29 | url: `/inject-data/${page}?${query}`,
30 | method: 'POST',
31 | payload: {
32 | isGeek: false
33 | },
34 | headers: {
35 | 'X-Testing-Header': 'Testing-123'
36 | }
37 | }
38 |
39 | server.inject(options, response => {
40 | const payload = JSON.parse(response.payload || '{}')
41 |
42 | Code.expect(response.statusCode).to.equal(200)
43 | Code.expect(payload.name).to.equal('Marcus')
44 | Code.expect(payload.isGeek).to.equal(false)
45 | Code.expect(parseInt(payload.page)).to.equal(page)
46 | Code.expect(payload['x-testing-header']).to.equal('Testing-123')
47 |
48 | done()
49 | })
50 | })
51 | })
52 |
--------------------------------------------------------------------------------
/hapi-16/testing-inject-requests/test/plugin-index-responds-with-json.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Lab = require('lab')
4 | const Code = require('code')
5 | const Hapi = require('hapi')
6 |
7 | const server = new Hapi.Server()
8 | server.connection()
9 |
10 | server.route({
11 | method: 'GET',
12 | path: '/',
13 | handler: (request, reply) => {
14 | reply({ name: 'Marcus', isDeveloper: true })
15 | }
16 | })
17 |
18 | const lab = (exports.lab = Lab.script())
19 | const experiment = lab.experiment
20 | const test = lab.test
21 |
22 | experiment('getting started with hapi testing', () => {
23 | test('test if the route returns JSON by default', done => {
24 | const options = {
25 | method: 'GET',
26 | url: '/'
27 | }
28 |
29 | server.inject(options, response => {
30 | const payload = JSON.parse(response.payload || '{}')
31 |
32 | Code.expect(response.statusCode).to.equal(200)
33 | Code.expect(payload.name).to.equal('Marcus')
34 | Code.expect(payload.isDeveloper).to.equal(true)
35 |
36 | done()
37 | })
38 | })
39 | })
40 |
--------------------------------------------------------------------------------
/hapi-16/upload-files/base-route.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const plugin = {
4 | register: function (server, options, next) {
5 | const routes = [
6 | {
7 | method: 'GET',
8 | path: '/',
9 | config: {
10 | handler: function (request, reply) {
11 | reply('Send a file in POST with name "file" to /upload')
12 | }
13 | }
14 | },
15 | {
16 | method: 'POST',
17 | path: '/upload',
18 | config: {
19 | handler: function (request, reply) {
20 | const payload = request.payload
21 |
22 | console.log(payload)
23 |
24 | reply(request.headers)
25 | },
26 | payload: {
27 | maxBytes: 209715200,
28 | output: 'file'
29 | }
30 | }
31 | },
32 | {
33 | method: 'POST',
34 | path: '/upload-stream',
35 | config: {
36 | handler: function (request, reply) {
37 | const payload = request.payload
38 |
39 | console.log(payload)
40 |
41 | reply(request.headers)
42 | },
43 | payload: {
44 | output: 'stream'
45 | }
46 | }
47 | },
48 | {
49 | method: 'POST',
50 | path: '/upload-data',
51 | config: {
52 | handler: function (request, reply) {
53 | const payload = request.payload
54 |
55 | console.log(payload)
56 |
57 | reply(request.headers)
58 | },
59 | payload: {
60 | output: 'data'
61 | }
62 | }
63 | }
64 | ]
65 |
66 | // add defined routes to hapi
67 | server.route(routes)
68 |
69 | next()
70 | }
71 | }
72 |
73 | plugin.register.attributes = {
74 | name: 'upload-files',
75 | version: '1.0.0'
76 | }
77 |
78 | module.exports = plugin
--------------------------------------------------------------------------------
/hapi-16/upload-files/server.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hapi = require('hapi')
4 | const Good = require('good')
5 |
6 | // create new server instance
7 | const server = new Hapi.Server()
8 |
9 | // add server’s connection information
10 | server.connection({
11 | host: 'localhost',
12 | port: 3000
13 | })
14 |
15 | // register plugins to server instance
16 | server.register([
17 | {
18 | register: require('./base-route')
19 | },
20 | {
21 | register: Good,
22 | options: {
23 | ops: {
24 | interval: 10000
25 | },
26 | reporters: {
27 | console: [
28 | {
29 | module: 'good-squeeze',
30 | name: 'Squeeze',
31 | args: [ { log: '*', response: '*', request: '*' } ]
32 | },
33 | {
34 | module: 'good-console'
35 | },
36 | 'stdout'
37 | ]
38 | }
39 | }
40 | }
41 | ], function (err) {
42 | if (err) {
43 | throw err
44 | }
45 |
46 | // start your server after plugin registration
47 | server.start(function (err) {
48 | if (err) {
49 | throw err
50 | }
51 |
52 | server.log('info', 'Server running at: ' + server.info.uri)
53 | })
54 | })
55 |
--------------------------------------------------------------------------------
/hapi-16/validation-parameters-and-payload/base-route.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Joi = require('joi')
4 |
5 | const plugin = {
6 | register: function (server, options, next) {
7 | server.route({
8 | method: 'POST',
9 | path: '/{page}',
10 | config: {
11 | handler: function (request, reply) {
12 | reply('You’ve passed all the validations :)')
13 | },
14 | validate: {
15 | params: {
16 | page: Joi.number().required()
17 | },
18 | query: {
19 | test: Joi.number().optional()
20 | },
21 | payload: {
22 | username: Joi.string().required()
23 | },
24 | headers: {
25 | 'user-agent': Joi.string()
26 | },
27 | options: {
28 | allowUnknown: true
29 | }
30 | }
31 | }
32 | })
33 |
34 | next()
35 | }
36 | }
37 |
38 | plugin.register.attributes = {
39 | name: 'validate-all-parameters-payload-headers',
40 | version: '1.0.0'
41 | }
42 |
43 | module.exports = plugin
--------------------------------------------------------------------------------
/hapi-16/validation-parameters-and-payload/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 |
4 | // create new server instance
5 | var server = new Hapi.Server()
6 |
7 | // add server’s connection information
8 | server.connection({
9 | host: 'localhost',
10 | port: 3000
11 | })
12 |
13 | // register plugins to server instance
14 | server.register([
15 | {
16 | register: Good,
17 | options: {
18 | ops: {
19 | interval: 10000
20 | },
21 | reporters: {
22 | console: [
23 | {
24 | module: 'good-squeeze',
25 | name: 'Squeeze',
26 | args: [ { log: '*', response: '*', request: '*' } ]
27 | },
28 | {
29 | module: 'good-console'
30 | },
31 | 'stdout'
32 | ]
33 | }
34 | }
35 | },
36 | {
37 | register: require('./base-route')
38 | }
39 | ], function (err) {
40 | if (err) {
41 | throw err
42 | }
43 |
44 | // start your server after plugin registration
45 | server.start(function (err) {
46 | if (err) {
47 | throw err
48 | }
49 |
50 | server.log('info', 'Server running at: ' + server.info.uri)
51 | })
52 | })
53 |
--------------------------------------------------------------------------------
/hapi-16/validation-path-parameter/base-route.js:
--------------------------------------------------------------------------------
1 | var Joi = require('joi')
2 |
3 | var plugin = {
4 | register: function (server, options, next) {
5 | var routes = [
6 | {
7 | method: 'GET',
8 | path: '/tutorials/page/{page}',
9 | config: {
10 | handler: function (request, reply) {
11 | var pathParams = request.params
12 |
13 | server.log('info', pathParams)
14 |
15 | reply(pathParams)
16 | },
17 | validate: {
18 | params: {
19 | page: Joi.number().min(1)
20 | }
21 | }
22 | }
23 | }
24 | ]
25 |
26 | // add defined routes to hapi
27 | server.route(routes)
28 |
29 | next()
30 | }
31 | }
32 |
33 | plugin.register.attributes = {
34 | name: 'validate-path-parameters',
35 | version: '1.0.0'
36 | }
37 |
38 | module.exports = plugin
--------------------------------------------------------------------------------
/hapi-16/validation-path-parameter/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 |
4 | // create new server instance
5 | var server = new Hapi.Server()
6 |
7 | // add server’s connection information
8 | server.connection({
9 | host: 'localhost',
10 | port: 3000
11 | })
12 |
13 | // register plugins to server instance
14 | server.register([
15 | {
16 | register: Good,
17 | options: {
18 | ops: {
19 | interval: 10000
20 | },
21 | reporters: {
22 | console: [
23 | {
24 | module: 'good-squeeze',
25 | name: 'Squeeze',
26 | args: [ { log: '*', response: '*', request: '*' } ]
27 | },
28 | {
29 | module: 'good-console'
30 | },
31 | 'stdout'
32 | ]
33 | }
34 | }
35 | },
36 | {
37 | register: require('./base-route')
38 | }
39 | ], function (err) {
40 | if (err) {
41 | throw err
42 | }
43 |
44 | // start your server after plugin registration
45 | server.start(function (err) {
46 | if (err) {
47 | throw err
48 | }
49 |
50 | server.log('info', 'Server running at: ' + server.info.uri)
51 | })
52 | })
53 |
--------------------------------------------------------------------------------
/hapi-16/validation-payload/base-route.js:
--------------------------------------------------------------------------------
1 | var Joi = require('joi')
2 |
3 | var plugin = {
4 | register: function (server, options, next) {
5 | var routes = [
6 | {
7 | method: 'POST',
8 | path: '/',
9 | config: {
10 | handler: function (request, reply) {
11 | var payload = request.payload
12 |
13 | server.log('info', payload)
14 |
15 | reply(payload)
16 | },
17 | validate: {
18 | payload: {
19 | email: Joi.string().email().required(),
20 | password: Joi.string().min(6).max(200).required()
21 | }
22 | }
23 | }
24 | }
25 | ]
26 |
27 | // add defined routes to hapi
28 | server.route(routes)
29 |
30 | next()
31 | }
32 | }
33 |
34 | plugin.register.attributes = {
35 | name: 'validation-request-payload',
36 | version: '1.0.0'
37 | }
38 |
39 | module.exports = plugin
--------------------------------------------------------------------------------
/hapi-16/validation-payload/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 |
4 | // create new server instance
5 | var server = new Hapi.Server()
6 |
7 | // add server’s connection information
8 | server.connection({
9 | host: 'localhost',
10 | port: 3000
11 | })
12 |
13 | // register plugins to server instance
14 | server.register([
15 | {
16 | register: require('./base-route')
17 | },
18 | {
19 | register: Good,
20 | options: {
21 | ops: {
22 | interval: 10000
23 | },
24 | reporters: {
25 | console: [
26 | {
27 | module: 'good-squeeze',
28 | name: 'Squeeze',
29 | args: [ { log: '*', response: '*', request: '*' } ]
30 | },
31 | {
32 | module: 'good-console'
33 | },
34 | 'stdout'
35 | ]
36 | }
37 | }
38 | }
39 | ], function (err) {
40 | if (err) {
41 | throw err
42 | }
43 |
44 | // start your server after plugin registration
45 | server.start(function (err) {
46 | if (err) {
47 | throw err
48 | }
49 |
50 | server.log('info', 'Server running at: ' + server.info.uri)
51 | })
52 | })
53 |
--------------------------------------------------------------------------------
/hapi-16/validation-query-parameter/base-route.js:
--------------------------------------------------------------------------------
1 | var Joi = require('joi')
2 |
3 | var plugin = {
4 | register: function (server, options, next) {
5 | var routes = [
6 | {
7 | method: 'GET',
8 | path: '/tutorials',
9 | config: {
10 | handler: function (request, reply) {
11 | var queryParams = request.query
12 |
13 | server.log('info', queryParams)
14 |
15 | reply(queryParams)
16 | },
17 | validate: {
18 | query: {
19 | filter: Joi.array().items(Joi.string().valid('premium', 'video')).single(),
20 | page: Joi.number().min(1)
21 | }
22 | }
23 | }
24 | }
25 | ]
26 |
27 | // add defined routes to hapi
28 | server.route(routes)
29 |
30 | next()
31 | }
32 | }
33 |
34 | plugin.register.attributes = {
35 | name: 'validate-query-parameters',
36 | version: '1.0.0'
37 | }
38 |
39 | module.exports = plugin
--------------------------------------------------------------------------------
/hapi-16/validation-query-parameter/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 |
4 | // create new server instance
5 | var server = new Hapi.Server()
6 |
7 | // add server’s connection information
8 | server.connection({
9 | host: 'localhost',
10 | port: 3000
11 | })
12 |
13 | // register plugins to server instance
14 | server.register([
15 | {
16 | register: Good,
17 | options: {
18 | ops: {
19 | interval: 10000
20 | },
21 | reporters: {
22 | console: [
23 | {
24 | module: 'good-squeeze',
25 | name: 'Squeeze',
26 | args: [ { log: '*', response: '*', request: '*' } ]
27 | },
28 | {
29 | module: 'good-console'
30 | },
31 | 'stdout'
32 | ]
33 | }
34 | }
35 | },
36 | {
37 | register: require('./base-route')
38 | }
39 | ], function (err) {
40 | if (err) {
41 | throw err
42 | }
43 |
44 | // start your server after plugin registration
45 | server.start(function (err) {
46 | if (err) {
47 | throw err
48 | }
49 |
50 | server.log('info', 'Server running at: ' + server.info.uri)
51 | })
52 | })
53 |
--------------------------------------------------------------------------------
/hapi-16/validation-request-headers/base-route.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Joi = require('joi')
4 |
5 | const plugin = {
6 | register: function (server, options, next) {
7 | server.route({
8 | method: 'GET',
9 | path: '/',
10 | config: {
11 | handler: function (request, reply) {
12 | const headers = request.headers
13 |
14 | server.log('info', headers)
15 |
16 | reply(headers)
17 | },
18 | validate: {
19 | headers: {
20 | 'user-agent': Joi.string().required(),
21 | username: Joi.string().required()
22 | },
23 | options: {
24 | allowUnknown: true
25 | }
26 | }
27 | }
28 | })
29 |
30 | next()
31 | }
32 | }
33 |
34 | plugin.register.attributes = {
35 | name: 'validation-return-all-errors',
36 | version: '1.0.0'
37 | }
38 |
39 | module.exports = plugin
40 |
--------------------------------------------------------------------------------
/hapi-16/validation-request-headers/server.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hapi = require('hapi')
4 | const Good = require('good')
5 |
6 | // create new server instance
7 | const server = new Hapi.Server()
8 |
9 | // add server’s connection information
10 | server.connection({
11 | host: 'localhost',
12 | port: 3000
13 | })
14 |
15 | // register plugins to server instance
16 | server.register([
17 | {
18 | register: require('./base-route')
19 | },
20 | {
21 | register: Good,
22 | options: {
23 | ops: {
24 | interval: 10000
25 | },
26 | reporters: {
27 | console: [
28 | {
29 | module: 'good-squeeze',
30 | name: 'Squeeze',
31 | args: [ { log: '*', response: '*', request: '*' } ]
32 | },
33 | {
34 | module: 'good-console'
35 | },
36 | 'stdout'
37 | ]
38 | }
39 | }
40 | }
41 | ], function (err) {
42 | if (err) {
43 | throw err
44 | }
45 |
46 | // start your server after plugin registration
47 | server.start(function (err) {
48 | if (err) {
49 | throw err
50 | }
51 |
52 | server.log('info', 'Server running at: ' + server.info.uri)
53 | })
54 | })
55 |
--------------------------------------------------------------------------------
/hapi-16/validation-return-all-errors/base-route.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Joi = require('joi')
4 |
5 | const plugin = {
6 | register: function (server, options, next) {
7 | server.route({
8 | method: 'POST',
9 | path: '/',
10 | config: {
11 | handler: function (request, reply) {
12 | reply('You’ve passed all the validations :)')
13 | },
14 | validate: {
15 | payload: {
16 | username: Joi.string().required(),
17 | password: Joi.string().min(6).required(),
18 | email: Joi.string().email().required()
19 | },
20 | options: {
21 | abortEarly: false
22 | }
23 | }
24 | }
25 | })
26 |
27 | next()
28 | }
29 | }
30 |
31 | plugin.register.attributes = {
32 | name: 'validation-request-headers',
33 | version: '1.0.0'
34 | }
35 |
36 | module.exports = plugin
37 |
--------------------------------------------------------------------------------
/hapi-16/validation-return-all-errors/server.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hapi = require('hapi')
4 | const Good = require('good')
5 |
6 | // create new server instance
7 | const server = new Hapi.Server()
8 |
9 | // add server’s connection information
10 | server.connection({
11 | host: 'localhost',
12 | port: 3000
13 | })
14 |
15 | // register plugins to server instance
16 | server.register([
17 | {
18 | register: require('./base-route')
19 | },
20 | {
21 | register: Good,
22 | options: {
23 | ops: {
24 | interval: 10000
25 | },
26 | reporters: {
27 | console: [
28 | {
29 | module: 'good-squeeze',
30 | name: 'Squeeze',
31 | args: [ { log: '*', response: '*', request: '*' } ]
32 | },
33 | {
34 | module: 'good-console'
35 | },
36 | 'stdout'
37 | ]
38 | }
39 | }
40 | }
41 | ], function (err) {
42 | if (err) {
43 | throw err
44 | }
45 |
46 | // start your server after plugin registration
47 | server.start(function (err) {
48 | if (err) {
49 | throw err
50 | }
51 |
52 | server.log('info', 'Server running at: ' + server.info.uri)
53 | })
54 | })
55 |
--------------------------------------------------------------------------------
/hapi-16/vuejs-and-handlebars/index/handler.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Handler = {
4 | index: {
5 | handler: function (request, reply) {
6 | reply.view('index')
7 | }
8 | }
9 | }
10 |
11 | module.exports = Handler
12 |
--------------------------------------------------------------------------------
/hapi-16/vuejs-and-handlebars/index/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Routes = require('./routes')
4 |
5 | exports.register = (server, options, next) => {
6 | server.dependency([ 'vision' ])
7 |
8 | server.route(Routes)
9 | server.log('info', 'Plugin registered: use Vue.js with Handlebars in hapi')
10 |
11 | next()
12 | }
13 |
14 | exports.register.attributes = {
15 | name: 'vue-and-handlebars',
16 | version: '1.0.0'
17 | }
18 |
--------------------------------------------------------------------------------
/hapi-16/vuejs-and-handlebars/index/routes.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Handler = require('./handler')
4 |
5 | const Routes = [
6 | {
7 | method: 'GET',
8 | path: '/',
9 | config: Handler.index
10 | }
11 | ]
12 |
13 | module.exports = Routes
14 |
--------------------------------------------------------------------------------
/hapi-16/vuejs-and-handlebars/server.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hapi = require('hapi')
4 |
5 | // create new server instance
6 | const server = new Hapi.Server()
7 |
8 | // add server’s connection information
9 | server.connection({
10 | host: 'localhost',
11 | port: 3000
12 | })
13 |
14 | // register plugins to server instance
15 | server.register([
16 | {
17 | register: require('vision')
18 | },
19 | {
20 | register: require('./index')
21 | }
22 | ], function (err) {
23 | if (err) {
24 | throw err
25 | }
26 |
27 | server.views({
28 | engines: {
29 | html: require('handlebars')
30 | },
31 | path: __dirname + '/views',
32 | layout: 'layout'
33 | })
34 |
35 | // start your server
36 | server.start(function (err) {
37 |
38 | if (err) {
39 | throw err
40 | }
41 |
42 | console.log('Server running at: ' + server.info.uri)
43 | })
44 | })
45 |
--------------------------------------------------------------------------------
/hapi-16/vuejs-and-handlebars/views/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Use Vue.js and Handlebars in hapi
5 |
6 | Both, Vue.js and Handlebars use Mustache \{{ tag }}
templates
7 | to render properties into views. This tutorial shows you how to bring
8 | both worlds together:
9 | server side Handlebars and client side Vue.js rendering.
10 |
11 |
17 |
18 | Name is: \{{ name }}
19 |
20 |
21 |
22 |
23 |
24 |
33 |
--------------------------------------------------------------------------------
/hapi-16/vuejs-and-handlebars/views/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Vue.js and Handlebars in hapi
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{{ content }}}
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/hapi-16/wildcard-path-params/base-route.js:
--------------------------------------------------------------------------------
1 | var plugin = {
2 | register: function (server, options, next) {
3 | var routes = [
4 | {
5 | method: 'GET',
6 | path: '/js/{file*}',
7 | handler: function (request, reply) {
8 | // this route matches everything except the restrictive route definition below
9 | var params = request.params
10 |
11 | server.log('info', params)
12 |
13 | reply(params)
14 | }
15 | },
16 | {
17 | method: 'GET',
18 | path: '/filter/{type*2}',
19 | handler: function (request, reply) {
20 | // this route matches only if 2 path segments are provided after "filter"
21 | var params = request.params
22 |
23 | server.log('info', params)
24 |
25 | reply(params)
26 | }
27 | }
28 | ]
29 |
30 | // add defined routes to hapi
31 | server.route(routes)
32 |
33 | next()
34 | }
35 | }
36 |
37 | plugin.register.attributes = {
38 | name: 'wildcard-path-params',
39 | version: '1.0.0'
40 | }
41 |
42 | module.exports = plugin
--------------------------------------------------------------------------------
/hapi-16/wildcard-path-params/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 | var Good = require('good')
3 |
4 | // create new server instance
5 | var server = new Hapi.Server()
6 |
7 | // add server’s connection information
8 | server.connection({
9 | host: 'localhost',
10 | port: 3000
11 | })
12 |
13 | // register plugins to server instance
14 | server.register([
15 | {
16 | register: require('./base-route')
17 | },
18 | {
19 | register: Good,
20 | options: {
21 | ops: {
22 | interval: 10000
23 | },
24 | reporters: {
25 | console: [
26 | {
27 | module: 'good-squeeze',
28 | name: 'Squeeze',
29 | args: [ { log: '*', response: '*', request: '*' } ]
30 | },
31 | {
32 | module: 'good-console'
33 | },
34 | 'stdout'
35 | ]
36 | }
37 | }
38 | }
39 | ], function (err) {
40 | if (err) {
41 | throw err
42 | }
43 |
44 | // start your server after plugin registration
45 | server.start(function (err) {
46 | if (err) {
47 | throw err
48 | }
49 |
50 | server.log('info', 'Server running at: ' + server.info.uri)
51 | })
52 | })
53 |
--------------------------------------------------------------------------------
/hapi-16/write-your-own-plugin/base-route.js:
--------------------------------------------------------------------------------
1 | var baseRoutes = {
2 | register: function (server, options, next) {
3 | // add “hello world” route
4 | server.route({
5 | method: 'GET',
6 | path: '/',
7 | handler: function (request, reply) {
8 | reply('Hello Future Studio!')
9 | }
10 | })
11 |
12 | next()
13 | }
14 | }
15 |
16 | baseRoutes.register.attributes = {
17 | name: 'base-routes',
18 | version: '1.0.0'
19 | }
20 |
21 | module.exports = baseRoutes
--------------------------------------------------------------------------------
/hapi-16/write-your-own-plugin/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi')
2 |
3 | // create new server instance
4 | var server = new Hapi.Server()
5 |
6 | // add server’s connection information
7 | server.connection({
8 | host: 'localhost',
9 | port: 3000
10 | })
11 |
12 | // register plugins to server instance
13 | server.register({
14 | register: require('./base-route')
15 | })
16 |
17 | // start your server
18 | server.start(function (err) {
19 | if (err) {
20 | throw err
21 | }
22 |
23 | console.log('Server running at: ' + server.info.uri)
24 | })
25 |
--------------------------------------------------------------------------------
/hapi-18/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "es6": true,
4 | "node": true
5 | },
6 | "extends": [
7 | "standard"
8 | ],
9 | "plugins": [
10 | "standard"
11 | ],
12 | "parserOptions": {
13 | "ecmaVersion": 2018
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/hapi-18/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hapi-18",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "MIT",
12 | "dependencies": {
13 | "@hapi/hapi": "~18.3.1"
14 | },
15 | "devDependencies": {
16 | "eslint": "~6.0.1",
17 | "eslint-config-standard": "~13.0.1",
18 | "eslint-plugin-import": "~2.18.0",
19 | "eslint-plugin-node": "~9.1.0",
20 | "eslint-plugin-promise": "~4.2.1",
21 | "eslint-plugin-standard": "~4.0.0"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/hapi-18/redirect-including-request-payload/redirect-including-request-payload.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const Hapi = require('@hapi/hapi')
4 |
5 | const server = new Hapi.Server({
6 | host: 'localhost',
7 | port: 3000
8 | })
9 |
10 | async function start() {
11 | server.route([
12 | {
13 | method: 'POST',
14 | path: '/',
15 | handler: (_, h) => {
16 | return h.redirect('/new').code(307)
17 | }
18 | },
19 | {
20 | method: 'POST',
21 | path: '/new',
22 | handler: ({ payload }) => {
23 | return {
24 | message: 'Received your request including the payload!',
25 | payload
26 | }
27 | }
28 | }
29 | ])
30 |
31 | await server.start()
32 | console.log('Server running on %s', server.info.uri);
33 | }
34 |
35 | start()
36 |
--------------------------------------------------------------------------------