tag:code.tutsplus.com,2005:/categories/expressEnvato Tuts+ Code - Express2018-11-09T22:25:19Ztag:code.tutsplus.com,2005:PostPresenter/cms-32088File Upload With Multer in Node.js and Express<p>When a web client uploads a file to a server, it is generally submitted through a form and encoded as <code class="inline">multipart/form-data</code>. Multer is middleware for Express and Node.js that makes it easy to handle this <code class="inline">multipart/form-data</code> when your users upload files. </p><p>In this tutorial, I'll show you how to use the Multer library to handle different file upload situations in Node.</p><h2>How Does Multer Work?<br>
</h2><p>As I said above, Multer is Express middleware. Middleware is a piece of software that connects different applications or software components. In Express, middleware processes and transforms incoming requests to the server. In our case, Multer acts as a helper when uploading files.</p><h3>Project Setup<br>
</h3><p>We will be using the Node Express framework for this project. Of course, you'll need to have Node installed. </p><p>Create a directory for our project, navigate into the directory, and issue <code class="inline">npm init</code> to create a <strong>.json</strong> file that manages all the dependencies for our application.</p><pre class="brush: bash noskimlinks noskimwords">mkdir upload-express
cd upload-express
npm init</pre><p>Next, install Multer, Express, and the other dependencies necessary to bootstrap an Express app.</p><pre class="brush: bash noskimlinks noskimwords">npm install express multer body-parser --save</pre><p>Next, create a <strong>server.js</strong> file. <br></p><pre class="brush: bash noskimlinks noskimwords">touch server.js</pre><p>Then, in <strong>server.js</strong>, we will initialize all the modules, create an Express app, and create a server for connecting to browsers. <br></p><pre class="brush: javascript noskimlinks noskimwords">// call all the required packages
const express = require('express')
const bodyParser= require('body-parser')
const multer = require('multer');
app.use(bodyParser.urlencoded({extended: true}))
const app = express()
//CREATE EXPRESS APP
const app = express();
//ROUTES WILL GO HERE
app.get('/', function(req, res) {
res.json({ message: 'WELCOME' });
});
app.listen(3000, () =&gt; console.log('Server started on port 3000'));</pre><p>Running <code>node server.js</code> and navigating to <code>localhost:3000</code> on your browser should give you the following message.</p><figure class="post_image"><img alt="welcome message" data-src="https://cms-assets.tutsplus.com/uploads/users/1885/posts/32088/image/welcome.png" title="Image: https://cms-assets.tutsplus.com/uploads/users/1885/posts/32088/image/welcome.png"></figure><h3>Create the Client Code</h3><p>The next thing will be to create an <strong>index.html</strong> file to write all the code that will be served to the client.<br><strong></strong></p><pre class="brush: bash noskimlinks noskimwords">touch index.html</pre><p>This file will contain the different forms that we will use for uploading our different file types.</p><pre class="brush: html noskimlinks noskimwords">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;title&gt;MY APP&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;!-- SINGLE FILE --&gt;
&lt;form action="/uploadfile" enctype="multipart/form-data" method="POST"&gt;
&lt;input type="file" name="myFile" /&gt;
&lt;input type="submit" value="Upload a file"/&gt;
&lt;/form&gt;
&lt;!-- MULTIPLE FILES --&gt;
&lt;form action="/uploadmultiple" enctype="multipart/form-data" method="POST"&gt;
Select images: &lt;input type="file" name="myFiles" multiple&gt;
&lt;input type="submit" value="Upload your files"/&gt;
&lt;/form&gt;
&lt;!-- PHOTO--&gt;
&lt;form action="/upload/photo" enctype="multipart/form-data" method="POST"&gt;
&lt;input type="file" name="myImage" accept="image/*" /&gt;
&lt;input type="submit" value="Upload Photo"/&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre><p>Open <strong>server.js</strong> and write a GET route that renders the <strong>index.html</strong> file instead of the <strong>"WELCOME"</strong> message. <br></p><pre class="brush: javascript noskimlinks noskimwords">// ROUTES
app.get('/',function(req,res){
res.sendFile(__dirname + '/index.html');
});</pre><h3>Multer Storage</h3><p>The next thing will be to define a storage location for our files. Multer gives the option of storing files to disk, as shown below. Here, we set up a directory where all our files will be saved, and we'll also give the files a new identifier.<br></p><pre class="brush: plain noskimlinks noskimwords">//server.js
// SET STORAGE
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
})
var upload = multer({ storage: storage })</pre><h3>Handling File Uploads</h3><h4>Uploading a Single File</h4><p>In the <strong>index.html</strong> file, we defined an action attribute that performs a POST request. Now we need to create an endpoint in the Express application. Open the <strong>server.js</strong> file and add the following code:</p><pre class="brush: javascript noskimlinks noskimwords">app.post('/uploadfile', upload.single('myFile'), (req, res, next) =&gt; {
const file = req.file
if (!file) {
const error = new Error('Please upload a file')
error.httpStatusCode = 400
return next(error)
}
res.send(file)
})</pre><p>Note that the name of the file field should be the same as the <code class="inline">myFile</code> argument passed to the <code class="inline">upload.single</code> function.</p><h4>Uploading Multiple Files</h4><p>Uploading multiple files with Multer is similar to a single file upload, but with a few changes.</p><pre class="brush: javascript noskimlinks noskimwords">//Uploading multiple files
app.post('/uploadmultiple', upload.array('myFiles', 12), (req, res, next) =&gt; {
const files = req.files
if (!files) {
const error = new Error('Please choose files')
error.httpStatusCode = 400
return next(error)
}
res.send(files)
})
</pre><h4>Uploading Images</h4><p>Instead of saving uploaded images to the file system, we will store them in a MongoDB database so that we can retrieve them later as needed. But first, let's install MongoDB.<br></p><pre class="brush: bash noskimlinks noskimwords">npm install mongodb --save</pre><p>We will then connect to MongoDB through the <code class="inline">Mongo.client</code> method and then add the MongoDB URL to that method. You can use a cloud service like Mlab, which offers a free plan, or simply use the locally available connection.</p><pre class="brush: javascript noskimlinks noskimwords">const MongoClient = require('mongodb').MongoClient
const myurl = 'mongodb://localhost:27017';
MongoClient.connect(myurl, (err, client) =&gt; {
if (err) return console.log(err)
db = client.db('test')
app.listen(3000, () =&gt; {
console.log('listening on 3000')
})
})
</pre><p>Open <strong>server.js</strong> and define a POST request that enables the saving of images to the database.</p><pre class="brush: javascript noskimlinks noskimwords">app.post('/uploadphoto', upload.single('picture'), (req, res) =&gt; {
var img = fs.readFileSync(req.file.path);
var encode_image = img.toString('base64');
// Define a JSONobject for the image attributes for saving to database
var finalImg = {
contentType: req.file.mimetype,
image: new Buffer(encode_image, 'base64')
};
db.collection('quotes').insertOne(finalImg, (err, result) =&gt; {
console.log(result)
if (err) return console.log(err)
console.log('saved to database')
res.redirect('/')
})
})</pre><p>In the above code, we first encode the image to a base64 string, construct a new buffer from the base64 encoded string, and then save it to our database collection in JSON format.</p><p>We then display a success message and redirect the user to the index page.<br></p><h3>Retrieving Stored Images</h3><p>To retrieve the stored images, we perform a MongoDB search using the <code>find</code> method and return an array of results. We then go on and obtain the <code class="inline">_id</code> attributes of all the images and return them to the user.<br></p><pre class="brush: javascript noskimlinks noskimwords">app.get('/photos', (req, res) =&gt; {
db.collection('mycollection').find().toArray((err, result) =&gt; {
const imgArray= result.map(element =&gt; element._id);
console.log(imgArray);
if (err) return console.log(err)
res.send(imgArray)
})
});</pre><p>Since we already know the id's of the images, we can view an image by passing its id in the browser, as illustrated below.</p><pre class="brush: javascript noskimlinks noskimwords">app.get('/photo/:id', (req, res) =&gt; {
var filename = req.params.id;
db.collection('mycollection').findOne({'_id': ObjectId(filename) }, (err, result) =&gt; {
if (err) return console.log(err)
res.contentType('image/jpeg');
res.send(result.image.buffer)
})
})
</pre><figure class="post_image"><img alt="Saved image" data-src="https://cms-assets.tutsplus.com/uploads/users/1885/posts/32088/image/Saved%20image.png" title="Image: https://cms-assets.tutsplus.com/uploads/users/1885/posts/32088/image/Saved%20image.png"></figure><h2>Conclusion</h2><p>I hope you found this tutorial helpful. File upload can be an intimidating topic, but it doesn't have to be hard to implement. With Express and Multer, handling <code class="inline">multipart/form-data</code> is easy and straightforward. </p><p>You can find the <a href="https://github.com/tutsplus/file-upload-with-multer-in-node" target="_self">full source code for the file upload example in our GitHub repo</a>.</p>2018-11-09T22:25:19.137Z2018-11-09T22:25:19.137ZEsther Vaatitag:code.tutsplus.com,2005:PostPresenter/cms-32006Angular Authentication With JWT<p>Security is an important part of every web app, and devs must ensure that they design apps with secure authentication. In this tutorial, you'll learn how to implement JWT-based authentication in Angular apps with the help of a simple Express server.</p><p>The <a href="https://github.com/tutsplus/angular-authentication-with-jwt" target="_self" title="Link: https://github.com/tutsplus/angular-authentication-with-jwt">full code can be found in our GitHub repo</a>. The app we'll be building will look like this: </p><figure class="post_image"><img alt="Final Look" data-src="https://cms-assets.tutsplus.com/uploads/users/1885/posts/32006/image/jwt-app.png" title="Image: https://cms-assets.tutsplus.com/uploads/users/1885/posts/32006/image/jwt-app.png"></figure><h2>
<strong>The Concept of JSON Web Tokens</strong><strong></strong>
</h2><p>A JSON Web Token (JWT) is basically an object represented by three strings that are used to transmit user information. The three strings, which are separated by dots, are:</p><ul>
<li>header</li>
<li>payload</li>
<li>signature</li>
</ul><p>When a user logs in to any web page with their username and password, the authenticating server usually creates and sends back a JWT. This JWT is then passed along with subsequent API calls to the server. The JWT remains valid unless it expires or the user signs out of the application.</p><p>This process can be illustrated in the diagram below.</p><figure class="post_image"><img alt="JWT authorization flow" data-src="https://cms-assets.tutsplus.com/uploads/users/1885/posts/32006/image/jwt-diagram.png" title="Image: https://cms-assets.tutsplus.com/uploads/users/1885/posts/32006/image/jwt-diagram.png"></figure><h3>Cookies vs. Local Storage</h3><p>We'll be using local storage to store tokens. Local storage is a means by which data is stored locally and can only be removed via JavaScript or by clearing the cache in the browser. Data stored in local storage can persist for a very long time. Cookies, on the other hand, are messages that are sent from the server to the browser and offer only limited storage.</p><h2>Building the Express Server</h2><p>We will start by building a back-end server that will feature the following endpoints:</p><ul>
<li>POST <strong>&lt;webservice&gt;/login</strong> <br>
</li>
<li>POST <strong>&lt;webservice&gt;/profile</strong> <br>
</li>
</ul><p>Let's get started by creating a directory for the Express application and then run the command <code class="inline">npm init</code> to set up the required files for the project.</p><pre class="brush: bash noskimlinks noskimwords">mkdir server
cd server
npm init</pre><p>Next, create a file <strong>server.js</strong> and install the modules: <code class="inline">express</code>, <code class="inline">jsonwebtoken</code>, <code class="inline">cors</code>, and <code class="inline">bodyParser</code>.</p><pre class="brush: bash noskimlinks noskimwords">touch server.js
npm install express jsonwebtoken cors bodyParser –save</pre><p>Now open <strong>server.js</strong> and start by importing the modules.</p><pre class="brush: javascript noskimlinks noskimwords">// server.js
const cors = require('cors');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');
const express = require('express');
</pre><p>Then create an Express app and define the secret key that will be used to encode and decode the user details.</p><pre class="brush: javascript noskimlinks noskimwords">//CREATE EXPRESS APP
const app = express();
app.use(cors());
app.use(bodyParser.json());
// DECLARE JWT-secret
const JWT_Secret = 'your_secret_key';</pre><p>We will not be using a database for this example. However, the concepts would be similar if you were building a proper database-backed server. </p><p>For our example, we will just use a variable to define a test user as shown below.</p><pre class="brush: javascript noskimlinks noskimwords">var testUser = { email: 'kelvin@gmai.com', password: '1234'};
</pre><p>The final step is to create routes for authenticating the user.</p><pre class="brush: javascript noskimlinks noskimwords">app.post('/api/authenticate', (req, res) =&gt; {
if (req.body) {
var user = req.body;
console.log(user)
if (testUser.email===req.body.email &amp;&amp; testUser.password === req.body.password) {
var token = jwt.sign(user, JWT_Secret);
res.status(200).send({
signed_user: user,
token: token
});
} else {
res.status(403).send({
errorMessage: 'Authorisation required!'
});
}
} else {
res.status(403).send({
errorMessage: 'Please provide email and password'
});
}
});</pre><p>Let's break down the code for the route above. </p><p>We first check if there is any data in the body of the request. If no data is found, we prompt the user to input some data. On the occasion that the user has provided the right data, we compare it to the data from the <code class="inline">testUser</code> and, if it matches, we use the user id to generate a unique token and send back the response to the user.</p><p>Finally, we create an endpoint for running the app.</p><pre class="brush: javascript noskimlinks noskimwords">app.listen(5000, () =&gt; console.log('Server started on port 5000'));
</pre><p>Our back-end is now complete, and you can test it with Postman<strong> </strong>or CURL and see the kind of data that will be returned to the user.</p><h2>Build an Angular Application</h2><p>Our Angular application will feature the following pages:</p><ul>
<li>Home—This page will contain links to the login and profile pages.</li>
<li>Login—On this page, a user will enter their email and password, which will be sent to the server for authentication. If the credentials are correct, then a JWT token will be returned and the user will be redirected to the profile page.</li>
<li>Profile—This is a protected page that can only be accessed by a user with a valid token.</li>
</ul><p>Create an Angular application and create the <code class="inline">Login</code> and <code class="inline">Profile</code> components as shown below:</p><pre class="brush: bash noskimlinks noskimwords">ng new angular6jwt
cd angular6jwt
ng g component Login
ng g component Profile</pre><p>Next, add the code for the home page in <strong>app.component.html.</strong></p><pre class="brush: html noskimlinks noskimwords">&lt;!--The content below is only a placeholder and can be replaced.--&gt;
&lt;div style="text-align:center"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="nav-link" routerLink="/" routerLinkActive="active"&gt;Home&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a class="nav-link" routerLink="profile" routerLinkActive="active"&gt;Profile&lt;/a&gt; &lt;/li&gt;
&lt;li style="float:right" &gt; &lt;a class="nav-link" style="float:right" routerLink="login" routerLinkActive="active"&gt;Login&lt;/a&gt; &lt;/li&gt;
&lt;li style="float:right" &gt; &lt;a class ="nav-link" (click)="logout()" href="#"&gt;Logout&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="text-center"&gt;
&lt;p&gt;
Angular 6 Authentication with JWT Tutorial
&lt;/p&gt;
&lt;/div&gt;
&lt;router-outlet&gt;&lt;/router-outlet&gt;
</pre><p>Next, import the <code class="inline">RouterModule</code> and define the routes in <strong>app.module.ts.</strong></p><pre class="brush: javascript noskimlinks noskimwords">import { RouterModule } from '@angular/router';
@NgModule({
declarations: [
AppComponent,
LoginComponent,
ProfileComponent
],
imports: [
BrowserModule,
RouterModule,
FormsModule,
RouterModule.forRoot([
{ path: '', redirectTo: '/', pathMatch: 'full' },
{ path: 'login', component: LoginComponent },
{ path: 'profile', component: ProfileComponent }
]),
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
</pre><h3>Create Login Page</h3><p>The login page will contain two input fields for email and password, and a submit button as shown below:</p><pre class="brush: html noskimlinks noskimwords">&lt;h3&gt;Login&lt;/h3&gt;
&lt;div&gt;
&lt;div class="spacer"&gt;
&lt;label for="Email"&gt;Email&lt;/label&gt;
&lt;input type="text" placeholder="Email" [(ngModel)]="email"&gt;
&lt;/div&gt;
&lt;div class="spacer"&gt;
&lt;label for="password"&gt;Password&lt;/label&gt;
&lt;input type="password" placeholder="password" [(ngModel)]="password" class="form-control"/&gt;
&lt;/div&gt;
&lt;div class="spacer"&gt;
&lt;button type="submit" (click)="Login()"&gt;Login&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
</pre><h3>Create Profile Page</h3><p>The profile page will just be a simple message as shown below:</p><pre class="brush: html noskimlinks noskimwords">&lt;p&gt;
If you can see this page, you are logged in!
&lt;/p&gt;
</pre><h2> Auth With JWT in Angular</h2><p>We will start by creating an <code class="inline">Auth</code> Service that will facilitate the validation of user input and communication with the server.</p><pre class="brush: javascript noskimlinks noskimwords">// Create authentication service named Auth
ng g service Auth</pre><p>This creates two files, but we will mainly be interested in the <strong>auth.service.ts</strong> file where we will write all the code that interacts with the server. We will start by defining the REST API and the token as shown below:</p><pre class="brush: javascript noskimlinks noskimwords">export class AuthService {
api = 'http://localhost:3000/api';
token;
}</pre><p>Next, we will write the code that performs a POST request to the server with the user credentials. Here, we make a request to the API—if it's successful we store the token in <code class="inline">localStorage</code> and redirect the user to the profile page.</p><pre class="brush: javascript noskimlinks noskimwords">import { Injectable } from '@angular/core';
import { HttpClientModule, HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class AuthService {
uri = 'http://localhost:5000/api';
token;
constructor(private http: HttpClient,private router: Router) { }
login(email: string, password: string) {
this.http.post(this.uri + '/authenticate', {email: email,password: password})
.subscribe((resp: any) =&gt; {
this.router.navigate(['profile']);
localStorage.setItem('auth_token', resp.token);
})
);
}
}
</pre><p>We also define login and logout functions as shown below.</p><pre class="brush: javascript noskimlinks noskimwords">logout() {
localStorage.removeItem('token');
}
public get logIn(): boolean {
return (localStorage.getItem('token') !== null);
}
</pre><ul>
<li>
<strong>logout</strong>—clears the token from the local storage</li>
<li>
<strong>logIn</strong>—returns a boolean property that determines if a user is authenticated</li>
</ul><p>We then update the <code class="inline">logIn</code> property on the home page as shown.</p><pre class="brush: html noskimlinks noskimwords">&lt;ul&gt;
&lt;li&gt;&lt;a class="nav-link" routerLink="/" routerLinkActive="active"&gt;Home&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a class="nav-link" routerLink="profile" routerLinkActive="active" *ngIf="authService.logIn"&gt;Profile&lt;/a&gt; &lt;/li&gt;
&lt;li style="float:right" &gt; &lt;a class="nav-link" style="float:right" routerLink="login" routerLinkActive="active" *ngIf="!authService.logIn"&gt;Login&lt;/a&gt; &lt;/li&gt;
&lt;li style="float:right" &gt; &lt;a class ="nav-link" (click)="logout()" href="#" *ngIf="authService.logIn"&gt;Logout&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;
</pre><h2>Responding to User Events</h2><p>Now that we are done with the code that interacts with the server, we'll move on to handling user-generated events for the front-end.</p><p>We will write the function that will listen for click events from the login page and then pass the values to the <code class="inline">AuthService</code> to authenticate the user. Update your <strong>login.component.ts</strong> file to look like this:</p><pre class="brush: javascript noskimlinks noskimwords">import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { AuthService } from '../auth.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
email = '';
password = '';
constructor(private authService: AuthService) {
}
Login() {
console.log("you are logging in")
this.authService.login(this.email, this.password)
}
ngOnInit() { }
}</pre><p>Now if you run <code class="inline">ng serve</code> and navigate to <a href="http://localhost:4200" title="Link: http://localhost:4200">http://localhost:4200</a>, you can test your app.</p><pre class="brush: bash noskimlinks noskimwords">ng serve</pre><p>Click on the login link and supply the user credentials—remember, the valid credentials are defined in the Express app. Now, when you click on the login button, you will be redirected to the profile page. </p><h2>Conclusion</h2><p>In this tutorial, you learned how to get started with JWT authentication in Angular. Now you can authenticate and authorize with JWT in your Angular applications. There are many aspects of JWT that were not covered in this tutorial—see if you can explore some of them on your own!</p><p>Note that this tutorial was written for Angular 6, but the same concepts should work with Angular 2 or Angular 4.</p>2018-10-22T14:00:00.000Z2018-10-22T14:00:00.000ZEsther Vaatitag:code.tutsplus.com,2005:PostPresenter/cms-31963New Course: Build an App With JavaScript and the MEAN Stack<p>You can make your web development work a whole lot easier by taking advantage of the MEAN stack (MongoDB, Express, Angular, and Node.js). Find out how in our comprehensive new course, <a href="https://code.tutsplus.com/courses/build-an-app-from-scratch-with-javascript-and-the-mean-stack?ec_promo=teaser_post" target="_self">Build an App From Scratch With JavaScript and the MEAN Stack</a>. </p><h2>What You’ll Learn</h2><p>Full-stack web development requires coding both a front-end for the browser and a back-end server. Using JavaScript for both parts of the app makes life a lot simpler for full-stack devs. With the MEAN technologies, you can code a cutting-edge web app in JavaScript, from the front-end all the way down to the database.</p><p>In this detailed 3.5-hour course, <a href="https://tutsplus.com/authors/derek-jensen?ec_promo=teaser_post" target="_self">Derek Jensen</a> will show you how to use the MEAN technologies to build full-stack web apps using only JavaScript (and its close cousin TypeScript). You'll start from absolute scratch, scaffolding an empty project, and build up a complete web app using the MEAN stack. </p><figure class="post_image"><a href="https://code.tutsplus.com/courses/build-an-app-from-scratch-with-javascript-and-the-mean-stack?ec_promo=teaser_post" target="_self"><img alt="App created with the MEAN stack" data-src="https://cms-assets.tutsplus.com/uploads/users/48/posts/31963/image/MEAN-Stack-app.jpg"></a></figure><p>You'll learn how to configure a MongoDB database, how to write a database abstraction layer, and how to create a REST API to make that data available to the front-end. On the client side, you'll learn how to structure an Angular app, how to create a service to connect with the back-end API, and how to implement each of the UI components that make a complete app.<br></p><h2>Watch the Introduction</h2><figure><script src="//fast.wistia.com/assets/external/E-v1.js" async="async"></script><div class="wistia_responsive_padding"><div class="wistia_responsive_wrapper"><div class="wistia_embed wistia_async_d7xgyscf4e videoFoam=true"> </div></div></div></figure><h2>Take the Course</h2><p>You can take our new course straight away with a <a href="https://tutsplus.com/subscribe-with-elements?ec_promo=teaser_post" rel="external" target="_blank">subscription to Envato Elements</a>. For a single low monthly fee, you get access not only to this course, but also to our growing library of over 1,000 video courses and industry-leading eBooks on Envato Tuts+. </p><p>Plus you now get unlimited downloads from the huge Envato Elements library of 700,000+ creative assets. Create with unique fonts, photos, graphics and templates, and deliver better projects faster.</p>2018-10-18T10:39:02.000Z2018-10-18T10:39:02.000ZAndrew Blackmantag:code.tutsplus.com,2005:PostPresenter/cms-31909How to Build Medium's Real-Time Applause Feature With Angular and Pusher<p>In this article, you'll learn how to code real-time Angular apps with Pusher. We'll make an app that gives real-time feedback when a post is clicked—just like Medium's applause feature!<br></p><h2>What Is Pusher?</h2><p>Pusher is a service that provides developers with APIs which enable them to integrate real-time functionalities in web, mobile, and back-end applications. To learn more about Pusher, check out this tutorial video for an introduction.</p><ul class="roundup-block__contents posts--half-width roundup-block--list"><li class="roundup-block__content"><a class="roundup-block__content-link" href="http://code.tutsplus.com/tutorials/get-started-with-pusher-introducing-channels--cms-31251"><img class="roundup-block__preview-image" data-src="https://cms-assets.tutsplus.com/uploads/users/769/posts/31251/preview_image/MetaImage@1.png"><div class="roundup-block__primary-category topic-code">Cloud Services</div>
<div class="roundup-block__content-title">Get Started With Pusher: Introducing Channels</div>
<div class="roundup-block__author">Jeremy McPeak</div></a></li></ul><h2>Getting Started With Pusher in Angular</h2><p>As mentioned at the beginning of this tutorial, our app will give real-time feedback whenever someone clicks a post. </p><p>For starters, <strong></strong>make sure you have Node and npm installed on your machine. You'll also need Angular CLI to quickly bootstrap our app, so make sure you have it installed as well. If you don't have Angular CLI installed, simply issue the following command.</p><pre class="brush: bash noskimlinks noskimwords">npm install -g @angular/cli</pre><p>Next, use Angular CLI to create the Angular app.</p><pre class="brush: bash noskimlinks noskimwords">ng new pusher-angular</pre><p>The UI of our app will be very simple. It will have a post, an applause button which will be represented by a hand icon, and a counter of the number of claps the post has garnered. Open <strong>app.component.html </strong>and add the following code, in which we tie the click event to the <code class="inline">Applause()</code> function.</p><pre class="brush: html noskimlinks noskimwords">&lt;div align="center"&gt;
&lt;h1&gt;
{{ title }}!
&lt;/h1&gt;
&lt;p&gt;This article will show how to implement real-time functionality in Angular Applications using Pusher. We will make an application that gives real-time feedback when a post is clicked. The application will mainly focus on adding real-time functionality to the Angular application.&lt;/p&gt;
&lt;p&gt;Real-time functionality is an important component in modern applications. Users want immediate feedback when interacting with applications. This has prompted many developers to consider inclusion of this functionality due to tremendous demand.&lt;/p&gt;
&lt;h3&gt;What Is Pusher?&lt;/h3&gt;
&lt;p&gt;Pusher is a service that provides developers with APIs which enable them to integrate real-time functionalities in web, mobile, and back-end applications.&lt;/p&gt;
&lt;div div align="center"&gt;
&lt;h3&gt;{{claps}}&lt;/h3&gt;
&lt;img width="30" alt="medium Applause" (click)="Applause()" src="../assets/download.png" /&gt;
&lt;/div&gt;
&lt;/div&gt;</pre><h3>Adding Pusher to Your App<br>
</h3><p>We will first need to install the Pusher library with the <code class="inline">npm install</code> command. </p><pre class="brush: bash noskimlinks noskimwords">npm install --save pusher-js</pre><p>Next, load the Pusher Library by adding the following script in the <code class="inline">angular.json</code> file.</p><pre class="brush: plain noskimlinks noskimwords">//angular.json
"scripts": ["../node_modules/pusher-js/dist/web/pusher.min.js"]</pre><p>You will also need to have Pusher credentials, which can be obtained from the Pusher dashboard.</p><p>To obtain the credentials, log in to the Pusher dashboard and click <strong>Create new app</strong>. You will then fill out some details about your application and finally click on <strong>Create my app</strong>. Pusher also gives you some code to get started according to the technology you have chosen. The most important aspect of this process is the app credentials, which can be found on the <strong>App Keys</strong> tab.<br></p><h3>Integrate the Pusher Service</h3><p>We will then create our <code class="inline">PusherService</code> by running the command:</p><pre class="brush: bash noskimlinks noskimwords">ng generate service Pusher</pre><p>The above command will create two files, namely <strong>pusher.service.ts</strong> and <strong>pusher.service.spec.ts, </strong>which contain some boilerplate code to get started<strong>. </strong></p><p>Now import the service in the main module and include it as a provider as follows:</p><pre class="brush: javascript noskimlinks noskimwords">// app.module.ts
import { PusherService } from './pusher.service';
...
@NgModule({
providers: [PusherService],
...
})</pre><p>Angular also provides an environment file for storing credentials for security purposes: include your pusher key in <strong>environment.ts</strong>.</p><pre class="brush: javascript noskimlinks noskimwords">// environment.ts
export const environment = {
pusher: {
production: false,
key: '&lt;PUSHER_KEY&gt;',
}
};</pre><p>Next, import the environment module for use, declare Pusher as an import from the script we added earlier in <strong>angular.json</strong>, and declare a <code class="inline">Pusher</code> constant in the <code class="inline">PusherService</code> file as follows:</p><pre class="brush: javascript noskimlinks noskimwords">// pusher.service.ts
import { environment } from '../environment/environment';
declare const Pusher: any;
export class PusherService {
pusher: any;
constructor() {
this.pusher = new Pusher(environment.pusher.key);
}
}</pre><p>We want to make a request containing the number of claps to the server whenever a person likes a post and also subscribe to our Pusher channel. Go ahead and include the <code class="inline">HttpClient</code> in the constructor of the <code class="inline">PusherService</code>. Your <strong>pusher.service</strong> file should now look like this:<br></p><pre class="brush: bash noskimlinks noskimwords">declare const Pusher: any;
import { Injectable } from '@angular/core';
import { environment } from '../environments/environment';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class PusherService {
pusher: any;
channel: any;
constructor(private http: HttpClient) {
this.pusher = new Pusher(environment.pusher.key);
this.channel = this.pusher.subscribe('my_channel');
}
}</pre><p>Next, create a function that sends the number of claps to the server when the applause button is clicked.</p><pre class="brush: javascript noskimlinks noskimwords">// pusher.service.ts
export class PusherService {
// ...
clap( claps_count ) {
this.http.get(`http://localhost:3000/add/${claps_count}`)
.subscribe();
}
}</pre><p>Still on the client side, we will write a function that listens for click events from the angular application and increments the number of claps. We will also bind the Pusher service to our event.<br></p><pre class="brush: javascript noskimlinks noskimwords">import { PusherService } from './pusher.service';
//...
export class AppComponent implements OnInit {
title = 'Pusher Realtime Notifications';
claps: any = 0;
// Listen to click event and send claps increment to server
Applause() {
this.claps = parseInt(this.claps, 10) + 1;
this.pusherService.clap( this.claps );
}
constructor(private pusherService: PusherService) {
}
ngOnInit() {
this.pusherService.channel.bind('new-event', data =&gt; {
this.claps = data.claps ;
});
}
}
</pre><h2>Building the Node.js Server</h2><p>A server will be used to receive the data requests from the Angular app—we'll build it using Express, a simple and fast Node.js framework.</p><p>Create a directory named <strong>server</strong>, and run the following commands.</p><pre class="brush: bash noskimlinks noskimwords">mkdir server
cd server
npm init</pre><p>This creates all the necessary files to bootstrap a Node.js application. Next, install the Pusher, Express, and body-parser modules.</p><pre class="brush: bash noskimlinks noskimwords"> npm install --save pusher express body-parser </pre><p>Next, create a file <strong>index.js</strong> and import all the required modules:</p><pre class="brush: javascript noskimlinks noskimwords">const express = require('express');
const http = require('http');
const bodyParser = require('body-parser');
const port = process.env.PORT || '3000';
const app = express();
const Pusher = require('pusher');</pre><p>The next step is to initialize Pusher by instantiating Pusher with the necessary credentials. You can obtain the credentials from the Pusher dashboard.</p><pre class="brush: javascript noskimlinks noskimwords">const pusher = new Pusher({
appId: '607521',
key: 'e9f68f905ee8a22675fa',
secret: '37ab37aac91d180050c2',
});</pre><p>Define middleware, CORS headers, and the rest of the Node application configurations.</p><pre class="brush: javascript noskimlinks noskimwords">// define middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use((req, res, next) =&gt; {
res.header("Access-Control-Allow-Origin", "*")
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
next();
});
// Define routes
app.set('port', port);
const server = http.createServer(app);
server.listen(port, () =&gt; console.log(`Running on port ${port}`));</pre><p>We will then create the endpoint that will listen to any incoming requests from our Angular app. The endpoint will get the number of claps from the client and then trigger a messaging event.</p><pre class="brush: plain noskimlinks noskimwords">//server.js
.....
app.get("/add/:claps",function(req, res) {
pusher.trigger("my_channel", "new-event", {
});
});
</pre><p>Our server is now complete; you can start listening to incoming subscriptions by running <code class="inline">npm start</code>.<br></p><h2>Testing Our App<br>
</h2><p>Now run the client and server at the same time by issuing <code class="inline">ng serve</code> for the Angular app and <code class="inline">npm start</code> for the Express Server.</p><p>Ensure you have enabled client events on the Pusher dashboard, as shown below.<br></p><figure class="post_image"><img alt="Enable Client events" data-src="https://cms-assets.tutsplus.com/uploads/users/1885/posts/31909/image/enable-client-pusher.png"></figure> <p>Navigate to <a href="http://localhost:4200/">http://localhost:4200</a> and start interacting with the app by clicking on the applause button. Ensure you have two tabs side by side so that you can observe in real time how the number of claps increases when a post is liked.</p><figure class="post_image"><img alt="Real time Pusher" data-src="https://cms-assets.tutsplus.com/uploads/users/1885/posts/31909/image/Webp.net-compress-image.jpg"></figure><p>Another cool feature of Pusher is that you can view all the connections and messages sent by using the dashboard. Here's a screenshot of the dashboard for this app.</p><figure class="post_image"><img alt="Pusher Activity" data-src="https://cms-assets.tutsplus.com/uploads/users/1885/posts/31909/image/activity-pusher.png"></figure><h2>Conclusion</h2><p>As you have seen, it's very easy to integrate Pusher with an Angular app. This makes it possible to add functionality like real-time data sharing and push notifications to your app.</p><p>Pusher is also available for different platforms, so head over to the site and discover the magic of Pusher.</p>2018-10-11T12:02:09.000Z2018-10-11T12:02:09.000ZEsther Vaatitag:code.tutsplus.com,2005:PostPresenter/cms-31699Code Your First API With Node.js and Express: Connect a Database<h2>Build a REST API With Node.js and Express: Connecting a Database</h2>
<p>In the first tutorial, <a href="http://code.tutsplus.com/tutorials/code-your-first-api-with-nodejs-and-express-understanding-rest-apis--cms-31697" target="_self">Understanding RESTful APIs</a>, we learned what the REST architecture is, what HTTP request methods and responses are, and how to understand a RESTful API endpoint. In the second tutorial, <a href="http://code.tutsplus.com/tutorials/code-your-first-api-with-nodejs-and-express-set-up-the-server--cms-31698" target="_self">How to Set Up an Express API Server</a>, we learned how to build servers with both Node's built-in <code>http</code> module and the Express framework, and how to route the app we created to different URL endpoints. </p>
<p>Currently, we're using static data to display user information in the form of a JSON feed when the API endpoint is hit with a <code>GET</code> request. In this tutorial, we're going to set up a MySQL database to store all the data, connect to the database from our Node.js app, and allow the API to use the <code>GET</code>, <code>POST</code>, <code>PUT</code>, and <code>DELETE</code> methods to create a complete API. </p>
<h2>Installation</h2>
<p>Up to this point, we have not used a database to store or manipulate any data, so we're going to set one up. This tutorial will be using MySQL, and if you already have MySQL installed on your computer, you'll be ready to go on to the next step.</p>
<p>If you don't have MySQL installed, you can download <a href="https://www.mamp.info/en/">MAMP</a> for macOS and Windows, which provides a free, local server environment and database. Once you have this downloaded, open the program and click <strong>Start Servers</strong> to start MySQL.</p>
<p>In addition to setting up MySQL itself, we'll want GUI software to view the database and tables. For Mac, download <a href="https://www.sequelpro.com/">SequelPro</a>, and for Windows download <a href="https://www.webyog.com/product/sqlyog">SQLyog</a>. Once you have MySQL downloaded and running, you can use SequelPro or SQLyog to connect to <code>localhost</code> with the username <code>root</code> and password <code>root</code> on port <code>3306</code>.</p>
<p>Once everything is set up here, we can move on to setting up the database for our API. </p>
<h2>Setting Up the Database</h2>
<p>In your database viewing software, add a new database and call it <code>api</code>. Make sure MySQL is running, or you won't be able to connect to <code>localhost</code>.</p>
<p>When you have the <code>api</code> database created, move into it and run the following query to create a new table.</p>
<pre class="brush: sql noskimlinks noskimwords">CREATE TABLE `users` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(30) DEFAULT '',
`email` varchar(50) DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
</pre>
<p>This SQL query will create the structure of our <code>users</code> table. Each user will have an auto-incrementing id, a name, and an email address. </p>
<p>We can also fill the database with the same data that we're currently displaying through a static JSON array by running an <code>INSERT</code> query.</p>
<pre class="brush: sql noskimlinks noskimwords">INSERT INTO users (name, email)
VALUES ('Richard Hendricks', 'richard@piedpiper.com'),
('Bertram Gilfoyle', 'gilfoyle@piedpiper.com');
</pre>
<p>There is no need to input the <code>id</code> field, as it is auto-incrementing. At this point, we have the structure of our table as well as some sample data to work with.</p>
<h2>Connecting to MySQL</h2>
<p>Back in our app, we have to connect to MySQL from Node.js to begin working with the data. Earlier, we installed the <code>mysql</code> npm module, and now we're going to use it.</p>
<p>Create a new directory called <strong>data</strong> and make a <strong>config.js</strong> file.</p>
<p>We'll begin by requiring the <code>mysql</code> module in <strong>data/config.js</strong>.</p>
<pre class="brush: javascript noskimlinks noskimwords">const mysql = require('mysql');
</pre>
<p>Let's create a <code>config</code> object that contains the host, user, password, and database. This should refer to the <code>api</code> database we made and use the default localhost settings.</p>
<pre class="brush: javascript noskimlinks noskimwords">// Set database connection credentials
const config = {
host: 'localhost',
user: 'root',
password: 'root',
database: 'api',
};
</pre>
<p>For efficiency, we're going to create a <a href="https://www.npmjs.com/package/mysql#pooling-connections">MySQL pool</a>, which allows us to use multiple connections at once instead of having to manually open and close multiple connections.</p>
<pre class="brush: javascript noskimlinks noskimwords">// Create a MySQL pool
const pool = mysql.createPool(config);
</pre>
<p>Finally, we'll export the MySQL pool so the app can use it.</p>
<pre class="brush: javascript noskimlinks noskimwords">// Export the pool
module.exports = pool;
</pre>
<p>You can see the completed database configuration file in our GitHub repo.</p>
<p>Now that we're connecting to MySQL and our settings are complete, we can move on to interacting with the database from the API.</p>
<h2>Getting API Data From MySQL</h2>
<p>Currently, our <code>routes.js</code> file is manually creating a JSON array of users, which looks like this.</p>
<pre class="noskimlinks noskimwords">const users = [{ ...
</pre><p>Since we're no longer going to be using static data, we can delete that entire array and replace it with a link to our MySQL pool.</p>
<pre class="brush: javascript noskimlinks noskimwords">// Load the MySQL pool connection
const pool = require('../data/config');
</pre>
<p>Previously, the <code>GET</code> for the <code>/users</code> path was sending the static <code>users</code> data. Our updated code is going to query the database for that data instead. We're going to use a SQL query to <code>SELECT</code> all from the <code>users</code> table, which looks like this.</p>
<pre class="brush: sql noskimlinks noskimwords">SELECT * FROM users
</pre>
<p>Here is what our new <code>/users</code> get route will look like, using the <code>pool.query()</code> method.</p>
<pre class="brush: javascript noskimlinks noskimwords">// Display all users
app.get('/users', (request, response) =&gt; {
pool.query('SELECT * FROM users', (error, result) =&gt; {
if (error) throw error;
response.send(result);
});
});
</pre>
<p>Here, we're running the <code>SELECT</code> query and then sending the result as JSON to the client via the <code>/users</code> endpoint. If you restart the server and navigate to the <code>/users</code> page, you'll see the same data as before, but now it's dynamic.</p>
<h2>Using URL Parameters</h2>
<p>So far, our endpoints have been static paths—either the <code>/</code> root or <code>/users</code>—but what about when we want to see data only about a specific user? We'll need to use a variable endpoint.</p>
<p>For our users, we might want to retrieve information about each individual user based on their unique id. To do that, we would use a colon (<code>:</code>) to denote that it's a route parameter.</p>
<pre class="brush: javascript noskimlinks noskimwords">// Display a single user by ID
app.get('/users/:id', (request, response) =&gt; {
...
});
});
</pre>
<p>We can retrieve the parameter for this path with the <code>request.params</code> property. Since ours is named <code>id</code>, that will be how we refer to it. </p>
<pre class="brush: javascript noskimlinks noskimwords">const id = request.params.id;
</pre>
<p>Now we'll add a <code>WHERE</code> clause to our <code>SELECT</code> statement to only get results that have the specified <code>id</code>. </p>
<p>We'll use <code>?</code> as a placeholder to avoid SQL injection and pass the id through as a parameter, instead of building a concatenated string, which would be less secure.</p>
<pre class="brush: javascript noskimlinks noskimwords">pool.query('SELECT * FROM users WHERE id = ?', id, (error, result) =&gt; {
if (error) throw error;
response.send(result);
});
</pre>
<p>The full code for our individual user resource now looks like this:</p>
<pre class="brush: javascript noskimlinks noskimwords">// Display a single user by ID
app.get('/users/:id', (request, response) =&gt; {
const id = request.params.id;
pool.query('SELECT * FROM users WHERE id = ?', id, (error, result) =&gt; {
if (error) throw error;
response.send(result);
});
});
</pre>
<p>Now you can restart the server and navigate to <code>http://localhost/users/2</code> to see only the information for Gilfoyle. If you get an error like <code>Cannot GET /users/2</code>, it means you need to restart the server.</p>
<p>Going to this URL should return a single result.</p>
<pre class="noskimlinks noskimwords">[{
id: 2,
name: "Bertram Gilfoyle",
email: "gilfoyle@piedpiper.com"
}]
</pre><p>If that's what you see, congratulations: you've successfully set up a dynamic route parameter!</p>
<h2>Sending a POST Request</h2>
<p>So far, everything we've been doing has used <code>GET</code> requests. These requests are safe, meaning they do not alter the state of the server. We've simply been viewing JSON data.</p>
<p>Now we're going to begin to make the API truly dynamic by using a <code>POST</code> request to add new data.</p>
<p>I mentioned earlier in the Understanding REST article that we don't use verbs like <code>add</code> or <code>delete</code> in the URL for performing actions. In order to add a new user to the database, we'll <code>POST</code> to the same URL we view them from, but just set up a separate route for it.</p>
<pre class="brush: javascript noskimlinks noskimwords">// Add a new user
app.post('/users', (request, response) =&gt; {
...
});
</pre>
<p>Note that we're using <code>app.post()</code> instead of <code>app.get()</code> now.</p>
<p>Since we're creating instead of reading, we'll use an <code>INSERT</code> query here, much like we did at the initialization of the database. We'll send the entire <code>request.body</code> through to the SQL query.</p>
<pre class="brush: javascript noskimlinks noskimwords">pool.query('INSERT INTO users SET ?', request.body, (error, result) =&gt; {
if (error) throw error;
</pre>
<p>We're also going to specify the status of the response as <code>201</code>, which stands for <code>Created</code>. In order to get the id of the last inserted item, we'll use the <code>insertId</code> property.</p>
<pre class="brush: javascript noskimlinks noskimwords">response.status(201).send(`User added with ID: ${result.insertId}`);
</pre>
<p>Our entire <code>POST</code> receive code will look like this.</p>
<pre class="brush: javascript noskimlinks noskimwords">// Add a new user
app.post('/users', (request, response) =&gt; {
pool.query('INSERT INTO users SET ?', request.body, (error, result) =&gt; {
if (error) throw error;
response.status(201).send(`User added with ID: ${result.insertId}`);
});
});
</pre>
<p>Now we can send a <code>POST</code> request through. Most of the time when you send a <code>POST</code> request, you're doing it through a web form. We'll learn how to set that up by the end of this article, but the fastest and easiest way to send a test <code>POST</code> is with cURL, using the <a href="https://curl.haxx.se/docs/manpage.html#-d"><code>-d (--data)</code></a> flag.</p>
<p>We'll run <code>curl -d</code>, followed by a query string containing all the key/value pairs and the request endpoint.</p>
<pre class="brush: bash noskimlinks noskimwords">curl -d "name=Dinesh Chugtai&amp;email=dinesh@piedpiper.com" http://localhost:3002/users
</pre>
<p>Once you send this request through, you should get a response from the server.</p>
<pre class="noskimlinks noskimwords">User added with ID: 3
</pre><p>If you navigate to <code>http://localhost/users</code>, you'll see the latest entry added to the list.</p>
<h2>Sending a PUT Request</h2>
<p><code>POST</code> is useful for adding a new user, but we'll want to use <code>PUT</code> to modify an existing user. <code>PUT</code> is idempotent, meaning you can send the same request through multiple times and only one action will be performed. This is different than <code>POST</code>, because if we sent our new user request through more than once, it would keep creating new users.</p>
<p>For our API, we're going to set up <code>PUT</code> to be able to handle editing a single user, so we're going to use the <code>:id</code> route parameter this time.</p>
<p>Let's create an <code>UPDATE</code> query and make sure it only applies to the requested id with the <code>WHERE</code> clause. We're using two <code>?</code> placeholders, and the values we pass will go in sequential order.</p>
<pre class="brush: javascript noskimlinks noskimwords">// Update an existing user
app.put('/users/:id', (request, response) =&gt; {
const id = request.params.id;
pool.query('UPDATE users SET ? WHERE id = ?', [request.body, id], (error, result) =&gt; {
if (error) throw error;
response.send('User updated successfully.');
});
});
</pre>
<p>For our test, we'll edit user <code>2</code> and update the email address from <a href="mailto:%60gilfoyle@piedpiper.com">gilfoyle@piedpiper.com</a> to <a href="mailto:bertram@piedpiper.com">bertram@piedpiper.com</a>. We can use cURL again, with the <code class="inline"><a href="https://curl.haxx.se/docs/manpage.html#-X" target="_self">[-X (--request)]</a></code> flag, to explicitly specify that we're sending a PUT request through.</p>
<pre class="brush: bash noskimlinks noskimwords">curl -X PUT -d "name=Bertram Gilfoyle" -d "email=bertram@piedpiper.com" http://localhost:3002/users/2
</pre>
<p>Make sure to restart the server before sending the request, or else you'll get the <code>Cannot PUT /users/2</code> error.</p>
<p>You should see this:</p>
<pre class="noskimlinks noskimwords">User updated successfully.
</pre><p>The user data with id <code>2</code> should now be updated.</p>
<h2>Sending a DELETE Request</h2>
<p>Our last task to complete the CRUD functionality of the API is to make an option for deleting a user from the database. This request will use the <code>DELETE</code> SQL query with <code>WHERE</code>, and it will delete an individual user specified by a route parameter.</p>
<pre class="brush: javascript noskimlinks noskimwords">// Delete a user
app.delete('/users/:id', (request, response) =&gt; {
const id = request.params.id;
pool.query('DELETE FROM users WHERE id = ?', id, (error, result) =&gt; {
if (error) throw error;
response.send('User deleted.');
});
});
</pre>
<p>We can use <code>-X</code> again with cURL to send the delete through. Let's delete the latest user we created.</p>
<pre class="noskimlinks noskimwords">curl -X DELETE http://localhost:3002/users/3
</pre><p>You'll see the success message.</p>
<pre class="noskimlinks noskimwords">User deleted.
</pre><p>Navigate to <code>http://localhost:3002</code>, and you'll see that there are only two users now.</p>
<p>Congratulations! At this point, the API is complete. Visit the <a href="https://github.com/tutsplus/code-your-first-api-with-nodejs-and-express-connect-a-database/blob/master/routes/routes.js" target="_self">GitHub repo to see the complete code for <strong>routes.js</strong></a>.</p>
<h2>Sending Requests Through the <code>request</code> Module</h2>
<p>At the beginning of this article, we installed four dependencies, and one of them was the <code>request</code> module. Instead of using cURL requests, you could make a new file with all the data and send it through. I'll create a file called <strong>post.js</strong> that will create a new user via <code>POST</code>.</p>
<pre class="brush: javascript noskimlinks noskimwords">const request = require('request');
const json = {
"name": "Dinesh Chugtai",
"email": "dinesh@piedpiper.com",
};
request.post({
url: 'http://localhost:3002/users',
body: json,
json: true,
}, function (error, response, body) {
console.log(body);
});
</pre>
<p>We can call this using <code>node post.js</code> in a new terminal window while the server is running, and it will have the same effect as using cURL. If something is not working with cURL, the <code>request</code> module is useful as we can view the error, response, and body.</p>
<h2>Sending Requests Through a Web Form</h2>
<p>Usually, <code>POST</code> and other HTTP methods that alter the state of the server are sent using HTML forms. In this very simple example, we can create an <strong>index.html</strong> file anywhere, and make a field for a name and email address. The form's action will point to the resource, in this case <code>http//localhost:3002/users</code>, and we'll specify the method as <code>post</code>.</p>
<p>Create <strong>index.html</strong> and add the following code to it:</p>
<pre class="brush: html noskimlinks noskimwords">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
&lt;meta charset="utf-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Node.js Express REST API&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;form action="http://localhost:3002/users" method="post"&gt;
&lt;label for="name"&gt;Name&lt;/label&gt;
&lt;input type="text" name="name"&gt;
&lt;label for="email"&gt;Email&lt;/label&gt;
&lt;input type="email" name="email"&gt;
&lt;input type="submit"&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Open this static HTML file in your browser, fill it out, and send it while the server is running in the terminal. You should see the response of <code>User added with ID: 4</code>, and you should be able to view the new list of users.</p>
<h2>Conclusion</h2>
<p>In this tutorial, we learned how to hook up an Express server to a MySQL database and set up routes that correspond to the <code>GET</code>, <code>POST</code>, <code>PUT</code>, and <code>DELETE</code> methods for paths and dynamic route parameters. We also learned how to send HTTP requests to an API server using cURL, the Node.js <code>request</code> module, and HTML forms. </p>
<p>At this point, you should have a very good understanding of how RESTful APIs work, and you can now create your own full-fledged API in Node.js with Express and MySQL!</p>2018-08-28T13:00:00.000Z2018-08-28T13:00:00.000ZTania Rasciatag:code.tutsplus.com,2005:PostPresenter/cms-31729Get Started With Node.js Express in Our New Course<p>Express is one of the most popular frameworks for building web applications in Node. In our new course, <a href="https://code.tutsplus.com/courses/get-started-with-nodejs-express?ec_promo=teaser_post_long" target="_self">Get Started With Node.js Express</a>, you’re going to learn Express from the ground up. If you haven’t had a chance to look into Express before, now’s your chance!</p><h2>What You’ll Learn</h2><p>In this course, <a href="https://tutsplus.com/authors/jeremy-mcpeak?ec_promo=teaser_post_long" target="_self">Jeremy McPeak</a> will teach you how to create a back-end web server with Node.js and Express. You’ll also learn:</p><ul>
<li>how to serve static assets such as CSS and images</li>
<li>how to use view engines to generate dynamic HTML</li>
<li>how to process POST requests with parameters</li>
<li>how to clean readable URLs</li>
<li>how to create middleware to keep your app architecture organized</li>
</ul><figure class="post_image"><a href="https://code.tutsplus.com/courses/get-started-with-nodejs-express?ec_promo=teaser_post_long" target="_self"><img alt="Getting started with Express" data-src="https://cms-assets.tutsplus.com/uploads/users/48/posts/31729/image/Express.jpg" title="Image: https://cms-assets.tutsplus.com/uploads/users/48/posts/31729/image/Express.jpg"></a></figure><p>In about an hour and a half, you’ll learn just about everything you need to get started using Express in your Node applications.</p><p>Here are some free lessons from this course, as a preview of what you can expect:</p><h3>Using a View Engine</h3><p>Web applications typically rely on view engines (aka templating engines) to generate HTML dynamically. In this video, you'll see how to start using the EJS templating engine so that you can serve more than static content.</p><figure><script src="//fast.wistia.com/assets/external/E-v1.js" async="async"></script><div class="wistia_responsive_padding"><div class="wistia_responsive_wrapper"><div class="wistia_embed wistia_async_csv8ote6sx videoFoam=true"> </div></div></div></figure><h3>Using Dynamic Routing and Query Strings</h3><p>In most data-driven apps, we don't know all the URLs ahead of time—they are dynamic. Fortunately, Express's routing engine makes it very easy to set up dynamic routes. You'll learn how to set them up and how to work with the query string in this video.</p><figure><script src="//fast.wistia.com/assets/external/E-v1.js" async="async"></script><div class="wistia_responsive_padding"><div class="wistia_responsive_wrapper"><div class="wistia_embed wistia_async_let7xjure2 videoFoam=true"> </div></div></div></figure><h3>Writing Middleware</h3><p>An Express app is really nothing more than a chain of middleware that processes the request. In this video, you'll learn how to write your own middleware to log requests to the console.</p><figure><script src="//fast.wistia.com/assets/external/E-v1.js" async="async"></script><div class="wistia_responsive_padding"><div class="wistia_responsive_wrapper"><div class="wistia_embed wistia_async_bw5ra4df45 videoFoam=true"> </div></div></div></figure><h2>Take the Course</h2><p>You can take our new course straight away with a <a href="https://tutsplus.com/subscribe-with-elements?ec_promo=teaser_post_long" rel="external" target="_blank">subscription to Envato Elements</a>. For a single low monthly fee, you get access not only to this course, but also to our growing library of over 1,000 video courses and industry-leading eBooks on Envato Tuts+. </p><p>Plus you now get unlimited downloads from the huge Envato Elements library of 650,000+ creative assets. Create with unique fonts, photos, graphics and templates, and deliver better projects faster.</p>2018-08-27T13:18:14.000Z2018-08-27T13:18:14.000ZAndrew Blackmantag:code.tutsplus.com,2005:PostPresenter/cms-31698Code Your First API With Node.js and Express: Set Up the Server<h2>How to Set Up an Express API Server in Node.js</h2>
<p>In the <a href="http://code.tutsplus.com/tutorials/code-your-first-api-with-nodejs-and-express-understanding-rest-apis--cms-31697" target="_self">previous tutorial</a>, we learned what the REST architecture is, the six guiding constraints of REST, how to understand HTTP request methods and their response codes, and the anatomy of a RESTful API endpoint.</p>
<p>In this tutorial, we'll set up a server for our API to live on. You can build an API with any programming language and server software, but we will use <a href="https://nodejs.org/en/">Node.js</a>, which is the back-end implementation of JavaScript, and <a href="https://expressjs.com/">Express</a>, a popular, minimal framework for Node. </p>
<h2>Installation</h2>
<p>Our first prerequisite is making sure Node.js and npm are installed globally on the computer. We can test both using the <code>-v</code> flag, which will display the version. Open up your command prompt and type the following.</p>
<pre class="brush: bash noskimlinks noskimwords">node -v &amp;&amp; npm -v</pre>
<pre class="noskimlinks noskimwords">v10.8.0
6.2.0</pre>
<p>Your versions may be slightly different than mine, but as long as both are there, we can get started.</p>
<p>Let's create a project directory called <code>express-api</code> and move to it.</p>
<pre class="brush: bash noskimlinks noskimwords">mkdir express-api &amp;&amp; cd express-api
</pre>
<p>Now that we're in our new directory, we can initialize our project with the init command.</p>
<pre class="brush: bash noskimlinks noskimwords">npm init
</pre>
<p>This command will prompt you to answer some questions about the project, which you can choose to fill out or not. Once the setup is complete, you'll have a <strong>package.json</strong> file that looks like this:</p>
<pre class="brush: javascript noskimlinks noskimwords">{
"name": "express-api",
"version": "1.0.0",
"description": "Node.js and Express REST API",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" &amp;&amp; exit 1"
},
"author": "Tania Rascia",
"license": "MIT"
}
</pre>
<p>Now that we have our <strong>package.json</strong>, we can install the dependencies required for our project. Fortunately we don't require too many dependencies, just these four listed below.</p>
<ul>
<li>
<a href="https://www.npmjs.com/package/body-parser">body-parser</a>: Body parsing middleware.</li>
<li>
<a href="https://www.npmjs.com/package/express">express</a>: A minimalist web framework we'll use for our server.</li>
<li>
<a href="https://www.npmjs.com/package/mysql">mysql</a>: A MySQL driver.</li>
<li>
<a href="https://www.npmjs.com/package/request">request</a> (optional): A simple way to make HTTP calls.</li>
</ul>
<p>We'll use the <code>install</code> command followed by each dependency to finish setting up our project.</p>
<pre class="brush: bash noskimlinks noskimwords">npm install body-parser express mysql request
</pre>
<p>This will create a <strong>package-lock.json</strong> file and a <strong>node_modules</strong> directory, and our <strong>package.json</strong> will be updated to look something like this:</p>
<pre class="brush: javascript noskimlinks noskimwords">{
"name": "express-api",
"version": "1.0.0",
"description": "Node.js and Express REST API",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" &amp;&amp; exit 1"
},
"author": "Tania Rascia",
"license": "MIT",
"dependencies": {
"dependencies": {
"body-parser": "^1.18.3",
"express": "^4.16.3",
"mysql": "^2.16.0",
"request": "^2.88.0"
}
}
</pre>
<h2>Setting Up an HTTP Server</h2>
<p>Before we get started on setting up an Express server, we will quickly set up an HTTP server with Node's built-in <code>http</code> module, to get an idea of how a simple server works.</p>
<p>Create a file called <strong>hello-server.js</strong>. Load in the <code>http</code> module, set a port number (I chose <code>3001</code>), and create the server with the <code>createServer()</code> method.</p>
<pre class="brush: javascript noskimlinks noskimwords">// Build a server with Node's HTTP module
const http = require('http');
const port = 3001;
const server = http.createServer();
</pre>
<p>In the introductory REST article, we discussed what requests and responses are with regards to an HTTP server. We're going to set our server to handle a request and display the URL requested on the server side, and display a <strong>Hello, server!</strong> message to the client on the response side.</p>
<pre class="brush: javascript noskimlinks noskimwords">server**on('request'** (request, response) =&gt; {
console.log(`URL: ${request.url}`);
response.end('Hello, server!')
})
</pre>
<p>Finally, we will tell the server which port to listen on, and display an error if there is one.</p>
<pre class="brush: javascript noskimlinks noskimwords">// Start the server
server.listen(port, (error) =&gt; {
if (error) return console.log(`Error: ${error}`);
console.log(`Server is listening on port ${port}`)
})
</pre>
<p>Now, we can start our server with <code>node</code> followed by the filename.</p>
<pre class="brush: bash noskimlinks noskimwords">node hello-server.js
</pre>
<p>You will see this response in the terminal:</p>
<pre class="noskimlinks noskimwords">Server is listening on port 3001
</pre><p>To check that the server is actually running, go to <code>http://localhost:3001/</code> in your browser's address bar. If all is working properly, you should see <strong>Hello, server!</strong> on the page. In your terminal, you'll also see the URLs that were requested.</p>
<pre class="noskimlinks noskimwords">URL: /
URL: /favicon.ico
</pre><p>If you were to navigate to <code>http://localhost:3001/hello</code>, you would see <code>URL: /hello</code>.</p>
<p>We can also use cURL on our local server, which will show us the exact headers and body that are being returned.</p>
<pre class="brush: bash noskimlinks noskimwords">curl -i http://localhost:3001
</pre>
<pre class="noskimlinks noskimwords">HTTP/1.1 200 OK
Date: Wed, 15 Aug 2018 22:14:23 GMT
Connection: keep-alive
Content-Length: 14
Hello, server!
</pre><p>If you close the terminal window at any time, the server will go away.</p>
<p>Now that we have an idea of how the server, request, and response all work together, we can rewrite this in Express, which has an even simpler interface and extended features.</p>
<h2>Setting Up an Express Server</h2>
<p>We're going to create a new file, <strong>app.js</strong>, which will be the entry point to our actual project. Just like with the original http server, we'll require a module and set a port to start.</p>
<p>Create an <strong>app.js</strong> file and put the following code in it.</p>
<pre class="brush: javascript noskimlinks noskimwords">// Require packages and set the port
const express = require('express');
const port = 3002;
const app = express();
</pre>
<p>Now, instead of looking for all requests, we will explicitly state that we are looking for a <code>GET</code> request on the root of the server (<code>/</code>). When <code>/</code> receives a request, we will display the URL requested and the "Hello, Server!" message.</p>
<pre class="brush: javascript noskimlinks noskimwords">app.get('/', (request, response) =&gt; {
console.log(`URL: ${request.url}`);
response.send('Hello, Server!');
});
</pre>
<p>Finally, we'll start the server on port <code>3002</code> with the <code>listen()</code> method.</p>
<pre class="brush: javascript noskimlinks noskimwords">// Start the server
const server = app.listen(port, (error) =&gt; {
if (error) return console.log(`Error: ${error}`);
console.log(`Server listening on port ${server.address().port}`);
});
</pre>
<p>We can start the server with <code>node app.js</code> as we did before, but we can also modify the <code>scripts</code> property in our <strong>package.json</strong> file to automatically run this specific command.</p>
<pre class="brush: javascript noskimlinks noskimwords">"scripts": {
"start": "node app.js"
},
</pre>
<p>Now we can use <code>npm start</code> to start the server, and we'll see our server message in the terminal.</p>
<pre class="noskimlinks noskimwords">Server listening on port 3002
</pre><p>If we run a <code>curl -i</code> on the URL, we will see that it is powered by Express now, and there are some additional headers such as <code>Content-Type</code>.</p>
<pre class="brush: bash noskimlinks noskimwords">curl -i http://localhost:3002
</pre>
<pre class="noskimlinks noskimwords">HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 14
ETag: W/"e-gaHDsc0MZK+LfDiTM4ruVL4pUqI"
Date: Wed, 15 Aug 2018 22:38:45 GMT
Connection: keep-alive
Hello, Server!
</pre><h2>Add Body Parsing Middleware</h2>
<p>In order to easily deal with <code>POST</code> and <code>PUT</code> requests to our API, we will add body parsing middleware. This is where our <code>body-parser</code> module comes in. <code>body-parser</code> will extract the entire body of an incoming request and parse it into a JSON object that we can work with.</p>
<p>We'll simply require the module at the top of our file. Add the following <code>require</code> statement to the top of your <strong>app.js</strong> file.</p>
<pre class="brush: javascript noskimlinks noskimwords">const bodyParser = require('body-parser');
...
</pre>
<p>Then we'll tell our Express app to use <code>body-parser</code>, and look for JSON.</p>
<pre class="brush: javascript noskimlinks noskimwords">// Use Node.js body parsing middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true,
}));
</pre>
<p>Also, let's change our message to send a JSON object as a response instead of plain text.</p>
<pre class="brush: javascript noskimlinks noskimwords">response.send({message: 'Node.js and Express REST API'});
</pre>
<p>Following is our full <strong>app.json</strong> file as it stands now.</p>
<pre class="brush: javascript noskimlinks noskimwords">// Require packages and set the port
const express = require('express');
const port = 3002;
const bodyParser = require('body-parser');
const app = express();
// Use Node.js body parsing middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true,
}));
app.get('/', (request, response) =&gt; {
response.send({
message: 'Node.js and Express REST API'}
);
});
// Start the server
const server = app.listen(port, (error) =&gt; {
if (error) return console.log(`Error: ${error}`);
console.log(`Server listening on port ${server.address().port}`);
});
</pre>
<p>If you send a <code>curl -i</code> to the server, you'll see that the header now returns <code>Content-Type: application/json; charset=utf-8</code>.</p>
<h2>Set Up Routes</h2>
<p>So far, we only have a <code>GET</code> route to the root (<code>/</code>), but our API should be able to handle all four major HTTP request methods on multiple URLs. We're going to set up a router and make some fake data to display.</p>
<p>Let's create a new directory called <strong>routes</strong>, and a file within called <strong>routes.js</strong>. We'll link to it at the top of <strong>app.js</strong>.</p>
<pre class="brush: javascript noskimlinks noskimwords">const routes = require('./routes/routes');
</pre>
<p>Note that the <code>.js</code> extension is not necessary in the require. Now we'll move our app's <code>GET</code> listener to <strong>routes.js</strong>. Enter the following code in <strong>routes.js</strong>.</p>
<pre class="brush: javascript noskimlinks noskimwords">const router = app =&gt; {
app.get('/', (request, response) =&gt; {
response.send({
message: 'Node.js and Express REST API'
});
});
}
</pre>
<p>Finally, export the <code>router</code> so we can use it in our <strong>app.js</strong> file.</p>
<pre class="brush: javascript noskimlinks noskimwords">// Export the router
module.exports = router;
</pre>
<p>In <strong>app.js</strong>, replace the <code>app.get()</code> code you had before with a call to <code>routes()</code>:</p>
<pre class="brush: javascript noskimlinks noskimwords">routes(app);
</pre>
<p>You should now be able to go to <code>http://localhost:3002</code> and see the same thing as before. (Don't forget to restart the server!)</p>
<p>Once that is all set up and working properly, we'll serve some JSON data with another route. We'll just use fake data for now, since our database is not yet set up.</p>
<p>Let's create a <code>users</code> variable in <strong>routes.js</strong>, with some fake user data in JSON format.</p>
<pre class="brush: javascript noskimlinks noskimwords">const users = [{
id: 1,
name: "Richard Hendricks",
email: "richard@piedpiper.com",
},
{
id: 2,
name: "Bertram Gilfoyle",
email: "gilfoyle@piedpiper.com",
},
];
</pre>
<p>We'll add another <code>GET</code> route to our router, <code>/users</code>, and send the user data through.</p>
<pre class="brush: javascript noskimlinks noskimwords">app.get('/users', (request, response) =&gt; {
response.send(users);
});
</pre>
<p>After restarting the server, you can now navigate to <code>http://localhost:3002/users</code> and see all our data displayed. </p>
<p>Note: If you do not have a JSON viewer extension on your browser, I highly recommend you download one, such as <a href="https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc?hl=en">JSONView</a> for Chrome. This will make the data much easier to read!</p>
<p>Visit our <a href="https://github.com/tutsplus/code-your-first-api-with-nodejs-and-express-set-up-the-server" target="_self">GitHub Repo</a> to see the completed code for this post and compare it to your own.</p>
<h2>Conclusion</h2>
<p>In this tutorial, we learned how to set up a built-in HTTP server and an Express server in node, route requests and URLs, and consume JSON data with get requests. </p><p>In the final installment of the RESTful API series, we will hook up our Express server to MySQL to create, view, update, and delete users in a database, finalizing our API's functionality.</p>2018-08-23T14:00:00.000Z2018-08-23T14:00:00.000ZTania Rasciatag:code.tutsplus.com,2005:PostPresenter/cms-31697Code Your First API With Node.js and Express: Understanding REST APIs<h2>Understanding REST and RESTful APIs</h2>
<p>If you've spent any amount of time with modern web development, you will have come across terms like REST and API. If you've heard of these terms or work with APIs but don't have a complete understanding of how they work or how to build your own API, this series is for you.</p>
<p>In this tutorial series, we will start with an overview of REST principles and concepts. Then we will go on to create our own full-fledged API that runs on a Node.js Express server and connects to a MySQL database. After finishing this series, you should feel confident building your own API or delving into the documentation of an existing API.</p>
<h3>Prerequisites</h3>
<p>In order to get the most out of this tutorial, you should already have some <a href="https://www.taniarascia.com/how-to-use-the-command-line-for-apple-macos-and-linux/">basic command line knowledge</a>, know the fundamentals of JavaScript, and have <a href="https://www.taniarascia.com/how-to-install-and-use-node-js-and-npm-mac-and-windows/">Node.js installed globally</a>.</p><ul class="roundup-block__contents posts--half-width roundup-block--list"><li class="roundup-block__content"><a class="roundup-block__content-link" href="http://code.tutsplus.com/tutorials/the-command-line-is-your-best-friend--net-30362"><img class="roundup-block__preview-image" data-src="https://cdn.tutsplus.com/net/authors/jeffreyway/command-line-is-your-best-friend.jpg"><div class="roundup-block__primary-category topic-code">Tools &amp; Tips</div>
<div class="roundup-block__content-title">The Command Line is Your Best Friend</div>
<div class="roundup-block__author">Patkos Csaba</div></a></li></ul>
<h2>What Are REST and RESTful APIs?</h2>
<p>Representational State Transfer, or <strong>REST</strong>, describes an architectural style for web services. REST consists of a set of standards or constraints for sharing data between different systems, and systems that implement REST are known as RESTful. REST is an abstract concept, not a language, framework, or type of software.</p>
<p>A loose analogy for REST would be keeping a collection of vinyl vs. using a streaming music service. With the physical vinyl collection, each record must be duplicated in its entirety to share and distribute copies. With a streaming service, however, the same music can be shared in perpetuity via a reference to some data such as a song title. In this case, the streaming music is a RESTful service, and the vinyl collection is a non-RESTful service.</p>
<p>An <strong>API</strong> is an Application Programming Interface, which is an interface that allows software programs to communicate with each other. A <strong>RESTful API</strong> is simply an API that adheres to the principles and constraints of REST. In a Web API, a server receives a <strong>request</strong> through a URL endpoint and sends a <strong>response</strong> in return, which is often data in a format such as JSON.</p>
<h2>REST Principles</h2>
<p>Six guiding constraints define the REST architecture, outlined below.</p>
<ol>
<li>
<strong>Uniform Interface</strong>: The interface of components must be the same. This means using the URI standard to identify resources—in other words, paths that could be entered into the browser's location bar.</li>
<li>
<strong>Client-Server</strong>: There is a separation of concerns between the server, which stores and manipulates data, and the client, which requests and displays the response.</li>
<li>
<strong>Stateless Interactions</strong>: All information about each request is contained in each individual request and does not depend on session state.</li>
<li>
<strong>Cacheable</strong>: The client and server can cache resources.</li>
<li>
<strong>Layered System</strong>: The client can be connected to the end server, or an intermediate layer such as a load-balancer.</li>
<li>
<strong>Code on Demand (Optional)</strong>: A client can download code, which reduces visibility from the outside.</li>
</ol>
<h2>Request and Response</h2>
<p>You will already be familiar with the fact that all websites have URLs that begin with <code>http</code> (or <code>https</code> for the secure version). HyperText Transfer Protocol, or <strong>HTTP</strong>, is the method of communication between clients and servers on the internet. </p>
<p>We see it most obviously in the URL bar of our browsers, but HTTP can be used for more than just requesting websites from servers. When you go to a URL on the web, you are actually doing a <code>GET</code> request on that specific resource, and the website you see is the body of the response. We will go over <code>GET</code> and other types of requests shortly.</p>
<p>HTTP works by opening a <strong>TCP</strong> (Transmission Control Protocol) connection to a server port (<code>80</code> for <code>http</code>, <code>443</code> for <code>https</code>) to make a request, and the listening server responds with a status and a body.</p>
<p>A request must consist of a URL, a method, header information, and a body.</p>
<h3>Request Methods</h3>
<p>There are four major HTTP methods, also referred to as HTTP verbs, that are commonly used to interact with web APIs. These methods define the action that will be performed with any given resource. </p>
<p>HTTP request methods loosely correspond to the paradigm of <strong>CRUD</strong>, which stands for <em>Create, Update, Read, Delete</em>. Although CRUD refers to functions used in database operations, we can apply those design principles to HTTP verbs in a RESTful API.</p><table>
<thead><tr>
<th>Action</th>
<th>Request Method</th>
<th>Definition</th>
</tr></thead>
<tbody>
<tr>
<td>Read</td>
<td><code>GET</code></td>
<td>Retrieves a resource</td>
</tr>
<tr>
<td>Create</td>
<td><code>POST</code></td>
<td>Creates a new resource</td>
</tr>
<tr>
<td>Update</td>
<td><code>PUT</code></td>
<td>Updates an existing resource</td>
</tr>
<tr>
<td>Delete</td>
<td><code>DELETE</code></td>
<td>Deletes a resource</td>
</tr>
</tbody>
</table><p><code>GET</code> is a safe, read-only operation that will not alter the state of a server. Every time you hit a URL in your browser, such as <code>https://www.google.com</code>, you are sending a <code>GET</code> request to Google's servers.</p>
<p><code>POST</code> is used to create a new resource. A familiar example of <code>POST</code> is signing up as a user on a website or app. After submitting the form, a <code>POST</code> request with the user data might be sent to the server, which will then write that information into a database. </p>
<p><code>PUT</code> updates an existing resource, which might be used to edit the settings of an existing user. Unlike <code>POST</code>, <code>PUT</code> is <strong>idempotent</strong>, meaning the same call can be made multiple times without producing a different result. For example, if you sent the same <code>POST</code> request to create a new user in a database multiple times, it would create a new user with the same data for each request you made. However, using the same <code>PUT</code> request on the same user would continuously produce the same result.</p>
<p><code>DELETE</code>, as the name suggests, will simply delete an existing resource.</p>
<h3>Response Codes</h3>
<p>Once a request goes through from the client to the server, the server will send back an HTTP response, which will include metadata about the response known as headers, as well as the body. The first and most important part of the response is the <strong>status code</strong>, which indicates if a request was successful, if there was an error, or if another action must be taken. </p>
<p>The most well-known response code you will be familiar with is <code>404</code>, which means <code>Not Found</code>. <code>404</code> is part of the <code>4xx</code> class of status codes, which indicate client errors. There are five classes of status codes that each contain a range of responses.</p><ul>
<li>
<code class="inline">1xx</code>: Information</li>
<li>
<code class="inline">2xx</code>: Success<br>
</li>
<li>
<em></em><code class="inline">3xx</code>: Redirection<br>
</li>
<li>
<code class="inline">4xx<em></em></code>: Client Error<br>
</li>
<li>
<code class="inline">5xx</code>: Server Error</li>
</ul>
<p>Other common responses you may be familiar with are <code>301 Moved Permanently</code>, which is used to redirect websites to new URLs, and <code>500 Internal Server Error</code>, which is an error that comes up frequently when something unexpected has happened on a server that makes it impossible to fulfil the intended request.</p><p>With regards to RESTful APIs and their corresponding HTTP verbs, all the responses should be in the <code>2xx</code> range. </p><table>
<thead><tr>
<th>Request</th>
<th>Response</th>
</tr></thead>
<tbody>
<tr>
<td><code>GET</code></td>
<td>
<code>200</code> (OK)</td>
</tr>
<tr>
<td><code>POST</code></td>
<td>
<code>201</code> (Created)</td>
</tr>
<tr>
<td><code>PUT</code></td>
<td>
<code>200</code> (OK)</td>
</tr>
<tr>
<td><code>DELETE</code></td>
<td>
<code>200</code> (OK), <code>202</code> (Accepted), or <code>204</code> (No Content)</td>
</tr>
</tbody>
</table><p><code>200 OK</code> is the response that indicates that a request is successful. It is used as a response when sending a <code>GET</code> or <code>PUT</code> request. <code>POST</code> will return a <code>201 Created</code> to indicate that a new resource has been created, and <code>DELETE</code> has a few acceptable responses, which convey that either the request has been accepted (<code>202</code>), or there is no content to return because the resource no longer exists (<code>204</code>). </p>
<p>We can test the status code of a resource request using cURL, which is a command-line tool used for transferring data via URLs. Using <code>curl</code>, followed by the <code>-i</code> or <code>--include</code> flag, will send a <code>GET</code> request to a URL and display the headers and body. We can test this by opening the command-line program and testing cURL with Google.</p>
<pre class="noskimlinks noskimwords"><code>curl -i https://www.google.com
</code></pre><p>Google's server will respond with the following.</p>
<pre class="brush: plain noskimlinks noskimwords">HTTP/2 200
date: Tue, 14 Aug 2018 05:15:40 GMT
expires: -1
cache-control: private, max-age=0
content-type: text/html; charset=ISO-8859-1
...</pre><p>As we can see, the <code>curl</code> request returns multiple headers and the entire HTML body of the response. Since the request went through successfully, the first part of the response is the <code>200</code> status code, along with the version of HTTP (this will either be HTTP/1.1 or HTTP/2).</p>
<p>Since this particular request is returning a website, the <code>content-type</code> (MIME type) being returned is <code>text/html</code>. In a RESTful API, you will likely see <code>application/json</code> to indicate the response is JSON.</p>
<p>Interestingly, we can see another type of response by inputting a slightly different URL. Do a <code>curl</code> on Google without the <code>www</code>.</p>
<pre class="noskimlinks noskimwords"><code>curl -i https://google.com
</code></pre><pre class="brush: plain noskimlinks noskimwords">HTTP/2 301
location: https://www.google.com/
content-type: text/html;
charset=UTF-8</pre><p>Google redirects <code>google.com</code> to <code>www.google.com</code>, and uses a <code>301</code> response to indicate that the resource should be redirected.</p>
<h2>REST API Endpoints</h2>
<p>When an API is created on a server, the data it contains is accessible via endpoints. An <strong>endpoint</strong> is the URL of the request that can accept and process the <code>GET</code>, <code>POST</code>, <code>PUT</code>, or <code>DELETE</code> request. </p>
<p>An API URL will consist of the root, path, and optional query string.</p>
<ul>
<li>
<strong>Root</strong> e.g. <code>https://api.example.com</code> or <code>https://api.example.com/v2</code>: The root of the API, which may consist of the protocol, domain, and version.</li>
<li>
<strong>Path</strong> e.g. <code>/users/</code>or <code>/users/5</code>: Unique location of the specific resource.</li>
<li>
<strong>Query Parameters (optional)</strong> e.g. <code>?location=chicago&amp;age=29</code>: Optional key value pairs used for sorting, filtering, and pagination.<br>We can put them all together to implement something such as the example below, which would return a list of all users and use a query parameter of <code>limit</code> to filter the responses to only include ten results.</li>
</ul>
<p><code>https://api.example.com/users?limit=10</code></p>
<p>Generally, when people refer to an API as a RESTful API, they are referring to the naming conventions that go into building API URL endpoints. A few important conventions for a standard RESTful API are as follows:</p>
<ul>
<li>
<strong>Paths should be plural</strong>: For example, to get the user with an id of <code>5</code>, we would use <code>/users/5</code>, not <code>/user/5</code>.</li>
<li>
<strong>Endpoints should not display the file extension</strong>: Although an API will most likely be returning JSON, the URL should not end in <code>.json</code>.</li>
<li>
<strong>Endpoints should use nouns, not verbs</strong>: Words like <code>add</code> and <code>delete</code> should not appear in a REST URL. In order to add a new user, you would simply send a <code>POST</code> request to <code>/users</code>, not something like <code>/users/add</code>. The API should be developed to handle multiple types of requests to the same URL.</li>
<li>
<strong>Paths are case sensitive, and should be written in lowercase with hyphens as opposed to underscores</strong>.</li>
</ul>
<p>All of these conventions are guidelines, as there are no strict REST standards to follow. However, using these guidelines will make your API consistent, familiar, and easy to read and understand.</p>
<h2>Conclusion</h2>
<p>In this article, we learned what REST and RESTful APIs are, how HTTP request methods and response codes work, the structure of an API URL, and common RESTful API conventions. In the next tutorial, we will learn how to put all this theory to use by setting up an Express server with Node.js and building our own API.</p><p></p>2018-08-21T13:00:00.000Z2018-08-21T13:00:00.000ZTania Rasciatag:code.tutsplus.com,2005:PostPresenter/cms-26086Building a REST API With AWS SimpleDB and Node.js<p><a href="https://aws.amazon.com/simpledb/" rel="external" target="_blank">SimpleDB</a> is a remote database offered by Amazon Web Services (AWS). The world of data stores is usually divided into SQL and NoSQL, based on the use (or non-use) of the SQL language. NoSQL data stores are usually based on a simpler key/value setup. SimpleDB straddles this line—it is a key/value store and it can also use a variant of SQL for retrieval. Most SQL languages are based on a schema that lays out the rows and columns of the data, but SimpleDB is a schema-less database, making for a very flexible data store.<br></p><p>In the SimpleDB database model, you have <b>items, attributes and values. </b> Each row in the database is an <b>item</b> and can be identified by a unique and assignable item name. Each item can have up to 256 pairs of <b>attributes</b> and <b>values</b>. An unexpected aspect of SimpleDB is that an attribute can have more than one pair per item. I think the best way to think about SimpleDB is to think of a spreadsheet, but instead of each column/row intersection representing a single value, it represents an array of values.</p><figure class="post_image"><img alt="Grid illustrating Item Name Attribute Value relationship" data-src="https://cms-assets.tutsplus.com/uploads/users/1197/posts/26086/image/grid.png"></figure><p>This chart represents two items stored in a SimpleDB <i>domain. </i>The term <i>domain</i> is analogous to a “table” in other databases. </p><p>The first column is the item name—this is the only column where you can have only a single value, and you can think of it as a unique index column. </p><p>The other four columns (<em>pets</em>, <em>cars</em>, <em>furniture</em>, and <em>phones</em>) represent attributes that are currently in this domain—you aren’t limited to this, so every item can have an entirely unique set of attributes. In this data, the attribute <i>pets</i> on the item <i>personInventory1 </i>has three pairs; expressed in JSON, it’ll look something like this:</p><pre class="brush: javascript noskimlinks noskimwords">{ "Name" : "pets", "Value" : "dog" },
{ "Name" : "pets", "Value" : "cat" },
{ "Name" : "pets", "Value" : "fish" }</pre><p>On the other hand, the item <em>personInventory2</em> has only one pair:</p><pre class="brush: javascript noskimlinks noskimwords">{ "Name" : "pets", "Value" : "cat" }</pre><p>While you don’t have to supply the same attributes for each item, you do need to supply at least one pair. This means that you cannot have an ‘empty’ item. Each attribute can have a value up to 1kb in size, so this means that each item is functionally limited to 256kb, due to the 1kb value limit and the 256 pair limit.</p><p>SimpleDB is distributed, which has some distinct traits that you need to understand and keep in mind as you design your app. Being a distributed database means a whole group of machines will respond to your requests and your data will be replicated throughout these servers. This distribution will be completely transparent to your program, but it does introduce the possibility of consistency issues—your data cannot be guaranteed to be present on all servers initially. </p><p>Don’t panic: it’s not as bad as it sounds for a few reasons. With SimpleDB, the consistency isn’t promised, but it is usually pretty good and quickly reaches all nodes from my experience. Designing around this also isn’t so hard—normally you try to avoid immediately reading a record you just wrote. Finally, SimpleDB has the option to perform consistent reads, but they are slower and may consume more resources. If your app requires consistent reading every time, you might want to reconsider using SimpleDB as your data store, but for many applications, this can be designed around or not even worried about.</p><p>On the upside, the distributed nature also affords SimpleDB a few advantages that mesh nicely with the Node.js environment. Since you don’t have a single server responding to your requests, you don’t need to worry about saturating the service, and you can achieve good performance by making many parallel requests to SimpleDB. Parallel and asynchronous requests are something that Node.js can handle easily.</p><p>Unlike many AWS services, there isn’t an Amazon-delivered console for management of SimpleDB. Luckily, there is a nice in-browser management console in the form of a Google Chrome plugin, <a href="https://chrome.google.com/webstore/detail/sdbnavigator/ddhigekdfabonefhiildaiccafacphgg" rel="external" target="_blank">SdbNavigator</a>. In the SdbNavigator you can add or delete domains, insert, update and delete items, modify attributes, and perform queries.</p><h2>AWS SDK</h2><p>Now that we’ve gotten to know the SimpleDB service, let’s start writing our REST server. First, we’ll need to install the AWS SDK. This SDK handles not just SimpleDB but all the AWS services, so you may already be including it in your package.json file. To install the SDK, run the following from the command line:</p><pre class="brush: bash noskimlinks noskimwords">npm install aws-sdk —-save</pre><p>To use SimpleDB, you’ll also need to get your <a href="https://aws.amazon.com/free/" rel="external" target="_blank">AWS credentials</a>, which include an Access Key and a Secret Key. SimpleDB is a pay-as-you-go service, but AWS currently includes a generous free allowance for SimpleDB. </p><p><em>Word of warning</em><em>: As with any pay-as-you-go service, be aware that it’s possible to write code that can rack up big bills, so you’re going to want to keep an eye on your usage and keep your credentials private and safe. </em></p><p>Once you get the AWS SDK installed and have acquired your credentials, you’ll need to set up SimpleDB in your code. In this example, we'll use AWS credentials stored in a JSON file in your home directory. First, you’ll need to include the SDK module, create an AWS object, and finally set up your SimpleDB interface.</p><pre class="brush: javascript noskimlinks noskimwords">var
aws = require('aws-sdk'),
simpledb;
aws.config.loadFromPath(process.env['HOME'] + '/aws.credentials.json');
//We'll use the Northern Virginia datacenter, change the region / endpoint for other datacenters http://docs.aws.amazon.com/general/latest/gr/rande.html#sdb_region
simpledb = new aws.SimpleDB({
region : 'US-East',
endpoint : 'https://sdb.amazonaws.com'
});</pre><p>Notice that we are using a specific endpoint and region. Each datacenter is entirely independent, so if you create a Domain named “<em>mysuperawesomedata</em>” in Northern Virginia, it will not be replicated to nor present in the Sao Paulo datacenter, for example.</p><p>The SimpleDB object that you’ve created with <code class="inline">new aws.SimpleDB</code> is where all your methods for interacting with SimpleDB will be based. The <a href="http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SimpleDB.html" rel="external" target="_blank">AWS SDK for SimpleDB has only a few methods</a>:</p><p><b>Batch Operations</b></p><ul>
<li>batchDeleteAttributes</li>
<li>batchPutAttributes</li>
</ul><p><b>Domain Management &amp; Information</b></p><ul>
<li>createDomain</li>
<li>deleteDomain</li>
<li>domainMetadata</li>
<li>listDomains</li>
</ul><p><b>Item/Attribute Manipulation</b></p><ul>
<li>deleteAttributes</li>
<li>getAttributes</li>
<li>putAttributes</li>
</ul><p><b>Querying</b></p><ul><li> select</li></ul><p>In this tutorial, we will only be dealing with Item/Attribute Manipulation and Querying; while the other categories are useful, many applications will not have any use for them.</p><h2>Test Data</h2><p>Using SdbNavigator, enter your access and security keys into the tool, select ‘US-East’, and click connect.</p><figure class="post_image"><img alt="Connection UI to SdbNavigator" data-src="https://cms-assets.tutsplus.com/uploads/users/1197/posts/26086/image/connect.png"></figure><p>Once you’ve successfully connected, let’s create a domain for testing. Click <strong>Add domain</strong>.</p><figure class="post_image"><img alt="Adding a domain via the SdbNavigator" data-src="https://cms-assets.tutsplus.com/uploads/users/1197/posts/26086/image/Screen%20Shot%202016-02-21%20at%202.06.57%20PM.png"></figure><p>Then enter the domain name ‘sdb-rest-tut’ and click <strong>OK</strong>.</p><figure class="post_image"><img alt="Entering the name of the new domain" data-src="https://cms-assets.tutsplus.com/uploads/users/1197/posts/26086/image/Screen%20Shot%202016-02-21%20at%202.07.17%20PM.png"></figure><p>Now that you’ve created a domain, let’s enter some test data. Click <strong>Add property</strong> and add a property named “colors”. As a convention, I usually name properties in plural form to reflect the multi-value nature of SimpleDB.</p><figure class="post_image"><img alt="Adding a property name to the record" data-src="https://cms-assets.tutsplus.com/uploads/users/1197/posts/26086/image/Screen%20Shot%202016-02-21%20at%202.22.34%20PM.png"></figure><p>Finally, we’ll click <strong>Add record</strong> to create our first SimpleDB item. In the ItemName() column, enter your unique item name. A quirk of SdbNavigator is that, by default, it will only accept a single value to each item, but this obscures the fact that a property can contain multiple values. To enter multiple values, click the <strong>S</strong> along the right edge of the property column.</p><figure class="post_image"><img alt="Entering a unique item name" data-src="https://cms-assets.tutsplus.com/uploads/users/1197/posts/26086/image/Screen%20Shot%202016-02-21%20at%202.29.02%20PM.png"></figure><p>In the new box, select <strong>Array</strong> to enter multiple values. In the <strong>Value</strong> column, enter “red”, and then click <strong>Add value</strong> and enter “blue”.</p><figure class="post_image"><img alt="Entering the data type of the item" data-src="https://cms-assets.tutsplus.com/uploads/users/1197/posts/26086/image/Screen%20Shot%202016-02-21%20at%202.30.09%20PM.png"></figure><p>Finally, click <strong>Update</strong> to save the changes to this row.</p><figure class="post_image"><img alt="Updating the data type of the item" data-src="https://cms-assets.tutsplus.com/uploads/users/1197/posts/26086/image/Screen%20Shot%202016-02-21%20at%202.32.07%20PM.png"></figure><p>Now that we’ve entered some test data, let’s make our first SimpleDB request from Node. We’ll just get everything in the Domain, which, at this point, will be just a single row.</p><pre class="brush: javascript noskimlinks noskimwords">var
aws = require('aws-sdk'),
simpledb;
aws.config.loadFromPath(process.env['HOME'] + '/aws.credentials.json');
simpledb = new aws.SimpleDB({
region : 'US-East',
endpoint : 'https://sdb.amazonaws.com'
});
simpledb.select({
SelectExpression : 'select * from `sdb-rest-tut` limit 100'
}, function(err,resp) {
if (err) {
console.error(err);
} else {
console.log(JSON.stringify(resp,null,' '));
}
});</pre><p>The response will be logged to the console. Here is the response, annotated for explanation:</p><pre class="brush: javascript noskimlinks noskimwords">{
"ResponseMetadata": {
"RequestId": "...", //Every request made to SimpleDB has a request ID
"BoxUsage": "0.0000228616" //This is how your account is charged, as of time of writing US-East region is 14 US cents per hour, so this request costs 0.00032 cents + the transfer cost (if you are currently outside of your free tier)
},
"Items": [ //For a Select, your response will be in the "Items" object property
{
"Name": "myfirstitem", //this is the itemName()
"Attributes": [ //these are the attribute pairs
{
"Name": "colors", //attribute name
"Value": "red" //value - note that every Value is a string, regardless of the contents
},
{
"Name": "colors", //Since the attribute name is repeated, we can see that `colors` has more than one value
"Value": "blue"
}
]
}
]
}</pre><h2>A REST Server</h2><p>Since we’ll be building a REST Server that stores data in SimpleDB, it’s important to understand what a REST server does. REST stands for <strong>RE</strong>presentational <strong>S</strong>tate <strong>T</strong>ransfer. A REST server is really just a server that uses HTTP standard mechanisms as an interface for your data. Often, REST is used for server-to-server communications, but you can use REST servers with the client through JavaScript libraries such as jQuery or Angular. Generally, however, an end-user won’t interact directly with a REST server.</p><p>Interestingly, the AWS SDK actually uses the REST protocol to interact with SimpleDB, so it may seem odd to create a REST server to another REST server. You wouldn’t want to use the SimpleDB REST API directly because you need to authenticate your requests, which would risk the security of your AWS account. Also, by writing a server, you’ll be able to add a layer of both abstraction and validation to your data storage that will make the rest of your whole application much easier to deal with.</p><p>In this tutorial we will be building the basic CRUD+L functions, that is <strong>C</strong>reate, <strong>R</strong>ead, <strong>U</strong>pdate, <strong>D</strong>elete and <strong>L</strong>ist. If you think about it, you can break down most applications into CRUD+L. With REST, you will use a limited number of paths and several HTTP methods or verbs to create an intuitive API. Most developers are familiar with a few of the HTTP verbs, namely GET and POST, as they are used most often in web applications, but there are <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html" target="_self">several others</a>.</p><table>
<thead><tr>
<th>Operation</th>
<th>HTTP Verb</th>
</tr></thead>
<tbody>
<tr>
<td>Create</td>
<td>POST</td>
</tr>
<tr>
<td>Read</td>
<td>GET</td>
</tr>
<tr>
<td>Update</td>
<td>PUT</td>
</tr>
<tr>
<td>Delete</td>
<td>DELETE</td>
</tr>
<tr>
<td>List</td>
<td>GET</td>
</tr>
</tbody>
</table>
<p>Notice that Read and List both use the same verb; we will be using slightly different paths to differentiate between the two. We’re using POST to represent Create as creating is not considered idempotent. <em>Idempotent</em> means that multiple identical calls will have the same result to the user and in your data, so an update (aka PUT) would be considered idempotent.</p><p>As our example, we’ll build a personal inventory server—a database to save whatever you own. Here is how the paths will look:</p><table>
<thead><tr>
<th>Operation</th>
<th>HTTP Verb</th>
<th>Path</th>
</tr></thead>
<tbody>
<tr>
<td>Create</td>
<td>POST</td>
<td>/inventory</td>
</tr>
<tr>
<td>Read</td>
<td>GET</td>
<td>/inventory/1234</td>
</tr>
<tr>
<td>Update</td>
<td>PUT</td>
<td>/inventory/1234</td>
</tr>
<tr>
<td>Delete</td>
<td>DELETE</td>
<td>/inventory/1234</td>
</tr>
<tr>
<td>List</td>
<td>GET</td>
<td>/inventory</td>
</tr>
</tbody>
</table><p><em>1234</em> is a placeholder for the person identifier (ID)—note that ‘create' and ‘list' do not have an ID. In the case of create, the ID will be generated, and with list, we’ll be getting all the names, so we don’t need a specific ID. </p><h2>Building the Server</h2><p>To get started, let's install <a href="http://expressjs.com/" rel="external" target="_blank">Express</a>, a Node.js HTTP server framework:</p><pre class="brush: bash noskimlinks noskimwords">npm install express —-save</pre><p>Express manages most of the minutiae in setting up a server, but it doesn't include any facility for handling the HTTP request body, so we'll need to install another module, <a href="https://github.com/expressjs/body-parser" rel="external" target="_blank">body-parser</a>, to enable us to read the request body.</p><pre class="brush: bash noskimlinks noskimwords">npm install body-parser --save</pre><p>Body-parser has a few different options for parsing the body of the HTTP request. We’ll use the <code class="inline">json()</code> method for readability, but switching to another method is just swapping out the method on the <code class="inline">bodyParser</code> object. We only need the <code class="inline">bodyParser</code> method on the create and update methods, so we can just include it in those particular routes.</p><h3>Create</h3><p>Since each SimpleDB <code class="inline">itemName</code> needs to be unique, we can auto-generate a new <code class="inline">itemName</code> for each newly created item. We’re going to use the <a href="https://github.com/ericelliott/cuid" rel="external" target="_blank">cuid</a> module, which is a lightweight way to generate unique identifiers.</p><pre class="brush: bash noskimlinks noskimwords">npm install cuid --save</pre><p>SimpleDB expects attributes to be in the attribute name/value pair format:<br></p><pre class="brush: javascript noskimlinks noskimwords">[
{ "Name" : "attribute1", "Value" : "value1" },
{ "Name" : "attribute1", "Value" : "value2" },
{ "Name" : "attribute2", "Value" : "value3" },
{ "Name" : "attribute3", "Value" : "value4" }
]</pre><p>Your server could certainly just accept and pass the values in this format directly to SimpleDB, but it is counter-intuitive to how data is often structured, and it's a difficult concept with which to work. We'll use a more intuitive data structure, an object/value array:</p><pre class="brush: javascript noskimlinks noskimwords">{
"attribute1" : ["value1","value2"],
"attribute2" : ["value3","value4"]
}</pre><p>Here is a basic Express-based server with the create operation:</p><pre class="brush: javascript noskimlinks noskimwords">var
aws = require('aws-sdk'),
bodyParser = require('body-parser'),
cuid = require('cuid'),
express = require('express'),
sdbDomain = 'sdb-rest-tut',
app = express(),
simpledb;
aws.config.loadFromPath(process.env['HOME'] + '/aws.credentials.json');
simpledb = new aws.SimpleDB({
region : 'US-East',
endpoint : 'https://sdb.amazonaws.com'
});
//create
app.post(
'/inventory',
bodyParser.json(),
function(req,res,next) {
var
sdbAttributes = [],
newItemName = cuid();
//start with:
/*
{ attributeN : ['value1','value2',..'valueN'] }
*/
Object.keys(req.body).forEach(function(anAttributeName) {
req.body[anAttributeName].forEach(function(aValue) {
sdbAttributes.push({
Name : anAttributeName,
Value : aValue
});
});
});
//end up with:
/*
[
{ Name : 'attributeN', Value : 'value1' },
{ Name : 'attributeN', Value : 'value2' },
...
{ Name : 'attributeN', Value : 'valueN' },
]
*/
simpledb.putAttributes({
DomainName : sdbDomain,
ItemName : newItemName,
Attributes : sdbAttributes
}, function(err,awsResp) {
if (err) {
next(err); //server error to user
} else {
res.send({
itemName : newItemName
});
}
});
}
);
app.listen(3000, function () {
console.log('SimpleDB-powered REST server started.');
});</pre><p>Let's start up your server and try it out. A great way to interact with a REST server is to use the <a href="https://curl.haxx.se/" rel="external" target="_blank">cURL tool</a>. This tool allows you to make an HTTP request with any verb right from the command line. To try out creating an item with our REST server, we'll need to activate a few extra options:</p><pre class="brush: bash noskimlinks noskimwords">curl -H "Content-Type: application/json" -X POST -d '{"pets" : ["dog","cat"], "cars" : ["saab"]}' http://localhost:3000/inventory</pre><table>
<thead><tr>
<th>Option</th>
<th>Purpose</th>
</tr></thead>
<tbody>
<tr>
<td>-H</td>
<td>Add a line to the HTTP heading</td>
</tr>
<tr>
<td>-X</td>
<td>Define which verb will be used</td>
</tr>
<tr>
<td>-d</td>
<td>Data to be sent in the HTTP request body</td>
</tr>
</tbody>
</table><p>After running the command, you'll see a JSON response with your newly created itemName or ID. If you switch over to SdbNavigator, you should see the new data when you query all the items.</p><h3>Read</h3><p>Now let’s build a basic function to read an item from SimpleDB. For this, we don’t need to perform a query since we’ll be getting the itemName or ID from the path of the request. We can perform a <code class="inline">getAttributes</code> request with that itemName or ID.</p><p>If we stopped here, we would have a functional but not very friendly form of our data. Let’s transform the Name/Value array into the same form we’re using to accept data (attribute : array of values). To accomplish this, we will need to go through each name/value pair and add it to a new array for each unique name. </p><p>Finally, let’s add the itemName and return the results. </p><pre class="brush: javascript noskimlinks noskimwords">//Read
app.get('/inventory/:itemID', function(req,res,next) {
simpledb.getAttributes({
DomainName : sdbDomain,
ItemName : req.params.itemID //this gets the value from :itemID in the path
}, function(err,awsResp) {
var
attributes = {};
if (err) {
next(err); //server error to users
} else {
awsResp.Attributes.forEach(function(aPair) {
// if this is the first time we are seeing the aPair.Name, let's add it to the response object, attributes as an array
if (!attributes[aPair.Name]) {
attributes[aPair.Name] = [];
}
//push the value into the correct array
attributes[aPair.Name].push(aPair.Value);
});
res.send({
itemName : req.params.itemID,
inventory : attributes
});
}
});
});</pre><p>To test this, we need to use curl again. Try replacing <code class="inline">[cuid]</code> with the itemName or ID returned from our example of creating an item earlier in this tutorial.</p><pre class="brush: bash noskimlinks noskimwords">curl -D- http://localhost:3000/inventory/[cuid]</pre><p>Notice that we're using the<i> </i><code class="inline">-D-</code> option. This will dump the HTTP head so we can see the response code.</p><p>Another aspect of REST is to use your <a href="http://www.restapitutorial.com/httpstatuscodes.html" rel="external" target="_blank">response codes</a> meaningfully. In the current example, if you supply a non-existent ID to curl, the above server will crash because you’re trying to <code class="inline">forEach</code> a non-existent array. We need to account for this and return a meaningful HTTP response code indicating that the item was not found. </p><p>To prevent the error, we should test for the existence of the variable <code class="inline">awsResp.Attributes</code>. If it doesn’t exist, let’s set the status code to 404 and end the http request. If it exists, then we can serve the response with attributes. </p><pre class="brush: javascript noskimlinks noskimwords">app.get('/inventory/:itemID', function(req,res,next) {
simpledb.getAttributes({
DomainName : sdbDomain,
ItemName : req.params.itemID
}, function(err,awsResp) {
var
attributes = {};
if (err) {
next(err);
} else {
if (!awsResp.Attributes) {
//set the status response to 404 because we didn't find any attributes then end it
res.status(404).end();
} else {
awsResp.Attributes.forEach(function(aPair) {
if (!attributes[aPair.Name]) {
attributes[aPair.Name] = [];
}
attributes[aPair.Name].push(aPair.Value);
});
res.send({
itemName : req.params.itemID,
inventory : attributes
});
}
}
});
});
</pre><p>Try it out with the new code and a non-existent ID and you'll see that the server returns a 404. </p><p>Now that we know how to use <code class="inline">status</code> to change the value, we should also update how we are responding to a POST/create. While the 200 response is technically correct as it means ‘OK’, a more insightful response code would be 201, which indicates ‘created’. To make this change, we’ll add it in the status method before sending.</p><pre class="brush: javascript noskimlinks noskimwords"> res
.status(201)
.send({
itemName : newItemName
});</pre><h3>Update</h3><p>Update is usually the most difficult operation for any system, and this REST server is no exception. </p><p>The nature of SimpleDB makes this operation a little more challenging as well. In the case of a REST server, an update is where you are replacing the entire piece of stored data; SimpleDB on the other hand, represents individual attribute/value pairs under an itemName. </p><p>To allow for an update to represent a single piece of data rather than a collection of name/value pairs, we need to define a schema for the purposes of our code (even though SimpleDB doesn’t need one). Don’t worry if this is unclear right now—keep reading and I’ll illustrate the requirement.</p><p>Compared to many other database systems, our schema will be very simple: just a defined array of attributes. For our example, we have four fields we are concerned with: <em>pets</em>, <em>cars</em>, <em>furniture</em>, and <em>phones</em>:</p><pre class="brush: javascript noskimlinks noskimwords">schema = ['pets','cars','furniture','phones'],</pre><p>With SimpleDB you can’t store an empty attribute/value pair, nor does SimpleDB have any concept of individual items, so we’ll assume that if SimpleDB doesn’t return a value, it doesn’t exist. Similarly, if we try to update a SimpleDB item with an empty attribute/value pair, it will ignore that data. Take, for example, this data:</p><pre class="brush: javascript noskimlinks noskimwords">{
"itemName": "cil89uvnm00011ma2fykmy79c",
"inventory": {
"cars": [],
"pets": [
"cat",
"dog"
]
}
}</pre><p>Logically, we know that <code class="inline">cars</code>, being an empty array, should have no values, and <code class="inline">pets</code> should have two values, but what about <code class="inline">phones</code> and <code class="inline">furniture</code>? What do you do to those? Here is how we translate this update request to work with SimpleDB:</p><ul>
<li>Put an attribute <code class="inline">pet</code> with a value to <code class="inline">cat</code>.</li>
<li>Put an attribute <code class="inline">pet</code> with a value to <code class="inline">dog</code>.<br>
</li>
<li>Delete attributes for <code class="inline">cars</code>.<br>
</li>
<li>Delete attributes for <code class="inline">phones</code>.</li>
<li>Delete attributes for <code class="inline">furniture</code>.</li>
</ul><p>Without some form of schema that at least defines the attributes, we wouldn’t know that <code class="inline">phones</code> and <code class="inline">furniture</code> needed to be deleted. Luckily, we can consolidate this update operation into two SimpleDB requests instead of five: one to put the attributes, and one to delete the attributes. This is a good time to pull out the code from the post/create function that transforms the attribute/array of values<i> </i>object into the attribute/value pair array.</p><pre class="brush: javascript noskimlinks noskimwords">function attributeObjectToAttributeValuePairs(attrObj, replace) {
var
sdbAttributes = [];
Object.keys(attrObj).forEach(function(anAttributeName) {
attrObj[anAttributeName].forEach(function(aValue) {
sdbAttributes.push({
Name : anAttributeName,
Value : aValue,
Replace : replace //if true, then SimpleDB will overwrite rather than append more values to an attribute
});
});
});
return sdbAttributes;
}</pre><p>We’re going to make an important alteration to the create function as well. We’ll be adding a new attribute/value to all items. This attribute will not be added to the schema and is effectively read-only. </p><p>We will add an attribute called <code class="inline">created</code> and set the value to <code class="inline">1</code>. With SimpleDB, there is limited ability to check if an item exists prior to adding attributes and values. On every <code class="inline">putAttributes</code> request you can check for the value and existence of a single attribute—in our case, we’ll use <code class="inline">created</code> and check for a value of 1. While this may seem like a strange workaround, it provides a very important safety to prevent the update operation from being able to create new items with an arbitrary ID.</p><pre class="brush: javascript noskimlinks noskimwords">newAttributes.push({
Name : 'created',
Value : '1'
});</pre><p>Since we’ll be doing a couple of asynchronous HTTP requests, let’s install the <a href="https://github.com/caolan/async" rel="external" target="_blank">async module</a> to ease the handling of those callbacks.<br></p><pre class="brush: bash noskimlinks noskimwords">npm install async —-save</pre><p>Remember, since SimpleDB is distributed, there is no reason to sequentially put our attributes and then delete. We’ll use the function <code class="inline">async.parallel</code> to run these two operations and get a callback when both have completed. The responses from AWS form <code class="inline">putAttributes</code> and <code class="inline">deleteAttributes</code> do not provide important information, so we will just send an empty response with a status code 200 if there are no errors.</p><pre class="brush: javascript noskimlinks noskimwords">app.put(
'/inventory/:itemID',
bodyParser.json(),
function(req,res,next) {
var
updateValues = {},
deleteValues = [];
schema.forEach(function(anAttribute) {
if ((!req.body[anAttribute]) || (req.body[anAttribute].length === 0)) {
deleteValues.push({ Name : anAttribute});
} else {
updateValues[anAttribute] = req.body[anAttribute];
}
});
async.parallel([
function(cb) {
//update anything that is present
simpledb.putAttributes({
DomainName : sdbDomain,
ItemName : req.params.itemID,
Attributes : attributeObjectToAttributeValuePairs(updateValues,true),
Expected : {
Name : 'created',
Value : '1',
Exists : true
}
},
cb
);
},
function(cb) {
//delete any attributes that not present
simpledb.deleteAttributes({
DomainName : sdbDomain,
ItemName : req.params.itemID,
Attributes : deleteValues
},
cb
);
}
],
function(err) {
if (err) {
next(err);
} else {
res.status(200).end();
}
}
);
}
);</pre><p>To take this for a spin, let's update a previously created entry. This time, we will make the inventory only include a "dog", removing all other items. Again, with cURL, run the command, substituting [cuid] with one of your item IDs.</p><pre class="brush: bash noskimlinks noskimwords">curl -H "Content-Type: application/json" -X PUT -d '{"pets" : ["dog"] }' http://localhost:3000/inventory/[cuid]</pre><h3>Delete</h3><p>SimpleDB has no concept of an item deletion, but it can delete attributes, as mentioned above. To delete an item, we’ll need to delete all the attributes and the ‘item' will cease to be. </p><p>Since we’ve defined a list of attributes in our schema, we’ll use the <code class="inline">deleteAttributes</code> call to remove all of those attributes as well as the <code class="inline">created</code> attribute. As per our plan, this operation will be at the same path as Update, but using the verb delete. </p><pre class="brush: javascript noskimlinks noskimwords">app.delete(
'/inventory/:itemID',
function(req,res,next) {
var
attributesToDelete;
attributesToDelete = schema.map(function(anAttribute){
return { Name : anAttribute };
});
attributesToDelete.push({ Name : 'created' });
simpledb.deleteAttributes({
DomainName : sdbDomain,
ItemName : req.params.itemID,
Attributes : attributesToDelete
},
function(err) {
if (err) {
next(err);
} else {
res.status(200).end();
}
}
);
}
);</pre><h3>List</h3><p>Rounding out our REST verbs is list. To achieve the list operation, we’re going to use the select command and the SQL-like query language. Our list function will be barebones, but will serve as a good basis for more complex retrieval later on. We’re going to make a very simple query:</p><pre class="brush: sql noskimlinks noskimwords">select * from `sdb-rest-tut` limit 100</pre><p>As we ran into with the get/read operation, the response from SimpleDB isn’t very useful as it is focused on the attribute/value pairs. To avoid repeating ourselves, we’ll refactor the part of the get/read operation into a separate function and use it here. While we are at it, we’ll also filter out the <code class="inline">created</code> attribute (as it will show up in the get operation).</p><pre class="brush: javascript noskimlinks noskimwords">function attributeValuePairsToAttributeObject(pairs) {
var
attributes = {};
pairs
.filter(function(aPair) {
return aPair.Name !== 'created';
})
.forEach(function(aPair) {
if (!attributes[aPair.Name]) {
attributes[aPair.Name] = [];
}
attributes[aPair.Name].push(aPair.Value);
});
return attributes;
}</pre><p>With a select operation, SimpleDB returns the values in the <code class="inline">Items</code> array. Each item is represented by an object that contains the itemName (as simply <code class="inline">Name</code>) and the attribute/value pairs. </p><p>To simplify this response, let’s return everything in a single object. First, we’ll convert the attribute/value pairs into an attribute/value array as we did in the read/get operation, and then we can add the itemName as the property ID. </p><pre class="brush: javascript noskimlinks noskimwords">app.get(
'/inventory',
function(req,res,next) {
simpledb.select({
SelectExpression : 'select * from `sdb-rest-tut` limit 100'
},
function(err,awsResp) {
var
items = [];
if (err) {
next(err);
} else {
items = awsResp.Items.map(function(anAwsItem) {
var
anItem;
anItem = attributeValuePairsToAttributeObject(anAwsItem.Attributes);
anItem.id = anAwsItem.Name;
return anItem;
});
res.send(items);
}
});
}
);</pre><p>To see our results, we can use curl:</p><pre class="brush: javascript noskimlinks noskimwords">curl -D- -X GET http://localhost:3000/inventory</pre><h3>Validation</h3><p>Validation is whole a subject of its own, but with the code we’ve already written, we have a start for a simple validation system. </p><p>For now, all we want to make sure is that a user can’t submit anything but what is in the schema. Looking back at the code that was written for update/put, <code class="inline">forEach</code>ing over the schema will prevent any unauthorized attributes from being added, so we really just need to apply something similar to our create/post operation. In this case, we will filter the attribute/value pairs, eliminating any non-schema attributes.</p><pre class="brush: javascript noskimlinks noskimwords">newAttributes = newAttributes.filter(function(anAttribute) {
return schema.indexOf(anAttribute.Name) !== -1;
});</pre><p>In your production code, you will likely want a more robust validation system. I would suggest integrating a JSON schema validator like <a href="http://code.tutsplus.com/tutorials/validating-data-with-json-schema-part-1--cms-25343" rel="external" target="_blank">ajv</a> and building a middleware that sits between <code class="inline">bodyParser</code> and your route function on create and update operations.</p><h2>Next Steps</h2><p>With the code outlined in this article, you have all the operations needed to store, read and modify data, but this is only the start of your journey. In most cases, you’ll need to start thinking about the following topics:</p><ul>
<li>Authentication</li>
<li>Pagination</li>
<li>Complex list/query operations</li>
<li>Additional output formats (xml, csv, etc.)</li>
</ul><p>This basis for a REST server powered by SimpleDB allows you to add middleware and additional logic to build a backbone for your application.</p><p>The finalized server code is available at <a href="https://github.com/tutsplus/simpledb-rest-api">simpledb-rest-api</a> on GitHub.</p>2016-07-27T12:00:04.000Z2016-07-27T12:00:04.000ZKyle Davistag:code.tutsplus.com,2005:PostPresenter/cms-25530Adding Social Sharing in a Node.js Single-Page Application<p>Single-Page Applications (SPAs) are powered by client-side rendering templates, which give the end user a very dynamic experience. Recently, <a href="http://googlewebmastercentral.blogspot.com/2014/05/understanding-web-pages-better.html">Google announced that they crawl web pages</a> and <a href="http://googlewebmastercentral.blogspot.com/2015/10/deprecating-our-ajax-crawling-scheme.html">execute JavaScript as a normal user would</a>, resulting in sites powered by SPA frameworks (Angular, Ember, and Vue, to name a few) being <a href="http://searchengineland.com/tested-googlebot-crawls-javascript-heres-learned-220157">crawled without Google penalty</a>.</p>
<p>Beyond search, other web crawlers are important to your site’s visibility—namely rich social-sharing robots that rely on meta tags are still blind to JavaScript.</p>
<p>In this tutorial, we will build an alternate route and rendering module for your Express and Node.js server that you can use with most SPA frameworks and that will enable your site to have rich sharing on Twitter, Facebook and Pinterest.</p>
<h2>A Word of Warning</h2>
<p>This tutorial deals exclusively with web robots that extract social sharing information. <em>Do not attempt this technique with search engine web crawlers.</em> Search engine companies can take this kind of behavior seriously and treat it as <a href="https://support.google.com/webmasters/answer/66355?hl=en">spam or fraudulent behavior</a>, and as such your rankings may quickly tank.</p>
<p>Similarly, with rich social-sharing information, make sure you are representing content in a way that aligns what the user sees with what the robot reads. Failing to keep this alignment could result in restrictions from social media sites.</p>
<h2>Rich Social Sharing</h2>
<p>If you post an update in Facebook and include a URL, a Facebook robot will read the HTML and look for <a href="http://ogp.me/">OpenGraph</a> meta tags. Here is an example of the Envato Tuts+ homepage:</p>
<figure class="post_image">
<img data-src="https://cms-assets.tutsplus.com/uploads/users/1197/posts/25530/attachment/Screen%20Shot%202015-12-08%20at%207.44.43%20AM.png" alt="Envato Tuts+ Social Share Screenshot">
</figure>
<p>Inspecting the page, in the <code class="inline">head</code> tag, here are the relevant tags that generate this preview:</p>
<p>```html</p>
<meta content="Envato Tuts+" property="og:title">
<meta content="Envato Tuts+ teaches creative and technical skills across many topics to millions of people worldwide. We offer tutorials, articles, news and insights that help you take your knowledge to the next level." property="og:description">
<meta content="http://static.tutsplus.com/assets/favicon-8b86ba48e7f31535461f183680fe2ac9.png" property="og:image">
<p>```</p>
<p>Pinterest uses the same protocol as Facebook, <a href="http://ogp.me/">OpenGraph</a>, so their sharing works much the same.</p>
<p>On Twitter, the concept is called a “card”, and Twitter has a few different varieties depending on how you want to present your content. Here is an example of a Twitter card from GitHub:</p>
<figure class="post_image">
<img data-src="https://cms-assets.tutsplus.com/uploads/users/1197/posts/25530/attachment/Screen%20Shot%202015-12-08%20at%207.52.24%20AM.png" alt="Screenshot of Twitter Card generated by a GitHub page">
</figure>
<p>And here is the HTML that generates this card:</p>
<p>```html</p>
<meta content="@github" name="twitter:site">
<meta content="summary" name="twitter:card">
<meta content="NodeRedis/node_redis" name="twitter:title">
<meta content="redis client for node. Contribute to node_redis development by creating an account on GitHub." name="twitter:description">
<meta content="https://avatars1.githubusercontent.com/u/5845577?v=3&amp;s=400" name="twitter:image:src">
<p>```</p>
<p><em>Note: GitHub is using a similar technique to what is described in this tutorial. The page HTML is slightly different in the tag with the name attribute set to <code class="inline">twitter:description</code>. I had to change the user agent as described later in the article to get the correct meta tag.</em></p>
<h2>The Rub With Client-Side Rendering</h2>
<p>Adding the meta tags is not a problem if you want just one title, description or image for the entire site. Just hard-code the values into the <code class="inline">head</code> of your HTML document. Likely, however, you are building a site that is much more complex and you want your rich social sharing to vary based on URL (which is probably a wrapper around the <a href="https://developer.mozilla.org/en-US/docs/Web/API/History_API">HTML5 History API</a> which your framework is manipulating).</p>
<p>The first attempt might be to build your template and add the values to the meta tags as you would with any other content. Since, at this time, the bots that extract this information do not execute JavaScript, you’ll end up with your template tags instead of your intended values when trying to share.</p>
<p>To make the site readable by bots, we’re building a middleware that detects the user agent of the social sharing bots, and then an alternate router that will serve up the correct content to the bots, avoiding using your SPA framework.</p>
<h2>The User Agent Middleware</h2>
<p>Clients (robots, web crawlers, browsers) send a User Agent (UA) string in the HTTP headers of every request. This is supposed to identify the client software; while web browsers have a huge variety of UA strings, bots tend to be more or less stable. Facebook, Twitter and Pinterest publish the user agent strings of their bots as a courtesy.</p>
<p>In Express, the UA string is contained in the <code class="inline">req</code>uest object as <code class="inline">user-agent</code>. I’m using a regular expression to identify the different bots I’m interested in serving alternate content. We’ll contain this in a middleware. Middlewares are like routes, but they don’t need a path or method and they (generally) pass the request on to another middleware or to the routes. In Express, routes and middlewares are sequential, so place this above any other routes in your Express app.</p>
<p>```javascript
app.use(function(req,res,next) {
var
ua = req.headers[‘user-agent’];</p>
<p>if (/^(facebookexternalhit)|(Twitterbot)|(Pinterest)/gi.test(ua)) {
console.log(ua,’ is a bot’);
}</p>
<p>next();
});
```</p>
<p>The regular expression above looks for “facebookexternalhit”, “Twitterbot” or “Pinterest” at the start of the UA string. If it exists, it will log the UA to the console.</p>
<p>Here is the whole server:</p>
<p>```javascript
var
express = require(‘express’),
app = express(),
server;</p>
<p>app.use(function(req,res,next) {
var
ua = req.headers[‘user-agent’];</p>
<p>if (/^(facebookexternalhit)|(Twitterbot)|(Pinterest)/gi.test(ua)) {
console.log(ua,’ is a bot’);
}</p>
<p>next();
});</p>
<p>app.get(‘/’,function(req,res) {
res.send(‘Serve SPA’);
});</p>
<p>server = app.listen(
8000,
function() {
console.log(‘Server started.’);
}
);
```</p>
<h2>Testing Your Middleware</h2>
<p>In Chrome, navigate to your new server (which should be <code class="inline">http://localhost:8000/</code>). Open DevTools and turn on ‘Device Mode’ by clicking the smartphone icon in the upper left part of the developer pane.</p>
<figure class="post_image">
<img data-src="https://cms-assets.tutsplus.com/uploads/users/1197/posts/25530/attachment/Screen%20Shot%202015-12-08%20at%209.00.24%20AM.png" alt="Screenshot of Chrome DevTools showing the location of Device Mode">
</figure>
<p>On the device toolbar, put “Twitterbot/1.0” into the UA edit box.</p>
<figure class="post_image">
<img data-src="https://cms-assets.tutsplus.com/uploads/users/1197/posts/25530/attachment/Screen%20Shot%202015-12-08%20at%209.01.58%20AM.png" alt="Screenshot of Chrome DevTools illustrating the location of the input box for user agents">
</figure>
<p>Now, reload the page.</p>
<p>At this point, you should see “Serve SPA” in the page, but looking at the console output of your Express app, you should see:</p>
<p><code class="inline">Twitterbot/1.0 is a bot</code></p>
<h2>Alternate Routing</h2>
<p>Now that we can identify bots, let’s build an alternate router. Express can use multiple routers, often used to partition routes out by paths. In this case, we’re going to use a router in a slightly different way. Routers are essentially middlewares, so they except <code class="inline">req</code>, <code class="inline">res</code>, and <code class="inline">next</code>, just like any other middleware. The idea here is to generate a different set of routes that has the same paths.</p>
<p><code class="inline">javascript
nonSPArouter = express.Router();
nonSPArouter.get('/', function(req,res) {
res.send('Serve regular HTML with metatags');
});
</code></p>
<p>Our middleware needs to be changed as well. Instead of just logging that the client is a bot, we will now send the request to the new router and, importantly, only pass it along with <code class="inline">next()</code> if the UA test fails. So, in short, bots get one router and everyone else gets the standard router that serves the SPA code.</p>
<p>```javascript
var
express = require(‘express’),
app = express(),</p>
<p>nonSPArouter <br>
= express.Router(),
server;</p>
<p>nonSPArouter.get(‘/’, function(req,res) {
res.send(‘Serve regular HTML with metatags’);
});</p>
<p>app.use(function(req,res,next) {
var
ua = req.headers[‘user-agent’];</p>
<p>if (/^(facebookexternalhit)|(Twitterbot)|(Pinterest)/gi.test(ua)) {
console.log(ua,’ is a bot’);
nonSPArouter(req,res,next);
} else {
next();
}
});</p>
<p>app.get(‘/’,function(req,res) {
res.send(‘Serve SPA’);
});</p>
<p>server = app.listen(
8000,
function() {
console.log(‘Server started.’);
}
);
```</p>
<p>If we test using the same routine as above, setting the UA to <code class="inline">Twitterbot/1.0</code> the browser will show on reload:</p>
<p><code class="inline">Serve regular HTML with metatags</code></p>
<p>While with the standard Chrome UA you’ll get:</p>
<p><code class="inline">Serve SPA</code></p>
<h2>Meta Tags</h2>
<p>As we examined above, rich social sharing relies on <code class="inline">meta</code> tags inside the head of your HTML document. Since you’re building a SPA, you may not even have a templating engine installed. For this tutorial, we’ll use jade. Jade is a fairly simple tempting language where spaces and tabs are relevant and closing tags are not needed. We can install it by running:</p>
<p><code class="inline">npm install jade</code></p>
<p>In our server source code, add this line before your <code class="inline">app.listen</code>.</p>
<p><code class="inline">app.set('view engine', 'jade');</code></p>
<p>Now, we’re going to input the information we want to serve to the bot only. We’ll modify the <code class="inline">nonSPArouter</code>. Since we’ve set up the view engine in app set, <code class="inline">res.render</code> will do the jade rendering.</p>
<p>Let’s set up a small jade template to serve to the social sharing bots:</p>
<p><code class="inline">plain
doctype html
html
head
title= title
meta(property="og:url" name="twitter:url" content= url)
meta(property="og:title" name="twitter:title" content= title)
meta(property="og:description" name="twitter:description" content= descriptionText)
meta(property="og:image" content= imageUrl)
meta(property="og:type" content="article")
meta(name="twitter:card" content="summary")
body
h1= title
img(src= img alt= title)
p= descriptionText
</code></p>
<p>Most of this template is the <code class="inline">meta</code> tags, but you can also see that I included the information in the body of the document. As of the writing of this tutorial, none of the social sharing bots seem to actually look at anything else beyond the meta tags, but it’s good practice to include the information in a somewhat human readable way, should any sort of human checking be implemented at a later date.</p>
<p>Save the template to your app’s <code class="inline">view</code> directory and name it <code class="inline">bot.jade</code>. The filename without an extension (‘bot’) will be the first argument of the res.render function.</p>
<p>While it’s always a good idea to develop locally, you’re going to need to expose your app in its final location to fully debug your <code class="inline">meta</code> tags. A deployable version of our tiny server looks like this:</p>
<p>```javascript
var
express = require(‘express’),
app = express(),</p>
<p>nonSPArouter <br>
= express.Router(),
server;</p>
<p>nonSPArouter.get(‘/’, function(req,res) {
var
img = ‘placeholder.png’;</p>
<p>res.render(‘bot’, {
img : img,
url : ‘https://bot-social-share.herokuapp.com/’,
title : ‘Bot Test’,
descriptionText
: ‘This is designed to appeal to bots’,
imageUrl : ‘https://bot-social-share.herokuapp.com/’+img
});
});</p>
<p>app.use(function(req,res,next) {
var
ua = req.headers[‘user-agent’];</p>
<p>if (/^(facebookexternalhit)|(Twitterbot)|(Pinterest)/gi.test(ua)) {
console.log(ua,’ is a bot’);
nonSPArouter(req,res,next);
} else {
next();
}
});</p>
<p>app.get(‘/’,function(req,res) {
res.send(‘Serve SPA’);
});
app.use(‘/’,express.static(__dirname + ‘/static’));
app.set(‘view engine’, ‘jade’);
server = app.listen(
process.env.PORT || 8000,
function() {
console.log(‘Server started.’);
}
);
```</p>
<p><em>Also note that I’m using the <code class="inline">express.static</code> middleware to serve the image from the <code class="inline">/static</code> directory.</em></p>
<h2>Debugging Your App</h2>
<p>Once you’ve deployed your app to somewhere publicly accessible, you should verify that your <code class="inline">meta</code> tags are working as desired.</p>
<p>First up, you can test with the <a href="https://developers.facebook.com/tools/debug/og/object/">Facebook Debugger</a>. Input your URL and click <strong>Fetch new scrape information</strong>.</p>
<p>You should see something like:</p>
<figure class="post_image">
<img data-src="https://cms-assets.tutsplus.com/uploads/users/1197/posts/25530/attachment/Screen%20Shot%202015-12-09%20at%203.08.07%20PM.png" alt="Screenshot of the Facebook open graph debugger">
</figure>
<p>Next, you can move on to testing your Twitter card with the <a href="https://cards-dev.twitter.com/validator">Twitter Card Validator</a>. For this one, you need to be logged in with your Twitter account.</p>
<figure class="post_image">
<img data-src="https://cms-assets.tutsplus.com/uploads/users/1197/posts/25530/attachment/Screen%20Shot%202015-12-09%20at%203.07.07%20PM.png" alt="Screenshot of the Twitter Card Validator">
</figure>
<p>Pinterest provides a <a href="https://developers.pinterest.com/tools/url-debugger/">debugger</a>, but this example will not work out-of-the-box because Pinterest only allows “rich pins” on URLs other than your homepage.</p>
<h2>Next Steps</h2>
<p>In your actual implementation, you’ll need to handle integrating your data source and routing. It’s best to look at the routes specified in your SPA code and create an alternate version for everything you think may be shared. After you’ve established the routes that will be likely to be shared, set up <code class="inline">meta</code> tags in your primary template that function as your fallback in the situation that someone shares a page you didn’t expect.</p>
<p>While Pinterest, Facebook and Twitter represent a large chunk of the social media market, you may have other services that you want to integrate. Some services do publish the name of their social sharing robots, while others may not. To determine the user agent, you can <code class="inline">console.log</code> and examine the console output—try this first on a non-production server as you may have a bad time trying to determine the user agent on a busy site. From that point, you can modify the regular expression in our middleware to also catch the new user agent.</p>
<p>Rich social media shares can be a great way to pull people into your fancy single-page-application-based website. By selectively directing robots to machine-readable content, you can provide just the right information to the robots.</p>
2016-02-04T13:00:29.000Z2016-02-04T13:00:29.000ZKyle Davistag:code.tutsplus.com,2005:PostPresenter/cms-25180Data Persistence and Sessions With React<figure class="post_image">
<img data-src="https://cms-assets.tutsplus.com/uploads%2Fusers%2F48%2Fposts%2F25180%2Fimage-1451577414907.jpg" alt="file">
</figure>
<p>Having a “remember me” function is a very useful feature, and implementation with React and Express is relatively easy. Continuing from our last part where we set up a WebRTC chat application, we will now add Mongo-backed persistent sessions and a database-backed online user list for good measure.</p>
<h2>Sessions?</h2>
<p>If you have not used sessions before, in brief they are pretty similar to cookies, in that sessions enable you to track the active users of your application in real time. Sessions actually work via a <code class="inline">session cookie</code>, which is sent in the request / response headers from your app.</p>
<p>So cookies and sessions are intertwined by nature. Then why do we need sessions if we already have cookies? What sessions give you in addition is the ability to define the back-end storage used by the server part of your application. This means that whenever the information is required by your app, it can be retrieved from the database.</p>
<p>So in a real-life example for our chat application, we can now store the username of the user—and if we reconfigured our app somewhat, also insert the entire chat history into the database for logging.</p>
<p>In this next example we will use a Mongo database for persistent back-end storage. This is one of several options available for session storage, and another I highly recommend for larger-scale production setups with multiple web servers is <a href="https://github.com/balor/connect-memcached">memcache</a>.</p>
<h2>Document Storage</h2>
<p>Mongo is a NoSQL document storage engine rather than a relational data store such as the popular MySQL. NoSQL is really easy to get your head around if you are coming from MySQL or similar databases and need to get up to speed with Mongo—it won’t take you long. The biggest differences you should know are the following:</p>
<ul>
<li>As the name says, NoSQL doesn’t use SQL to perform queries. Instead the data is abstracted with method calls; for example <code class="inline">db.collectionName.find()</code> would be a <code class="inline">SELECT * FROM table</code>.</li>
<li>Terminology is different: in MySQL we have Tables, Rows and Columns, and in Mongo it’s Collections, Documents and Keys.</li>
<li>Data is structured, the same as a JSON object.</li>
</ul>
<p>If you do not have Mongo yet, please install it via your package manager. In Linux-based distributions, for example:</p>
<p><code class="inline">bash
$ sudo apt-get install mongodb
</code></p>
<p>Once we have Mongo installed, we can easily add Mongo support to our chat application with the <code class="inline">mongoose</code> module available from npm. Install <code class="inline">mongoose</code> with the following:</p>
<p><code class="inline">bash
$ npm install mongoose --save
</code></p>
<p>Now let’s add some Mongo to our app. Fire up your code editor, and open <code class="inline">app.js</code> and set the top of your script to be as follows.</p>
<p>```js
//Configure our Services
var PeerServer = require(‘peer’).PeerServer,
express = require(‘express’),
mongoose = require(‘mongoose’),
assert = require(‘assert’),
events = require(‘./src/events.js’),
app = express(),
port = process.env.PORT || 3001;</p>
<p>//Connect to the database
mongoose.connect(‘mongodb://localhost:27017/chat’);
var db = mongoose.connection;</p>
<p>mongoose.set(‘debug’, true);</p>
<p>db.on(‘error’, console.error.bind(console, ‘# Mongo DB: connection error:’));
```</p>
<p>We include <code class="inline">mongoose</code> with <code class="inline">require('mongoose')</code> and then utilise our database connection via <code class="inline">mongoose.connect('mongodb://localhost:27017/chat');</code>.</p>
<p>The <code class="inline">/chat</code> defines the name of the database we are connecting to.</p>
<p>Next, for development purposes, I recommend we set the debugging to on.</p>
<p><code class="inline">js
mongoose.set('debug', true);
</code></p>
<p>Finally we add a handler for any error events:</p>
<p><code class="inline">js
db.on('error', console.error.bind(console, '# Mongo DB: connection error:'));
</code></p>
<p>Next you can add your check for the connection with the following code:</p>
<p><code class="inline">js
db.once('open', function (callback) {
console.log("# Mongo DB: Connected to server");
}
</code></p>
<p>The way that <code class="inline">mongoose</code> is used is that once the <code class="inline">db</code> instance receives the <code class="inline">open</code> event, we will enter into execution for our mongo connection. So we will need to wrap our existing code into this new mongo connection in order to utilise it.</p>
<p>Here is a full code listing with mongoose added and inserting rows and deleting them as users come online and go offline.</p>
<p>```js</p>
<p>//Configure our Services
var PeerServer = require(‘peer’).PeerServer,
express = require(‘express’),
mongoose = require(‘mongoose’),
assert = require(‘assert’),
events = require(‘./src/events.js’),
app = express(),
port = process.env.PORT || 3001;</p>
<p>//Tell express to use the ‘src’ directory
app.use(express.static(__dirname + ‘/src’));</p>
<p>//Connect to the database
mongoose.connect(‘mongodb://localhost:27017/chat’);
var db = mongoose.connection;</p>
<p>mongoose.set(‘debug’, true);</p>
<p>db.on(‘error’, console.error.bind(console, ‘# Mongo DB: connection error:’));</p>
<p>db.once(‘open’, function (callback) {</p>
<p>console.log(“# Mongo DB: Connected to server”);</p>
<p>//Setup our User Schema
var usersSchema = mongoose.Schema({username: String});
var User = mongoose.model(‘User’, usersSchema);</p>
<p>//Configure the http server and PeerJS Server
var expressServer = app.listen(port);
var io = require(‘socket.io’).listen(expressServer);
var peer = new PeerServer({ port: 9000, path: ‘/chat’ });</p>
<p>//Print some console output
console.log(‘#### – Server Running – ####’);
console.log(‘# Express: Listening on port’, port);</p>
<p>peer.on(‘connection’, function (id) {
io.emit(events.CONNECT, id);
console.log(‘# Connected: ‘, id);</p>
<pre class="noskimlinks noskimwords">//Store Peer in database
var user = new User({ username: id });
user.save(function (err, user) {
if (err) return console.error(err);
console.log('# User '+ id + ' saved to database');
});
</pre>
<p>});</p>
<p>peer.on(‘disconnect’, function (id) {
io.emit(events.DISCONNECT, id);
console.log(‘# Disconnected: ‘, id);</p>
<pre class="noskimlinks noskimwords">//Remove Peer from database
User.remove({username: id}, function(err){ if(err) return console.error(err)});
</pre>
<p>});</p>
<p>});
```</p>
<p>To see this working, let’s fire up the chat application. Just run <code class="inline">npm start</code> to get ‘er up.</p>
<p>Now connect to the chat as normal inside the browser (default at <a href="http://localhost:3001">http://localhost:3001</a>).</p>
<p>Once you have connected to your chat, in a new terminal window open <code class="inline">mongo chat</code> to enter the mongo cli.</p>
<p><code class="inline">bash
$ mongo chat
MongoDB shell version: 2.0.6
connecting to: chat
&gt; db.users.find()
{ "username" : "CameronLovesPigs", "_id" : ObjectId("5636e9d7bd4533d610040730"), "__v" : 0 }
</code></p>
<p>Here you have the document record stored inside your <code class="inline">mongo</code>, and now you can always check how many users are online by running at the mongo prompt <code class="inline">db.users.count()</code>.</p>
<p><code class="inline">bash
&gt; db.users.count()
3
</code></p>
<h2>Adding Sessions to Our App</h2>
<p>Because we used Express to build our application, this part is really pretty simple and just requires the installation of a couple modules from <code class="inline">npm</code> to get us going.</p>
<p>Get the <code class="inline">express-session</code> and <code class="inline">connect-mongo</code> packages from npm:</p>
<p><code class="inline">bash
$ npm install express-session connect-mongo cookie-parser --save
</code></p>
<p>Now include them in the top of <code class="inline">app.js</code>:</p>
<p><code class="inline">js
var PeerServer = require('peer').PeerServer,
cookieParser = require('cookie-parser'),
express = require('express'),
session = require('express-session'),
mongoose = require('mongoose'),
MongoStore = require('connect-mongo')(session),
//...
</code></p>
<p>After you set up <code class="inline">mongoose.connect</code> you can configure sessions with express. Change your code to the following; you can specify your own <code class="inline">secret</code> string.</p>
<p>```js
//Connect to the database
mongoose.connect(‘mongodb://localhost:27017/chat’);
var db = mongoose.connection;</p>
<p>mongoose.set(‘debug’, true);</p>
<p>db.on(‘error’, console.error.bind(console, ‘# Mongo DB: connection error:’));</p>
<p>app.use(cookieParser());
app.use(session({
secret: ‘supersecretstring12345!’,
saveUninitialized: true,
resave: true,
store: new MongoStore({ mongooseConnection: db })
}))
```</p>
<p>Here a crucial setting to note is the <code class="inline">saveUninitialized: true</code> inside the last <code class="inline">app.use</code>. This will ensure the sessions are saved.</p>
<p>We specify where with the <code class="inline">store</code> property, which we set to the <code class="inline">MongoStore</code> instance, specifying which connection to use via <code class="inline">mongooseConnection</code> and our <code class="inline">db</code> object.</p>
<p>To store to the session, we need to use express for the request handling because we need access to the request value, for example:</p>
<p><code class="inline">js
//Start persistent session for user
app.use(function(req, res, next) {
req.session.username = id;
req.session.save();
</code></p>
<p>This will create the <code class="inline">req.session.username</code> variable with the value being entered by the user and save it for later.</p>
<p>Next, we can check for this value with our client-side code and automatically log the user in when they refresh so that they never get signed out of the chat and are automatically logged in as their chosen username.</p>
<p>Also interesting to note, because we have database-backed sessions, is that in the event of the developers changing the application and the back-end reloading, the users logged in to their clients will stay logged in as the session store is now persistent. This is a great feature to keep your users happy and logged in all the while you are developing, or if there’s a disconnection from an unstable client.</p>
<h3>Persistent Login</h3>
<p>Now that we have the session cookie part set up, let’s work on adding persistent login to our front-end code.</p>
<p>So far we have just used the default route provided by Express for an SPA application, and not defined any route handling for Express. As I mentioned before, to get access to the session you will need Express’s request / response variables.</p>
<p>First we need one route so we can access the <code class="inline">request</code> object Express provides and display it for debugging purposes. Inside your Express configuration in <code class="inline">/app.js</code>, add the following near the top of the file, after the session setup:</p>
<p>```js
app.use(session({
secret: ‘supersecretstring12345!’,
saveUninitialized: true,
resave: true,
store: new MongoStore({ mongooseConnection: db })
}))</p>
<p>app.get(‘/’, function (req, res) {
res.sendFile(__dirname +’/src/index.html’);
if(req.session.username == undefined){
console.log(“# Username not set in session yet”);
} else {
console.log(“# Username from session: “+ req.session.username);</p>
<p>}
});
```</p>
<p>Now we have some basic logging to see what is happening with our session value. In order to set it, we need to configure getter and setter routes like so:</p>
<p>```js
//Save the username when the user posts the set username form
app.post(‘/username’, function(req, res){
console.log(“# Username set to “+ req.body.username);
req.session.username = req.body.username;
req.session.save();
console.log(“# Session value set “+ req.session.username);
res.end();
});</p>
<p>//Return the session value when the client checks
app.get(‘/username’, function(req,res){
console.log(“# Client Username check “+ req.session.username);
res.json({username: req.session.username})
});
```</p>
<p>These two routes will function as the get and set for the username session var. Now with a bit of basic JavaScript we can implement autologin for our app. Open up <code class="inline">src/App.js</code> and change it as follows:</p>
<p>```js
/* global EventEmitter, events, io, Peer */
/** @jsx React.DOM */</p>
<p>$(function () {
‘use strict’;</p>
<p>// Check for session value
$(document).ready(function(){
$.ajax({
url: ‘/username’
}).done(function (data) {
console.log(“data loaded: “ + data.username);
if(data.username)
initChat($(‘#container’)[0], data.username);
});
});</p>
<p>// Set the session
$(‘#connect-btn’).click(function(){
var data = JSON.stringify({username: $(‘#username-input’).val()});
$.ajax({ url: ‘/username’,
method: “POST”,
data: data,
contentType: ‘application/json’,
dataType: ‘json’
});
});</p>
<p>// Initialize the chat
$(‘#connect-btn’).click(function () {
initChat($(‘#container’)[0],
$(‘#username-input’).val());
});</p>
<p>function initChat(container, username) {
var proxy = new ChatServer();
React.renderComponent(&lt;ChatBox chatProxy={proxy}
username={username}&gt;&lt;/ChatBox&gt;, container);
}</p>
<p>window.onbeforeunload = function () {
return ‘Are you sure you want to leave the chat?’;
};</p>
<p>});
```</p>
<p>With the <code class="inline">$.ajax</code> facility of jQuery we create a request to check the value of the session variable when the <code class="inline">document</code> becomes available. If it is set, we then initialise our React component with the stored value, resulting in an autologin feature for our users.</p>
<p>Fire up the chat again with <code class="inline">npm start</code> and have a look in your browser to see the sessions working.</p>
<h2>Conclusions</h2>
<p>Now you have seen how easy it is to use Mongoose in conjunction with Express and set up Express sessions. Taking your application development further with React as the view controller linked to database-backed elements will create some serious applications.</p>
<p>If you want to go a step further with React and look at how your components can communicate with one another internally inside the React framework, this <a href="https://facebook.github.io/react/tips/communicate-between-components.html">guide</a> from the official documentation is very useful.</p>
2016-01-05T13:00:31.000Z2016-01-05T13:00:31.000ZTom Whitbreadtag:code.tutsplus.com,2005:PostPresenter/cms-24983Quiz: Do You Understand WebSockets?<p>Do you understand WebSockets? Take our quiz and find out.<br></p><figure><iframe src="https://app.qzzr.com/quiz/112156/widget" width="850" height="665" frameborder="0" scrolling="yes"></iframe></figure><h2>Connect the Web With WebSockets<br>
</h2><p>WebSockets make it possible to have interactive, two-way communication sessions between the user's browser and a server. With this API, you can receive event-driven messages without having to poll the server for updates. This makes WebSockets a powerful and efficient tool for building interactive websites.</p><p>Libraries such as Socket.IO make it easy to integrate WebSockets into the front-end and back-end of a site. In our course, <a href="http://code.tutsplus.com/courses/connect-the-web-with-websockets?ec_promo=tuts_quiz&amp;ec_unit=in_post" target="_self">Connect the Web With WebSockets</a>, Tuts+ instructor Daniel Stern will show you how to build a real-time link-sharing application that uses Express and Socket.IO.</p>2015-10-13T14:21:45.000Z2015-10-13T14:21:45.000ZAdam Brown