Search in sources :

Example 1 with BackendConfiguration

use of org.carapaceproxy.server.config.BackendConfiguration in project carapaceproxy by diennea.

the class BasicStandardEndpointMapperTest method test.

@Test
public void test() throws Exception {
    stubFor(get(urlEqualTo("/index.html")).willReturn(aResponse().withStatus(200).withHeader("Content-Type", "text/html").withBody("it <b>works</b> !!")));
    stubFor(get(urlEqualTo("/index2.html")).willReturn(aResponse().withStatus(200).withHeader("Content-Type", "text/html").withBody("it <b>works</b> !!")));
    stubFor(get(urlEqualTo("/index3.html")).willReturn(aResponse().withStatus(200).withHeader("Content-Type", "text/html").withBody("it <b>works</b> !!")));
    int backendPort = backend1.port();
    StandardEndpointMapper mapper = new StandardEndpointMapper();
    mapper.addBackend(new BackendConfiguration("backend-a", "localhost", backendPort, "/"));
    mapper.addBackend(new BackendConfiguration("backend-b", "localhost", backendPort, "/"));
    mapper.addDirector(new DirectorConfiguration("director-1").addBackend("backend-a"));
    mapper.addDirector(new DirectorConfiguration("director-2").addBackend("backend-b"));
    // all of the known backends
    mapper.addDirector(new DirectorConfiguration("director-all").addBackend("*"));
    mapper.addAction(new ActionConfiguration("proxy-1", ActionConfiguration.TYPE_PROXY, "director-1", null, -1));
    mapper.addAction(new ActionConfiguration("cache-1", ActionConfiguration.TYPE_CACHE, "director-2", null, -1));
    mapper.addAction(new ActionConfiguration("all-1", ActionConfiguration.TYPE_CACHE, "director-all", null, -1));
    mapper.addAction(new ActionConfiguration("not-found-custom", ActionConfiguration.TYPE_STATIC, null, StaticContentsManager.DEFAULT_NOT_FOUND, 404));
    mapper.addAction(new ActionConfiguration("error-custom", ActionConfiguration.TYPE_STATIC, null, StaticContentsManager.DEFAULT_INTERNAL_SERVER_ERROR, 500));
    mapper.addAction(new ActionConfiguration("static-custom", ActionConfiguration.TYPE_STATIC, null, CLASSPATH_RESOURCE + "/test-static-page.html", 200));
    mapper.addRoute(new RouteConfiguration("route-1", "proxy-1", true, new RegexpRequestMatcher(PROPERTY_URI, ".*index.html.*")));
    mapper.addRoute(new RouteConfiguration("route-1b", "cache-1", true, new RegexpRequestMatcher(PROPERTY_URI, ".*index2.html.*")));
    mapper.addRoute(new RouteConfiguration("route-1c", "all-1", true, new RegexpRequestMatcher(PROPERTY_URI, ".*index3.html.*")));
    mapper.addRoute(new RouteConfiguration("route-2-not-found", "not-found-custom", true, new RegexpRequestMatcher(PROPERTY_URI, ".*notfound.html.*")));
    mapper.addRoute(new RouteConfiguration("route-3-error", "error-custom", true, new RegexpRequestMatcher(PROPERTY_URI, ".*error.html.*")));
    mapper.addRoute(new RouteConfiguration("route-4-static", "static-custom", true, new RegexpRequestMatcher(PROPERTY_URI, ".*static.html.*")));
    try (HttpProxyServer server = HttpProxyServer.buildForTests("localhost", 0, mapper, tmpDir.newFolder())) {
        server.start();
        int port = server.getLocalPort();
        {
            // proxy on director 1
            String s = IOUtils.toString(new URL("http://localhost:" + port + "/index.html").toURI(), "utf-8");
            assertEquals("it <b>works</b> !!", s);
        }
        {
            // cache on director 2
            String s = IOUtils.toString(new URL("http://localhost:" + port + "/index2.html").toURI(), "utf-8");
            assertEquals("it <b>works</b> !!", s);
        }
        {
            // director "all"
            String s = IOUtils.toString(new URL("http://localhost:" + port + "/index3.html").toURI(), "utf-8");
            assertEquals("it <b>works</b> !!", s);
        }
        try {
            IOUtils.toString(new URL("http://localhost:" + port + "/notfound.html").toURI(), "utf-8");
            fail("expected 404");
        } catch (FileNotFoundException ok) {
        }
        {
            String staticContent = IOUtils.toString(new URL("http://localhost:" + port + "/static.html").toURI(), "utf-8");
            assertEquals("Test static page", staticContent);
        }
        {
            String staticContent = IOUtils.toString(new URL("http://localhost:" + port + "/static.html").toURI(), "utf-8");
            assertEquals("Test static page", staticContent);
        }
        try {
            IOUtils.toString(new URL("http://localhost:" + port + "/error.html").toURI(), "utf-8");
            fail("expected 500");
        } catch (IOException ok) {
        }
        try {
            IOUtils.toString(new URL("http://localhost:" + port + "/notmapped.html").toURI(), "utf-8");
            fail("expected 404");
        } catch (FileNotFoundException ok) {
        }
    }
}
Also used : HttpProxyServer(org.carapaceproxy.core.HttpProxyServer) RouteConfiguration(org.carapaceproxy.server.config.RouteConfiguration) DirectorConfiguration(org.carapaceproxy.server.config.DirectorConfiguration) FileNotFoundException(java.io.FileNotFoundException) RegexpRequestMatcher(org.carapaceproxy.server.mapper.requestmatcher.RegexpRequestMatcher) IOException(java.io.IOException) ActionConfiguration(org.carapaceproxy.server.config.ActionConfiguration) BackendConfiguration(org.carapaceproxy.server.config.BackendConfiguration) URL(java.net.URL) Test(org.junit.Test)

Example 2 with BackendConfiguration

use of org.carapaceproxy.server.config.BackendConfiguration in project carapaceproxy by diennea.

the class BasicStandardEndpointMapperTest method testDefaultRoute.

@Test
public void testDefaultRoute() throws Exception {
    stubFor(get(urlEqualTo("/index.html")).willReturn(aResponse().withStatus(200).withHeader("Content-Type", "text/html").withBody("it <b>works</b> !!")));
    stubFor(get(urlEqualTo("/notmapped.html")).willReturn(aResponse().withStatus(200).withHeader("Content-Type", "text/html").withBody("it <b>works</b> !!")));
    stubFor(get(urlEqualTo("/down.html")).willReturn(aResponse().withStatus(200).withHeader("Content-Type", "text/html").withBody("it <b>works</b> !!")));
    int backendPort = backend1.port();
    StandardEndpointMapper mapper = new StandardEndpointMapper();
    mapper.addBackend(new BackendConfiguration("backend", "localhost", backendPort, "/"));
    mapper.addBackend(new BackendConfiguration("backend-down", "localhost-down", backendPort, "/"));
    mapper.addDirector(new DirectorConfiguration("director").addBackend("backend"));
    mapper.addDirector(new DirectorConfiguration("director-down").addBackend("backend-down"));
    mapper.addAction(new ActionConfiguration("cache", ActionConfiguration.TYPE_CACHE, "director", null, -1));
    mapper.addAction(new ActionConfiguration("cache-down", ActionConfiguration.TYPE_CACHE, "director-down", null, -1));
    mapper.addRoute(new RouteConfiguration("route", "cache", true, new RegexpRequestMatcher(PROPERTY_URI, ".*index.html.*")));
    mapper.addRoute(new RouteConfiguration("route-down", "cache-down", true, new RegexpRequestMatcher(PROPERTY_URI, ".*down.html.*")));
    mapper.addRoute(new RouteConfiguration("route-default", "cache", true, new RegexpRequestMatcher(PROPERTY_URI, ".*html")));
    BackendHealthManager bhMan = mock(BackendHealthManager.class);
    when(bhMan.isAvailable(eq("localhost:" + backendPort))).thenReturn(true);
    // simulate unreachable backend -> expected 500 error
    when(bhMan.isAvailable(eq("localhost-down:" + backendPort))).thenReturn(false);
    try (HttpProxyServer server = HttpProxyServer.buildForTests("localhost", 0, mapper, tmpDir.newFolder())) {
        server.setBackendHealthManager(bhMan);
        server.start();
        int port = server.getLocalPort();
        // index.html matches with route
        {
            String s = IOUtils.toString(new URL("http://localhost:" + port + "/index.html").toURI(), "utf-8");
            assertEquals("it <b>works</b> !!", s);
        }
        // notmapped.html matches with route-default
        {
            String s = IOUtils.toString(new URL("http://localhost:" + port + "/notmapped.html").toURI(), "utf-8");
            assertEquals("it <b>works</b> !!", s);
        }
        // down.html (request to unreachable backend) has NOT to match to route-deafult BUT get internal-error
        try {
            IOUtils.toString(new URL("http://localhost:" + port + "/down.html").toURI(), "utf-8");
            fail("expected 500");
        } catch (IOException ok) {
        }
    }
}
Also used : HttpProxyServer(org.carapaceproxy.core.HttpProxyServer) RouteConfiguration(org.carapaceproxy.server.config.RouteConfiguration) BackendHealthManager(org.carapaceproxy.server.backends.BackendHealthManager) DirectorConfiguration(org.carapaceproxy.server.config.DirectorConfiguration) RegexpRequestMatcher(org.carapaceproxy.server.mapper.requestmatcher.RegexpRequestMatcher) IOException(java.io.IOException) ActionConfiguration(org.carapaceproxy.server.config.ActionConfiguration) BackendConfiguration(org.carapaceproxy.server.config.BackendConfiguration) URL(java.net.URL) Test(org.junit.Test)

Example 3 with BackendConfiguration

use of org.carapaceproxy.server.config.BackendConfiguration in project carapaceproxy by diennea.

the class ForceBackendTest method test.

@Test
public void test() throws Exception {
    stubFor(get(urlEqualTo("/index.html?thedirector=director-2")).willReturn(aResponse().withStatus(200).withHeader("Content-Type", "text/html").withBody("it <b>works</b> !!")));
    stubFor(get(urlEqualTo("/index.html?thebackend=backend-b")).willReturn(aResponse().withStatus(200).withHeader("Content-Type", "text/html").withBody("it <b>works</b> !!")));
    int backendPort = backend1.port();
    StandardEndpointMapper mapper = new StandardEndpointMapper();
    Properties properties = new Properties();
    properties.put("mapper.forcedirector.parameter", "thedirector");
    properties.put("mapper.forcebackend.parameter", "thebackend");
    mapper.configure(new PropertiesConfigurationStore(properties));
    assertEquals("thedirector", mapper.getForceDirectorParameter());
    assertEquals("thebackend", mapper.getForceBackendParameter());
    mapper.addBackend(new BackendConfiguration("backend-a", "localhost", backendPort, "/"));
    mapper.addBackend(new BackendConfiguration("backend-b", "localhost", backendPort, "/"));
    mapper.addDirector(new DirectorConfiguration("director-1").addBackend("backend-a"));
    mapper.addDirector(new DirectorConfiguration("director-2").addBackend("backend-b"));
    mapper.addAction(new ActionConfiguration("proxy-1", ActionConfiguration.TYPE_PROXY, "director-1", null, -1));
    mapper.addRoute(new RouteConfiguration("route-1", "proxy-1", true, new RegexpRequestMatcher(PROPERTY_URI, ".*index.html.*")));
    try (HttpProxyServer server = HttpProxyServer.buildForTests("localhost", 0, mapper, tmpDir.newFolder())) {
        server.start();
        int port = server.getLocalPort();
        {
            // proxy on director 2
            String s = IOUtils.toString(new URL("http://localhost:" + port + "/index.html?thedirector=director-2").toURI(), "utf-8");
            assertEquals("it <b>works</b> !!", s);
        }
        {
            // proxy on backend 2
            String s = IOUtils.toString(new URL("http://localhost:" + port + "/index.html?thebackend=backend-b").toURI(), "utf-8");
            assertEquals("it <b>works</b> !!", s);
        }
    }
}
Also used : HttpProxyServer(org.carapaceproxy.core.HttpProxyServer) PropertiesConfigurationStore(org.carapaceproxy.configstore.PropertiesConfigurationStore) RouteConfiguration(org.carapaceproxy.server.config.RouteConfiguration) DirectorConfiguration(org.carapaceproxy.server.config.DirectorConfiguration) RegexpRequestMatcher(org.carapaceproxy.server.mapper.requestmatcher.RegexpRequestMatcher) Properties(java.util.Properties) ActionConfiguration(org.carapaceproxy.server.config.ActionConfiguration) BackendConfiguration(org.carapaceproxy.server.config.BackendConfiguration) URL(java.net.URL) Test(org.junit.Test)

Example 4 with BackendConfiguration

use of org.carapaceproxy.server.config.BackendConfiguration in project carapaceproxy by diennea.

the class StandardEndpointMapper method map.

@Override
public MapResult map(ProxyRequest request) {
    for (RouteConfiguration route : routes) {
        if (!route.isEnabled()) {
            continue;
        }
        boolean matchResult = route.matches(request);
        if (LOG.isLoggable(Level.FINER)) {
            LOG.log(Level.FINER, "route {0}, map {1} -> {2}", new Object[] { route.getId(), request.getUri(), matchResult });
        }
        if (matchResult) {
            ActionConfiguration action = actions.get(route.getAction());
            if (action == null) {
                LOG.log(Level.INFO, "no action ''{0}'' -> not-found for {1}, valid {2}", new Object[] { route.getAction(), request.getUri(), actions.keySet() });
                return MapResult.internalError(route.getId());
            }
            if (ActionConfiguration.TYPE_REDIRECT.equals(action.getType())) {
                return MapResult.builder().host(action.getRedirectHost()).port(action.getRedirectPort()).action(MapResult.Action.REDIRECT).routeId(route.getId()).redirectLocation(action.getRedirectLocation()).redirectProto(action.getRedirectProto()).redirectPath(action.getRedirectPath()).errorCode(action.getErrorCode()).customHeaders(action.getCustomHeaders()).build();
            }
            if (ActionConfiguration.TYPE_STATIC.equals(action.getType())) {
                return MapResult.builder().action(MapResult.Action.STATIC).routeId(route.getId()).resource(action.getFile()).errorCode(action.getErrorCode()).customHeaders(action.getCustomHeaders()).build();
            }
            if (ActionConfiguration.TYPE_ACME_CHALLENGE.equals(action.getType())) {
                String tokenName = request.getUri().replaceFirst(".*" + ACME_CHALLENGE_URI_PATTERN, "");
                String tokenData = parent.getDynamicCertificatesManager().getChallengeToken(tokenName);
                if (tokenData == null) {
                    return MapResult.notFound(route.getId());
                }
                return MapResult.builder().action(MapResult.Action.ACME_CHALLENGE).routeId(route.getId()).resource(IN_MEMORY_RESOURCE + tokenData).errorCode(action.getErrorCode()).build();
            }
            UrlEncodedQueryString queryString = request.getQueryString();
            String director = action.getDirector();
            String forceBackendParameterValue = queryString.get(forceBackendParameter);
            final List<String> selectedBackends;
            if (forceBackendParameterValue != null) {
                LOG.log(Level.INFO, "forcing backend = {0} for {1}", new Object[] { forceBackendParameterValue, request.getUri() });
                selectedBackends = Collections.singletonList(forceBackendParameterValue);
            } else {
                String forceDirectorParameterValue = queryString.get(forceDirectorParameter);
                if (forceDirectorParameterValue != null) {
                    director = forceDirectorParameterValue;
                    LOG.log(Level.INFO, "forcing director = {0} for {1}", new Object[] { director, request.getUri() });
                }
                selectedBackends = backendSelector.selectBackends(request.getUserId(), request.getSessionId(), director);
            }
            LOG.log(Level.FINEST, "selected {0} backends for {1}, director is {2}", new Object[] { selectedBackends, request.getUri(), director });
            for (String backendId : selectedBackends) {
                Action selectedAction;
                switch(action.getType()) {
                    case ActionConfiguration.TYPE_PROXY:
                        selectedAction = MapResult.Action.PROXY;
                        break;
                    case ActionConfiguration.TYPE_CACHE:
                        selectedAction = MapResult.Action.CACHE;
                        break;
                    default:
                        return MapResult.internalError(route.getId());
                }
                BackendConfiguration backend = this.backends.get(backendId);
                if (backend != null && parent.getBackendHealthManager().isAvailable(backend.getHostPort())) {
                    List<CustomHeader> customHeaders = action.getCustomHeaders();
                    if (this.debuggingHeaderEnabled) {
                        customHeaders = new ArrayList(customHeaders);
                        String routingPath = route.getId() + ";" + action.getId() + ";" + action.getDirector() + ";" + backendId;
                        customHeaders.add(new CustomHeader(DEBUGGING_HEADER_ID, debuggingHeaderName, routingPath, HeaderMode.ADD));
                    }
                    return MapResult.builder().host(backend.getHost()).port(backend.getPort()).action(selectedAction).routeId(route.getId()).customHeaders(customHeaders).build();
                }
            }
            // none of selected backends available
            if (!selectedBackends.isEmpty()) {
                return MapResult.internalError(route.getId());
            }
        }
    }
    // no one route matched
    return MapResult.notFound(MapResult.NO_ROUTE);
}
Also used : Action(org.carapaceproxy.server.mapper.MapResult.Action) UrlEncodedQueryString(org.carapaceproxy.server.filters.UrlEncodedQueryString) RouteConfiguration(org.carapaceproxy.server.config.RouteConfiguration) ArrayList(java.util.ArrayList) UrlEncodedQueryString(org.carapaceproxy.server.filters.UrlEncodedQueryString) ActionConfiguration(org.carapaceproxy.server.config.ActionConfiguration) BackendConfiguration(org.carapaceproxy.server.config.BackendConfiguration)

Example 5 with BackendConfiguration

use of org.carapaceproxy.server.config.BackendConfiguration in project carapaceproxy by diennea.

the class HttpProxyServer method applyDynamicConfiguration.

private void applyDynamicConfiguration(ConfigurationStore newConfigurationStore, boolean atBoot) throws InterruptedException, ConfigurationChangeInProgressException {
    if (atBoot && newConfigurationStore != null) {
        throw new IllegalStateException();
    }
    if (!atBoot && newConfigurationStore == null) {
        throw new IllegalStateException();
    }
    // at boot we are constructing a configuration from the database
    // if the system is already "up" we have to only apply the new config
    ConfigurationStore storeWithConfig = atBoot ? dynamicConfigurationStore : newConfigurationStore;
    if (!configurationLock.tryLock()) {
        throw new ConfigurationChangeInProgressException();
    }
    try {
        RuntimeServerConfiguration newConfiguration = buildValidConfiguration(storeWithConfig);
        EndpointMapper newMapper = buildMapper(newConfiguration.getMapperClassname(), storeWithConfig);
        newMapper.setParent(this);
        UserRealm newRealm = buildRealm(userRealmClassname, storeWithConfig);
        this.filters = buildFilters(newConfiguration);
        this.backendHealthManager.reloadConfiguration(newConfiguration, newMapper);
        this.dynamicCertificatesManager.reloadConfiguration(newConfiguration);
        this.ocspStaplingManager.reloadConfiguration(newConfiguration);
        this.listeners.reloadConfiguration(newConfiguration);
        this.cache.reloadConfiguration(newConfiguration);
        this.requestsLogger.reloadConfiguration(newConfiguration);
        this.realm = newRealm;
        Map<String, BackendConfiguration> currentBackends = mapper != null ? mapper.getBackends() : Collections.emptyMap();
        Map<String, BackendConfiguration> newBackends = newMapper.getBackends();
        this.mapper = newMapper;
        if (atBoot || !newBackends.equals(currentBackends) || isConnectionsConfigurationChanged(newConfiguration)) {
            prometheusRegistry.clear();
            Metrics.globalRegistry.clear();
            proxyRequestsManager.reloadConfiguration(newConfiguration, newBackends.values());
        }
        if (!atBoot) {
            dynamicConfigurationStore.commitConfiguration(newConfigurationStore);
        }
        this.currentConfiguration = newConfiguration;
    } catch (ConfigurationNotValidException err) {
        // impossible to have a non valid configuration here
        throw new IllegalStateException(err);
    } finally {
        configurationLock.unlock();
    }
}
Also used : ConfigurationNotValidException(org.carapaceproxy.server.config.ConfigurationNotValidException) PropertiesConfigurationStore(org.carapaceproxy.configstore.PropertiesConfigurationStore) ConfigurationStore(org.carapaceproxy.configstore.ConfigurationStore) HerdDBConfigurationStore(org.carapaceproxy.configstore.HerdDBConfigurationStore) EndpointMapper(org.carapaceproxy.server.mapper.EndpointMapper) UserRealm(org.carapaceproxy.user.UserRealm) SimpleUserRealm(org.carapaceproxy.user.SimpleUserRealm) ConfigurationChangeInProgressException(org.carapaceproxy.server.config.ConfigurationChangeInProgressException) BackendConfiguration(org.carapaceproxy.server.config.BackendConfiguration)

Aggregations

BackendConfiguration (org.carapaceproxy.server.config.BackendConfiguration)9 ActionConfiguration (org.carapaceproxy.server.config.ActionConfiguration)6 RouteConfiguration (org.carapaceproxy.server.config.RouteConfiguration)6 DirectorConfiguration (org.carapaceproxy.server.config.DirectorConfiguration)5 RegexpRequestMatcher (org.carapaceproxy.server.mapper.requestmatcher.RegexpRequestMatcher)5 Test (org.junit.Test)5 HttpProxyServer (org.carapaceproxy.core.HttpProxyServer)4 URL (java.net.URL)3 ArrayList (java.util.ArrayList)3 PropertiesConfigurationStore (org.carapaceproxy.configstore.PropertiesConfigurationStore)3 IOException (java.io.IOException)2 Properties (java.util.Properties)2 BackendHealthManager (org.carapaceproxy.server.backends.BackendHealthManager)2 ConfigurationNotValidException (org.carapaceproxy.server.config.ConfigurationNotValidException)2 UrlEncodedQueryString (org.carapaceproxy.server.filters.UrlEncodedQueryString)2 FileNotFoundException (java.io.FileNotFoundException)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 Map (java.util.Map)1 Parameters (junitparams.Parameters)1