Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/297 customize request routing outside knots #299

Merged

Conversation

mariuszkubis
Copy link
Contributor

I hereby agree to the terms of the Knot.x Contributor License Agreement.

Previously, every request in Knot.X was routed through:
-Server
-RepositoryConnector
-FragmentSplitter
-customizable Knots (Engine)
-FragmentAssembler

This is now called a "default flow", a typical way of processing requests in Knot.X

Here, we introduce a new way of processing - "custom flow", which allows you to omit some blocks of the default flow.

A custom flow consists of:
-Server
-Gateway knot which sets the knot context of the request
-customizable Knots (Engine)
-Response provider Knot, which returns the result to the client (like FragmentAssembler in default flow, but it doesn't operate on Fragments)

To test this solution, run Example App and visit http://localhost:8092/customFlow/remote/simple.json to retrieve a JSON message processed by a custom flow.

@@ -0,0 +1,41 @@
# Gateway Mode

The gateway mode provides an alternative way of processing requests, alternative to than presented in [[Knot Routing section|KnotRouting]].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The gateway mode provides an alternative way of processing requests, alternative to than presented in [[Knot Routing section|KnotRouting]].

Some repetition and awkward grammar here. How about rewriting this as follows:

The gateway mode provides a way of processing requests alternative to that presented in the [[Knot Routing section|KnotRouting]].


After the routing is over, the response is returned from a verticle called Response Provider.

//TODO an image of the routing simillar to this on Knot Routing page
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this be provided as part of this Pull Request?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be done as part of this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, I do not have access to the images in editable form.
If you can provide it, I will create the needed image.


//TODO an image of the routing simillar to this on Knot Routing page

Depending of your routing implementation, you can use the Gateway Mode to return the external services response
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depending on

@@ -13,7 +13,7 @@ Diagram below depicts high level Knot.x architecture.

Custom business logic can be encapsulated in dedicated Knots / Adapters.

Knot is module which defines custom step while [request routing](#KnotRouting). It can process custom
Knot is module which defines custom step while [[request routing|KnotRouting]]. It can process custom
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awkward grammar.

A Knot is a module which defines a custom step in the process of [[request routing|KnotRouting]].

@@ -86,3 +86,6 @@ Knot performs its business logic and returns a transition. The transition define
In some cases Knot can decide to break the route and redirect the user to a different page.

When all Knots on the route processed the request or one of Knots break the routing, Server returns a response to the user.

It is also possible to define custom request flow, skipping Repository Connector, Fragment Splitter and Fragment Assembler.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a custom request flow

@@ -116,6 +121,7 @@ In short, by default, server does:
- Listens on port 8092
- Displays exception details on error pages (for development purposes)
- Returns certain headers in Http Response to the client (as shown above)
- Uses [[default Knot.X routing mechanism|KnotRouting]]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uses the default Knot.x routing mechanism.

Copy link
Member

@malaskowski malaskowski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really great work, thank you guys.
I left some comments.


public class RequestProcessorKnotProxyImpl extends AbstractKnotProxy {

private final static String RESPONSE = "{\"message\":\"This is a sample custom flow response\"}";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this class be a part of gateway implementation? It rather looks like an example. Maybe in such case this should go to knotx-examples or even to wiki docs?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely, this class was here just to show some example use-case and should not be a part of the implementation.
I've moved the RequestProcessorKnot to knotx-example module and updated the docs. I think having an example usage of Gateway Mode in the example application is beneficial.

}
},
error -> {
LOGGER.error("Error happened while communicating with {} engine", error,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing one {} in this log message.

HttpMethod method = context.request().method();
boolean pathNotAllowedInDefaultFlow = isPathNotPresentInFlow(path, defaultFlow);
boolean pathNotAllowedInCustomFlow = isPathNotPresentInFlow(path, customFlow);
if (pathNotAllowedInDefaultFlow && pathNotAllowedInCustomFlow) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a candidate for some unit tests.

context.fail(HttpResponseStatus.NOT_FOUND.code());
} else if (!pathNotAllowedInDefaultFlow && isMethodDisallowedInFlow(method, defaultFlow)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So.. what exactly should happen, when defaultPath and defaultMethod are not allowed, but customPath and customMethod are allowed :) ?
It looks that we finish without any action on context (tip: there is double if).

@malaskowski
Copy link
Member

malaskowski commented May 25, 2017

I've refactored a bit and (I think that I...) fixed SupportedMethodsAndPathsHandler case I mentioned above.
Please check if this is still valid :)
I also added a unit test for this handler.

Please correct me if I'm wrong - this custom flow feature enables defining only a single custom routing? It is not possible to create two or more custom flows?

@rkarwacki
Copy link
Contributor

rkarwacki commented May 25, 2017

@Skejven - that looks great.

Yes, it is possible to define only one custom flow. Why? Because you can still process your request in any way you want by plugging your custom logic between GatewayKnot and ResponseProviderKnot. They provide a minimal functionality to process any request - setting up the RequestContext and returning the response. We couldn't figure out a case when someone might need a few custom flows.

Similarly, you can only have one KnotRouting in the default flow - once the fragments are split, you can process them in any way you want, and the universal way of returning them is to route them through the FragmentAssembler. Having a second KnotRouting would not be beneficial because in every case, they could have been merged into one. The same applies to the Gateway Mode feature.

I think that the feature is quite powerful, and possibly you could even get rid of the default flow if you really wanted to, since you could just plug the whole existing logic (Connectors, Splitter, KnotRouting, Assembler) between GatewayKnot and ResponseProviderKnot on some paths. In this case, you could still have the ability to define any other custom routings.

@malaskowski
Copy link
Member

Thanks @rkarwacki for explaining. I've added smal code refactors and I think work is ready to merge. This is great feature, thank you guys!

@malaskowski malaskowski merged commit 42a0341 into master May 26, 2017
@malaskowski malaskowski deleted the feature/297-customize-request-routing-outside-knots branch May 26, 2017 14:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants