public ProxyRouteConfig build() { return new ProxyRouteConfig( valueOrFallback(methods, fallbackObject.methods()), valueOrFallback(host, fallbackObject.host()), valueOrFallback(path, fallbackObject.path()), valueOrFallback(permissionNeeded, fallbackObject.permissionNeeded()), valueOrFallback(clientConfigs, fallbackObject.clientConfigs()), valueOrFallback(proxyHostPolicy, fallbackObject.proxyHostPolicy()), valueOrFallback(proxyHost, fallbackObject.proxyHost()), valueOrFallback(proxyPath, fallbackObject.proxyPath())); }
public String buildProxyHost(Request request, ClientConfig clientConfig) { switch (config.proxyHostPolicy()) { case UseRequestHeader: return request.host(); case UseRemoteAddress: return clientConfig.remote().getHostString() + ":" + clientConfig.remote().getPort(); case UseConfigValue: return config.proxyHost(); default: log.error("Unknown proxyHostPolicy {}", config.proxyHostPolicy()); return null; } }
public Optional<ClientConfig> getClientConfig(ChannelHandlerContext ctx, Request request) { List<ClientConfig> clientConfigs = config.clientConfigs(); if (clientConfigs.size() > 0) { return Optional.of(clientConfigs.get(0)); } return Optional.empty(); }
@Test public void testBuilderFallbackValues() { ProxyRouteConfig fallbackObject = new ProxyRouteConfig(ConfigFactory.load().getConfig("xio.proxyRouteTemplate")); ProxyRouteConfig subject = ProxyRouteConfig.newBuilder(fallbackObject).build(); assertNotNull(subject); } }
public void start(Config config) { ApplicationState appState = new ApplicationState(ApplicationConfig.fromConfig(proxyConfig, config)); Stream<ProxyRouteConfig> proxyRouteConfigs = Arrays.stream(routeConfig.split(",")).map(it -> new ProxyRouteConfig(config.getConfig(it))); ProxyClientFactory clientFactory = new ProxyClientFactory(appState); RouteStates routeStates = new RouteStates(proxyRouteConfigs, appState, clientFactory); application = new ApplicationBootstrap(appState.config()) .addServer( "main", bs -> bs.addToPipeline( new SmartHttpPipeline() { @Override public ChannelHandler getApplicationRouter() { return new PipelineRouter(routeStates.routeMap()) { @Override protected void channelRead0(ChannelHandlerContext ctx, Request msg) { super.channelRead0(ctx, msg); if (msg.endOfMessage()) { requestCount.incrementAndGet(); } } }; } })) .build(); }
public String buildProxyPath(Request request, RouteState state) { Optional<String> pathSuffix = state .route() .groups(request.path()) // apply the regex .entrySet() .stream() // stream the entry set of matches .filter(e -> e.getKey().equals("path")) // find the entry with key path .map(e -> e.getValue()) // extract the value (aka what did the regex match) .findFirst(); // extract the first (Optional) result return pathSuffix .map(config.proxyPath()::concat) // append the path suffix (if it exists) .orElse(config.proxyPath()); // use the provided path with no suffix }
private Optional<ClientConfig> computeRoundRobin() { int idx = next.getAndIncrement(); // when we overflow from incrementing if (idx < 0) { next.set(0); idx = 0; } val clientConfigs = config.clientConfigs(); if (clientConfigs.size() > 0) { return Optional.of(clientConfigs.get(idx % clientConfigs.size())); } return Optional.empty(); }
new ProxyRouteConfig(ConfigFactory.load().getConfig("xio.testProxyRoute")); ApplicationConfig appConfig = ApplicationConfig.fromConfig("xio.testApplication", root); ClientFactory factory =
@Test public void testBuilderCustomValues() { ProxyRouteConfig fallbackObject = new ProxyRouteConfig(ConfigFactory.load().getConfig("xio.proxyRouteTemplate")); List<HttpMethod> expectedMethods = Lists.newArrayList(HttpMethod.CONNECT); String expectedHost = "host"; ProxyRouteConfig.newBuilder(fallbackObject) .setMethods(expectedMethods) .setHost(expectedHost) .build(); assertEquals(expectedMethods, subject.methods()); assertEquals(expectedHost, subject.host()); assertEquals(expectedPath, subject.path()); assertEquals(expectedPermissionNeeded, subject.permissionNeeded()); assertEquals(expectedClientConfigs, subject.clientConfigs()); assertEquals(expectedProxyHostPolicy, subject.proxyHostPolicy()); assertEquals(expectedProxyHost, subject.proxyHost()); assertEquals(expectedProxyPath, subject.proxyPath());
private Optional<ClientConfig> computeStatisticalRoundRobin(Supplier<Random> randomSupplier) { List<ClientConfig> clientConfigs = config.clientConfigs(); if (clientConfigs.size() > 0) { int index = randomSupplier.get().nextInt(clientConfigs.size()); return Optional.of(clientConfigs.get(index)); } else { return Optional.empty(); } } }
public PersistentProxyHandler( ClientFactory factory, ProxyRouteConfig config, SocketAddressHelper addressHelper) { super(factory, config, addressHelper); val clientConfigs = config.clientConfigs(); persistentProxyHasher = buildHasher(clientConfigMap, clientConfigs.size()); }
private RendezvousHash<CharSequence> buildHasher( Map<String, ClientConfig> configMap, int configSize) { List<String> randomIdPool = new ArrayList<>(); val clientConfigs = config.clientConfigs(); // map each client config to a randomly-generated ID for (int i = 0; i < configSize; i++) { String id = UUID.randomUUID().toString(); randomIdPool.add(id); configMap.put(id, clientConfigs.get(i)); } return new RendezvousHash<>(Funnels.stringFunnel(Constants.DEFAULT_CHARSET), randomIdPool); }
public static ProxyRouteState create( ApplicationState state, ProxyRouteConfig config, ProxyHandler handler) { List<ClientConfig> configs = config.clientConfigs(); List<ClientState> clientStates = configs .stream() .map(clientConfig -> new ClientState(clientConfig, state.workerGroup())) .collect(Collectors.toList()); return new ProxyRouteState(config, handler, clientStates); }
@Test public void testChunkedRequestsHttp1Statistical() { when(config.clientConfigs()).thenReturn(clientConfigs); Random mockRandom = mock(Random.class); subject = new RoundRobinProxyHandler(null, config, null, () -> mockRandom); when(mockRandom.nextInt(eq(config.clientConfigs().size()))).thenReturn(0); ClientConfig result1 = subject.getClientConfig(cacheMap, request1).orElse(null); assertEquals(clientConfig1, result1); when(mockRandom.nextInt(eq(config.clientConfigs().size()))).thenReturn(1); ClientConfig result2 = subject.getClientConfig(cacheMap, request2).orElse(null); assertEquals(clientConfig1, result2); when(mockRandom.nextInt(eq(config.clientConfigs().size()))).thenReturn(2); ClientConfig result3 = subject.getClientConfig(cacheMap, request3).orElse(null); assertEquals(clientConfig1, result3);
@Test public void testFullRequestsStatistical() { when(config.clientConfigs()).thenReturn(clientConfigs); Random mockRandom = mock(Random.class); subject = new RoundRobinProxyHandler(null, config, null, () -> mockRandom); when(mockRandom.nextInt(eq(config.clientConfigs().size()))).thenReturn(0); ClientConfig result1 = subject.getClientConfig(cacheMap, request1).orElse(null); assertEquals(clientConfig1, result1); when(mockRandom.nextInt(eq(config.clientConfigs().size()))).thenReturn(1); ClientConfig result2 = subject.getClientConfig(cacheMap, request2).orElse(null); assertEquals(clientConfig2, result2); when(mockRandom.nextInt(eq(config.clientConfigs().size()))).thenReturn(2); ClientConfig result3 = subject.getClientConfig(cacheMap, request3).orElse(null); assertEquals(clientConfig3, result3); when(mockRandom.nextInt(eq(config.clientConfigs().size()))).thenReturn(0); ClientConfig result4 = subject.getClientConfig(cacheMap, request3).orElse(null); assertEquals(clientConfig1, result4);
@Test public void testChunkedRequestsHttp1Standard() { when(config.clientConfigs()).thenReturn(clientConfigs); subject = RoundRobinProxyHandler.createStandardRoundRobinHandler(null, config, null);
@Test public void testFullRequestsStandard() { when(config.clientConfigs()).thenReturn(clientConfigs); subject = RoundRobinProxyHandler.createStandardRoundRobinHandler(null, config, null);
@Test public void testChunkedRequestsHttp2Statistical() { when(config.clientConfigs()).thenReturn(clientConfigs); Random mockRandom = mock(Random.class); subject = new RoundRobinProxyHandler(null, config, null, () -> mockRandom); when(mockRandom.nextInt(eq(config.clientConfigs().size()))).thenReturn(0); ClientConfig result1a = subject.getClientConfig(cacheMap, request1a).orElse(null); assertEquals(clientConfig1, result1a); when(mockRandom.nextInt(eq(config.clientConfigs().size()))).thenReturn(1); ClientConfig result1b = subject.getClientConfig(cacheMap, request1b).orElse(null); assertEquals(clientConfig2, result1b);
@Test public void testChunkedRequestsHttp2Standard() { when(config.clientConfigs()).thenReturn(clientConfigs); subject = RoundRobinProxyHandler.createStandardRoundRobinHandler(null, config, null);
@Test public void testNoClients() { request = RequestBuilders.newGet("https://www.google.com/").build(); when(config.clientConfigs()).thenReturn(new ArrayList<ClientConfig>()); subject = new ProxyHandler(factory, config, addressHelper); EmbeddedChannel channel = new EmbeddedChannel(new TestHandler(subject)); channel.writeInbound("doesn't matter"); assertTrue(channel.finish()); DefaultFullResponse result = channel.readOutbound(); assertEquals(result.status().code(), 503); } }