7.2: Accessing a Server Using Node.js, Sails
- Page ID
- 27574
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)
( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\id}{\mathrm{id}}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\kernel}{\mathrm{null}\,}\)
\( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\)
\( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\)
\( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)
\( \newcommand{\vectorA}[1]{\vec{#1}} % arrow\)
\( \newcommand{\vectorAt}[1]{\vec{\text{#1}}} % arrow\)
\( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vectorC}[1]{\textbf{#1}} \)
\( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)
\( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)
\( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)Now that the application server is running, it can be accessed through any browser. To see this type the following Uniform Resource Locator into any web browser:
http://localhost:1337/MapData
The statement tells the browser to look on the local host for a program attached to port 1337. At that port a resource, MapData, will be found, and data from that application will be shown on the web page.
Depending on the browser, you will get different outputs. Chrome will display an open and close square bracket, indicating that there is no MapData in the application.
Firefox recognizes that the data is JSON data, and it consists of an empty array. It gives you move options to query this data, but looking at the raw data gives the same open and close square bracket.
This is the concept of a REST server. All commands are accessed via HyperText Transport Protocol (HTTP) using HTML requests. These requests can all be generated from the browser, and later in this chapter this will be accomplished using AJAX requests from JavaScript. But to have to write an entire program just to test that the REST services work is inefficient.
Fortunately, there are a number of apps that can be used for interacting with REST APIs. The one used in this text is Postman.
7.2.1 Getting started with Postman
To install Postman, go to the website https://www.getpostman.com/, and download the free app. Follow the installation instructions, and the Postman application should come up with a window that appears similar to the one below.
From this window, choose the GET method and type in the URL for the server. When you hit the Send button, the window should come back with the two square brackets, as it did with the web page. Postman is now ready to test your system.
7.2.2 Creating data
If all Postman does is emulate a very poorly setup browser, it is not that useful. But it does much more. As we said at the end of Chapter 7.1.4, the server has implemented a full set of CRUD operations. However, to access them we need a way to format the requests. Formatting these requests is really not practical (or possible) from a web browser without using JavaScript. And for testing the application, implementing the test cases in JavaScript would be a poor choice.
The only reason the web browser was able to easily access the application earlier is because the default request, get with no parameters, is the default request.
Postman allows us to easily develop and test the REST server application. This is probably best seen in the context of using Postman, so the following is a life cycle of an application presented using Postman.
The first step, making sure Postman can reach the server, is already done in the last section.
Next data should be added to the server. This is accomplished using the POST method with the same URL. When sending a POST request, note that a body of the post request can be included by clicking the Body button. Click the button and include the following JSON object in the body of the request, as shown in the figure below.
Program 113 – Input object for Postman POST request { "title":"map1", "resize":"true", "recenter":"true", "mapType":"Stamen", "screenSize":"1024x768", "latitude":"-75", "longitude":"45" }
When this request is sent, the server sends back a status code of 200 indicating the request was successful. It also sends back a copy of the object as it was stored in the database. Note that 3 fields are included that were not part of the original request but are added by Sails. These fields are createdAt, updatedAt, and id. The important filed is the id field, which will be the primary unique key for this record in the persistent storage. This key will be used for subsequent queries to read/update/delete this record.
Add 2 more records, changing at least the title in the Postman body so that you know 3 different records have been saved.
7.2.3 Retrieving Data
Now retrieve all of the records placed in the Node.js server and show them in Postman. This is done by sending a GET request, localhost:1337/mapData, to the server for MapData. This was done earlier to show that the connection to Node.js was valid and returned a null array as there were no records in the database. Now this query will return an array of the 3 map elements that were posted to the array, as shown in the following figure.
To retrieve the information for an individual record, the id of the record to be retrieved is appended to the URL. For example, the second MapData record inserted into the data store was given the id of 2. To retrieve this record, append the number 2 onto the GET query, localhost:1337/mapData, and just the second record will be returned as a JSON object.
If a request is made for an ID that does not exist, the server will return a 404 status code and return the message “Not Found”.
7.2.4 Updating and Deleting records
The last two operations for a CRUD interface are Update and Delete. To Update a record in the server, the PUT or PATCH method is used with the URL for a specific record in the server. The PATCH request with the URL and fields for ID 2 is shown below. The Update requires all fields in the object to be sent, though in this case only the title is updated.
There are technical differences between PUT and PATCH requests, but either normally will work. If one causes difficulties, try the other.
Finally, the Delete CRUD option is accomplished by using the URL for a specific record and the DELETE method. The following shows an example of deleting the record with an ID of 2. In this case, the server sent back a Status code of 200, saying the transaction worked, and the JSON of the record that was deleted.
Different servers will choose different Status codes for these transactions, and the Delete transaction will often return a 404 saying the record was not found because it was deleted. This can be confusing, as it could say that the record was not found, OR the record was deleted. What status codes are returned for different operations, especially when there is a complex transaction, can be confusing, and even the documentation as to what a server will return can be hard to understand. The best advice might be to use trial-and-error to find out what status codes will be returned.
7.2.5 Summary of CRUD REST server transactions
Method |
URL |
Meaning |
GET |
/:model |
Return an array of JSON objects that are stored for this model |
GET |
/:model/:id |
Return an JSON object for this model with this ID |
PUT |
/:model |
Create a record for this model in the server |
POST or PATCH |
/:model/:id |
Update the record for this model with this ID |
DELETE |
/:model/:id |
Delete the record for this model with this ID |