Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add plugin examples to Styx #432

Merged
merged 11 commits into from
Jul 1, 2019
185 changes: 53 additions & 132 deletions plugin-examples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,29 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">


<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>

<groupId>com.hotels.styx</groupId>
<artifactId>plugin-examples</artifactId>
<name>Styx proxy plugin examples</name>
<version>0.0.1-SNAPSHOT</version>
<groupId>com.hotels.styx</groupId>
<version>1.0-SNAPSHOT</version>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<main.basedir>${project.parent.basedir}</main.basedir>
<java.source>1.8</java.source>
<java.target>1.8</java.target>

<!-- Styx Version -->
<styx.version>0.9-SNAPSHOT</styx.version>
<rxjava.version>1.1.6</rxjava.version>
<jackson.version>2.9.9</jackson.version>
<!--Testing-->
<testng.version>6.8</testng.version>

<!-- apache plugin versions and configurations, please sort alphabetically -->
<maven-compiler-plugin.version>3.0</maven-compiler-plugin.version>
<maven-jar-plugin.version>2.4</maven-jar-plugin.version>
<maven-resources-plugin.version>2.6</maven-resources-plugin.version>
<maven-surefire-plugin.version>2.16</maven-surefire-plugin.version>
<testng.version>6.14.3</testng.version>
</properties>


<dependencies>
<dependency>
<groupId>com.hotels.styx</groupId>
<artifactId>styx-api</artifactId>
<version>${styx.version}</version>
<!-- The dependency is explicitlu needed only during compile time, styx is already available in the runtime-->
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
Expand Down Expand Up @@ -68,138 +56,71 @@
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>

</dependencies>

<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*</include>
</includes>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
</testResources>

<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>${maven-resources-plugin.version}</version>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>

<!-- This plugin was copied from the parent pom. It may not all be relevant. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<version>3.3</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<source>${java.source}</source>
<target>${java.target}</target>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
</plugin>


<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.0</version>
<executions>
<!-- Replacing default-compile as it is treated specially by maven -->
<execution>
<id>get-local-ip</id>
<phase>initialize</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<classpath>
<element>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.4</version>
</element>
</classpath>
<source>
project.properties.localIP = java.net.InetAddress.getLocalHost().getHostAddress()
</source>
</configuration>
<id>default-compile</id>
<phase>none</phase>
</execution>
<!-- Replacing default-testCompile as it is treated specially by maven -->
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<phase>compile</phase>
<goals> <goal>compile</goal> </goals>
</execution>
<execution>
<id>java-test-compile</id>
<phase>test-compile</phase>
<goals> <goal>testCompile</goal> </goals>
</execution>
</executions>
</plugin>

</plugins>

<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>

<profiles>
<profile>
<id>styx</id>
<properties>
<use.docker>false</use.docker>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
</plugin>

<!-- We use the Shade plugin to bundle all the plugin dependencies together and ensure classloader-level
isolation for different plugins.
This sample plugin does not have any external dependencies.
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<shadedClassifierName>jar-with-dependencies</shadedClassifierName>
<outputDirectory>${pluginsDir}</outputDirectory>
<!--
Since we are creating a single shaded JAR, signed JARs will not be valid anymore. To avoid this issue,
we just remove the signature files in the JARs.
For filters, see:
http://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar
-->
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
Copyright (C) 2013-2019 Expedia Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package com.hotels.styx;

import com.hotels.styx.api.Eventual;
import com.hotels.styx.api.HttpResponse;
import com.hotels.styx.api.LiveHttpRequest;
import com.hotels.styx.api.LiveHttpResponse;
import com.hotels.styx.api.plugins.spi.Plugin;

import static com.hotels.styx.api.HttpHeaderNames.CONTENT_TYPE;
import static com.hotels.styx.api.HttpResponseStatus.OK;
import static java.nio.charset.StandardCharsets.UTF_8;

/**
* This shows an example of a plugin that responds immediately to a received request, instead of proxying it downstream.
* It takes a request and if the HTTP request contains a header named `X-Respond`, then it returns an eventual wrapping
* the HTTP response
* The eventual object is returned immediately, even if the response has not yet arrived.
*/

public class EarlyReturnExamplePlugin implements Plugin {

@Override
public Eventual<LiveHttpResponse> intercept(LiveHttpRequest request, Chain chain) {
if (request.header("X-Respond").isPresent()) {
return Eventual.of(HttpResponse.response(OK)
.header(CONTENT_TYPE, "text/plain; charset=utf-8")
.body("Responding from plugin", UTF_8)
.build()
.stream());
} else {
return chain.proceed(request);
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
Copyright (C) 2013-2019 Expedia Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package com.hotels.styx;

import com.hotels.styx.api.Eventual;
import com.hotels.styx.api.HttpResponse;
import com.hotels.styx.api.LiveHttpRequest;
import com.hotels.styx.api.LiveHttpResponse;
import com.hotels.styx.api.plugins.spi.Plugin;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Objects.requireNonNull;

/**
* You can replace content after aggregating it in memory.
* For example, if the message content contains a JSON object and you need to modify the object somehow.
* You can aggregate the live HTTP message into a full HTTP message. Transform the content into a full message context
* and convert the results back to live HTTP message
*
*This can be used when you need the entire content in order to operate on it.
*Please note that this uses more heap space as the full response is transiently stored in the heap.
*/

public class ModifyContentByAggregationExamplePlugin implements Plugin {
private final Config config;

public ModifyContentByAggregationExamplePlugin(Config config) {
this.config = requireNonNull(config);
}

@Override
public Eventual<LiveHttpResponse> intercept(LiveHttpRequest request, Chain chain) {
return chain.proceed(request)
.flatMap(response -> response.aggregate(10000))
.map(response -> {
String body = response.bodyAs(UTF_8);
return response.newBuilder()
.body(body + config.extraText(), UTF_8)
.build();
})
.map(HttpResponse::stream);
}

/**
* Config for example plugin.
*/
public static class Config {
private final String extraText;

public Config(String extraText) {
this.extraText = requireNonNull(extraText);
}

public String extraText() {
return extraText;
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@
* You can change it in whatever way you like (provided it still implements the Plugin interface),
* and should rename it to something relevant to your project.
*/
public class ExamplePlugin implements Plugin {
private final ExamplePluginConfig config;
public class ModifyHeadersExamplePlugin implements Plugin {
private final ModifyHeadersExamplePluginConfig config;

/**
* The plugin will be constructed by your plugin factory, so the constructor can take whatever form you like.
*
* @param config
*/
public ExamplePlugin(ExamplePluginConfig config) {
public ModifyHeadersExamplePlugin(ModifyHeadersExamplePluginConfig config) {
this.config = requireNonNull(config);
}

Expand Down Expand Up @@ -84,4 +84,4 @@ public Eventual<LiveHttpResponse> intercept(LiveHttpRequest request, Chain chain
public Map<String, HttpHandler> adminInterfaceHandlers() {
return emptyMap();
}
}
}
Loading