├── .gitignore
├── _config.yml
├── .travis.yml
├── src
└── main
│ ├── resources
│ ├── conf
│ │ └── application.properties
│ ├── META-INF
│ │ └── spring.handlers
│ ├── spring
│ │ ├── beans-proxy-routes.xml
│ │ ├── beans-vertx.xml
│ │ └── samples
│ │ │ └── beans-proxy-routes-samples.xml
│ └── log4j2.xml
│ └── java
│ └── com
│ └── github
│ └── kislayverma
│ └── throo
│ ├── routes
│ ├── BaseRouteConfigurer.java
│ ├── ProxyRouteConfigurer.java
│ ├── ProxyRouteFactory.java
│ └── ProxyRoute.java
│ ├── bootstrap
│ ├── ApplicationConfig.java
│ ├── SpringContextLoader.java
│ └── Application.java
│ ├── util
│ └── MiscUtil.java
│ └── verticle
│ └── HttpProxyVerticle.java
├── README.md
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | target/*
2 | logs/*
3 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-slate
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | install: mvn clean package -Dgpg.skip=true -U
3 | jdk:
4 | - oraclejdk8
--------------------------------------------------------------------------------
/src/main/resources/conf/application.properties:
--------------------------------------------------------------------------------
1 | spring.configs=spring/beans-vertx.xml,spring/beans-proxy-routes.xml
2 | application.verticleInstances=1
3 | application.workerPoolSize=25
4 | application.workerPoolName="proxyWorkerPool"
--------------------------------------------------------------------------------
/src/main/java/com/github/kislayverma/throo/routes/BaseRouteConfigurer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kislay Verma.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.kislayverma.throo.routes;
17 |
18 | import io.vertx.core.Vertx;
19 | import io.vertx.ext.web.Router;
20 | import org.slf4j.Logger;
21 | import org.slf4j.LoggerFactory;
22 |
23 | /**
24 | *
25 | * @author Kislay Verma
26 | */
27 | public abstract class BaseRouteConfigurer {
28 |
29 | protected Vertx vertx;
30 |
31 | protected final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
32 |
33 | public abstract Router setRouteHandlers(Vertx vertx);
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/resources/META-INF/spring.handlers:
--------------------------------------------------------------------------------
1 | http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
2 | http\://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler
3 | http\://www.springframework.org/schema/c=org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandler
4 | http\://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler
5 | http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
6 | http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
7 | http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
8 | http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
9 | http\://www.springframework.org/schema/jdbc=org.springframework.jdbc.config.JdbcNamespaceHandler
10 | http\://www.springframework.org/schema/security=org.springframework.security.config.SecurityNamespaceHandler
11 | http\://www.springframework.org/schema/tx=org.springframework.transaction.config.TxNamespaceHandler
12 | http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler
13 |
--------------------------------------------------------------------------------
/src/main/resources/spring/beans-proxy-routes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/kislayverma/throo)
2 |
3 | # Throo
4 | A Vert.x/Spring based HTTP reverse-proxy
5 |
6 | ## How to use this application
7 | ### Clone
8 | Clone this repository to your system.
9 |
10 | ### Configure proxy routes
11 | Open the "src/main/resources/spring/beans-proxy-routes.xml" file with your favourite editor and add the routes you want to proxy there along with other data to get this proxy working. A few sample routes are given under "src/main/resources/spring/samples/".
12 |
13 | ### Build
14 | mvn clean package
15 | This will generate a "throo-[version]-fat.jar" under the "target" folder. This is an executable fat jar.
16 |
17 | ### Run
18 | Execute the fat jar using the command : java -jar target/throo--fat.jar
19 | This should start up Nexus on port 8080 of your machine. Hitting http://localhost:8080/[your proxied route] should get you the data from the target server.
20 |
21 | If you face problems related to DNS resolution (i.e. if you get an error saying the targte host could not be resolved, or no such host etc.), try running the application by disabling the netty DNS resolver and defaulting to the JDK DNS resolver.
22 |
23 | Like this : java -Dvertx.disableDnsResolver=true -jar target/throo-[version]-fat.jar
24 |
--------------------------------------------------------------------------------
/src/main/java/com/github/kislayverma/throo/bootstrap/ApplicationConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kislay Verma.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.kislayverma.throo.bootstrap;
17 |
18 | import java.io.FileNotFoundException;
19 | import java.io.IOException;
20 | import java.io.InputStream;
21 | import java.util.Properties;
22 |
23 | /**
24 | *
25 | * @author Kislay Verma
26 | */
27 | public class ApplicationConfig {
28 |
29 | private final Properties prop;
30 |
31 | public ApplicationConfig(String propFileName) throws IOException {
32 | InputStream inputStream = getClass().getClassLoader().getResourceAsStream(propFileName);
33 |
34 | if (inputStream != null) {
35 | prop = new Properties();
36 | prop.load(inputStream);
37 | } else {
38 | throw new FileNotFoundException("Property file '" + propFileName + "' not found in the classpath");
39 | }
40 | }
41 |
42 | public String getProperty(String propertyName) {
43 | return prop.getProperty(propertyName);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/resources/spring/beans-vertx.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/main/java/com/github/kislayverma/throo/util/MiscUtil.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kislay Verma.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.kislayverma.throo.util;
17 |
18 | import com.github.kislayverma.throo.routes.ProxyRoute;
19 | import io.vertx.ext.web.RoutingContext;
20 | import io.vertx.ext.web.client.HttpRequest;
21 | import io.vertx.ext.web.client.HttpResponse;
22 | import org.slf4j.Logger;
23 | import org.slf4j.LoggerFactory;
24 |
25 | /**
26 | *
27 | * @author Kislay Verma
28 | */
29 | public class MiscUtil {
30 | private static final Logger LOGGER = LoggerFactory.getLogger(MiscUtil.class);
31 |
32 | public static HttpRequest setRequestHeaders(HttpRequest request, RoutingContext routingContext, ProxyRoute proxyRoute) {
33 | routingContext.request().headers().entries().forEach((entry) -> {
34 | LOGGER.debug("Setting request header : " + entry.getKey() + " : " + entry.getValue());
35 | request.putHeader(entry.getKey(), entry.getValue());
36 | });
37 | request.putHeader("Host", proxyRoute.getTargetBaseUrl());
38 |
39 | return request;
40 | }
41 |
42 | public static void setResponseHeaders(HttpResponse response, RoutingContext routingContext) {
43 | response.headers().entries().forEach((entry) -> {
44 | LOGGER.debug("Setting response header : " + entry.getKey() + " : " + entry.getValue());
45 | routingContext.response().putHeader(entry.getKey(), entry.getValue());
46 | });
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/resources/log4j2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/main/java/com/github/kislayverma/throo/bootstrap/SpringContextLoader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kislay Verma.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.kislayverma.throo.bootstrap;
17 |
18 | import org.slf4j.Logger;
19 | import org.slf4j.LoggerFactory;
20 | import org.springframework.context.ApplicationContext;
21 | import org.springframework.context.annotation.AnnotationConfigApplicationContext;
22 | import org.springframework.context.support.ClassPathXmlApplicationContext;
23 |
24 | /**
25 | *
26 | * @author Kislay Verma
27 | */
28 | public class SpringContextLoader {
29 | private final AnnotationConfigApplicationContext ctx;
30 | private final ApplicationContext context;
31 | private static final Logger LOGGER = LoggerFactory.getLogger(SpringContextLoader.class);
32 |
33 | public SpringContextLoader(String[] springContextFilePaths) {
34 | LOGGER.info("Loading Spring configs...");
35 | ctx = new AnnotationConfigApplicationContext();
36 | ctx.refresh();
37 | ctx.registerShutdownHook();
38 |
39 | context = new ClassPathXmlApplicationContext(springContextFilePaths);
40 | for (String beanName : context.getBeanDefinitionNames()) {
41 | LOGGER.debug("Loading spring bean : " + beanName);
42 | ctx.getBeanFactory().registerSingleton(beanName, context.getBean(beanName));
43 | }
44 |
45 | LOGGER.info("Finished loading spring beans");
46 | }
47 |
48 | public A getBean(Class clazz) {
49 | return ctx.getBean(clazz);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/github/kislayverma/throo/routes/ProxyRouteConfigurer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kislay Verma.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.kislayverma.throo.routes;
17 |
18 | import io.vertx.core.Vertx;
19 | import io.vertx.core.http.HttpMethod;
20 | import io.vertx.ext.web.Router;
21 | import io.vertx.ext.web.handler.BodyHandler;
22 | import io.vertx.ext.web.handler.ResponseTimeHandler;
23 |
24 | /**
25 | * This class gets and loads all the proxy routes.
26 | * @author Kislay Verma
27 | */
28 | public class ProxyRouteConfigurer extends BaseRouteConfigurer {
29 |
30 | private static ProxyRouteFactory proxyRouteFactory;
31 |
32 | @Override
33 | public Router setRouteHandlers(Vertx vertx) {
34 | LOGGER.info("Configuring proxy routes and registering handlers...");
35 |
36 | Router router = Router.router(vertx);
37 |
38 | // Enable response time handlers fr all requests and body handler for all POST and PUT requests
39 | router.route().handler(ResponseTimeHandler.create());
40 | router.route(HttpMethod.POST, "/*").handler(BodyHandler.create());
41 | router.route(HttpMethod.PUT, "/*").handler(BodyHandler.create());
42 |
43 | // Load all the proxy routes
44 | for (ProxyRoute proxyRoute : proxyRouteFactory.getAllRoutes()) {
45 | LOGGER.info("Configuring route : [" + proxyRoute.getHttpMethod() + "] " + proxyRoute.getRoute());
46 | router = proxyRoute.configure(vertx, router);
47 | }
48 |
49 | return router;
50 | }
51 |
52 | public void setProxyRouteFactory(ProxyRouteFactory aProxyRouteFactory) {
53 | proxyRouteFactory = aProxyRouteFactory;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/com/github/kislayverma/throo/verticle/HttpProxyVerticle.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kislay Verma.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.kislayverma.throo.verticle;
17 |
18 | import com.github.kislayverma.throo.routes.BaseRouteConfigurer;
19 | import io.vertx.core.AbstractVerticle;
20 | import io.vertx.core.Future;
21 | import io.vertx.core.http.HttpServerOptions;
22 | import io.vertx.ext.web.Router;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | *
28 | * @author Kislay Verma
29 | */
30 | public class HttpProxyVerticle extends AbstractVerticle {
31 |
32 | private static BaseRouteConfigurer routeConfigurer;
33 | private static final Logger LOGGER = LoggerFactory.getLogger(HttpProxyVerticle.class);
34 |
35 | @Override
36 | public void start(Future fut) {
37 | LOGGER.info("Starting proxy verticle...");
38 |
39 | // Set up all the routes and their handlers
40 | Router router = routeConfigurer.setRouteHandlers(vertx);
41 | HttpServerOptions options = new HttpServerOptions().setLogActivity(true);
42 | // Create the HTTP server
43 | vertx.createHttpServer(options)
44 | .requestHandler(router::accept)
45 | .listen(
46 | // Retrieve the port from the configuration,
47 | // default to 8080.
48 | config().getInteger("http.port", 8080),
49 | result -> {
50 | if (result.succeeded()) {
51 | fut.complete();
52 | } else {
53 | fut.fail(result.cause());
54 | }
55 | }
56 | );
57 | }
58 |
59 | public void setRouteConfigurer(BaseRouteConfigurer aRouteConfigurer) {
60 | routeConfigurer = aRouteConfigurer;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/com/github/kislayverma/throo/routes/ProxyRouteFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kislay Verma.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.kislayverma.throo.routes;
17 |
18 | import java.util.ArrayList;
19 | import java.util.Collections;
20 | import java.util.HashMap;
21 | import java.util.List;
22 | import java.util.Map;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 | import org.springframework.beans.BeansException;
26 | import org.springframework.context.ApplicationContext;
27 | import org.springframework.context.ApplicationContextAware;
28 |
29 | /**
30 | *
31 | * @author Kislay Verma
32 | */
33 | public class ProxyRouteFactory implements ApplicationContextAware {
34 |
35 | private ApplicationContext context;
36 |
37 | private Map keyToBeanMap;
38 |
39 | private static final Logger LOGGER = LoggerFactory.getLogger(ProxyRouteFactory.class);
40 | public void init() {
41 | Map h = new HashMap<>();
42 |
43 | for (ProxyRoute bean : getBeans()) {
44 | try {
45 | LOGGER.info("Adding bean with key :" + bean.getRoute() + "-- class name :" + bean.getClass());
46 | h.put(bean.getRoute(), bean);
47 | } catch (Exception e) {
48 | LOGGER.debug("Error initializing ProxyRouteFactory", e);
49 | }
50 | }
51 | synchronized (this.getClass()) {
52 | keyToBeanMap = Collections.unmodifiableMap(h);
53 | }
54 | }
55 |
56 | public ProxyRoute getBean(String key) {
57 | ProxyRoute bean = keyToBeanMap.get(key);
58 | if (bean == null) {
59 | LOGGER.error("No bean with key " + key);
60 | }
61 |
62 | return bean;
63 | }
64 |
65 | public List getAllRoutes() {
66 | return this.getBeans();
67 | }
68 |
69 | private List getBeans() {
70 | return new ArrayList<>(context.getBeansOfType(ProxyRoute.class, true, true).values());
71 | }
72 |
73 | @Override
74 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
75 | this.context = applicationContext;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/resources/spring/samples/beans-proxy-routes-samples.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/main/java/com/github/kislayverma/throo/bootstrap/Application.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kislay Verma.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.kislayverma.throo.bootstrap;
17 |
18 | import com.github.kislayverma.throo.verticle.HttpProxyVerticle;
19 | import io.vertx.core.DeploymentOptions;
20 | import io.vertx.core.Vertx;
21 | import java.io.IOException;
22 | import org.slf4j.Logger;
23 | import org.slf4j.LoggerFactory;
24 |
25 | /**
26 | * This is the class that launches the application.
27 | * Lifted from https://github.com/yasha-tymoshenko/vertx-rest-crud/blob/master/src/main/java/com/tymoshenko/MainApp.java
28 | *
29 | * @author Kislay Verma
30 | */
31 | public class Application {
32 | private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);
33 |
34 | public static void main(String[] args) throws IOException {
35 | ApplicationConfig config = new ApplicationConfig("conf/application.properties");
36 | String springFilesStr = config.getProperty("spring.configs");
37 | if (springFilesStr != null) {
38 | String[] springFilesArr = springFilesStr.split(",");
39 | if (springFilesArr.length > 0) {
40 | LOGGER.info("Loading spring config files : " + springFilesStr);
41 | SpringContextLoader contextLoader = new SpringContextLoader(springFilesArr);
42 | }
43 | }
44 |
45 | int verticleInstances = 1;
46 | String configuredVerticleInstances = config.getProperty("application.verticleInstances");
47 | if (configuredVerticleInstances != null && !configuredVerticleInstances.isEmpty()) {
48 | verticleInstances = Integer.parseInt(configuredVerticleInstances);
49 | }
50 | LOGGER.info("Number of proxy verticles to instantiate : " + verticleInstances);
51 |
52 | int workerPoolSize = 25;
53 | String configuredWorkerPoolSize = config.getProperty("application.workerPoolSize");
54 | if (configuredWorkerPoolSize != null && !configuredWorkerPoolSize.isEmpty()) {
55 | workerPoolSize = Integer.parseInt(configuredWorkerPoolSize);
56 | }
57 | LOGGER.info("Worker pool size : " + workerPoolSize);
58 |
59 | String workerPoolName = "proxyWorkerPool";
60 | String configuredWorkerPoolName = config.getProperty("application.workerPoolName");
61 | if (configuredWorkerPoolName != null && !configuredWorkerPoolName.isEmpty()) {
62 | workerPoolName = configuredWorkerPoolName;
63 | }
64 | LOGGER.info("Worker pool name : " + workerPoolName);
65 |
66 | final Vertx vertx = Vertx.vertx();
67 |
68 | LOGGER.info("Deploying verticles...");
69 | vertx.deployVerticle(HttpProxyVerticle.class.getName(),new DeploymentOptions()
70 | .setInstances(verticleInstances).setWorkerPoolSize(workerPoolSize).setWorkerPoolName(workerPoolName));
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/com/github/kislayverma/throo/routes/ProxyRoute.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Kislay Verma.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.kislayverma.throo.routes;
17 |
18 | import com.github.kislayverma.throo.util.MiscUtil;
19 | import io.vertx.core.AsyncResult;
20 | import io.vertx.core.Vertx;
21 | import io.vertx.core.buffer.Buffer;
22 | import io.vertx.ext.web.Router;
23 | import io.vertx.ext.web.RoutingContext;
24 | import io.vertx.ext.web.client.HttpRequest;
25 | import io.vertx.ext.web.client.HttpResponse;
26 | import io.vertx.ext.web.client.WebClient;
27 | import io.vertx.ext.web.client.WebClientOptions;
28 | import java.util.Date;
29 | import org.slf4j.Logger;
30 | import org.slf4j.LoggerFactory;
31 |
32 | /**
33 | *
34 | * @author Kislay Verma
35 | */
36 | public class ProxyRoute {
37 | private String route;
38 | private String targetBaseUrl;
39 | private String httpMethod;
40 | private Long timeout;
41 | private Integer port;
42 | private WebClient client;
43 |
44 | private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
45 | private static final String START_TIME_KEY = "proxyHandlerStartTime";
46 |
47 | public Router configure(Vertx vertx, Router router) {
48 | WebClientOptions clientOptions = new WebClientOptions().setLogActivity(true).setMaxPoolSize(100);
49 | this.client = WebClient.create(vertx, clientOptions);
50 |
51 | switch (httpMethod.toUpperCase()) {
52 | case "GET":
53 | router.get(route).handler(this::doProxyGet);
54 | break;
55 | case "POST":
56 | router.post(route).handler(this::doProxyPost);
57 | break;
58 | case "PUT":
59 | router.put(route).handler(this::doProxyPut);
60 | break;
61 | default:
62 | throw new RuntimeException("Unsupported HTTP method on proxy route " + route);
63 | }
64 |
65 | return router;
66 | }
67 |
68 | public void doProxyGet(RoutingContext routingContext) {
69 | LOGGER.debug("Matched route " + route);
70 |
71 | long timeoutToUse = this.timeout == null ? 1000L : this.timeout;
72 | int portToUse = (this.port == null) ? 80 : this.port;
73 |
74 | routingContext.put(START_TIME_KEY, new Date().getTime());
75 | // Blind passthrough - only change the host and port part of the incoming request.
76 | // Sending the request URI will send both the path and the query params onwards
77 | HttpRequest request = client.get(portToUse, targetBaseUrl, routingContext.request().uri()).timeout(timeoutToUse);
78 | request = MiscUtil.setRequestHeaders(request, routingContext, this);
79 |
80 | request.send(r -> {
81 | AsyncResult> ar = (AsyncResult) r;
82 | handleResponse(routingContext, ar);
83 | });
84 | }
85 |
86 | private void doProxyPost(RoutingContext routingContext) {
87 | LOGGER.debug("Matched route " + route);
88 |
89 | long timeoutToUse = this.timeout == null ? 1000L : this.timeout;
90 | int portToUse = (this.port == null) ? 80 : this.port;
91 |
92 | routingContext.put(START_TIME_KEY, new Date().getTime());
93 | // Blind passthrough - only change the host and port part of the incoming request.
94 | // Sending the request URI will send both the path and the query params onwards
95 | HttpRequest request = client.post(portToUse, targetBaseUrl, routingContext.request().uri()).timeout(timeoutToUse);
96 | request = MiscUtil.setRequestHeaders(request, routingContext, this);
97 | LOGGER.debug("Request body : " + routingContext.getBody());
98 | request.sendBuffer(routingContext.getBody(), r -> {
99 | AsyncResult> ar = (AsyncResult) r;
100 | handleResponse(routingContext, ar);
101 | });
102 | }
103 |
104 | private void doProxyPut(RoutingContext routingContext) {
105 | LOGGER.debug("Matched route " + route);
106 |
107 | long timeoutToUse = this.timeout == null ? 1000L : this.timeout;
108 | int portToUse = (this.port == null) ? 80 : this.port;
109 |
110 | routingContext.put(START_TIME_KEY, new Date().getTime());
111 | // Blind passthrough - only change the host and port part of the incoming request.
112 | // Sending the request URI will send both the path and the query params onwards
113 | HttpRequest request = client.put(portToUse, targetBaseUrl, routingContext.request().uri()).timeout(timeoutToUse);
114 | request = MiscUtil.setRequestHeaders(request, routingContext, this);
115 | LOGGER.debug("Request body : " + routingContext.getBody());
116 | request.sendBuffer(routingContext.getBody(), r -> {
117 | AsyncResult> ar = (AsyncResult) r;
118 | handleResponse(routingContext, ar);
119 | });
120 | }
121 |
122 | private void handleResponse(RoutingContext routingContext, AsyncResult> ar) {
123 | if (ar.succeeded()) {
124 | HttpResponse response = ar.result();
125 | long timeTaken = (new Date().getTime()) - ((Long)routingContext.get(START_TIME_KEY));
126 | LOGGER.info("Request : " + (targetBaseUrl + routingContext.request().uri()) +
127 | "\tResponse status code : " + response.statusCode() +
128 | "\tResponse time : " + timeTaken);
129 | LOGGER.debug("Response body : " + response.bodyAsString());
130 |
131 | MiscUtil.setResponseHeaders(response, routingContext);
132 | routingContext.response().setStatusCode(response.statusCode());
133 | routingContext.response().setStatusMessage(response.statusMessage());
134 |
135 | routingContext.response().end(response.bodyAsBuffer());
136 | } else {
137 | routingContext.fail(ar.cause());
138 | }
139 | }
140 |
141 | public String getRoute() {
142 | return route;
143 | }
144 |
145 | public void setRoute(String route) {
146 | this.route = route;
147 | }
148 |
149 | public String getTargetBaseUrl() {
150 | return targetBaseUrl;
151 | }
152 |
153 | public void setTargetBaseUrl(String targetBaseUrl) {
154 | this.targetBaseUrl = targetBaseUrl;
155 | }
156 |
157 | public String getHttpMethod() {
158 | return httpMethod;
159 | }
160 |
161 | public void setHttpMethod(String httpMethod) {
162 | this.httpMethod = httpMethod;
163 | }
164 |
165 | public Long getTimeout() {
166 | return timeout;
167 | }
168 |
169 | public void setTimeout(Long timeout) {
170 | this.timeout = timeout;
171 | }
172 |
173 | public Integer getPort() {
174 | return port;
175 | }
176 |
177 | public void setPort(Integer port) {
178 | this.port = port;
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.github.kislayverma
4 | throo
5 | 1.0.0-SNAPSHOT
6 | jar
7 | Throo
8 | A Vert.x/Spring based HTTP-HTTP reverse proxy
9 | https://github.com/kislayverma/nexus
10 |
11 |
12 |
13 | The Apache License, Version 2.0
14 | http://www.apache.org/licenses/LICENSE-2.0.txt
15 |
16 |
17 |
18 |
19 |
20 | Kislay Verma
21 | kislay.nsit@gmail.com
22 | None
23 | https://github.com/kislayverma
24 |
25 |
26 |
27 |
28 | scm:git:git@github.com:kislayverma/throo.git
29 | scm:git:git@github.com:kislayverma/throo.git
30 | scm:git:git@github.com:kislayverma/throo.git
31 | HEAD
32 |
33 |
34 |
35 |
36 | ossrh
37 | https://oss.sonatype.org/content/repositories/snapshots
38 |
39 |
40 | ossrh
41 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
42 |
43 |
44 |
45 |
46 | io.vertx
47 | vertx-core
48 | 3.4.2
49 |
50 |
51 | io.vertx
52 | vertx-web
53 | 3.4.2
54 |
55 |
56 | io.vertx
57 | vertx-web-client
58 | 3.4.2
59 |
60 |
61 | org.springframework
62 | spring-context
63 | 4.3.9.RELEASE
64 |
65 |
66 | org.springframework
67 | spring-core
68 | 4.3.9.RELEASE
69 |
70 |
71 | org.springframework
72 | spring-aop
73 | 4.3.9.RELEASE
74 |
75 |
76 | org.springframework
77 | spring-context-support
78 | 4.3.9.RELEASE
79 |
80 |
81 | org.apache.logging.log4j
82 | log4j-core
83 | 2.8.2
84 |
85 |
86 | org.apache.logging.log4j
87 | log4j-slf4j-impl
88 | 2.8.2
89 |
90 |
91 | org.apache.logging.log4j
92 | log4j-1.2-api
93 | 2.8.2
94 |
95 |
96 | org.slf4j
97 | slf4j-api
98 | 1.7.25
99 |
100 |
101 | junit
102 | junit
103 | 4.8.1
104 | jar
105 | test
106 |
107 |
108 |
109 |
110 |
111 |
112 | maven-compiler-plugin
113 | 3.6.1
114 |
115 | 1.8
116 | 1.8
117 |
118 |
119 |
120 | org.apache.maven.plugins
121 | maven-shade-plugin
122 | 3.0.0
123 |
124 |
125 | package
126 |
127 | shade
128 |
129 |
130 |
131 |
132 |
134 |
135 | com.github.kislayverma.throo.bootstrap.Application
136 | com.github.kislayverma.throo.verticle.HttpProxyVerticle
137 |
138 |
139 |
144 |
145 | META-INF/spring.schemas
146 |
147 |
148 |
149 | ${project.build.directory}/${project.artifactId}-${project.version}-fat.jar
150 |
151 |
152 |
153 |
154 |
155 | org.codehaus.mojo
156 | cobertura-maven-plugin
157 | 2.7
158 |
159 |
160 | 0
161 |
162 |
163 |
164 |
165 | org.apache.maven.plugins
166 | maven-surefire-plugin
167 | 2.18.1
168 | true
169 |
170 |
171 | org.apache.maven.plugins
172 | maven-pmd-plugin
173 | 3.5
174 |
175 |
176 |
177 | pmd
178 |
179 |
180 |
181 |
182 | true
183 | utf-8
184 | 100
185 | 1.7
186 |
187 |
188 |
189 | org.apache.maven.plugins
190 | maven-source-plugin
191 | 2.4
192 |
193 |
194 | attach-sources
195 |
196 | jar
197 |
198 |
199 |
200 |
201 |
202 | org.apache.maven.plugins
203 | maven-javadoc-plugin
204 | 2.10.3
205 |
206 |
207 | attach-javadocs
208 |
209 | jar
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 | org.apache.maven.plugins
221 | maven-jxr-plugin
222 | 2.5
223 |
224 |
225 | org.apache.maven.plugins
226 | maven-project-info-reports-plugin
227 | 2.9
228 |
229 | false
230 |
231 |
232 |
233 | org.apache.maven.plugins
234 | maven-javadoc-plugin
235 | 2.10.3
236 |
237 |
238 | org.codehaus.mojo
239 | cobertura-maven-plugin
240 | 2.7
241 |
242 |
243 | org.apache.maven.plugins
244 | maven-pmd-plugin
245 | 3.6
246 |
247 | true
248 | utf-8
249 | 100
250 | 1.7
251 |
252 |
253 |
254 |
255 |
256 |
--------------------------------------------------------------------------------