001/*
002 * Stallion Core: A Modern Web Framework
003 *
004 * Copyright (C) 2015 - 2016 Stallion Software LLC.
005 *
006 * This program is free software: you can redistribute it and/or modify it under the terms of the
007 * GNU General Public License as published by the Free Software Foundation, either version 2 of
008 * the License, or (at your option) any later version. This program is distributed in the hope that
009 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
011 * License for more details. You should have received a copy of the GNU General Public License
012 * along with this program.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>.
013 *
014 *
015 *
016 */
017
018package io.stallion.requests;
019
020import javax.servlet.http.HttpServletRequest;
021import javax.servlet.http.HttpServletResponse;
022
023import io.stallion.Context;
024import io.stallion.settings.SecondaryDomain;
025import io.stallion.settings.Settings;
026import io.stallion.services.Log;
027
028import org.eclipse.jetty.server.Request;
029import org.eclipse.jetty.server.handler.AbstractHandler;
030
031
032import java.util.*;
033
034import java.util.regex.Matcher;
035import java.util.regex.Pattern;
036
037import static io.stallion.utils.Literals.*;
038
039/**
040 * The implementation of the Jetty request handler to handle all HTTP
041 * requests for Stallion.
042 */
043public class RequestHandler extends AbstractHandler {
044
045
046    private static RequestHandler _instance;
047
048    public static RequestHandler instance() {
049        if (_instance == null) {
050            _instance = new RequestHandler();
051        }
052        return _instance;
053    }
054
055    public void handle(String path, Request baseRequest, HttpServletRequest request, HttpServletResponse response) {
056
057        StRequest stRequest = new StRequest(path, baseRequest, request);
058        StResponse stResponse = new StResponse(response);
059        handleStallionRequest(stRequest, stResponse);
060        baseRequest.setHandled(true);
061        if (response.getStatus() >= 400) {
062            Log.info("ErrorCode={0} url={1}", response.getStatus(), stRequest.requestUrl());
063        }
064    }
065
066    public void handleStallionRequest(StRequest stRequest, StResponse stResponse) {
067        Context.setRequest(stRequest);
068        Context.setResponse(stResponse);
069        rewriteRequest(stRequest);
070        RequestProcessor requestProcessor = new RequestProcessor(stRequest, stResponse);
071        requestProcessor.process();
072    }
073
074    public void rewriteRequest(StRequest request) {
075        String path = request.getPath();
076
077        // Check for secondary domain mappings
078        if (!path.startsWith("/st-")) { // Don't re-map internal endpoints and asset endpoints.
079            if (Settings.instance().getSecondaryDomains().size() > 0) {
080                for (SecondaryDomain domain : Settings.instance().getSecondaryDomains()) {
081                    if (request.getHost().equals(domain.getDomain()) && domain.isStripRootFromPageSlug()) {
082                        path = domain.getRewriteRoot() + path;
083                        Log.fine("SecondaryDomain rewrite {0} to {1}", request.getPath(), path);
084                        request.setPath(path);
085                        break;
086                    }
087                }
088            }
089        }
090
091        if (Settings.instance().getRewrites().containsKey(path)) {
092            path = Settings.instance().getRewrites().get(path);
093            request.setPath(path);
094            Log.fine("Non regex rewrite {0} to {1}", path, request.getPath());
095            return;
096        }
097
098        String fullPath = "";
099        String query = null;
100        if (!empty(request.getQueryString())) {
101            fullPath = path + "?" + request.getQueryString();
102        } else {
103            fullPath = path;
104        }
105
106        if (Settings.instance().getRewriteCompiledPatterns().size() > 0) {
107            for(Map.Entry<Pattern, String> entry: Settings.instance().getRewriteCompiledPatterns()) {
108                Matcher matcher = null;
109                boolean matchedQuery = false;
110                if (entry.getKey().toString().contains("\\?")) {
111                    matcher = entry.getKey().matcher(fullPath);
112                    matchedQuery = true;
113                } else {
114                    matcher = entry.getKey().matcher(path);
115                }
116                if (matcher.matches()) {
117                    Log.fine("Regex matched: {0}", entry.getKey());
118                    String newPath = matcher.replaceAll(entry.getValue());
119                    if (newPath.contains("?")) {
120                        String[] parts = newPath.split("\\?", 2);
121                        request.setPath(parts[0]);
122                        request.setQuery(parts[1]);
123                    } else {
124                        request.setPath(newPath);
125                    }
126                    String newFullPath = request.getPath();
127                    if (!empty(request.getQueryString())) {
128                        newFullPath += "?" + request.getQueryString();
129                    }
130
131                    Log.fine("Rewrote {0} to {1}", fullPath, newFullPath);
132                }
133            }
134        }
135    }
136
137}