Skip to content

Commit

Permalink
docs: setting up the request-responses infrastruture
Browse files Browse the repository at this point in the history
Completed setting up the request-responses infrastruture

Signed-off-by: Yaapa Hage <[email protected]>
  • Loading branch information
Yaapa Hage committed Mar 19, 2020
1 parent 5ae59be commit 91bbe7a
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 42 deletions.
115 changes: 87 additions & 28 deletions docs/site/Req-res-cycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,65 +17,124 @@ framework to return a result.

The endpoints on a LoopBack app can be categorized into controller endpoints and
non-controller endpoints. Controller endpoints are those that are created by
LoopBack controller methods, non-controller endpoints are those that are created by
other APIs.
LoopBack controller methods, non-controller endpoints are those that are created
by other APIs.

#### Controller endpoints

Controller methods decorated with operation decorators like `@get()`, `@post()`,
`@put` etc., create enpoints on the app for the corresponding HTTP verbs. The behavior
of these endpoints are entirely dependent on the implementation of the controller method.
`@put` etc., create enpoints on the app for the corresponding HTTP verbs. The
behavior of these endpoints are entirely dependent on the implementation of the
controller method.

{% include tip.html content="Apart from controller files in the `controllers` directory,
controllers may be added to the app by [components](https://loopback.io/doc/en/lb4/Components.html)." %}

In the request-response cycle section we will see how implemenation details determine
the course of a request these endpoints - they may or may not actually interact with a model.
In the request-response cycle section we will see how implemenation details
determine the course of a request these endpoints - they may or may not actually
interact with a model.

#### Non-controller endpoints

The following APIs can create non-controller endpoints.

[TODO: elaborate these]
##### 1. app.static(path, rootDir, options)

1. app.static()
2. app.redirect()
3. app.mountExpressRouter() //express routes
4. non-controller endpoints added by components
5. app.handler() <-- include this?
6. app.route() <-- include this?
This method maps to the underlying Express' [static](https://expressjs.com/en/4x/api.html#express.static)
method. It creates dynamic enpoints for files in the `rootDir` to be servered
at `path`.

More details at [RestApplication.static()](https://loopback.io/doc/en/lb4/apidocs.rest.restapplication.static.html)
doc.

##### 2. app.redirect(fromPath, toPathOrUrl, statusCode)

This method redirects requests to `fromPath` to `toPathOrUrl` with the status
code `statusCode`.

More details at [RestApplication.redirect()](https://loopback.io/doc/en/lb4/apidocs.rest.restapplication.redirect.html)
doc.

##### 3. app.mountExpressRouter(basePath, router, spec)

This method mounts an Express [router](https://expressjs.com/en/4x/api.html#router)
in the LoopBack app. You can use it for adding custom enpoints in your app using
the Express middleware format.

More details at [RestApplication.mountExpressRouter()
](https://loopback.io/doc/en/lb4/apidocs.rest.restapplication.mountexpressrouter.html) doc.

##### 4. non-controller endpoints added by components

[Components](https://loopback.io/doc/en/lb4/Components.html) are the extension
units of LoopBack. Since they can access the LoopBack app instance, the request
and response instances using [dependency injection](https://loopback.io/doc/en/lb4/Dependency-injection.html),
they are capable of adding new endpoints and determining the result of a request.

### The request-response cycle

The request-response cycle involves many components, especially if the request
is to a controller-endpoint which interacts with a model.

![Components of LoopBack 4 request-response cycle](./imgs/req-res-high-level.png)

The request handling process starts with the app's [sequence](https://loopback.io/doc/en/lb4/Sequence.html);
it is the gatekeeper of all requests to the app. Every request, whether to controller
endpoints or non-controller endpoints, must pass through the sequence.
it is the gatekeeper of all requests to the app. Every request, whether to
controller endpoints or non-controller endpoints, must pass through the sequence.

The sequence identifies the responsible handlers for the requested endpoint and passes
on the request to the handlers. The handlers then take care of sending the response back to
the client.
The sequence identifies the responsible handlers for the requested endpoint and
passes on the request to the handlers. The handlers then take care of sending
the response back to the client.

#### The sequence

The sequence is a simple class with five injected helper methods. These five methods
come together in the sequence class to make the request-response cycle possible in
LoopBack.
The sequence is a simple class with five injected helper methods. These five
methods come together in the sequence class to make the request-response cycle
possible in LoopBack.

{% include tip.html content="All of the injected helper methods are [providers](https://loopback.io/doc/en/lb4/Creating-components.html#providers).
Providers support [dependency injection](https://loopback.io/doc/en/lb4/Binding.html#a-provider)
and are perfect for returning values from the [context](https://loopback.io/doc/en/lb4/Context.html)." %}

![LoopBack 4 sequence](./imgs/sequence-details.png)

##### 1. FindRoute

Finds the appropriate endpoint (route or controller method, spec and args) for
invocation. If no endpoint is fount, it throws an error.

https://loopback.io/doc/en/lb4/apidocs.rest.findrouteprovider.html

##### 2. ParseParams

https://loopback.io/doc/en/lb4/apidocs.rest.parseparamsprovider.html

##### 3. InvokeMethod

https://loopback.io/doc/en/lb4/apidocs.rest.invokemethodprovider.html

##### 4. Send

Responsible for sending the

https://loopback.io/doc/en/lb4/apidocs.rest.sendprovider.html

##### 5. Reject

[TODO: elaborate these]
Responsible for sending error back to the client in case any of the above helper
methods throw or encounter any errors.

1. FindRoute
2. ParseParams
3. InvokeMethod
4. Send
5. Reject
https://loopback.io/doc/en/lb4/apidocs.rest.rejectprovider.html

#### Request to a controller endpoint

[TODO: explain]

- How controller methods work with various types of services
- How controller methods work with repositories (and datasource) to get/set model data
- How controller methods work with repositories (and datasource) to get/set
model data
- What are interceptors and how they can affect the req-res cycle
- Walk through a single REST API

#### Request to a non-controller endpoint

Expand Down
Binary file added docs/site/imgs/req-res-high-level.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/site/imgs/sequence-details.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 2 additions & 13 deletions packages/rest/src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,13 @@
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {
isReferenceObject,
OperationObject,
ParameterObject,
REQUEST_BODY_INDEX,
SchemasObject,
} from '@loopback/openapi-v3';
import {isReferenceObject, OperationObject, ParameterObject, REQUEST_BODY_INDEX, SchemasObject} from '@loopback/openapi-v3';
import debugFactory from 'debug';
import {RequestBody, RequestBodyParser} from './body-parsers';
import {coerceParameter} from './coercion/coerce-parameter';
import {RestHttpErrors} from './rest-http-error';
import {ResolvedRoute} from './router';
import {
OperationArgs,
PathParameterValues,
Request,
RequestBodyValidationOptions,
} from './types';
import {OperationArgs, PathParameterValues, Request, RequestBodyValidationOptions} from './types';
import {validateRequestBody} from './validation/request-body.validator';
const debug = debugFactory('loopback:rest:parser');

Expand Down
2 changes: 1 addition & 1 deletion packages/rest/src/providers/find-route.provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
// License text available at https://opensource.org/licenses/MIT

import {Context, inject, Provider} from '@loopback/context';
import {FindRoute, Request} from '../types';
import {HttpHandler} from '../http-handler';
import {RestBindings} from '../keys';
import {ResolvedRoute} from '../router';
import {FindRoute, Request} from '../types';

export class FindRouteProvider implements Provider<FindRoute> {
constructor(
Expand Down

0 comments on commit 91bbe7a

Please sign in to comment.