Delphi MVCFramework Middleware

Middleware is a powerful and flexible api/layer within the DMVC Framework. With this layer you can write SOLID code by separate code which would be repeatedly implemented in each controller method. It is the perfect layer for cross cutting concerns or for controlling HTTP requests/response. Here are some examples for the usage of Middleware:

  • Redirect calls to another url (URL Rewrite; if you are not using a webserver like Apache or IIS)
  • Add some required parameter if the REST interface has changed (another version of the REST interface)
  • Enable CORS
  • HTTP Authentication
  • Logging
  • Caching

The basis of this api/layer is the interface IMVCMiddleware declared in MVCFramework.pas. You have to create a class which implements the IMVCMiddleware and all the methods. Middleware classes (classes that implement the IMVCMiddleware) can be added to the MVCEngine at startup. You can add as many as you want Middleware classes. Internally there is a list of IMVCMiddleware. The life time of this Middleware classes is handled by the MVCEngine.

Here is an example of how to add a Middleware object/interface to the MVCEngine:

procedure TWebModule1.WebModuleCreate(Sender: TObject);
begin
  MVC := TMVCEngine.Create(Self);
  MVC.AddController(TMyController);
  MVC.AddMiddleware(TMyMiddleware.Create);
end;

Middleware classes has to implement the following methods:

procedure OnBeforeRouting(
  Context: TWebContext; 
  var Handled: boolean);
procedure OnBeforeControllerAction(
  Context: TWebContext; 
  const AControllerQualifiedClassName: string; 
  const AActionNAme: string; 
  var Handled: boolean);
procedure OnAfterControllerAction(
  Context: TWebContext; 
  const AActionNAme: string; 
  const Handled: boolean);

Because of the nature of a class that implements an interface you have to implement all of the procedures. But you can leave the procedure empty, if you don't have anything to implement in this step. But you must add the procedure to your class.

This three procedures will be called at the right time during a call to the DMVC Server. For example if you call http://localhost/mycontroller/mymethod the MVCEngine will "execute" this url. First it will check for static files. If the requested url is a static file it will be rendered and the execution is finished. If the url is not a static file the OnBeforeRouting procedure of all added Middleware objects will be fired. During this call you could make a redirect to another url like in the middleware example (TMVCRedirectAndroidDeviceOnPlayStore) or you can add special html headers like in the MVCFramework.Middleware.CORS.pas unit. At this point the complete request is "on the server". You have full access to the complete TWebRequest object with all parameter and header values. After this the MVCEngine search for a controller/method that matches the request. If a controller method is found the OnBeforeControllerAction procedure is fired. During this call you can ask for an authentication like in the MVCFramework.Middleware.Authentication.pas unit. The next step is the execution of the real controller method. This means the controller is created, the corresponding method is executed and the controller is destroyed. Than the OnAfterControllerAction of each registered Middleware class is fired. This procedure is fired before the content is send to the client. This means you can add or modify HTML headers or the content itself. You can also cancel the execution by sending a 404 not found or 500 internal server error. During all this calls you have full access to the TWebContext which contains both the request and the response. You have also the possibility to cancel/finish the execution by setting the Handled parameter to true.

The DMVC Framework provides some ready to use Middleware implementations and also a simple example.

MVCFramework.Middleware.CORS.pas

With the help of this Middleware class you can enable Cross-origin resource sharing. (https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) CORS is a mechanism that allows restricted resources (e.g. fonts) on a web page to be requested from another domain outside the domain from which the resource originated.

Usage: Add the following line of code to the WebModule OnCreate event in which you create an instance of TMVCEngine. MVC.AddMiddleware(TCORSMiddleware.Create);

MVCFramework.Middleware.Authentication.pas

With the help of this Middleware class it is possible to make basic HTTP Authentication. TODO...

Usage: Add the following line of code to the WebModule OnCreate event in which you create an instance of TMVCEngine.

MVC.AddMiddleware(
    TMVCBasicAuthenticationMiddleware
        .Create(AMVCAuthenticationHandler));

Samples\middleware\MiddlewareSamples.dpr

This demo shows the implementation of two Middleware classes.

  1. TMVCSalutationMiddleware -> This Middleware add a custom HTTP header to each response.
  2. TMVCRedirectAndroidDeviceOnPlayStore -> This Middleware makes under certain circumstances (the HTTP header 'User-Agent' contains 'Android') a redirect to another url. (URL Rewrite)

unittests\TestServer\SpeedMiddlewareU.pas

This Middleware class demonstrates some kind of performance measurement. In the OnBeforeRouting event it takes the actual time and stores it in the Context.Data field which is a TDictionary(string, string). In the OnAfterControllerAction it takes the time again and save the MilliSecondsBetween in a custom header field. This field is send with the response to the client. In the client (web browser or VCL Client) you can read this value. This time is the time the actual DMVC Framework server needs from calling the server till finishing the execution of the controller method. There is no network traffic or work from the IIS/Apache in this time.

results matching ""

    No results matching ""