1. At first, Verify the status of our code, or clone it.
educacion@educacion:~/src/resthapi/v3/rest_echo_hapi$ hg status
2. This is our package.json
educacion@educacion:~/src/resthapi/v3/rest_echo_hapi$ cat package.json { "name": "rest_echo_hapi", "version": "1.0.0", "description": "This README would normally document whatever steps are necessary to get your application up and running.", "main": "server/index.js", "scripts": { "start": "node server/index.js", "test": "mocha --recursive ./test/**.js" }, "keywords": [], "author": "maximilianou@gmail.com", "license": "MIT", "dependencies": { "hapi": "^17.8.1", "isemail": "^3.2.0", "mocha": "^5.2.0", "node-fetch": "^2.3.0" } }
3. I'll try to run the test program, widthout the libraries installed
educacion@educacion:~/src/resthapi/v3/rest_echo_hapi$ npm test > rest_echo_hapi@1.0.0 test /home/educacion/src/resthapi/v3/rest_echo_hapi > mocha --recursive ./test/**.js sh: 1: mocha: not found npm ERR! Test failed. See above for more details.
4. Now i'm installing manualy, with npm, mocha the test suite, and node-fetch to have most standard fetch library updated. I'm sure this fetch is going to be part of our nodejs api. Standards are the most important thing a developer must be confident with.
educacion@educacion:~/src/resthapi/v3/rest_echo_hapi$ npm install mocha node-fetch
5. And, now, we are running the test, and the OK result, baby steps, it's really the minimal code size.
educacion@educacion:~/src/resthapi/v3/rest_echo_hapi$ npm test > rest_echo_hapi@1.0.0 test /home/educacion/src/resthapi/v3/rest_echo_hapi > mocha --recursive ./test/**.js routes :: server method http GET / ✓ should return text (43ms) method http POST / ✓ should return text metodo http PUT / ✓ should return text metodo http DELETE / ✓ should return text 4 passing (67ms)
6. Here we have our test code, plain, one line assert focus, just to run our baby steps. Testing GET POST PUT DELETE minimal, hardcodeing configuration like 127.0.0.1 and others. But having a structure of describe() one scenario, describe() each case, it check one value item in each case. Here we have the assert.ok() and the RegExp() from the standard node api, following our Standard way of programming, having our code clean from temporal dependencies in libraries that will may change, but we expect some standards to be done. ( This kind of temporal dependencies problems happended to some project where i was working some time ago, when the browsers doesn't support JSON parse and stringify, so i start using, from our Master Programmer, our Master Key Programmer, Doublas Crockford, his version of the standard, so we don't have to worry about the future, because he does!, https://github.com/douglascrockford/JSON-js, some time later i don't have to change my older code, because his library was thought with the stantard in mind, so JSON.parse() JSON.stringify() was all done native in the browser one day, now. )
educacion@educacion:~/src/resthapi/v3/rest_echo_hapi$ cat test/server_index_test.js const assert = require('assert'); const fetch = require('node-fetch'); describe('routes :: server', () => { describe('method http GET /', () => { it('should return text', (done) => { const thevalue = "Mafalda"; fetch( 'http://127.0.0.1:3002/'+thevalue ).then( res => res.text() ).then( (body) => { assert.ok( new RegExp(thevalue+"$").test( JSON.parse(body)) , ":::Data Error!!!"); done(); } ).catch(done); }); }); describe('method http POST /', () => { it('should return text', (done) => { const thevalue = "Larguirucho"; fetch( 'http://127.0.0.1:3002/msg', { method: 'POST', body: JSON.stringify(thevalue), headers: { 'Content-Type': 'application/json' }, } ).then( res => res.text() ).then( (body) => { assert.ok( new RegExp(thevalue+"$").test( JSON.parse(body)) , ":::Data Error!!!"); done(); } ).catch(done); }); }); describe('metodo http PUT /', () => { it('should return text', (done) => { const thevalue = "Profesor Neurus"; fetch( 'http://127.0.0.1:3002/msg', { method: 'PUT', body: JSON.stringify(thevalue), headers: { 'Content-Type': 'application/json' }, } ).then( res => res.text() ).then( (body) => { assert.ok( new RegExp(thevalue+"$").test( JSON.parse(body)) , ":::Data Error!!!"); done(); } ).catch(done); }); }); describe('metodo http DELETE /', () => { it('should return text', (done) => { const thevalue = "Pedrito"; fetch( 'http://127.0.0.1:3002/'+thevalue ).then( res => res.text() ).then( (body) => { assert.ok( new RegExp(thevalue+"$").test( JSON.parse(body)) , ":::Data Error!!!"); done(); } ).catch(done); }); }); });
7. Here we have our server REST API with JSON body request and JSON body response. Body or parameter depending on POST PUT, GET DELETE, in case.
educacion@educacion:~/src/resthapi/v3/rest_echo_hapi$ cat server/index.js const Hapi = require('hapi'); class EchoServerHapi{ constructor(args){ this.server = Hapi.server(args); } async init(){ try { await this.routing(); await this.server.start(); console.log(`Here we have the echo Server Hapi running:: ${this.server.info.uri}`); } catch (error) { console.log('Error while trying to run echo Server Hapi:: ' + error.message); } } async routing(){ this.server.route({ method: 'GET', path: '/', handler: (request, h) => { return JSON.stringify('Hello, Javascript Developer'); } }); this.server.route({ method: 'GET', path: '/{name}', handler: (request, h) => { return JSON.stringify('Hello, ' + encodeURIComponent(request.params.name) ); } }); this.server.route({ method: 'POST', path: '/msg', handler: (request, h) => { return JSON.stringify(request.payload); } }); this.server.route({ method: 'PUT', path: '/msg', handler: (request, h) => { return JSON.stringify(request.payload); } }); this.server.route({ method: 'DELETE', path: '/{name}', handler: (request, h) => { return JSON.stringify( 'Bye, ' + encodeURIComponent(request.params.name) ); } }); } } const firstEchoServer = new EchoServerHapi({ port: 3002, host: '0.0.0.0', app: {} }); firstEchoServer.init();
8. Our Dockerfile is just to have the posibility to change code when we are running our development environment API REST.
educacion@educacion:~/src/resthapi/v3/rest_echo_hapi$ cat Dockerfile FROM node WORKDIR /code RUN npm set prefix /usr/local && npm install -g nodemon COPY package.json /code/package.json RUN npm set prefix /usr/local && npm install && npm ls RUN mv /code/node_modules /node_modules COPY . /code #EXPOSE 3000 # expose but no publish, except useing docker -P CMD ["npm", "start"]
9. And, containers compose in docker-compose.yml, to have running the services
educacion@educacion:~/src/resthapi/v3/rest_echo_hapi$ cat docker-compose.yml version: "2" services: web: build: . command: nodemon -L --inspect=0.0.0.0:5858 volumes: - .:/code ports: - "3002:3002" - "5858:5858"
10. Once it's running OK, upload to the repository, to our bitbucket mercurial.
educacion@educacion:~/src/resthapi/v3/rest_echo_hapi$ hg commit -u maximilianou@gmail.com -m 'testing mocha, first steps ' educacion@educacion:~/src/resthapi/v3/rest_echo_hapi$ hg push