Step 1. Add the JitPack repository to your build file
Add it in your root settings.gradle at the end of repositories:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
Add it in your settings.gradle.kts at the end of repositories:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}
Add to pom.xml
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
Add it in your build.sbt at the end of resolvers:
resolvers += "jitpack" at "https://jitpack.io"
Add it in your project.clj at the end of repositories:
:repositories [["jitpack" "https://jitpack.io"]]
Step 2. Add the dependency
dependencies {
implementation 'com.github.RichardBradley:charon-spring-boot-starter:2.3.0-i45'
}
dependencies {
implementation("com.github.RichardBradley:charon-spring-boot-starter:2.3.0-i45")
}
<dependency>
<groupId>com.github.RichardBradley</groupId>
<artifactId>charon-spring-boot-starter</artifactId>
<version>2.3.0-i45</version>
</dependency>
libraryDependencies += "com.github.RichardBradley" % "charon-spring-boot-starter" % "2.3.0-i45"
:dependencies [[com.github.RichardBradley/charon-spring-boot-starter "2.3.0-i45"]]
Charon is a reverse proxy implementation. It automatically forwards HTTP requests from one web application to another and sends back the received HTTP response to the client. There are some alternative reverse proxy implementations like: Zuul or Smiley's HTTP Proxy Servlet. This tool tries to get the best of them joining their features into a one Spring Boot starter.
@EnableCharon
annotationcharon.mertics
properties in the application.yml file if collecting metrics is enabledcharon.timeout
properties are no longer available in the application.yml file, now timeouts can be set per mappingrepositories {
mavenCentral()
}
dependencies {
compile group: 'com.github.mkopylec', name: 'charon-spring-boot-starter', version: '2.3.0'
}
Create a Spring Boot web application:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Configure proxy mappings in application.yml file:
charon.mappings:
-
name: sample mapping
path: /some/path
destinations: http://firsthost:8080, http://secondhost:8081
When an application is configured like above then every request to /some/path/endpoint/**
will be forwarded to http://firsthost:8080/endpoint/** or http://secondhost:8081/endpoint/**.
Note that the mapped path /some/path is stripped from the forwarded request URL.
Also note that the charon.mappings
property's value is a list, therefore more mappings can be set.
Charon can be configured in many ways. This can be done via configuration properties in application.yml file or by creating Spring beans.
Mappings define how Charon will forward incoming HTTP requests. Every mapping must be named. By default the mapped path is stripped from the forward request URL. To preserve the mapped path in the URL set an appropriate configuration property:
charon.mappings:
-
...
strip-path: false
If the mappings configuration using configuration properties is not enough, a custom mappings provider can be created.
This can be done by creating a Spring bean of type MappingsProvider
:
@Component
@EnableConfigurationProperties({CharonProperties.class, ServerProperties.class})
public class CustomMappingsProvider extends MappingsProvider {
@Autowired
public CustomMappingsProvider(ServerProperties server, CharonProperties charon, MappingsCorrector mappingsCorrector) {
super(server, charon, mappingsCorrector);
}
@Override
protected boolean shouldUpdateMappings(HttpServletRequest request) {
...
}
@Override
protected List<Mapping> retrieveMappings() {
...
}
}
Using custom MappingsProvider
the mappings are populated during application startup using retrieveMappings
method.
The mappings are also updated during application runtime every time the shouldUpdateMappings
method returns true
.
By default there is only one attempt to forward request. Forward request retrying can be enabled for each mapping by setting an appropriate configuration property:
charon.mappings:
-
...
retryable: true
By default a next try is triggered by any Exception
that occurs during proxying process and also by 5xx HTTP responses from destination hosts.
To change the retryable exceptions set an appropriate configuration property:
charon.retrying.retry-on.exceptions: <comma-separated list fo exceptions>
To disable retrying on 5xx HTTP responses set an appropriate configuration property:
charon.retrying.retry-on.server-http-error: false
Retrying on 4xx HTTP responses from destination hosts is disabled by default. To turn it on set an appropriate configuration property:
charon.retrying.retry-on.client-http-error: true
If retrying is enabled there are maximum three attempts to forward request. To change the maximum number of attempts set an appropriate configuration property:
charon.retrying.max-attempts: <number_of_tries>
The default load balancer randomly chooses a destination host from the available list.
A custom load balancer can be created by creating a Spring bean of type LoadBalancer
:
@Component
public class CustomLoadBalancer implements LoadBalancer {
@Override
public String chooseDestination(List<String> destinations) {
...
}
}
Collecting performance metrics is disabled by default. To turn them on set an appropriate configuration property:
charon.metrics.enabled: true
Charon collects metrics per mapping. To report collected metrics a reporter is needed. Charon includes two metrics reporters but they are disabled by default. To enable a reporter that logs collected metrics set an appropriate configuration property:
charon.metrics.reporting.logger.enabled: true
To enable a reporter that sends collected metrics to a Graphite server set an appropriate configuration properties:
charon.metrics.reporting.graphite:
enabled: true
hostname: <graphite_hostname>
port: <graphite_port>
The default metrics reporters report results every 60 seconds. The interval can be changed by setting an appropriate configuration property:
charon.metrics.reporting.interval-in-seconds: <interval_in_seconds>
To create a custom metrics reporter create a Spring bean that extends ScheduledReporter
:
@Component
public class CustomMetricsReporter extends ScheduledReporter {
@Autowired
public CustomMetricsReporter(MetricRegistry registry) {
...
}
@Override
public void report(SortedMap<String, Gauge> gauges, SortedMap<String, Counter> counters, SortedMap<String, Histogram> histograms, SortedMap<String, Meter> meters, SortedMap<String, Timer> timers) {
...
}
@PostConstruct
private void startCapturingMetrics() {
start(...);
}
}
Charon gives a possibility to change the outgoing HTTP requests.
Particularly any aspect of the request can be modified: method, URI, headers and body.
To intercept requests create a Spring bean of type ForwardedRequestInterceptor
and modify the RequestData
object:
@Component
public class CustomForwardedRequestInterceptor implements ForwardedRequestInterceptor {
@Override
public void intercept(RequestData data) {
...
}
}
Charon gives a possibility to change the incoming HTTP responses.
Particularly any aspect of the response can be modified: status, headers and body.
To intercept responses create a Spring bean of type ReceivedResponseInterceptor
and modify the ResponseData
object:
@Component
public class CustomReceivedResponseInterceptor implements ReceivedResponseInterceptor {
@Override
public void intercept(ResponseData data) {
...
}
}
Charon can trace a proxying process. Tracing allows applications to collect detailed information about Charon's activity. To enable it set an appropriate configuration property:
charon.tracing.enabled: true
Every trace collects information at five checkpoints:
In each checkpoint a trace ID and current HTTP data are captured.
A trace ID remains the same throughout the whole proxying process of a single HTTP request, therefore trace checkpoints can be joined by trace IDs value.
By default, when tracing is enabled, Charon logs the captured information.
To change this behaviour create a Spring bean of type TraceInterceptor
:
@Component
public class CustomTraceInterceptor implements TraceInterceptor {
@Override
public void onRequestReceived(String traceId, IncomingRequest request) {
...
}
@Override
public void onNoMappingFound(String traceId, IncomingRequest request) {
...
}
@Override
public void onForwardStart(String traceId, ForwardRequest request) {
...
}
@Override
public void onForwardError(String traceId, Throwable error) {
...
}
@Override
public void onForwardComplete(String traceId, ReceivedResponse response) {
...
}
}
By default HTTP requests are forwarded synchronously. Forwarding process can also be asynchronous. In asynchronous mode a response is returned immediately with 202 (accepted) HTTP status. To enable asynchronous forwarding set an appropriate configuration property:
charon.mappings:
-
...
asynchronous: true
For asynchronous forwarding a thread pool executor is used.
Its configuration is exposed by charon.asynchronous-forwarding-thread-pool
configuration properties.
com.github.mkopylec.charon
to DEBUG to see what's going on under the hoodCharonConfiguration
to see what else can be overridden by creating a Spring beanThe following list contains all available configuration properties with their default values.
charon:
filter-order: Ordered.LOWEST_PRECEDENCE # Charon servlet filter order.
retrying:
max-attempts: 3 # Maximum number of HTTP request forward tries.
retry-on:
client-http-error: false # Flag for enabling and disabling triggering HTTP requests forward retries on 4xx HTTP responses from destination.
server-http-error: true # Flag for enabling and disabling triggering HTTP requests forward retries on 5xx HTTP responses from destination.
exceptions: java.lang.Exception # Comma-separated list of exceptions that triggers HTTP request forward retries.
metrics:
enabled: false # Flag for enabling and disabling collecting metrics during HTTP requests forwarding.
names-prefix: charon # Global metrics names prefix.
reporting:
interval-in-seconds: 60 # Metrics reporting interval in seconds.
logger:
enabled: false # Flag for enabling and disabling reporting metrics to application logger.
graphite:
enabled: false # Flag for enabling and disabling reporting metrics to Graphite server.
hostname: # Graphite server hostname.
port: 2003 # Graphite server port.
tracing:
enabled: false # Flag for enabling and disabling tracing HTTP requests proxying processes.
asynchronous-forwarding-thread-pool:
queue-capacity: 50 # Thread pool executor queue capacity.
size:
initial: 5 # Thread pool executor initial number of threads.
maximum: 30 # Thread pool executor maximum number of threads.
mappings:
-
name: # Name of the mapping.
path: / # Path for mapping incoming HTTP requests URIs.
destinations: # List of destination hosts where HTTP requests will be forwarded.
asynchronous: false # Flag for enabling and disabling asynchronous HTTP request forwarding.
strip-path: true # Flag for enabling and disabling mapped path stripping from forwarded request URI.
retryable: false # Flag for enabling and disabling retrying of HTTP requests forwarding.
timeout:
connect: 200 # Connect timeout for HTTP requests forwarding.
read: 2000 # Read timeout for HTTP requests forwarding.
See test application for more examples.
Charon Spring Boot Starter is published under Apache License 2.0.