Differences between LB3 and LB4 req-res cycle#4974
Conversation
52067ab to
a054e32
Compare
|
|
||
| ### Request/response infrastructure | ||
|
|
||
| The difference begins with the LoopBack object itself. In LoopBack 3, it is an |
There was a problem hiding this comment.
LoopBack object? Do you mean LoopBack application object?
| separation of concerns and decoupling the functionality makes the codebase | ||
| cleaner, easier to maintain, and much easier to customize functionality at | ||
| various levels. This can be better appreciated as the complexity of your app | ||
| grows. |
There was a problem hiding this comment.
We should mention rest-crud here to mimic creating REST CRUD APIs from a model and a datasource by convention. See https://github.com/strongloop/loopback-next/blob/master/docs/site/Creating-CRUD-REST-apis.md
There was a problem hiding this comment.
Ah yes, thanks!
There was a problem hiding this comment.
Added:
For those who are uncomfortable with the concept of having to creating a
repository and a controller for a model, we have a component @loopback/rest-crud
; with a little bit of configuration, a model file is all you will need to
create the REST endpoints. Once your requirements outgrow what
@loopback/rest-crudprovides, you can implement your REST endpoints the
idiomatic way.
There was a problem hiding this comment.
I think we can use page https://loopback.io/doc/en/lb4/Creating-crud-rest-apis.html on the site
There was a problem hiding this comment.
@loopback/rest-crud links to https://loopback.io/doc/en/lb4/Creating-crud-rest-apis.html .
|
|
||
| In LoopBack 3 you could add routes and load custom middleware using `app.get()`, | ||
| `app.post()`, `app.use()`, etc., just like how you do in Express. | ||
| In LoopBack 4, you cannot do it anymore. The closest to doing this is to use the |
There was a problem hiding this comment.
In LoopBack 4, you cannot do it anymore
Maybe we can make this more positive. :). Some suggestion:
In LoopBack 4, a custom Express router can be mounted on a LoopBack app using the RestApplication.mountExpressRouter() API.
There was a problem hiding this comment.
Facts should be presented as clearly and straightforwardly as possibly, so that expectations are set right there are no misconceptions. If we don't tell a certain popular way of doing something is not supported anymore, we are adding ambiguity. Let's not do that.
There was a problem hiding this comment.
I agree with Diana that "you cannot do it anymore" leaves negative impression. We have plans to support Express middleware, see #1293 and #2035. It is also possible to mount a LB4 app in a new top-level Express app, that's our currently recommended way for installing Express middleware - see https://loopback.io/doc/en/lb4/express-with-lb4-rest-tutorial.html
I am proposing to rephrase the sentence as "you cannot do it yet" and provide users with details about the current status (workaround) and future plans.
There was a problem hiding this comment.
I am proposing to rephrase the sentence as "you cannot do it yet"
Even better: "LoopBack 4 does not provide first-class support for mounting application-wide Express middleware yet." (and so on)
| and [Interceptors](https://loopback.io/doc/en/lb4/Interceptors.html) makes it a | ||
| very powerful extension mechanism. | ||
|
|
||
| LoopBack 4 has gotten rid of |
There was a problem hiding this comment.
just wondering... does middleware.json related to the paragraph below?
Suggested change:
LoopBack 4 does not have
[middleware.json](https://loopback.io/doc/en/lb3/middleware.json.html)
as LoopBack 3 because it is not required because of the architectural changes.
There was a problem hiding this comment.
Updated:
In LoopBack 4 middleware.json is not require anymore because of architectural changes.
| [middleware.json](https://loopback.io/doc/en/lb3/middleware.json.html) | ||
| by. It is not require anymore because of the architectural changes. | ||
|
|
||
| In LoopBack 3, models files automatically created the corresponding REST API |
There was a problem hiding this comment.
models files automatically created -> model files automatically create?
There was a problem hiding this comment.
I'm thinking whether we can put it something along the line:
In LoopBack 3, the model and datasources are tightly coupled. Therefore, once both are specified, the corresponding REST APIs can be created.
In LoopBack 4, there is a separation of concerns where models and datasources are not tightly coupled. The Repository does xxxxx. The Controller does xxxxxx. With the rest-crud package, a similar mechanism can be achieved.
There was a problem hiding this comment.
Edited:
In LoopBack 3, models files automatically create the corresponding REST API
endpoints and the database query machinery (using the configured datasource).
Apart from that, I'd like to keep it as such.
| [servers](https://loopback.io/doc/en/lb4/Server.html), | ||
| [observers](https://loopback.io/doc/en/lb4/Life-cycle.html), | ||
| [providers](https://loopback.io/doc/en/lb4/Creating-components.html#providers), | ||
| and controllers to the app using dependency injection. |
There was a problem hiding this comment.
I don't know if we have any tutorial/blog that puts everything together. It'd be good to link it here.
There was a problem hiding this comment.
That link https://loopback.io/doc/en/lb4/Creating-components.html is supposed to be it.
| [Migrating boot scripts](https://loopback.io/doc/en/lb4/migration-boot-scripts.html) | ||
| ." %} | ||
|
|
||
| ### Request/response pathway |
There was a problem hiding this comment.
Are the contents of Request/response pathway forthcoming` ?
bajtos
left a comment
There was a problem hiding this comment.
Thank you @hacksparrow for sharing the early draft. I like that you are covering various aspects of migration.
I find it difficult to orientate myself in the text, I am lacking at least a bit of structure - it feels like a raw dump of ideas to me.
|
|
||
| In LoopBack 3 you could add routes and load custom middleware using `app.get()`, | ||
| `app.post()`, `app.use()`, etc., just like how you do in Express. | ||
| In LoopBack 4, you cannot do it anymore. The closest to doing this is to use the |
There was a problem hiding this comment.
I agree with Diana that "you cannot do it anymore" leaves negative impression. We have plans to support Express middleware, see #1293 and #2035. It is also possible to mount a LB4 app in a new top-level Express app, that's our currently recommended way for installing Express middleware - see https://loopback.io/doc/en/lb4/express-with-lb4-rest-tutorial.html
I am proposing to rephrase the sentence as "you cannot do it yet" and provide users with details about the current status (workaround) and future plans.
| In LoopBack 4, model files are limited only to describing the properties of the | ||
| data. You will have to create a corresponding | ||
| [Repository](https://loopback.io/doc/en/lb4/Repositories.html) | ||
| for database connectivity, and controller creating the REST API endpoint. |
There was a problem hiding this comment.
Since you are using a link for Repository, please use a link for Controller too. https://loopback.io/doc/en/lb4/Controllers.html
There was a problem hiding this comment.
Controllers already linked two paragraphs up. Will link, anyway.
| idiomatic way. | ||
|
|
||
| Components are still supported in LoopBack 4, but the concept of component | ||
| has completely changed. |
There was a problem hiding this comment.
I feel the components are out of scope of request/response life cycle. We have a standalone doc page to cover migration of components - see https://loopback.io/doc/en/lb4/migration-extensions.html
Unless there is something specific to the way how components interact (or contribute to) request/response life cycle, then I am proposing to remove this and the next paragraph.
There was a problem hiding this comment.
As someone who wrote a component to add routes to the app, who is going through the docs to see what has changed in LB4 from the req-res perspective, this info will definitely help me; instead of having to browse through the docs, with no certainty when and where I will find the info I need.
|
|
||
| If you used LoopBack 3 boot scripts for adding routes to the app, it | ||
| should now be moved to a standalone controller, a component, or implemented | ||
| using `app.mountExpressRouter()`. |
There was a problem hiding this comment.
Migration of boot scripts are covered by https://loopback.io/doc/en/lb4/migration-boot-scripts.html.
In the context of this page, I would like to see instructions on migrating custom Express routes contributed by a boot script. I think the solution is to convert such Express routes to regular LB4 Controllers? Maybe that's something belonging to our docs for boot script migration? IDK.
There was a problem hiding this comment.
Will add an example of migrating a simple route, using a controller.
There was a problem hiding this comment.
agreed, the bootscript migration doc contains the guide of retrieving different artifacts, but not adding artifacts like endpoints.
server.get('/hello', (req, res) => {
res.send('Hello!');
});is not covered yet, but we should add an entry for it, I mean in the bootscript migration guide.
| functionality to the controller of a LoopBack 4 component. | ||
|
|
||
| Because of the architectural changes, `component-config.json` is not required | ||
| in LoopBack 4 anymore. |
There was a problem hiding this comment.
I don't see how is this relevant to request/response life cycle? IMO, this belongs to https://loopback.io/doc/en/lb4/migration-extensions.html
There was a problem hiding this comment.
Imagine someone wrote LB3 components to add routes to the app. It would help them to know what happens to those components from the context of the changes in the req-res cycle.
Maybe the lack of sub headers. I struggled with it too, but as the size of the content is growing, I think they can be contained within sub headers, and it will look much better. |
|
@bajtos I have applied your feedback and added sub headers. |
jannyHou
left a comment
There was a problem hiding this comment.
👍 Good start! I like the beginning part of section "Request/response infrastructure", it would be good if it has brief outline about how the other artifact comparisons(other sections afterwards) are related/connected to "the means of adding request/response infrastructure".
|
|
||
| In LoopBack 4 | ||
| [middleware.json](https://loopback.io/doc/en/lb3/middleware.json.html) | ||
| is not require anymore because of architectural changes. |
There was a problem hiding this comment.
| is not require anymore because of architectural changes. | |
| is not required anymore because of architectural changes. |
Doesn't that hint that the following sub-sections are about the the means of adding request/response infrastructure? |
@hacksparrow oh let me explain, you have 4 sections as
I was suggesting add a brief sentence describing how they are related to the Req/Res cycle. |
989154e to
ae4514f
Compare
ae4514f to
bb11a04
Compare
bajtos
left a comment
There was a problem hiding this comment.
Nice progress!
The content starting from "Request/response pathway" is exactly what I was looking for in this page! 👏
I feel the initial sections (up to but excluding "Request/response pathway") are duplicating content from other parts of the migration guide, but I can live with that 🤷
I found few places that deserves further clarification, PTAL at my comments below 👇
| LoopBack 3 models come with | ||
| [validation methods](https://loopback.io/doc/en/lb3/Validating-model-data.html) | ||
| . The validation rules are derived from the model definition files or are | ||
| applied by calling the validation methods in the model's JavaScript file. |
There was a problem hiding this comment.
I feel this section is misplaced here. As I understand the content, it describes how LoopBack 4 validates model data at data-access (Repository/ORM) layer. Please note that we are not using AJV there!
Now this page is about REST layer. I agree it's a good idea to describe how validation (and coercion) works at the REST layer, so let's improve/rework the validation section to be more accurate.
In LB3, this part is handled by strong-remoting - see https://github.com/strongloop/strong-remoting/tree/master/lib/types:
- The validation is very minimal, we check only that the provided value matches the expected type (e.g. a string is not allowed for a numeric parameter, but any object will be accepted for object parameters). See
validatemethods in individual types. - Coercion is pretty comprehensive and applies different rules for values coming from JSON (implemented by
fromTypeValue) or from string sources like the url query & HTTP headers (implemented byfromSloppyValue)
In LB4, we use OpenAPI to describe the type & constraints of request parameters. In a typical controller, we build OpenAPI Schemas describing model data from the metadata provided by LoopBack Models. Non-model parameters (e.g. id in findById(id), filter in find(filter)) are described using inline schema.
At runtime, parameter handling involves several steps:
- We start with lightweight coercion & validation at OpenAPI parameter level, see https://github.com/strongloop/loopback-next/blob/master/packages/rest/src/coercion/coerce-parameter.ts and https://github.com/strongloop/loopback-next/blob/master/packages/rest/src/coercion/validator.ts
- Then we convert OpenAPI Schema to JSON Schema and run AJV to validate values against the schema, see https://github.com/strongloop/loopback-next/tree/master/packages/rest/src/validation. I think we are not using AJV-based coercion, but I am not sure. Also at the moment, schema-based validation is implemented for request bodies only, see Validate parameter values against their schema #1573
There was a problem hiding this comment.
@bajtos this section is not about validation at the Repository/ORM layer, it is more about how to do something (validation) in LB4, what you did in LB3 - as closely as possible.
I have updated the content and rephrased some sentences, I hope it makes more sense now.
There was a problem hiding this comment.
I see. I am afraid I find the new content still misleading.
Specifically, the following paragraph refers to validation rules like validatesPresenceOf that are not applied by the HTTP/REST layer at all.
LoopBack 3 models come with
[validation methods](https://loopback.io/doc/en/lb3/Validating-model-data.html)
. The validation rules are derived from the model definition files or are
applied by calling the validation methods in the model's JavaScript file.
I am missing a mention of the validation & coercion rules applied by strong-remoting.
I think it would be really helpful for our users to capture more content & pointer from ea52b6f#r408201456 in the docs, this is the kind of information that's almost impossible to find otherwise.
I am proposing the following high-level structure for this section:
- In LB3, we have strong-remoting validation defined by
acceptsmetadata and data-access-level validation defined by model methods likevalidatesPresenceOf. - Briefly describe how strong-remoting validates & coerces data, add links to source code. This way we don't have to go into too much detail now, but still provide useful links to anybody wanting to dig deeper (including us in the future).
- In LB4, we do full JSON Schema validation at REST layer and property-based validation at data-access level.
- Briefly describe how LB4 REST layer validates & coerces data, add links to source code.
- LB4 does not validate non-body parameters against schema yet, + include a link to GH issue.
- In LB4, it's possible to apply additional validation of model data at REST layer via
jsonSchemamodel setting, which can partially replace advanced validations provided by LB3 at data-access level. Explain the caveats. - LB4 does not yet offer advanced validation rules at data-access layer like LB3 does, + include a link to GH issue.
|
|
||
| Model validation methods like `validatesLengthOf()`, | ||
| `validatesLengthOf()`, etc., from LoopBack 3 can be implemented in LoopBack 4 | ||
| by specifying the `jsonSchema` property in a model's property definition. |
There was a problem hiding this comment.
Nice! This is showing how to provide custom validations that will be applied at REST layer only. Please note this is not a direct replacement for validatesLenghtOf() and friends, because those validations are applied only at data-access level in LB3.
I feel it's important to be very clear about which validation rules are applied at which layer.
validatesLengthOf()is defined in LB3 models and executed by the data-access layer, it's ignored by REST API layer (strong-remoting). This constraint is enforced always, both for REST API requests and when modifying data via JS API.jsonSchemafield in LB4 property definition is executed by REST API layer and is ignored by the data-access layer. These constraints are enforced only for REST API requests, they can be violated/by-passed when modifying data via JS/TS Repository APIs.
emonddr
left a comment
There was a problem hiding this comment.
Nice writeup, @hacksparrow ! :)
agnes512
left a comment
There was a problem hiding this comment.
Good progress. I like the examples you have to show the differences. Just have a few comments.
There was a problem hiding this comment.
👏 Good stuff I like the diagrams showing LB3 vs LB4 req/res cycle. A few suggestions and comments.
And I think interceptor also plays an important role in the cycle because they are invoked right before/after the controller methods and have a chance to process the req/res. Maybe mention it in section "Access to the request/response object" or "Request/response pathway"?
| Although LoopBack 4 uses Express as the HTTP server, it is not directly exposed | ||
| anymore. | ||
|
|
||
| In LoopBack 3, Express middleware and routers, models, components, boot scripts, |
| In LoopBack 3 you could add routes and load custom middleware using `app.get()`, | ||
| `app.post()`, `app.use()`, etc., just like how you do in Express. | ||
| In LoopBack 4, you cannot do it yet. However, you can | ||
| [mount a LoopBack 4](https://loopback.io/doc/en/lb4/express-with-lb4-rest-tutorial.html) |
There was a problem hiding this comment.
nitpick: we usually use relative links like ./express-with-lb4-rest-tutorial.md(the path may not be accurate).
| In LoopBack 3 you could add routes and load custom middleware using `app.get()`, | ||
| `app.post()`, `app.use()`, etc., just like how you do in Express. | ||
| In LoopBack 4, you cannot do it yet. However, you can | ||
| [mount a LoopBack 4](https://loopback.io/doc/en/lb4/express-with-lb4-rest-tutorial.html) |
There was a problem hiding this comment.
| [mount a LoopBack 4](https://loopback.io/doc/en/lb4/express-with-lb4-rest-tutorial.html) | |
| [mount a LoopBack 4 application](https://loopback.io/doc/en/lb4/express-with-lb4-rest-tutorial.html) |
| [#2035](https://github.com/strongloop/loopback-next/issues/2035) | ||
| to track the progress on supporting Express middlweware in LoopBack 4." %} | ||
|
|
||
| If you want to mount a Express router, you can use the |
There was a problem hiding this comment.
| If you want to mount a Express router, you can use the | |
| If you want to mount an Express router in a LoopBack 4 application, you can use the |
| [servers](https://loopback.io/doc/en/lb4/Server.html), | ||
| [observers](https://loopback.io/doc/en/lb4/Life-cycle.html), | ||
| [providers](https://loopback.io/doc/en/lb4/Creating-components.html#providers), | ||
| and controllers to the app using dependency injection. |
There was a problem hiding this comment.
| and controllers to the app using dependency injection. | |
| and [controllers](the_link_of_controller) to the app using dependency injection. |
|
|
||
| If you used LoopBack 3 boot scripts for adding routes to the app, it | ||
| should now be moved to a standalone controller, a component, or implemented | ||
| using `app.mountExpressRouter()`. |
There was a problem hiding this comment.
agreed, the bootscript migration doc contains the guide of retrieving different artifacts, but not adding artifacts like endpoints.
server.get('/hello', (req, res) => {
res.send('Hello!');
});is not covered yet, but we should add an entry for it, I mean in the bootscript migration guide.
| and querying the undelying database for the corresponding REST requests. | ||
|
|
||
| In LoopBack 4, the [sequence](https://loopback.io/doc/en/lb4/Sequence.html) is | ||
| the gatekeeper of all requests to the app. Every request to the app must pass |
There was a problem hiding this comment.
sth maybe worth mentioning here: a sequence consists of a series of actions. Developers can add custom actions to process the request and response.
There was a problem hiding this comment.
Let's leave that to the sequence doc, which is linked.
| [app.mountExpressRouter() ](https://loopback.io/doc/en/lb4/apidocs.rest.restapplication.mountexpressrouter.html) | ||
| method, using the familiar Express middleware signature. | ||
|
|
||
| Controllers, services, and repositories are LoopBack 4 components that |
There was a problem hiding this comment.
nitpick: adding links for the 3 artifacts like the previous content.
| [app.mountExpressRouter() ](https://loopback.io/doc/en/lb4/apidocs.rest.restapplication.mountexpressrouter.html) | ||
| method, using the familiar Express middleware signature. | ||
|
|
||
| Controllers, services, and repositories are LoopBack 4 components that |
There was a problem hiding this comment.
| Controllers, services, and repositories are LoopBack 4 components that | |
| Controllers, services, and repositories are LoopBack 4 artifacts that |
| validated against the attributes specified in the `@property()` decorator of the | ||
| corresponding model. | ||
|
|
||
| Model validation methods like `validatesLengthOf()`, |
There was a problem hiding this comment.
We now have the validation docs explaining the 3 layers data validation in lb4, see https://github.com/strongloop/loopback-next/blob/master/docs/site/Validation.md (maybe not published yet)
You probably want to add it as a reference here :p
264d69e to
ea52b6f
Compare
bajtos
left a comment
There was a problem hiding this comment.
Much better!
I feel some of the changed sections still need more attention, see my comments below.
| [sequence handler](https://loopback.io/doc/en/lb4/apidocs.rest.defaultsequence.md) | ||
| that sits infront of a | ||
| [routing table](https://loopback.io/doc/en/lb4/apidocs.rest.routingtable.html). | ||
| [routing table](https://loopback.io/doc/en/lb4/apidocs.rest.routingtable.md). |
There was a problem hiding this comment.
Please replace absolute URLs with relative paths.
| [routing table](https://loopback.io/doc/en/lb4/apidocs.rest.routingtable.md). | |
| [routing table](./apidocs/apidocs.rest.routingtable.md). |
The same comment applies to all links starting with https://loopback.io/doc/en/lb4. Please search for them yourself.
You can run the following command to generate files in docs/site/apidocs:
$ (cd docs && npm run prepack)
There was a problem hiding this comment.
Oh, actually I added them back manually as I imagined those missing files will be a problem.
| LoopBack 3 models come with | ||
| [validation methods](https://loopback.io/doc/en/lb3/Validating-model-data.html) | ||
| . The validation rules are derived from the model definition files or are | ||
| applied by calling the validation methods in the model's JavaScript file. |
There was a problem hiding this comment.
I see. I am afraid I find the new content still misleading.
Specifically, the following paragraph refers to validation rules like validatesPresenceOf that are not applied by the HTTP/REST layer at all.
LoopBack 3 models come with
[validation methods](https://loopback.io/doc/en/lb3/Validating-model-data.html)
. The validation rules are derived from the model definition files or are
applied by calling the validation methods in the model's JavaScript file.
I am missing a mention of the validation & coercion rules applied by strong-remoting.
I think it would be really helpful for our users to capture more content & pointer from ea52b6f#r408201456 in the docs, this is the kind of information that's almost impossible to find otherwise.
I am proposing the following high-level structure for this section:
- In LB3, we have strong-remoting validation defined by
acceptsmetadata and data-access-level validation defined by model methods likevalidatesPresenceOf. - Briefly describe how strong-remoting validates & coerces data, add links to source code. This way we don't have to go into too much detail now, but still provide useful links to anybody wanting to dig deeper (including us in the future).
- In LB4, we do full JSON Schema validation at REST layer and property-based validation at data-access level.
- Briefly describe how LB4 REST layer validates & coerces data, add links to source code.
- LB4 does not validate non-body parameters against schema yet, + include a link to GH issue.
- In LB4, it's possible to apply additional validation of model data at REST layer via
jsonSchemamodel setting, which can partially replace advanced validations provided by LB3 at data-access level. Explain the caveats. - LB4 does not yet offer advanced validation rules at data-access layer like LB3 does, + include a link to GH issue.
| users to access the model data before it is written to the database. A similar | ||
| functionality can be achieved in LoopBack 4 by overriding the `create()` method | ||
| of the | ||
| [default CRUD repository](https://loopback.io/doc/en/lb4/apidocs.repository.defaultcrudrepository.html) |
There was a problem hiding this comment.
| [default CRUD repository](https://loopback.io/doc/en/lb4/apidocs.repository.defaultcrudrepository.html) | |
| [default CRUD repository](apidocs/apidocs.repository.defaultcrudrepository.md) |
cf5ea53 to
55f5fed
Compare
e0a10b8 to
cf12a69
Compare
bajtos
left a comment
There was a problem hiding this comment.
LGTM 👏
I have few minor suggestions to consider, see below.
|
|
||
| Currently, LoopBack 4 does not validate non-body parameters against schema. It | ||
| will be supported in future, follow | ||
| [this issue](https://github.com/strongloop/loopback-next/issues/1573) |
There was a problem hiding this comment.
| [this issue](https://github.com/strongloop/loopback-next/issues/1573) | |
| [loopback-next#1573](https://github.com/strongloop/loopback-next/issues/1573) |
bajtos
left a comment
There was a problem hiding this comment.
(The last review was meant to be an approval.)
Differences between LB3 and LB4 req-res cycle
23e556d to
2fb1070
Compare
Differences between LB3 and LB4 req-res cycle. Addresses #4836.