001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *        http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 */
019package org.apache.isis.core.webapp.routing;
020
021import java.io.IOException;
022
023import javax.servlet.Filter;
024import javax.servlet.FilterChain;
025import javax.servlet.FilterConfig;
026import javax.servlet.ServletException;
027import javax.servlet.ServletRequest;
028import javax.servlet.ServletResponse;
029import javax.servlet.http.HttpServletRequest;
030import javax.servlet.http.HttpServletResponse;
031
032import org.slf4j.Logger;
033import org.slf4j.LoggerFactory;
034
035/**
036 * This filter attempts to ensure that would-be users of the framework are
037 * directed to the bundled documentation, rather than just hitting the REST API
038 * (ie the json viewer).
039 * 
040 * <p>
041 * Specifically, if the request is to "/" but the Accept header is anything
042 * other than "application/json" (eg is set to "text/html" and suggesting that
043 * the user is using a browser to access the webapp) then the filter redirects
044 * to /index.html (the documentation pages).
045 * 
046 * <p>
047 * Only if the Accept header is set to application/json is the request allowed
048 * to continue through.
049 */
050public class RedirectToDocsFilter implements Filter {
051
052    private static final Logger LOG = LoggerFactory.getLogger(RedirectToDocsFilter.class);
053
054    private static final String REDIRECT_TO_KEY = "redirectTo";
055    private static final String REDIRECT_TO_DEFAULT = "/index.html";
056
057    private static final String ACCEPT_HEADER = "Accept";
058    private static final String APPLICATION_JSON_MIME_TYPE = "application/json";
059
060    private String redirectTo;
061
062    @Override
063    public void init(final FilterConfig cfg) throws ServletException {
064        redirectTo = cfg.getInitParameter(REDIRECT_TO_KEY);
065        if (redirectTo == null) {
066            redirectTo = REDIRECT_TO_DEFAULT;
067        }
068        System.out.println("redirectToDocsFilter: redirectTo=" + redirectTo);
069        LOG.info("redirectToDocsFilter: redirectTo=" + redirectTo);
070    }
071
072    @Override
073    public void destroy() {
074    }
075
076    @Override
077    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
078        final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
079        final HttpServletResponse httpServletResponse = (HttpServletResponse) response;
080
081        // do nothing if not requesting "/"
082        final String servletPath = httpServletRequest.getServletPath();
083        System.out.println("redirectToDocsFilter: servletPath: " + servletPath);
084        LOG.info("redirectToDocsFilter: servletPath: " + servletPath);
085
086        if (!"/".equals(servletPath)) {
087            chain.doFilter(request, response);
088            return;
089        }
090
091        final String acceptHeader = httpServletRequest.getHeader(ACCEPT_HEADER);
092        if (acceptHeader != null && acceptHeader.startsWith(APPLICATION_JSON_MIME_TYPE)) {
093            // let request through
094            chain.doFilter(request, response);
095            return;
096        }
097
098        // otherwise redirect
099        final String redirect = combine(httpServletRequest.getContextPath(), redirectTo);
100        System.out.println("redirectToDocsFilter: redirecting to: " + redirect);
101        LOG.info("redirectToDocsFilter: redirecting to: " + redirect);
102
103        httpServletResponse.sendRedirect(redirect);
104    }
105
106    private static String combine(final String str1, final String str2) {
107        final StringBuilder buf = new StringBuilder(str1);
108        if (!str2.startsWith("/")) {
109            buf.append("/");
110        }
111        buf.append(str2);
112        return buf.toString();
113    }
114
115}