Using AtmosphereInterceptor to customize Atmosphere Framework Dispatch Mechanism - Atmosphere/atmosphere GitHub Wiki

The AtmosphereInterceptor interface allows application or framework integrator to intercept the AtmosphereResource before it gets dispatched to an AtmosphereHandler. As an example, The ReflectorServletProcessor handler' role is to dispatch AtmosphereResource to Servlet based application or framework. An application/framework can defines one or multiple AtmosphereInterceptor in order to intercept AtmosphereResource and manipulate its associated AtmosphereRequest and AtmosphereResponse. You define them in web.xml or atmosphere.xml In web.xml

        <init-param>
            <param-name>org.atmosphere.cpr.AtmosphereInterceptor</param-name>
            <param-value>org.foo.BarAtmosphereInterceptor, org.bar.FooAtmosphereInterceptor</param-value>
        </init-param>

or in atmosphere.xml

        <applicationConfig>
            <param-name>org.atmosphere.cpr.AtmosphereInterceptor</param-name>
            <param-value>org.foo.BarAtmosphereInterceptor, org.bar.FooAtmosphereInterceptor</param-value>
        </applicationConfig>

or by annotating your implementation with the @AtmosphereInterceptorService annotation.

The AtmosphereInterceptor API looks like

public interface AtmosphereInterceptor {

    void configure(AtmosphereConfig config);

    Action inspect(AtmosphereResource r);

    void postInspect(AtmosphereResource r);
}

An AtmosphereInterceptor can suspend, resume, timeout, cancel or just continue the AtmosphereResource processing by returning the appropriate Action . As an example, the following AtmosphereInterceptor will cancel the processing based on some security token

            @Override
            public Action inspect(AtmosphereResource r) {
                
                AtmosphereRequest req = r.getRequest();
                if (req.getHeader("SomeSecurityToken") == null) {
                    return Action.CANCELLED;                   
                } else {
                    return Action.CONTINUE;                   
                }
            }

You can also suspend the AtmosphereResource without delivering the request to an application/framework. This is useful when you just want to suspend and not dispatch anything.

            @Override
            public Action inspect(AtmosphereResource r) {
                r.suspend();
                return Action.SUSPEND;
            }

You can also manipulate the AtmosphereResponse. As an example, below is an SSEAtmosphereInterceptor, which add Server Side Events support to Atmosphere

    @Override
    public Action inspect(AtmosphereResource r) {
        final AtmosphereResponse response = r.getResponse();

        if (r.transport().equals(AtmosphereResource.TRANSPORT.SSE)) {
            r.addEventListener(new AtmosphereResourceEventListenerAdapter() {
                 @Override
                public void onSuspend(AtmosphereResourceEvent event) {
                     response.setContentType("text/event-stream");
                     response.setCharacterEncoding("utf-8");
                     OutputStream stream = null;
                     try {
                         stream = response.getOutputStream();
                     } catch (IOException e) {
                         logger.trace("", e);
                     }

                     try {
                         stream.write(padding);
                         stream.flush();
                     } catch (IOException ex) {
                         logger.warn("SSE may not work", ex);
                     }
                }
            });

            response.asyncIOWriter(new AsyncIOWriterAdapter() {
                @Override
                public AsyncIOWriter redirect(String location) throws IOException {
                    response.sendRedirect(location);
                    return this;
                }

                @Override
                public AsyncIOWriter writeError(int errorCode, String message) throws IOException {
                    response.sendError(errorCode);
                    return this;
                }

                @Override
                public AsyncIOWriter write(String data) throws IOException {
                    response.write("data:" + data + "\n\n");
                    return this;
                }

                // TODO: Performance: execute a single write
                @Override
                public AsyncIOWriter write(byte[] data) throws IOException {
                    response.write("data:").write(data).write("\n\n");
                    return this;
                }

                @Override
                public AsyncIOWriter write(byte[] data, int offset, int length) throws IOException {
                    response.write("data:").write(data, offset, length).write("\n\n");
                    return this;
                }

                @Override
                public void close() throws IOException {
                    response.closeStreamOrWriter();
                }

                @Override
                public AsyncIOWriter flush() throws IOException {
                    response.flushBuffer();
                    return this;
                }
            });
        }
        return Action.CONTINUE;
    }
⚠️ **GitHub.com Fallback** ⚠️