diff --git a/docs/site/Req-res-cycle.md b/docs/site/Req-res-cycle.md index 15807088f8b2..2efd2c99bfb0 100644 --- a/docs/site/Req-res-cycle.md +++ b/docs/site/Req-res-cycle.md @@ -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 diff --git a/docs/site/imgs/req-res-high-level.png b/docs/site/imgs/req-res-high-level.png new file mode 100644 index 000000000000..0700e3cd8f26 Binary files /dev/null and b/docs/site/imgs/req-res-high-level.png differ diff --git a/docs/site/imgs/sequence-details.png b/docs/site/imgs/sequence-details.png new file mode 100644 index 000000000000..b7cfe1a6103f Binary files /dev/null and b/docs/site/imgs/sequence-details.png differ diff --git a/packages/rest/src/parser.ts b/packages/rest/src/parser.ts index bd27e3b5bafa..bac72a3f82b7 100644 --- a/packages/rest/src/parser.ts +++ b/packages/rest/src/parser.ts @@ -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'); diff --git a/packages/rest/src/providers/find-route.provider.ts b/packages/rest/src/providers/find-route.provider.ts index eb3e0654d45c..36b61d0bc214 100644 --- a/packages/rest/src/providers/find-route.provider.ts +++ b/packages/rest/src/providers/find-route.provider.ts @@ -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 { constructor(