Middleware
The Middleware API allows developers to execute code before a request is processed. Based on the incoming request, you can run custom logic, return custom streams and files, modify responses, rewrite, redirect, add headers, and more. All that before returning a response.
Middleware Use Cases
-
Authentication.
-
Response filtering.
-
Redirects.
-
Rewrites.
-
Custom handling of bundle resources (OSGi).
Using Middleware in an OSGi Application
To use the Middleware in an OSGi application, you need to run the following bundles:
-
com.equo.middleware.api
-
com.equo.middleware.ee.provider
API
You can use the middleware
API in your application by injecting it as an OSGi service. Resource handlers for custom schemes must be added before any browser is initialized. Schemes http and https support the addition of handlers at any moment of the program execution.
Here’s an example of how you could set up a resource handler using a bundle activator and OSGi:
import org.osgi.service.component.annotations.Component;
import com.equo.middleware.api.IMiddlewareService;
@Component
public class ContributionComponent {
@Reference
private IMiddlewareService middlewareService;
@Activate
public void configureSchemes() {
middlewareService.addResourceHandler("customscheme", "", (request, headers) -> {
// Modify response headers if needed
// Build response for the given request
// Return readable InputStream containing the response data
});
...
}
...
}
In the example above we can see all that’s needed to add a resource handler to your application. A resource handler is used by the middleware implementation to know which requests to intercept, it’s defined by the parameters of the addResourceHandler method. The first parameter of the API is the scheme of the URL you’ll be intercepting requests from. The second parameter is the domain of that URL, if empty or NULL your resource handler will be used for all domains in the scheme. The third parameter is an instance of an IResponseHandler, it will be used for every request done to the resource handler.
Scheme
You can use existing schemes such as http
and https
and you can also pass arbitrary schemes like customscheme
used in the examples in this documentation page.
Domain
You can also intercept requests to arbitrary domains, if you wish to intercept requests to all domains in the defined scheme you can pass an empty string or a null reference in this parameter.
IResponseHandler
The IResponseHandler that you pass to the resource handler will be called in every request intercepted by the middleware. It can be defined with a lambda, but it has two methods: shouldProcessRequest(Request request) : boolean
and getResponseData(Request request, Map<String, String> headers) : InputStream
. The middleware first asks the response handler if it should handle the request (by default it handles all requests), and only if it returns true we try to get the response data for the request.
Custom Streams and Files
You can read your responses directly from the filesystem or use resources that you bundled directly in your jars.
import org.osgi.service.component.annotations.Component;
import com.equo.middleware.api.IMiddlewareService;
@Component
public class ContributionComponent {
@Reference
private IMiddlewareService middlewareService;
@Activate
public void configureSchemes() {
middlewareService.addResourceHandler("customscheme", "", (request, headers) -> {
File htmlResource = new File("path/to/a/resource.html");
if (htmlResource.exists()) {
return new FileInputStream(htmlResource);
}
// If the file doesn't exist fall back to a default resource contained in our classpath.
return getClass().getClassLoader().getResourceAsStream("default.html");
});
...
}
...
}
Dynamic Content
You can also create your responses on demand depending on the Request.
import org.osgi.service.component.annotations.Component;
import com.equo.middleware.api.IMiddlewareService;
import com.equo.middleware.api.handler.IResponseConstants;
@Component
public class ContributionComponent {
@Reference
private IMiddlewareService middlewareService;
@Activate
public void configureSchemes() {
middlewareService.addResourceHandler("customscheme", "", (request, headers) -> {
headers.put(IResponseConstants.CONTENT_TYPE_HEADER, "text/html");
StringBuilder sb = new StringBuilder("<!doctype html><html><body>");
if (request.getUrl().endsWith("welcome")) {
sb.append("<div> An awesome welcome page! </div>");
} else {
sb.append("This page is not implemented yet.");
}
sb.append("</body></html>");
return new ByteArrayInputStream(sb.toString().getBytes());
});
...
}
...
}
Blocking requests
You can block requests by default if you want complete control over the requests done in the browser.
import org.osgi.service.component.annotations.Component;
import com.equo.middleware.api.IMiddlewareService;
@Component
public class ContributionComponent {
@Reference
private IMiddlewareService middlewareService;
@Activate
public void setupMiddleware() {
middlewareService.blockByDefault(true);
middlewareService.addAllowed("domain.com", "www.domain.com", "sub.domain.com");
...
}
...
}