Add routing, controller and database logic.
By Dan McGhan
September/October 2018
after U.Sshort detour to create a generic database module,It's time to move on to building the common REST API components for Node.js that were discussed inthe first articleIn this series, you add routing, controller, and database logic to process an HTTP GET request on a "worker" API endpoint.
Note: The instructions and steps in this article assume that you have completed the processthe steps in Part 2this series of articles.
Add routing logic
Express, which creates the web server for this project, comes with aRouterA class that makes it easy to route HTTP requests to the appropriate controller logic.track pathsdefine the endpoints of the API URL and can containroute parametersCollecting values in the URL (query strings are not part of route paths).
There are many ways to define routes for your application. For example, when the application starts, it can read all files in the controller directory and, based on some predefined rules, such as B. file names and the properties they provide, automatically generate routing logic. Alternatively, you can add a file to the configuration directory and read it on boot. Consider this automation when your API is mature and your patterns are known.
In this application, you use a slightly lower-level approach by defining routes programmatically through a new router module. Create a new file named router.js in the services directory. Add the following code to the file and save the changes:
const express = require('express');const router = new express.Router();const Empleados = require('../controllers/employees.js');router.route('/employees/:id?') .get(empleados.get);module.exports = rotador;
This router module starts embedding Express and then creates a new instance of the Express router class. of the routerlistused to define a route based on the route driven route. The route includes a parameter calledI would go, which is optional with the question mark that follows it. The route that returns fromlistcontains methods that correspond to HTTP methods and allow you to define controllers. In this case thetake itThe method is used to assign an incoming GET request to thetake itFunction defined in Employees controller (will be created in the next part of this article).
At this point you have a router, but it is not currently being used in the application. To use it, open the services/web-server.js file and remove the line above that requires the database engine (only used for testing in the previous article). Instead, add the following line of code:
// *** the line that requires ../config/web-server.js is here ***const router = require('./router.js');
Then replace the entire app.get controller that responds to GET requests with the database engine (all seven lines) with the following code:
// *** Line Morgan adds to app here ***// Mount router on /api so all routes start with /apiapp.use('/api', router);
The router is now required in the Webservices module and mounted under /api. This means that the full URL for the employee endpoint is http://server:port/api/employees/:id.
Adding controller logic
The controller logic takes over from the point where the URL endpoint and HTTP method are known. Because the web server is built with Express, the controller logic is defined using custom middleware or functions that have access to the request and response objects, as well as theNextOccupation.
The middleware function uses the input data from the request object to generate a response that is sent using the response object. EITHERNextThe function is typically used to call the next middleware function in the pipeline. However, in this API, the controller logic is the final step in the pipeline and completes the HTTP response. The following function is only called when an error occurs, in which case control is passed to Express.Standard-Error-Handler.
I usually create a module in the controller directory for each endpoint in the API. Here are some examples:
URL endpoint | driver file |
/api/employee/:id | Controller/Employee.js |
/api/departments/:id | Controllers/Departments.js |
/api/departments/:dept_id/employees/:emp_id | controllers/departments_employees.js |
Each module defines and exposes a middleware function that handles a specific HTTP method. I usually name each function after the HTTP method it handles, which makes it easy to hook things up in the router module.
Go to the driver directory and create a new file calledEmployee.js. Copy and paste the following code into the file and save the changes:
const employees = require('../db_apis/employees.js'); asynchronous function get(req, res, next) { try { const context = {}; context.id = parseInt(req.params.id, 10); linhas const = wait for Employees.find(context); if (req.params.id) { if (rows.length === 1) { res.status(200).json(rows[0]); } else {res.status(404).end(); } } Else {res.status(200).json(rows); } } catch (error) { next (error); }}module.exports.get = get;
Here is a review of the driver module so far:
lines) | description |
1 | The Employee Database API (created in the next part of this article) is required. |
3–23 | An asynchronous function calledtake itit explains. A try-catch block is used in the body of the function to catch exceptions thrown on the main thread and propagate them to theNextOccupation. |
5–7 | a constant callcontextit explains. This is a generic object that contains properties relevant to the database API.to thinkMethod. An ID property is addedcontext, com base no value entered overreq.params.id. |
9 | The Database APIto thinkThe method is used to retrieve the appropriate employee records from the database. |
11–19 | Conditional logic is used to determine the correct HTTP status code and response body. If an employee is requested but not found, the error code "404 Not Found" is returned in response. Otherwise, a "200 OK" code is sent along with a JSON-based response body. |
25 | Ötake itThe function is exported from the module so that it can be used in the router module. |
Öinheritance paramObject is just one of several properties used to retrieve data from inputrequest object. Other common features includeconsultation required, for query string values in the URL;body requirement, for the request body; Yrequired cookies. HTTP headers can be retrieved using thereq.getMethod.
If you don't like the magic numbers used for status codes, you should use a module likehttp-StatusInstead of. This module provides constants likeOKmiNOT FOUND, which can add clarity to the code.
Add database logic
As I mentioned in Part 1 of this article series, I will be using the Node.js database driver/API for the Oracle database, node-oracledb, instead of a higher-level Object Relational Mapping (ORM). To start the employee database engine, go to the db_apis directory and create a new file called Employees.js. Add the following code to the file:
const banco de dados = require('../services/database.js');const baseQuery = `selecione employee_id "id", first_name "first_name", last_name "last_name", email "email", phone_number "phone_number", Hire_date "fecha_contratación", job_id "job_id", salario "salario", comisión_pct "comisión_pct", manager_id "manager_id", department_id "department_id" from Employees`;async function find(context) { let query = baseQuery; konstante Liga = {}; if (context.id) {binds.employee_id = context.id; consulta += `\nwhere empleado_id = :employee_id`; } const resultado = espera base de datos.simpleExecute (consulta, enlaces); return result.rows;}module.exports.find = localizar;
The employee database engine contains the generic database engine and initializes a called constantbaseQueryto an SQL query in the Employees table. Double-quoted column aliases are used in the query to control the case of the returned keys.
So a called functionto thinkis declared and used to execute the query and return the rows fetched. If hecontextThe passed parameter has the value "true" forI would go, a WHERE clause is added to the query so that only a single employee is returned.
Note that the value ofcontexto.idit was not attached directly to the query. Instead, a placeholder named:Employee IDwas used - this is known asbinding variable. Using bind variables with Oracle Database isveryImportant for security and performance reasons. The value of the link variable is assigned to theLigaObject passed to with the querydatabase.simpleExecute. Finally, the rows returned from the database are returned to the caller.
Once the database engine is installed, you can test everything. Start the application and navigate to http://localhost:3000/api/employees in Firefox. You should see a list of employees (I've collected a few) as shown inillustration 1.
|
|
You can search for an individual employee by adding an ID to the end of the URL, e.g. B. http://localhost:3000/api/employees/100 as shown inFigure 2.
At this point, your API can handle GET requests on the employee endpoint. In the next article, you complete the CRUD (Create, Replace, Update, and Delete) function by adding logic that handles POST, PUT, and DELETE requests.
Next Steps
LER Part 1 of this series of articles.
LER Part 2 of this series of articles.
TO LEARNmore aboutJavaScript und Oracle.
TO ATTEMPT orakel cloud.
TAKE ITmore aboutthe code from this GitHub article.
Illustration by Wes Rowell