Skip to content

Commit

Permalink
Merge pull request #4 from kekru/feature/custom-host-header
Browse files Browse the repository at this point in the history
option to send a host header different from the upstream server
  • Loading branch information
kekru authored Mar 15, 2021
2 parents 4f2f841 + c1b928c commit c2ed204
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 8 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ Inspired by [robszumski/k8s-service-proxy](https://github.com/robszumski/k8s-ser

## Configuration

Every proxy rule consist of three env variables:
Every proxy rule consist of three or four env variables:

+ `RULE_1_MODE`: <mode>
+ `RULE_1_PATTERN`: <regex pattern> (see [nginx regex names](http://nginx.org/en/docs/http/server_names.html#regex_names))
+ `RULE_1_TARGET`: <target with usage of pattern variables>
+ `RULE_1_TARGET_HOST_HEADER`: <(Optional) modified host header, defaults to TARGET>

Example:

Expand All @@ -23,6 +24,7 @@ RULE_1_TARGET: 'https://$service.ab.example.com'
RULE_2_MODE: 'HTTP'
RULE_2_PATTERN: '(?<service>.+).xy.127-0-0-1.nip.io'
RULE_2_TARGET: 'https://$service.xy.example.com'
RULE_2_TARGET_HOST_HEADER: '$service.modified-host.example.com'
```

This creates two rules.
Expand All @@ -31,7 +33,8 @@ The following example requests will get the shown proxy actions:
+ `http://hello.ab.127-0-0-1.nip.io` will proxy pass to
`https://hello.ab.example.com`
+ `http://world.xy.127-0-0-1.nip.io` will proxy pass to
`https://world.xy.example.com`
`https://world.xy.example.com`
but send the host header `world.modified-host.example.com`

> Currently only mode HTTP is implemented
Expand Down
9 changes: 7 additions & 2 deletions script/createConfigs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ do
eval mode='$RULE_'$ruleName'_MODE'
eval pattern='$RULE_'$ruleName'_PATTERN'
eval target='$RULE_'$ruleName'_TARGET'
eval targetHostHeader='$RULE_'$ruleName'_TARGET_HOST_HEADER'

echo "Configuring rule $ruleName, mode: $mode, pattern: $pattern, target: $target"
echo "Configuring rule $ruleName, mode: $mode, pattern: $pattern, target: $target, targetHostHeader: $targetHostHeader"

if [[ "$mode" == "TLSPASS" ]]; then
echo "MODE TLSPASS is not yet implemented"
Expand All @@ -43,7 +44,11 @@ do
file="/data/configs/http/http-$ruleName.conf"
cp /data/templates/HTTP.conf $file
sed -i "s|PATTERN|$pattern|g" $file
sed -i "s|TARGET|$target|g" $file
sed -i "s|TARGET_HOST_ADDRESS|$target|g" $file
if [ -z "$targetHostHeader" ]; then
targetHostHeader="\$proxy_host"
fi
sed -i "s|TARGET_HOST_HEADER|$targetHostHeader|g" $file
sed -i "s|DNS_RESOLVER|$DNS_RESOLVER|g" $file
fi

Expand Down
7 changes: 4 additions & 3 deletions templates/HTTP.conf
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ server {

location / {
resolver DNS_RESOLVER;
proxy_pass TARGET;
proxy_pass TARGET_HOST_ADDRESS;
proxy_set_header Host TARGET_HOST_HEADER;

# Replace TARGET in 303 redirects with current hostname and port (from clients request)
proxy_redirect TARGET $scheme://$http_host;
# Replace TARGET_HOST_ADDRESS in 303 redirects with current hostname and port (from clients request)
proxy_redirect TARGET_HOST_ADDRESS $scheme://$http_host;
}
}
2 changes: 1 addition & 1 deletion test/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.14.2</version>
<version>1.15.2</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
45 changes: 45 additions & 0 deletions test/src/test/java/de/kekru/patternproxy/test/IntegrationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.HttpResponse.response;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.junit.Test;
import org.mockserver.client.MockServerClient;
import org.mockserver.model.MediaType;
Expand Down Expand Up @@ -89,19 +93,60 @@ public void testRedirectReaplacesWithClientsRequestHostHeader() {
}
}

@Test
public void testUsingDifferentHostHeaders() {
Map<String, String> additionalEnv = new HashMap<>();
additionalEnv.put("RULE_1_TARGET_HOST_HEADER", "something-strange-$service-that-does-not-resolve");
try (
Network network = createNetwork();
GenericContainer mockServerContainer = createMockServer(network);
GenericContainer patternProxyContainer = createPatternProxy(network, additionalEnv);
) {
mockServerContainer.start();
patternProxyContainer.start();
patternProxyMappedPort = patternProxyContainer.getMappedPort(80);
mockServerMappedPort = mockServerContainer.getMappedPort(1090);
patternProxyContainer.followOutput(new Slf4jLogConsumer(LOG_PATTERN_PROXY));


mockServerClient = new MockServerClient("localhost", mockServerMappedPort);
mockServerClient
.when(request()
.withMethod("GET")
.withHeader("Host", "something-strange-abc-that-does-not-resolve")
.withPath("/something"))
.respond(response()
.withStatusCode(200)
.withContentType(MediaType.JSON_UTF_8)
.withBody("{ \"message\": \"It Works, requested was something-strange-abc-that-does-not-resolve\" }"));

given()
.when()
.redirects().follow(false)
.get("http://abc.pp.127-0-0-1.nip.io:" + patternProxyMappedPort + "/something")
.then()
.body("message", equalTo("It Works, requested was something-strange-abc-that-does-not-resolve"));
}
}


private Network createNetwork() {
return Network.newNetwork();
}

private GenericContainer createPatternProxy(Network network) {
return createPatternProxy(network, Collections.emptyMap());
}

private GenericContainer createPatternProxy(Network network, Map<String, String> additionalEnv) {

GenericContainer container = new GenericContainer("kekru/pattern-proxy:temp-for-unittests")
.withNetwork(network)
.withExposedPorts(80).withEnv("RULE_1_MODE", "HTTP")
.withEnv("RULE_1_PATTERN", "(?<service>.+).pp.127-0-0-1.nip.io")
.withEnv("RULE_1_TARGET", "http://$service.mock-server:1090")
.withEnv("DNS_RESOLVER", "127.0.0.11") // Internal Docker Network Resolver
.withEnv(additionalEnv)
;
return container;
}
Expand Down

0 comments on commit c2ed204

Please sign in to comment.