Dynamic Web Development with Seaside

24.4Handler and Filter

So far, our REST service did not interact much with the existing Seaside todo application (other than through the shared model). Often it is however desired to have both — the application and the REST services — served from the same URL.

To achieve this we have to subclass WARestfulFilter instead of WARestfulHandler. The WARestfulFilter simply wraps a Seaside application. That is, it handles REST requests exactly as the WARestfulHandler, but it can also delegate to the wrapped Seaside application.

To update our existing service we rename ToDoHandler to ToDoFilter and change its superclass to WARestfulFilter. Now the class definition should look like:

WARestfulFilter subclass: #ToDoFilter
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'ToDo-REST'

A filter cannot be registered as a an independent entry point anymore, thus we should remove it from the dispatcher to avoid errors:

WAAdmin unregister: 'todo-api'

Instead we attach the filter the todo application itself. On the class-side of ToDoListView we adapt the initialize method to:

ToDoListView class>>initialize
(WAAdmin register: self asApplicationAt: 'todo')
addFilter: ToDoFilter new

After evaluating the initialization code, the ToDoFilter is now executed whenever somebody accesses our application. The process is visualized in Figure 157. Whenever a request hits the filter (1), it processes the annotations (2). Eventually, if none of the annotated methods matched, it delegates to the wrapped application by invoking the method noRouteFound: (3).

Request handling of WARestfulFilter and WAApplication

Unfortunately — if you followed the creation of the REST API in the previous sections — our #list service hides the application by consuming all requests to http://localhost:8080/todo. We have two possibilities to fix the problem:

  1. We remove the method #list so that ToDoFilter automatically calls noRouteFound: that eventually calls the application.
  2. We add a new service that captures requests directed at our web application and explicitly dispatches them to the Seaside application. For example, the following code triggers the wrapped application whenever HTML is requested:
<produces: 'text/html'>

^ self noRouteFound: self requestContext

This change leaves the existing API intact and lets users access our web application with their favorite web browser. This works, because browser request documents with the mime-type text/html by default. Of course, we can combine this technique with any other of the matching techniques we discussed in the previous chapters.

Copyright © 23 April 2024 Stéphane Ducasse, Lukas Renggli, C. David Shaffer, Rick Zaccone
This book is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 license.

This book is published using Seaside, Magritte and the Pier book publishing engine.