Last Sync: 2022-07-14 08:00:04
This commit is contained in:
parent
6c327af1d8
commit
b79418c175
7 changed files with 24 additions and 94 deletions
|
@ -5,9 +5,11 @@ tags:
|
|||
- apis
|
||||
---
|
||||
|
||||
# RESTful APIs
|
||||
|
||||
## Definition of an API
|
||||
|
||||
An application programming interface is a set of definitions and protocols for building and integrating application software. It can be thought of as a contract between an information provider and an informational consumer. The API is a mediator between the clients and the resources they wish to acquire from a server or database.
|
||||
An application programming interface (API) is a set of definitions and protocols for building and integrating application software. It can be thought of as a contract between an information provider and an informational consumer. The API is a mediator between the clients and the resources they wish to acquire from a server or database.
|
||||
|
||||
## REST
|
||||
|
||||
|
@ -32,12 +34,12 @@ In order to qualify as RESTful, an API must meet the following constraints:
|
|||
|
||||
## Example
|
||||
|
||||
A basic example of a REST API would be a series of methods corresponding to the main [HTTP request types](HTTP%20request%20types.md).
|
||||
A basic example of a REST API would be a series of methods corresponding to the main [HTTP request types](/Databases/HTTP_request_types.md).
|
||||
|
||||
\| HTTP request type | URI | Action | Body ? |
|
||||
\|------------------- |--------------------- |------------------------------ |-------------------------- |
|
||||
\| GET | /api/customers | Retrieve customers as array | No |
|
||||
\| GET | /api/customers/guid | Get a specific customer | No, data comes from GUID |
|
||||
\| PUT | /api/customers/guid | Update an existing customer | Yes |
|
||||
\| DELETE | /api/customers/1 | Delete a customer | No, data comes from GUID |
|
||||
\| POST | /api/customers | Create a new customer | Yes |
|
||||
| HTTP request type | URI | Action | Body ? |
|
||||
|------------------- |--------------------- |------------------------------ |-------------------------- |
|
||||
| GET | /api/customers | Retrieve customers as array | No |
|
||||
| GET | /api/customers/guid | Get a specific customer | No, data comes from GUID |
|
||||
| PUT | /api/customers/guid | Update an existing customer | Yes |
|
||||
| DELETE | /api/customers/1 | Delete a customer | No, data comes from GUID |
|
||||
| POST | /api/customers | Create a new customer | Yes |
|
||||
|
|
0
Programming_Languages/NodeJS/Architecture/Events.md
Normal file
0
Programming_Languages/NodeJS/Architecture/Events.md
Normal file
|
@ -47,10 +47,10 @@ config/
|
|||
For example:
|
||||
|
||||
```json
|
||||
// default.json
|
||||
{
|
||||
"name": "My Express app"
|
||||
}
|
||||
// default.json
|
||||
{
|
||||
"name": "My Express app"
|
||||
}
|
||||
```
|
||||
Then to utilise config variables:
|
||||
|
||||
|
@ -88,7 +88,7 @@ We can then safely reference this value in the course of our normal code:
|
|||
console.log(config.get('password'))
|
||||
```
|
||||
|
||||
<p style="color:red">! But how would this be achieved in a production server></p>
|
||||
<p style="color:red">! But how would this be achieved in a production server?</p>
|
||||
|
||||
|
||||
<p style="color:red">! And how could we do this programmatically at the start of a local development session without manually setting each environment variable in the terminal?</p>
|
|
@ -28,11 +28,13 @@ app.use((req, res, next) => {
|
|||
|
||||
### `next`
|
||||
|
||||
The `next` parameter is key, it allows Express to move onto the next middleware function once the custom middleware executes. Without it, the request processing pipeline will get blocked. middleware functions are basically asynchronous requests and as such they use a similar syntax as Promises (e.g `then`) for sequencing processes.
|
||||
The `next` parameter is key, it allows Express to move onto the next middleware function once the custom middleware executes. Without it, the request processing pipeline will get blocked.
|
||||
|
||||
Middleware functions are basically asynchronous requests and as such they use a similar syntax as Promises (e.g `then`) for sequencing processes.
|
||||
|
||||
### Example of sequence
|
||||
|
||||
````js
|
||||
```js
|
||||
app.use((req, res, next) => {
|
||||
console.log('Do process A...')
|
||||
next()
|
||||
|
@ -43,57 +45,9 @@ app.use((req, res, next) => {
|
|||
next()
|
||||
})
|
||||
|
||||
````
|
||||
|
||||
Would return the following once the server starts:
|
||||
|
||||
````plain
|
||||
Do process A...
|
||||
Do process B...
|
||||
|
||||
````
|
||||
|
||||
>
|
||||
> It makes more sense of course to define our middleware within a function and then pass it as an argument to `app.use()`
|
||||
|
||||
## Useful built-in middleware
|
||||
|
||||
### `express.static()`
|
||||
|
||||
>
|
||||
> `app.use(express.static())`
|
||||
|
||||
Allows you to serve static files.
|
||||
Let's say we have a file called `something.txt` that resides at `public/something.txt`
|
||||
We can expose this to express with `app.use(static('public'))`. Then if we navigate to `localhost:3000/readme.txt` the file will be served in the browser. (Not the `public` subdirectory is not included in the URL, it will be served from root).
|
||||
|
||||
### `express.urlencoded()`
|
||||
|
||||
>
|
||||
> `app.use(express.urlencoded())`
|
||||
|
||||
Generally we handle the data of API requests via a JSON body and the `express.json()` middleware. However, in cases where the data is sent from the client in the form of `key=value&key=value` appendages to the request URL, `urlencoded` allows us to parse them.
|
||||
|
||||
|
||||
## Third-party middleware
|
||||
### Helmet
|
||||
|
||||
Helmet is middleware that makes it easier to set HTTP headers.
|
||||
|
||||
### Morgan
|
||||
|
||||
Morgan is middleware that is used to log HTTP requests to the Express instance.
|
||||
```js
|
||||
app.use(morgan('dev'))
|
||||
```
|
||||
With Morgan in place, every time we run a request it will be logged on the console that is running our Node application, e.g:
|
||||
|
||||
```plain
|
||||
GET /api/courses 200 95 - 1.774 ms
|
||||
```
|
||||
This uses the `tiny` default which logs the bare minimum giving us: request type; endpoint; response code; and time to execute.
|
||||
|
||||
It defaults to logging on the console but can also be configured to write to a log file.
|
||||
> It makes more sense of course to define our middleware within a function and then pass it as an argument to `app.use()`
|
||||
|
||||
## Including middleware based on environment
|
||||
With a full-scale Node application you will typically run three environments:
|
||||
|
@ -106,18 +60,7 @@ We will not want to run certain types of middleware in all environments. For exa
|
|||
### Accessing current Node environment
|
||||
We can control which middleware we run via the Node envrionment variables: `process.env` (see for instance [ports](./Ports.md)).
|
||||
|
||||
To determine the current environment we can use the variable `process.env.NODE_ENV`. This works globally regardless of the kind of Node app we are building. But in Express, there is a built in method for retrieving the current envrionment: `app.get('env')`.
|
||||
|
||||
If you haven't manually set up your environments Node will return `undefined` but express defaults to `development`.
|
||||
|
||||
```js
|
||||
|
||||
console.log(process.env.NODE_ENV); // undefined
|
||||
console.log(app.get("env")); // development
|
||||
|
||||
```
|
||||
|
||||
We can set Morgan to run only in development with:
|
||||
We could set [Morgan](/Programming_Languages/NodeJS/Modules/Third_party/Morgan.md) to run only in development with:
|
||||
|
||||
```js
|
||||
if (app.get("env") === 'development') {
|
||||
|
@ -125,10 +68,3 @@ if (app.get("env") === 'development') {
|
|||
console.log('Morgan enabled')
|
||||
}
|
||||
```
|
||||
|
||||
### Setting the current environment
|
||||
We could test that the previous code block works by switching the environment to production. We would do this by setting the environment variable in the terminal:
|
||||
|
||||
```
|
||||
export NODE_ENV=production
|
||||
```
|
|
@ -10,7 +10,7 @@ tags:
|
|||
|
||||
When working in development we are able to specify the specific port from which we want top serve our application. In production, we do not always have this control: the port will most likely be set by the provider of the server environment.
|
||||
|
||||
While we may not know the specific port, whichever it is, it will be accessible via the `PORT` environment variable. So we can use this when writing our [event listeners](Events%20module.md#event-emitters):
|
||||
While we may not know the specific port, whatever it is, it will be accessible via the `PORT` environment variable. So we can use this when writing our [event listeners](Events%20module.md#event-emitters):
|
||||
|
||||
````js
|
||||
const port = process.env.PORT || 3000;
|
||||
|
|
|
@ -28,12 +28,6 @@ const app = express()
|
|||
|
||||
````
|
||||
|
||||
## Nodemon
|
||||
|
||||
We don't want to have to restart the server every time we make a change to our files. We can use `nodemon` instead of `node` when running our `index.js` file so that file-changes are immediately registered without the need for a restart.
|
||||
|
||||
> Once `nodemon` is installed, update your start script from `node index.js` to `nodemon index.js`.
|
||||
|
||||
## Our data
|
||||
|
||||
> Typically when you create a RESTful API you are going to be returning data from a database. For simplicity we are just going simulate this with a simple data array so that we can focus on the Express syntax rather than database handling.
|
||||
|
|
|
@ -3,11 +3,9 @@ h1, h2, h3, h4, h5, h6, p {
|
|||
}
|
||||
|
||||
pre, code {
|
||||
font-family: 'LigaLiberationMono';
|
||||
font-size: 12px !important;
|
||||
font-family: 'JetBrains Mono';
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
h1 {
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue