└── readme.md /readme.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - [1.Intro](#1intro) 4 | - [Needs to make a web server](#needs-to-make-a-web-server) 5 | - [2.Modules, Export and Require](#2modules-export-and-require) 6 | - [Modules](#modules) 7 | - [Build a module](#build-a-module) 8 | - [Name value pair](#name-value-pair) 9 | - [Object](#object) 10 | - [Object Literal](#object-literal) 11 | - [Prototypal inheritance](#prototypal-inheritance) 12 | - [Function constructor](#function-constructor) 13 | - [Immediately Invoked Functions Expressions (IIFEs)](#immediately-invoked-functions-expressions-iifes) 14 | - [How Modules Work](#how-modules-work) 15 | - [Require](#require) 16 | - [Module Patterns](#module-patterns) 17 | - [Use always `module.exports` instead of `export` although they do the same.](#use-always-moduleexports-instead-of-export-although-they-do-the-same) 18 | - [Native Modules](#native-modules) 19 | - [Modules and ES6](#modules-and-es6) 20 | - [3.Events And EventEmitter](#3events-and-eventemitter) 21 | - [Events](#events) 22 | - [Object Properties and Methods](#object-properties-and-methods) 23 | - [Functions and Arrays](#functions-and-arrays) 24 | - [Node Event Emitter](#node-event-emitter) 25 | - [Event Listener](#event-listener) 26 | - [Our Event Emitter](#our-event-emitter) 27 | - [Magic String](#magic-string) 28 | - [Prototype chain](#prototype-chain) 29 | - [Inheriting from event emitter](#inheriting-from-event-emitter) 30 | - [ES5](#es5) 31 | - [Template literals](#template-literals) 32 | - [call() and apply()](#call-and-apply) 33 | - [Inheriting pattern 2](#inheriting-pattern-2) 34 | - [ES6 Classes](#es6-classes) 35 | - [Inheriting in ES6 Classes](#inheriting-in-es6-classes) 36 | - [4.Synchrony](#4synchrony) 37 | - [libuv](#libuv) 38 | - [Buffer](#buffer) 39 | - [Stream](#stream) 40 | - [Binary data](#binary-data) 41 | - [Character sets](#character-sets) 42 | - [Encoding](#encoding) 43 | - [Buffers](#buffers) 44 | - [ArrayBuffer](#arraybuffer) 45 | - [Callbacks](#callbacks) 46 | - [Files](#files) 47 | - [Error First Callback](#error-first-callback) 48 | - [Streams](#streams) 49 | - [Chunk](#chunk) 50 | - [Pipes](#pipes) 51 | - [Method chaining](#method-chaining) 52 | - [5.HTTP](#5http) 53 | - [Protocol](#protocol) 54 | - [Port](#port) 55 | - [HTTP](#http) 56 | - [MIME Type](#mime-type) 57 | - [http_parser](#httpparser) 58 | - [HTTP server](#http-server) 59 | - [Output HTML and Templates](#output-html-and-templates) 60 | - [Template](#template) 61 | - [Streams and Performance](#streams-and-performance) 62 | - [API](#api) 63 | - [Endpoint](#endpoint) 64 | - [Outputting a JSON](#outputting-a-json) 65 | - [Serialize](#serialize) 66 | - [Routing](#routing) 67 | - [6.NPM](#6npm) 68 | - [Semantic Versioning](#semantic-versioning) 69 | - [Package.json](#packagejson) 70 | - [Global dependencies](#global-dependencies) 71 | - [nodemon](#nodemon) 72 | - [7.Express](#7express) 73 | - [Environment variables](#environment-variables) 74 | - [Http method (verbs)](#http-method-verbs) 75 | - [Routes](#routes) 76 | - [Static Files and Middleware](#static-files-and-middleware) 77 | - [Midleware](#midleware) 78 | - [Templates and Template Engines](#templates-and-template-engines) 79 | - [Querystring and Post Parameters](#querystring-and-post-parameters) 80 | - [Querystring](#querystring) 81 | - [Form Post](#form-post) 82 | - [Post as json](#post-as-json) 83 | - [RESTful API and JSON](#restful-api-and-json) 84 | - [REST](#rest) 85 | - [Structuring the Application](#structuring-the-application) 86 | - [Structuring with Express](#structuring-with-express) 87 | - [Our own Structure](#our-own-structure) 88 | - [8.MEAN](#8mean) 89 | - [DOM](#dom) 90 | - [Angular](#angular) 91 | - [Separating Server code from Client code](#separating-server-code-from-client-code) 92 | - [9.Build an app](#9build-an-app) 93 | - [1. Init](#1-init) 94 | - [2. Connect to the Database](#2-connect-to-the-database) 95 | - [3. Adding Data](#3-adding-data) 96 | - [4. Create the API](#4-create-the-api) 97 | 98 | 99 | # 1.Intro 100 | ## Needs to make a web server 101 | 102 | * Better ways to organize our code into reusable pieces 103 | * Ways to deal with files 104 | * Ways to deal with databases 105 | * The ability to communicate over the Internet 106 | * The ability to accept requests and send responses 107 | * A way to deal with work that takes long time 108 | 109 | 110 | # 2.Modules, Export and Require 111 | ## Modules 112 | Reusable block of code whose existence does not accidentally impact other code 113 | 114 | **Common JS Modules** 115 | An agreed upon standard for how code modules should be structured 116 | 117 | **First class Functions** 118 | Everything you can do with other types you can do with functions 119 | 120 | **Expression** 121 | A block of code that results in a value 122 | 123 | 124 | ```javascript 125 | 126 | // function statement 127 | function greet() { 128 | console.log('hi'); 129 | } 130 | greet(); 131 | 132 | // functions are first-class 133 | function logGreeting(fn) { 134 | fn(); 135 | } 136 | logGreeting(greet); 137 | 138 | // function expression 139 | var greetMe = function() { 140 | console.log('Hi Tony!'); 141 | } 142 | greetMe(); 143 | 144 | // it's first-class 145 | logGreeting(greetMe); 146 | 147 | // use a function expression to create a function on the fly 148 | logGreeting(function() { 149 | console.log('Hello Tony!'); 150 | }); 151 | ``` 152 | 153 | ## Build a module 154 | 155 | **app.js** 156 | ```javascript 157 | 158 | var greet = require('./greet'); // returns what we have in `module.exports` 159 | greet(); 160 | ``` 161 | **greet.js** 162 | ```javascript 163 | 164 | var greet = function() { 165 | console.log('Hello!'); 166 | }; 167 | 168 | module.exports = greet; 169 | ``` 170 | #### Name value pair 171 | A name which maps to a value. 172 | The name can be defined more than once, but only can have one value in any given **context** 173 | `Address = "Sesam street"` 174 | #### Object 175 | Collection of name/value pairs 176 | #### Object Literal 177 | Name/value pairs separated by commas and surrounded by curly braces 178 | ```javascript 179 | 180 | var person = { 181 | name: 'Peter', 182 | lastname:'Doe', 183 | workplace:{ 184 | Street:'Sesam street', 185 | Number: '1' 186 | }, 187 | greet: function(){ 188 | console.log('Hello ' + this.name + ' ' + this.lastname ) 189 | } 190 | }; 191 | 192 | person.greet(); 193 | console.log(person['name']) 194 | ``` 195 | ## Prototypal inheritance 196 | Every object points to a `proto{}` object 197 | 198 | ## Function constructor 199 | A function used to build objects using `new` 200 | ```javascript 201 | 202 | function Person(firstname, lastname) { 203 | this.firstname = firstname; 204 | this.lastname = lastname; 205 | } 206 | 207 | 208 | Person.prototype.greet = function() { 209 | console.log('Hello, ' + this.firstname + ' ' + this.lastname); 210 | }; 211 | 212 | var john = new Person('John', 'Doe'); 213 | john.greet(); 214 | 215 | ``` 216 | 217 | ## Immediately Invoked Functions Expressions (IIFEs) 218 | Run the function at the point it is created. Add a `()` after its declaration. 219 | ```javascript 220 | 221 | var firstname = 'Jane'; 222 | 223 | (function (lastname) { 224 | 225 | var firstname = 'John'; 226 | console.log(firstname); 227 | console.log(lastname); 228 | 229 | }('Doe')); 230 | 231 | console.log(firstname); 232 | ``` 233 | 234 | ## How Modules Work 235 | `require` is a function, that you pass a 'path' to 236 | `module.exports` is what the require function returns 237 | this works because your code is actually wrapped in a function that is given these things as function parameters 238 | 239 | **app.js** 240 | ```javascript 241 | 242 | var greet = require('./greet'); // returns what we have in `module.exports` 243 | greet(); 244 | ``` 245 | **greet.js** 246 | ```javascript 247 | 248 | var greet = function() { 249 | console.log('Hello!'); 250 | }; 251 | 252 | module.exports = greet; 253 | ``` 254 | 255 | ## Require 256 | 257 | **app.js** 258 | ```javascript 259 | 260 | var greet = require('./greet'); 261 | 262 | greet.english(); 263 | greet.spanish(); 264 | ``` 265 | **greet/index.js** 266 | ```javascript 267 | 268 | var english = require('./english'); 269 | var spanish = require('./spanish'); 270 | 271 | module.exports = { 272 | english: english, 273 | spanish: spanish 274 | }; 275 | ``` 276 | **greet/english.js** 277 | ```javascript 278 | 279 | var greetings = require('./greetings.json'); 280 | 281 | var greet = function() { 282 | console.log(greetings.en); 283 | } 284 | 285 | module.exports = greet; 286 | ``` 287 | 288 | **greet/spanish.js** 289 | ```javascript 290 | 291 | var greetings = require('./greetings.json'); 292 | 293 | var greet = function() { 294 | console.log(greetings.es); 295 | } 296 | 297 | module.exports = greet; 298 | ``` 299 | **greet/greetings.json** 300 | ```json 301 | 302 | { 303 | "en": "Hello", 304 | "es": "Hola" 305 | } 306 | ``` 307 | 308 | ## Module Patterns 309 | 310 | **app.js** 311 | ```javascript 312 | 313 | var greet = require('./greet1'); 314 | greet(); 315 | 316 | var greet2 = require('./greet2').greet; 317 | greet2(); 318 | 319 | var greet3 = require('./greet3'); 320 | greet3.greet(); 321 | greet3.greeting = 'Changed hello world!'; 322 | 323 | var greet3b = require('./greet3'); 324 | greet3b.greet(); // Returns 'Changed hello world!' -> The result of module.export is cached so the whole greet3 is only called once 325 | 326 | var Greet4 = require('./greet4'); 327 | var grtr = new Greet4(); 328 | grtr.greet(); 329 | 330 | var greet5 = require('./greet5').greet; 331 | greet5(); 332 | ``` 333 | 334 | **greet1.js** 335 | ```javascript 336 | 337 | module.exports = function() { 338 | console.log('Hello world'); 339 | }; 340 | ``` 341 | 342 | **greet2.js** 343 | ```javascript 344 | 345 | module.exports.greet = function() { 346 | console.log('Hello world!'); 347 | }; 348 | ``` 349 | 350 | **greet3.js** 351 | ```javascript 352 | 353 | function Greetr() { 354 | this.greeting = 'Hello world!!'; 355 | this.greet = function() { 356 | console.log(this.greeting); 357 | } 358 | } 359 | 360 | module.exports = new Greetr(); 361 | ``` 362 | 363 | **greet4.js** 364 | ```javascript 365 | 366 | function Greetr() { 367 | this.greeting = 'Hello world!!!'; 368 | this.greet = function() { 369 | console.log(this.greeting); 370 | } 371 | } 372 | 373 | module.exports = Greetr; 374 | ``` 375 | 376 | **greet5.js** 377 | Revealing module pattern: Exposing only the properties and methods you want via a returned object 378 | ```javascript 379 | 380 | var greeting = 'Hello world!!!!'; 381 | 382 | function greet() { 383 | console.log(greeting); 384 | } 385 | 386 | module.exports = { 387 | greet: greet // Only the greet is "exposed" (public) 388 | } 389 | ``` 390 | #### Use always `module.exports` instead of `export` although they do the same. 391 | 392 | ## Native Modules 393 | [nodejs.org/api](nodejs.org/api) 394 | 395 | ```javascript 396 | 397 | var util = require('util'); 398 | 399 | var name = 'Tony'; 400 | var greeting = util.format('Hello, %s', name); 401 | util.log(greeting); 402 | ``` 403 | ## Modules and ES6 404 | 405 | **greet.js** 406 | ```javascript 407 | 408 | export function greet(){ 409 | console.log('Hello'); 410 | } 411 | ``` 412 | 413 | **app.js** 414 | ```javascript 415 | 416 | import * as greetr from 'greet'; 417 | greetr.greet(); 418 | ``` 419 | # 3.Events And EventEmitter 420 | ## Events 421 | Something that has happened in our application that we can respond to 422 | 423 | * **System Events**: C++ core (libuv) 424 | * **Custom Events**: Javascript core (Event Emitter) 425 | 426 | ### Object Properties and Methods 427 | ```javascript 428 | 429 | var obj = { 430 | greet: 'Hello' 431 | } 432 | 433 | console.log(obj.greet); 434 | console.log(obj['greet']); 435 | var prop = 'greet'; 436 | console.log(obj[prop]); 437 | ``` 438 | 439 | ### Functions and Arrays 440 | ```javascript 441 | 442 | var arr = []; 443 | 444 | arr.push(function() { 445 | console.log('Hello world 1'); 446 | }); 447 | arr.push(function() { 448 | console.log('Hello world 2'); 449 | }); 450 | arr.push(function() { 451 | console.log('Hello world 3'); 452 | }); 453 | 454 | arr.forEach(function(item) { 455 | item(); 456 | }); 457 | ``` 458 | 459 | ## Node Event Emitter 460 | ### Event Listener 461 | The code that responds to an event 462 | ### Our Event Emitter 463 | **Emitter.js** 464 | ```javascript 465 | 466 | function Emitter() { 467 | this.events = {}; 468 | } 469 | 470 | Emitter.prototype.on = function(type, listener) { 471 | this.events[type] = this.events[type] || []; 472 | this.events[type].push(listener); 473 | } 474 | 475 | Emitter.prototype.emit = function(type) { 476 | if (this.events[type]) { 477 | this.events[type].forEach(function(listener) { 478 | listener(); 479 | }); 480 | } 481 | } 482 | 483 | module.exports = Emitter; 484 | ``` 485 | **app.js** 486 | ```javascript 487 | 488 | var Emitter = require('./emitter'); 489 | 490 | var emtr = new Emitter(); 491 | 492 | emtr.on('greet', function() { 493 | console.log('Somewhere, someone said hello.'); 494 | }); 495 | 496 | emtr.on('greet', function() { 497 | console.log('A greeting occurred!'); 498 | }); 499 | 500 | console.log('Hello!'); 501 | emtr.emit('greet'); 502 | ``` 503 | ### Magic String 504 | A String that has some special meaning in our code. Bad because of typos. 505 | Use config files instead. 506 | ```javascript 507 | 508 | module.exports = { 509 | events: { 510 | GREET: 'greet' 511 | } 512 | } 513 | ``` 514 | 515 | ```javascript 516 | 517 | var Emitter = require('events'); 518 | var eventConfig = require('./config').events; 519 | 520 | var emtr = new Emitter(); 521 | 522 | emtr.on(eventConfig.GREET, function() { 523 | console.log('Somewhere, someone said hello.'); 524 | }); 525 | 526 | emtr.on(eventConfig.GREET, function() { 527 | console.log('A greeting occurred!'); 528 | }); 529 | 530 | console.log('Hello!'); 531 | emtr.emit(eventConfig.GREET); 532 | ``` 533 | ## Prototype chain 534 | Another way to create objects `Object.create(...)` 535 | 536 | ```javascript 537 | 538 | var person = { 539 | firstname: '', 540 | lastname: '', 541 | greet: function() { 542 | return this.firstname + ' ' + this.lastname; 543 | } 544 | } 545 | 546 | var john = Object.create(person); 547 | john.firstname = 'John'; 548 | john.lastname = 'Doe'; 549 | 550 | var jane = Object.create(person); 551 | jane.firstname = 'Jane'; 552 | jane.lastname = 'Doe'; 553 | 554 | console.log(john.greet()); 555 | console.log(jane.greet()); 556 | ``` 557 | 558 | ## Inheriting from event emitter 559 | Set to our object a prototype of the Emitter 560 | Allow us create objects with the Emitter properties 561 | 562 | ```javascript 563 | 564 | var EventEmitter = require('events'); 565 | var util = require('util'); 566 | 567 | function Greetr() { // This is call to a "function constructor" 568 | this.greeting = 'Hello world!'; 569 | } 570 | 571 | util.inherits(Greetr, EventEmitter); //<-- 572 | 573 | Greetr.prototype.greet = function(data) { 574 | console.log(this.greeting + ': ' + data); 575 | this.emit('greet', data); 576 | } 577 | 578 | var greeter1 = new Greetr(); 579 | 580 | greeter1.on('greet', function(data) { 581 | console.log('Someone greeted!: ' + data); 582 | }); 583 | 584 | greeter1.greet('Tony'); 585 | ``` 586 | 587 | ## ES5 588 | ### Template literals 589 | A way to concatenate strings in ES6 590 | ```javascript 591 | 592 | var greet2 = `Hello ${ name }`; 593 | ``` 594 | ```javascript 595 | 596 | var a = 5; 597 | var b = 10; 598 | console.log(`Fifteen is ${a + b} and\nnot ${2 * a + b}.`); 599 | ``` 600 | ### call() and apply() 601 | ```javascript 602 | 603 | var obj = { 604 | name: 'John Doe', 605 | greet: function() { 606 | console.log(`Hello ${ this.name }`); 607 | } 608 | } 609 | 610 | obj.greet(); 611 | obj.greet.call({ name: 'Jane Doe'}); // this will point the what is passed in call 612 | obj.greet.apply({ name: 'Jane Doe'}); // idem 613 | 614 | // With params we see the difference 615 | var obj = { 616 | name: 'John Doe', 617 | greet: function(param1,param2) { 618 | console.log(`Hello ${ this.name }`); 619 | } 620 | } 621 | 622 | obj.greet.call({ name: 'Jane Doe'},param1,param2); 623 | obj.greet.apply({ name: 'Jane Doe'},[param1,param2]); 624 | ``` 625 | ## Inheriting pattern 2 626 | We need the object that inherits to also have the `this` methods and properties of the inherited object. 627 | ```javascript 628 | 629 | function Greetr() { // This is call to a "function constructor" 630 | EventEmitter.call(this) //<-- also called "super constructor" 631 | this.greeting = 'Hello world!'; 632 | } 633 | 634 | ``` 635 | 636 | ```javascript 637 | 638 | var util = require('util'); 639 | 640 | function Person() { 641 | this.firstname = 'John'; 642 | this.lastname = 'Doe'; 643 | } 644 | 645 | Person.prototype.greet = function() { 646 | console.log('Hello ' + this.firstname + ' ' + this.lastname); 647 | } 648 | 649 | function Policeman() { 650 | Person.call(this);// Without this line `this` object wont have firstname and lastname. 651 | this.badgenumber = '1234'; 652 | } 653 | 654 | util.inherits(Policeman, Person); 655 | var officer = new Policeman(); 656 | officer.greet(); 657 | ``` 658 | 659 | ## ES6 Classes 660 | ```javascript 661 | 662 | 'use strict'; // like 'lint' for javascript 663 | 664 | class Person { 665 | constructor(firstname, lastname) { 666 | this.firstname = firstname; 667 | this.lastname = lastname; 668 | } 669 | 670 | greet() { 671 | console.log('Hello, ' + this.firstname + ' ' + this.lastname); 672 | } 673 | } 674 | 675 | ``` 676 | ## Inheriting in ES6 Classes 677 | 678 | ```javascript 679 | 680 | var EventEmitter = require('events'); 681 | 682 | class Greetr extends EventEmitter { 683 | constructor() { 684 | super(); 685 | this.greeting = 'Hello world!'; 686 | } 687 | 688 | greet(data) { 689 | console.log(`${ this.greeting }: ${ data }`); 690 | this.emit('greet', data); 691 | } 692 | } 693 | ``` 694 | 695 | # 4.Synchrony 696 | Javascript is synchronous 697 | Node.js is asynchronous 698 | #### libuv 699 | A C library inside node that deal events occurring in the operating system 700 | #### Buffer 701 | Limited size, temporary place for data being moved from one place to another 702 | #### Stream 703 | A sequence of data made available over time 704 | #### Binary data 705 | Data store in binary 706 | #### Character sets 707 | A representation of characters as numbers (Unicode, Ascii...) 708 | #### Encoding 709 | How characters are stored in binary (UTF-8). Bits used to represent each number 710 | ## Buffers 711 | Needed because javascript was not used to deal with binary data. In ES6 it does using ArrayBuffer 712 | ```javascript 713 | 714 | var buf = new Buffer('Hello', 'utf8'); 715 | console.log(buf); // 716 | console.log(buf.toString()); //Hello 717 | console.log(buf.toJSON()); // { type: 'Buffer', data: [ 72, 101, 108, 108, 111 ] } 718 | console.log(buf[2]); //108 719 | 720 | buf.write('wo'); 721 | console.log(buf.toString()); // wollo 722 | ``` 723 | ## ArrayBuffer 724 | [ArrayBuffer Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays) 725 | ```javascript 726 | 727 | var buffer = new ArrayBuffer(8); 728 | var view = new Int32Array(buffer); 729 | view[0] = 5; 730 | view[1] = 15; 731 | console.log(view); //Int32Array { '0': 5, '1': 15 } 732 | ``` 733 | ## Callbacks 734 | ```javascript 735 | 736 | function greet(callback) { 737 | console.log('Hello!'); 738 | var data = { 739 | name: 'John Doe' 740 | }; 741 | 742 | callback(data); 743 | } 744 | 745 | greet(function(data) { 746 | console.log('The callback was invoked!'); 747 | console.log(data); 748 | }); 749 | 750 | greet(function(data) { 751 | console.log('A different callback was invoked!'); 752 | console.log(data.name); 753 | }); 754 | 755 | //Hello! 756 | //The callback was invoked! 757 | //{ name: 'John Doe' } 758 | //Hello! 759 | //A different callback was invoked! 760 | //John Doe 761 | ``` 762 | ## Files 763 | ```javascript 764 | 765 | var fs = require('fs'); 766 | 767 | //synchronous 768 | var greet = fs.readFileSync(__dirname + '/greet.txt', 'utf8'); 769 | console.log(greet); //#1 770 | 771 | //asynchronous 772 | var greet2 = fs.readFile(__dirname + '/greet.txt', 'utf8', function(err, data) { 773 | console.log(data);//#3 774 | }); 775 | 776 | console.log('Done!');//#2 777 | ``` 778 | #### Error First Callback 779 | Callbacks take en error object as their first parameter. 780 | The Standard. 781 | null if no error. 782 | 783 | ## Streams 784 | #### Chunk 785 | A piece of data being sent through a Stream 786 | Data is split in 'chunks' and streamed 787 | ```javascript 788 | 789 | var fs = require('fs'); 790 | 791 | var readable = fs.createReadStream(__dirname + '/greet.txt', { encoding: 'utf8', highWaterMark: 16 * 1024 }); // highWaterMark numebr of the buffer 792 | 793 | var writable = fs.createWriteStream(__dirname + '/greetcopy.txt'); 794 | 795 | readable.on('data', function(chunk) { // Event emitter, just listenting the event starts the buffer 796 | console.log(chunk.length); 797 | // console.log(chunk); 798 | writable.write(chunk); 799 | }); 800 | ``` 801 | ## Pipes 802 | Conn ecting two streams by writing o one stream what is being read from another 803 | In node read from Readable stream to a Writable stream 804 | 805 | ``` javascript 806 | 807 | var fs = require('fs'); 808 | var zlib = require('zlib'); 809 | 810 | var readable = fs.createReadStream(__dirname + '/greet.txt'); 811 | 812 | var writable = fs.createWriteStream(__dirname + '/greetcopy.txt'); 813 | 814 | var compressed = fs.createWriteStream(__dirname + '/greet.txt.gz'); 815 | 816 | var gzip = zlib.createGzip(); 817 | 818 | readable.pipe(writable); // Same as forehead sample 819 | 820 | readable.pipe(gzip).pipe(compressed); // Chain pipes 821 | ``` 822 | #### Method chaining 823 | A Method returns an object so we can keep calling more methods. 824 | When it returns the parent object is called "cascading". 825 | 826 | # 5.HTTP 827 | #### Protocol 828 | A set of rules two sides agree on the use communicating. 829 | IP : Internet Protocol. Addresses 830 | TCP: Transmission Control Protocol. Send Packets 831 | #### Port 832 | Which program in a computer handles a packet received. 833 | #### HTTP 834 | A set of rules and format for data being transferred on the web 835 | 'Hypertext Transfer Protocol' (how the messages are written) 836 | #### MIME Type 837 | A standard for specifying the type of the data being sent 838 | 'Multipurpose Internet Mail Extensions' 839 | Examples: application/json, text/html, image/jpeg 840 | 841 | #### http_parser 842 | C program that parse http requests and responses 843 | 844 | ## HTTP server 845 | 846 | ```javascript 847 | 848 | var http = require('http'); 849 | 850 | http.createServer(function (req, res) { 851 | 852 | res.writeHead(200, {'Content-Type': 'text/plain'}); 853 | res.end('Hello World\n'); 854 | 855 | }).listen(1337, '127.0.0.1'); 856 | 857 | ``` 858 | ## Output HTML and Templates 859 | ```javascript 860 | 861 | var http = require('http'); 862 | var fs = require('fs'); 863 | 864 | http.createServer(function(req, res) { 865 | 866 | res.writeHead(200, { 'Content-Type': 'text/html' }); 867 | var html = fs.readFileSync(__dirname + '/index.htm', 'utf8'); 868 | var message = 'Hello world...'; 869 | html = html.replace('{Message}', message); 870 | res.end(html); 871 | 872 | }).listen(1337, '127.0.0.1'); 873 | ``` 874 | #### Template 875 | Text designed to be the basis for final text or content after being processed 876 | ## Streams and Performance 877 | We can send chunks of data instead all at once using Streams and piping it to the response. 878 | Use it always. 879 | ```javascript 880 | 881 | var http = require('http'); 882 | var fs = require('fs'); 883 | 884 | http.createServer(function(req, res) { 885 | 886 | res.writeHead(200, { 'Content-Type': 'text/html' }); 887 | fs.createReadStream(__dirname + '/index.htm').pipe(res); 888 | 889 | }).listen(1337, '127.0.0.1'); 890 | ``` 891 | 892 | #### API 893 | Application Programing Interface. 894 | In node's field URLs which accept and send only data via HTTP and TCP/IP 895 | 896 | #### Endpoint 897 | One URL in a web API 898 | 899 | ## Outputting a JSON 900 | ```javascript 901 | 902 | var http = require('http'); 903 | var fs = require('fs'); 904 | 905 | http.createServer(function(req, res) { 906 | 907 | res.writeHead(200, { 'Content-Type': 'application/json' }); 908 | var obj = { 909 | firstname: 'John', 910 | lastname: 'Doe' 911 | }; 912 | res.end(JSON.stringify(obj)); 913 | 914 | }).listen(1337, '127.0.0.1'); 915 | ``` 916 | #### Serialize 917 | Translating and object into a format that can be stored or transferred. 918 | JSON, CSV, XML are popular. 919 | 'Deserialize' is the opposite (converting the format back into an object) 920 | 921 | ## Routing 922 | Mapping HTTP requests to content. 923 | Get data in the server from parameters in the http call. 924 | 925 | ```javascript 926 | 927 | var http = require('http'); 928 | var fs = require('fs'); 929 | 930 | http.createServer(function(req, res) { 931 | 932 | if (req.url === '/') { 933 | fs.createReadStream(__dirname + '/index.htm').pipe(res); 934 | } 935 | 936 | else if (req.url === '/api') { 937 | res.writeHead(200, { 'Content-Type': 'application/json' }); 938 | var obj = { 939 | firstname: 'John', 940 | lastname: 'Doe' 941 | }; 942 | res.end(JSON.stringify(obj)); 943 | } 944 | else { 945 | res.writeHead(404); 946 | res.end(); 947 | } 948 | 949 | }).listen(1337, '127.0.0.1'); 950 | ``` 951 | # 6.NPM 952 | #### Semantic Versioning 953 | MAYOR.MINOR.PATCH 954 | ## Package.json 955 | `npm init` 956 | `npm install moment --save` The `--save` writes a reference in package.json 957 | 958 | ```javascript 959 | 960 | "dependencies": { 961 | "moment": "^2.13.0" // ^ automatically updates minors ~ updates only patches 962 | } 963 | ``` 964 | 965 | 966 | `npm install` : Once we have the package.json we dont need to copy the modules in a new environment, just calling `npm install` will download everything for us 967 | 968 | `require` will look directly in the `node_modules` folder 969 | 970 | ```javascript 971 | 972 | var moment = require('moment'); 973 | console.log(moment().format("ddd, hA")); 974 | ``` 975 | ## Global dependencies 976 | Install dependencies that we only need while developing 977 | `npm install jasmine-node --save-dev` 978 | Install globally, if we kwow we will us a package in many apps in our computer 979 | `npm install nodemon -g` 980 | They are stored at `/usr/local/lib/node_modules/npm/node_modules` 981 | 982 | #### nodemon 983 | It watches changes in the folder 984 | 985 | # 7.Express 986 | ```javascript 987 | 988 | var express = require('express'); 989 | var app = express(); 990 | 991 | var port = process.env.PORT || 3000; 992 | 993 | app.get('/', function(req, res) { 994 | res.send('

Hello world!

'); 995 | }); 996 | 997 | app.get('/api', function(req, res) { 998 | res.json({ firstname: 'John', lastname: 'Doe' }); 999 | }); 1000 | 1001 | app.listen(port); 1002 | ``` 1003 | #### Environment variables 1004 | Global variables specific to the environment (server) our code is living in. 1005 | #### Http method (verbs) 1006 | Specific type of action the request wishes to make. 1007 | GET, POST, DELETE... 1008 | ## Routes 1009 | ```javascript 1010 | 1011 | app.get('/person/:id', function(req, res) { 1012 | res.send('

Person: ' + req.params.id + '

'); 1013 | }); 1014 | ``` 1015 | 1016 | ## Static Files and Middleware 1017 | #### Midleware 1018 | Code that sit between 2 layers of software. 1019 | In Express: sitting between request and response 1020 | ```javascript 1021 | 1022 | app.use('/assets', express.static(__dirname + '/public')); 1023 | 1024 | app.use('/', function (req, res, next) { 1025 | console.log('Request Url:' + req.url); 1026 | next(); // call the next Middleware 1027 | }); 1028 | app.get('/', function(req, res) { 1029 | res.send('

Hello world!

'); 1030 | }); 1031 | ``` 1032 | ## Templates and Template Engines 1033 | ```javascript 1034 | 1035 | ... 1036 | 1037 | app.set('view engine', 'ejs'); 1038 | 1039 | app.get('/', function(req, res) { 1040 | res.render('index'); 1041 | }); 1042 | 1043 | app.get('/person/:id', function(req, res) { 1044 | res.render('person', { ID: req.params.id }); 1045 | }); 1046 | ... 1047 | 1048 | ``` 1049 | ```html 1050 | 1051 | 1052 | 1053 | // important the / before the path of the css 1054 | 1055 | 1056 |

Person: <%= ID %>

1057 | 1058 | 1059 | ``` 1060 | 1061 | ## Querystring and Post Parameters 1062 | ### Querystring 1063 | ```javascript 1064 | 1065 | GET /?id=4&page=3 HTTP/1.1 1066 | Host:www.learnweb.net 1067 | Cookie:username=abc:name:Tony 1068 | ``` 1069 | ```javascript 1070 | 1071 | app.get('/person/:id', function(req, res) { 1072 | res.render('person', { ID: req.params.id, Qstr: req.query.qstr }); //req.query get the querystring 1073 | }); 1074 | ``` 1075 | ### Form Post 1076 | Data in the body as objects 1077 | Use body-parser 1078 | 1079 | ```javascript 1080 | 1081 | POST HTTP/1.1 1082 | Host:www.learnweb.net 1083 | Content-Type:application/x-www-form-urlencoded 1084 | Cookie:num=4;page=3 1085 | username=Tony&password=pwd 1086 | ``` 1087 | 1088 | ```javascript 1089 | 1090 | var bodyParser = require('body-parser'); 1091 | var urlencodedParser = bodyParser.urlencoded({ extended: false }); 1092 | 1093 | app.post('/person', urlencodedParser, function(req, res) { 1094 | res.send('Thank you!'); 1095 | console.log(req.body.firstname); 1096 | console.log(req.body.lastname); 1097 | }); 1098 | ``` 1099 | ```html 1100 | 1101 |
1102 | First name:
1103 | Last name:
1104 | 1105 |
1106 | ``` 1107 | ### Post as json 1108 | Data in the body as json 1109 | ```javascript 1110 | 1111 | POST HTTP/1.1 1112 | Host:www.learnweb.net 1113 | Content-Type:application/json 1114 | Cookie:num=4;page=3 1115 | { 1116 | 'username'='Tony', 1117 | 'password'='pwd' 1118 | } 1119 | ``` 1120 | 1121 | ```javascript 1122 | 1123 | var jsonParser = bodyParser.json(); 1124 | 1125 | app.post('/personjson', jsonParser, function(req, res) { 1126 | res.send('Thank you for the JSON data!'); 1127 | console.log(req.body.firstname); 1128 | console.log(req.body.lastname); 1129 | }); 1130 | ``` 1131 | 1132 | ```html 1133 | 1134 | 1143 | ``` 1144 | ## RESTful API and JSON 1145 | #### REST 1146 | Representational State Transfer. Which HTTP verbs and URLs do what. 1147 | 1148 | ```javascript 1149 | 1150 | app.get('/api/person/:id', function(req, res) { 1151 | // get that data from database 1152 | res.json({ firstname: 'John', lastname: 'Doe' }); 1153 | }); 1154 | 1155 | app.post('/api/person', jsonParser, function(req, res) { 1156 | // save to the database 1157 | }); 1158 | 1159 | app.delete('/api/person/:id', function(req, res) { 1160 | // delete from the database 1161 | }); 1162 | ``` 1163 | 1164 | ## Structuring the Application 1165 | ### Structuring with Express 1166 | `install express-generator -g` // do it global 1167 | `express `// Create the architecture 1168 | `cd ` // go to the app 1169 | `npm install` // install the packages 1170 | 1171 | ### Our own Structure 1172 | Using controllers 1173 | 1174 | **app.js** 1175 | ```javascript 1176 | 1177 | var express = require('express'); 1178 | var app = express(); 1179 | 1180 | var apiController = require('./controllers/apiController'); 1181 | var htmlController = require('./controllers/htmlController'); 1182 | 1183 | var port = process.env.PORT || 3000; 1184 | 1185 | app.use('/assets', express.static(__dirname + '/public')); 1186 | 1187 | app.set('view engine', 'ejs'); 1188 | 1189 | app.use('/', function (req, res, next) { 1190 | console.log('Request Url:' + req.url); 1191 | next(); 1192 | }); 1193 | 1194 | htmlController(app); 1195 | apiController(app); 1196 | 1197 | app.listen(port); 1198 | ``` 1199 | **htmlController** 1200 | ```javascript 1201 | 1202 | var bodyParser = require('body-parser'); 1203 | 1204 | var urlencodedParser = bodyParser.urlencoded({ extended: false }); 1205 | 1206 | module.exports = function(app) { 1207 | 1208 | app.get('/', function(req, res) { 1209 | res.render('index'); 1210 | }); 1211 | 1212 | app.get('/person/:id', function(req, res) { 1213 | res.render('person', { ID: req.params.id, Qstr: req.query.qstr }); 1214 | }); 1215 | 1216 | app.post('/person', urlencodedParser, function(req, res) { 1217 | res.send('Thank you!'); 1218 | console.log(req.body.firstname); 1219 | console.log(req.body.lastname); 1220 | }); 1221 | } 1222 | ``` 1223 | 1224 | **apiController** 1225 | ```javascript 1226 | 1227 | module.exports = function(app) { 1228 | 1229 | app.get('/api/person/:id', function(req, res) { 1230 | // get that data from database 1231 | res.json({ firstname: 'John', lastname: 'Doe' }); 1232 | }); 1233 | 1234 | app.post('/api/person', function(req, res) { 1235 | // save to the database 1236 | }); 1237 | 1238 | app.delete('/api/person/:id', function(req, res) { 1239 | // delete from the database 1240 | }); 1241 | } 1242 | ``` 1243 | # 8.MEAN 1244 | #### DOM 1245 | Document Object Model 1246 | The structure browsers use to store and manage web pages 1247 | Browsers give JavaScript the ability to manipulate the DOM 1248 | ## Angular 1249 | 1250 | **app.js** 1251 | ```javascript 1252 | 1253 | var express = require('express'); 1254 | var app = express(); 1255 | 1256 | var port = process.env.PORT || 3000; 1257 | 1258 | app.set('view engine', 'ejs'); 1259 | app.use('/assets', express.static(__dirname + '/public')); 1260 | 1261 | app.get('/', function(req, res) { 1262 | 1263 | res.render('index'); 1264 | 1265 | }); 1266 | 1267 | app.listen(port); 1268 | ``` 1269 | **view/index.ejs** 1270 | ```html 1271 | 1272 | 1273 | 1274 | The MEAN stack 1275 | 1276 | 1277 | 1278 | 1279 | 1280 |
1281 | {{ vm.message }} 1282 |
1283 |
    1284 |
  • 1285 | {{ person.name }} 1286 |
  • 1287 |
1288 | 1289 | 1290 | 1291 | 1292 | ``` 1293 | **public/js/app.js** 1294 | ```javascript 1295 | 1296 | angular.module('TestApp', []); 1297 | 1298 | angular.module('TestApp') 1299 | .controller('MainController', ctrlFunc); 1300 | 1301 | function ctrlFunc() { 1302 | this.message = "Hello"; 1303 | 1304 | this.people = [ 1305 | { 1306 | name: 'John Doe' 1307 | }, 1308 | { 1309 | name: 'Jane Doe' 1310 | }, 1311 | { 1312 | name: 'Jim Doe' 1313 | } 1314 | ] 1315 | } 1316 | ``` 1317 | ## Separating Server code from Client code 1318 | We can set in the server what we show in client 1319 | **app.js** 1320 | ```javascript 1321 | 1322 | var express = require('express'); 1323 | var app = express(); 1324 | 1325 | var port = process.env.PORT || 3000; 1326 | 1327 | var people = [ 1328 | { 1329 | name: 'John Doe' 1330 | }, 1331 | { 1332 | name: 'Jane Doe' 1333 | }, 1334 | { 1335 | name: 'Jim Doe' 1336 | } 1337 | ]; 1338 | 1339 | app.set('view engine', 'ejs'); 1340 | app.use('/assets', express.static(__dirname + '/public')); 1341 | 1342 | app.get('/', function(req, res) { 1343 | 1344 | res.render('index', { serverPeople: people }); //<-- 1345 | 1346 | }); 1347 | 1348 | app.listen(port); 1349 | ``` 1350 | **view/index.ejs** 1351 | ```html 1352 | 1353 | 1354 | 1355 | The MEAN stack 1356 | 1357 | 1358 | 1359 |
    1360 |
  • 1361 | {{ person.name }} 1362 |
  • 1363 |
1364 | 1367 | 1368 | 1369 | 1370 | ``` 1371 | **public/js/app.js** 1372 | ```javascript 1373 | 1374 | angular.module('TestApp', []); 1375 | 1376 | angular.module('TestApp') 1377 | .controller('MainController', ctrlFunc); 1378 | 1379 | function ctrlFunc() { 1380 | this.people = clientPeople; 1381 | } 1382 | ``` 1383 | # 9.Build an app 1384 | ## 1. Init 1385 | *1 `npm init` 1386 | *2 `npm install express --save-dev` 1387 | *3 `npm install ejs --save-dev` 1388 | *4 `npm install body-parser --save-dev` 1389 | *5 `npm install mongoose --save-dev` 1390 | 1391 | **app.js** 1392 | ```javascript 1393 | 1394 | var express = require('express'); 1395 | var app = express(); 1396 | 1397 | var port = process.env.PORT || 3000; 1398 | 1399 | app.use('/assets', express.static(__dirname + '/public')); 1400 | 1401 | app.set('view engine', 'ejs'); 1402 | 1403 | app.listen(port); 1404 | ``` 1405 | ## 2. Connect to the Database 1406 | mLab.com 1407 | **config/config.json** 1408 | ```javascript 1409 | 1410 | { 1411 | "uname":"test", 1412 | "pwd":"test" 1413 | } 1414 | ``` 1415 | **config/index.js** 1416 | ```javascript 1417 | 1418 | var configValues = require('./config'); 1419 | 1420 | module.exports = { 1421 | getDbConnectionString: function() { 1422 | return `mongodb://${configValues.uname}:${configValues.pwd}@ds013212.mlab.com:13212/nodetodo`; 1423 | } 1424 | } 1425 | ``` 1426 | **models/todoModel.js** 1427 | ```javascript 1428 | 1429 | var mongoose = require('mongoose'); 1430 | 1431 | var Schema = mongoose.Schema; 1432 | 1433 | var todoSchema = new Schema({ 1434 | username: String, 1435 | todo: String, 1436 | isDone: Boolean, 1437 | hasAttachment: Boolean 1438 | }); 1439 | 1440 | var Todos = mongoose.model('Todos', todoSchema); 1441 | 1442 | module.exports = Todos; 1443 | ``` 1444 | 1445 | **app.js** 1446 | ```javascript 1447 | 1448 | var express = require('express'); 1449 | var app = express(); 1450 | var mongoose = require('mongoose'); 1451 | var config = require('./config'); 1452 | 1453 | var port = process.env.PORT || 3000; 1454 | 1455 | app.use('/assets', express.static(__dirname + '/public')); 1456 | 1457 | app.set('view engine', 'ejs'); 1458 | 1459 | mongoose.connect(config.getDbConnectionString()); 1460 | 1461 | app.listen(port); 1462 | ``` 1463 | ## 3. Adding Data 1464 | 1465 | **controllers/setupController.js** 1466 | ```javascript 1467 | 1468 | var Todos = require('../models/todoModel'); 1469 | 1470 | module.exports = function(app) { 1471 | 1472 | app.get('/api/setupTodos', function(req, res) { 1473 | 1474 | // seed database 1475 | var starterTodos = [ 1476 | { 1477 | username: 'test', 1478 | todo: 'Buy milk', 1479 | isDone: false, 1480 | hasAttachment: false 1481 | }, 1482 | { 1483 | username: 'test', 1484 | todo: 'Feed dog', 1485 | isDone: false, 1486 | hasAttachment: false 1487 | }, 1488 | { 1489 | username: 'test', 1490 | todo: 'Learn Node', 1491 | isDone: false, 1492 | hasAttachment: false 1493 | } 1494 | ]; 1495 | Todos.create(starterTodos, function(err, results) { 1496 | res.send(results); 1497 | }); 1498 | }); 1499 | 1500 | } 1501 | ``` 1502 | **app.js** 1503 | ```javascript 1504 | 1505 | var express = require('express'); 1506 | var app = express(); 1507 | var mongoose = require('mongoose'); 1508 | var config = require('./config'); 1509 | var setupController = require('./controllers/setupController'); 1510 | 1511 | var port = process.env.PORT || 3000; 1512 | 1513 | app.use('/assets', express.static(__dirname + '/public')); 1514 | 1515 | app.set('view engine', 'ejs'); 1516 | 1517 | mongoose.connect(config.getDbConnectionString()); 1518 | setupController(app); 1519 | 1520 | app.listen(port); 1521 | ``` 1522 | Run 1523 | `http://localhost:3000/api/setupTodos` 1524 | 1525 | ## 4. Create the API 1526 | **controllers/apiController** 1527 | ```javascript 1528 | 1529 | var Todos = require('../models/todoModel'); 1530 | var bodyParser = require('body-parser'); 1531 | 1532 | module.exports = function(app) { 1533 | 1534 | app.use(bodyParser.json()); // Middleware 1535 | app.use(bodyParser.urlencoded({ extended: true })); // Middleware 1536 | 1537 | app.get('/api/todos/:uname', function(req, res) { 1538 | 1539 | Todos.find({ username: req.params.uname }, function(err, todos) { 1540 | if (err) throw err; 1541 | 1542 | res.send(todos); 1543 | }); 1544 | 1545 | }); 1546 | 1547 | app.get('/api/todo/:id', function(req, res) { 1548 | 1549 | Todos.findById({ _id: req.params.id }, function(err, todo) { 1550 | if (err) throw err; 1551 | 1552 | res.send(todo); 1553 | }); 1554 | 1555 | }); 1556 | 1557 | app.post('/api/todo', function(req, res) { 1558 | 1559 | if (req.body.id) { // if i received an id I know that is an update 1560 | Todos.findByIdAndUpdate(req.body.id, { todo: req.body.todo, isDone: req.body.isDone, hasAttachment: req.body.hasAttachment }, function(err, todo) { 1561 | if (err) throw err; 1562 | 1563 | res.send('Success'); 1564 | }); 1565 | } 1566 | 1567 | else { 1568 | 1569 | var newTodo = Todos({ 1570 | username: 'test', 1571 | todo: req.body.todo, 1572 | isDone: req.body.isDone, 1573 | hasAttachment: req.body.hasAttachment 1574 | }); 1575 | newTodo.save(function(err) { 1576 | if (err) throw err; 1577 | res.send('Success'); 1578 | }); 1579 | 1580 | } 1581 | 1582 | }); 1583 | 1584 | app.delete('/api/todo', function(req, res) { 1585 | 1586 | Todos.findByIdAndRemove(req.body.id, function(err) { 1587 | if (err) throw err; 1588 | res.send('Success'); 1589 | }) 1590 | 1591 | }); 1592 | 1593 | } 1594 | ``` 1595 | **app.js** 1596 | ```javascript 1597 | 1598 | var express = require('express'); 1599 | var app = express(); 1600 | var mongoose = require('mongoose'); 1601 | var config = require('./config'); 1602 | var setupController = require('./controllers/setupController'); 1603 | var apiController = require('./controllers/apiController'); 1604 | 1605 | var port = process.env.PORT || 3000; 1606 | 1607 | app.use('/assets', express.static(__dirname + '/public')); 1608 | 1609 | app.set('view engine', 'ejs'); 1610 | 1611 | mongoose.connect(config.getDbConnectionString()); 1612 | setupController(app); 1613 | apiController(app); 1614 | 1615 | app.listen(port); 1616 | ``` 1617 | --------------------------------------------------------------------------------