Skip to content

Commit

Permalink
Version number deleted from server string. Documentation improvements…
Browse files Browse the repository at this point in the history
…. Fixed tests. (#694)
  • Loading branch information
predic8 authored Aug 21, 2023
1 parent 4a314cc commit 3e20594
Show file tree
Hide file tree
Showing 44 changed files with 198 additions and 321 deletions.
2 changes: 1 addition & 1 deletion BUILD.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Building Membrane Service Proxy
# Building Membrane API Gateway

### What you need
* Java JDK 17
Expand Down
10 changes: 1 addition & 9 deletions core/src/main/java/com/predic8/membrane/core/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ public class Constants {

public static final String MEMBRANE_HOME = "MEMBRANE_HOME";

public static final String EMPTY_STRING = "";

public static final String CRLF = "" + ((char) 13) + ((char) 10);

public static final byte[] CRLF_BYTES = { 13, 10 };
Expand All @@ -49,8 +47,6 @@ public class Constants {
VERSION = version;
}

public static final String XML_VERSION = "1.0";

public static final String ISO_8859_1 = "ISO-8859-1";

public static final String UNKNOWN = "unknown";
Expand All @@ -59,8 +55,6 @@ public class Constants {

public static final String HTTP_VERSION_11 = "1.1";

public static final String HTTP_VERSION_10 = "1.0";

public static final String WSDL_SOAP11_NS = "http://schemas.xmlsoap.org/wsdl/soap/";
public static final String WSDL_SOAP12_NS = "http://schemas.xmlsoap.org/wsdl/soap12/";
public static final String WSDL_HTTP_NS = "http://schemas.xmlsoap.org/wsdl/http/";
Expand All @@ -76,9 +70,7 @@ public class Constants {

public static final String PROTOCOL_SOAP12 = "SOAP12";

public static final String PROTOCOL_HTTP = "HTTP";

public static final String PRODUCT_NAME = "Membrane Service Proxy";
public static final String PRODUCT_NAME = "Membrane API Gateway";
public static final String PRODUCT_WEBSITE = "http://www.membrane-soa.org/api-gateway/";
public static final String PRODUCT_WEBSITE_DOC = "http://www.membrane-soa.org/api-gateway-doc/";
public static final String PRODUCT_CONTACT_EMAIL = "[email protected]";
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/com/predic8/membrane/core/Router.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@

/**
* @description <p>
* Membrane Service Proxy's main object.
* Membrane API Gateway's main object.
* </p>
* <p>
* The router is a Spring Lifecycle object: It is automatically started and stopped according to the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ public static ResponseBuilder ok(String msg) throws Exception {
return ok().contentType(TEXT_HTML_UTF8).body(msg);
}

private static final String SERVER_HEADER = PRODUCT_NAME + " " + VERSION + " http://membrane-api.io";
private static final String SERVER_HEADER = PRODUCT_NAME;

public static ResponseBuilder statusCode(int statusCode) {
return newInstance().status(statusCode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ public final String getHelpId() {
MCElement annotation = getClass().getAnnotation(MCElement.class);
if (annotation == null)
return null;
if (!annotation.id().isEmpty())
return annotation.id();
return annotation.name();
}

Expand Down Expand Up @@ -134,10 +136,6 @@ public static Message getMessage(Exchange exc, Interceptor.Flow flow) {
exc.setResponse(response);
yield response;
}
default -> {
log.info("Should never happen!");
yield null;
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
* <p>
* The text message is sent via <a href="http://www.developergarden.com/">Deutsche Telekom's developer
* garden</a> REST API. To use this API, a registered user account with sufficient balance is necessary and
* the <i>Send SMS</i> API has to be enabled for this account. Membrane Service Proxy must be registered as an
* the <i>Send SMS</i> API has to be enabled for this account. Membrane API Gateway must be registered as an
* "application" on the developer garden website, and the "Global SMS API" must be enabled both for the user account
* as well as the registered application. Once completed, the <i>scope</i>, <i>clientId</i> and <i>clientSecret</i>
* settings must be copied from the website into Membrane's proxies.xml configuration file. Membrane uses these three
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,39 +14,34 @@

package com.predic8.membrane.core.interceptor.balancer;

import static com.predic8.membrane.core.util.URLParamUtil.DuplicateKeyOrInvalidFormStrategy.ERROR;
import static com.predic8.membrane.core.util.URLParamUtil.parseQueryString;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import com.predic8.membrane.annot.*;
import com.predic8.membrane.core.exchange.*;
import com.predic8.membrane.core.http.*;
import com.predic8.membrane.core.interceptor.*;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.codec.binary.*;
import org.slf4j.*;

import javax.crypto.*;
import javax.crypto.spec.*;
import java.util.*;
import java.util.regex.*;

import com.predic8.membrane.annot.MCAttribute;
import com.predic8.membrane.annot.MCElement;
import com.predic8.membrane.core.exchange.Exchange;
import com.predic8.membrane.core.http.Response;
import com.predic8.membrane.core.interceptor.AbstractInterceptor;
import com.predic8.membrane.core.interceptor.Outcome;
import static com.predic8.membrane.core.interceptor.balancer.BalancerUtil.*;
import static com.predic8.membrane.core.util.URLParamUtil.DuplicateKeyOrInvalidFormStrategy.*;
import static com.predic8.membrane.core.util.URLParamUtil.*;
import static java.nio.charset.StandardCharsets.*;

/**
* @description Receives control messages to dynamically modify the configuration of a {@link LoadBalancingInterceptor}.
* @explanation See also examples/loadbalancer-client-2 in the Membrane Service Proxy distribution.
* @explanation See also examples/loadbalancer-client-2 in the Membrane API Gateway distribution.
* @topic 7. Clustering and Loadbalancing
*/
@MCElement(name="clusterNotification")
public class ClusterNotificationInterceptor extends AbstractInterceptor {
private static Logger log = LoggerFactory.getLogger(ClusterNotificationInterceptor.class.getName());
private static final Logger log = LoggerFactory.getLogger(ClusterNotificationInterceptor.class.getName());

private Pattern urlPattern = Pattern.compile("/clustermanager/(up|down|takeout)/?\\??(.*)");
private final Pattern urlPattern = Pattern.compile("/clustermanager/(up|down|takeout)/?\\??(.*)");

private boolean validateSignature = false;
private int timeout = 0;
Expand Down Expand Up @@ -85,24 +80,23 @@ public Outcome handleRequest(Exchange exc) throws Exception {
return Outcome.RETURN;
}

private void updateClusterManager(Matcher m, Map<String, String> params)
throws Exception {
private void updateClusterManager(Matcher m, Map<String, String> params) {
if ("up".equals(m.group(1))) {
BalancerUtil.up(
up(
router,
getBalancerParam(params),
getClusterParam(params),
params.get("host"),
getPortParam(params));
} else if ("down".equals(m.group(1))) {
BalancerUtil.down(
down(
router,
getBalancerParam(params),
getClusterParam(params),
params.get("host"),
getPortParam(params));
} else {
BalancerUtil.takeout(
takeout(
router,
getBalancerParam(params),
getClusterParam(params),
Expand All @@ -119,22 +113,22 @@ private Map<String, String> getDecryptedParams(String data) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
SecretKeySpec skeySpec = new SecretKeySpec(Hex.decodeHex(keyHex.toCharArray()), "AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
return parseQueryString(new String(cipher.doFinal(Base64.decodeBase64(data.getBytes("UTF-8"))),"UTF-8"), ERROR);
return parseQueryString(new String(cipher.doFinal(Base64.decodeBase64(data.getBytes(UTF_8))), UTF_8), ERROR);
}

private int getPortParam(Map<String, String> params) throws Exception {
private int getPortParam(Map<String, String> params) {
return Integer.parseInt(params.get("port"));
}

private String getClusterParam(Map<String, String> params) throws Exception {
private String getClusterParam(Map<String, String> params) {
return params.get("cluster") == null ? Cluster.DEFAULT_NAME : params.get("cluster");
}

private String getBalancerParam(Map<String, String> params) throws Exception {
private String getBalancerParam(Map<String, String> params) {
return params.get("balancer") == null ? Balancer.DEFAULT_NAME : params.get("balancer");
}

private Map<String, String> getParams(Exchange exc) throws Exception {
private Map<String, String> getParams(Exchange exc) {

String uri = exc.getOriginalRequestUri();
int qStart = uri.indexOf('?');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
/**
* @description Rewrites the scheme, hostname and port in the "Location" header in HTTP responses,
* as well as in the "Destination" header in HTTP requests. The rewriting reflects the different schemes,
* hostnames and ports used to access Membrane Service Proxy vs. the target HTTP server.
* hostnames and ports used to access Membrane vs. the target HTTP server.
* @topic 4. Interceptors/Features
*/
@MCElement(name="reverseProxying")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public void init(final Router router) throws Exception {
public Outcome handleRequest(Exchange exc) throws Exception {
if (WSDL.matcher(exc.getRequest().getUri()).find()) {
exc.setResponse(Response.ok().
header(SERVER, PRODUCT_NAME + " " + VERSION).
header(SERVER, PRODUCT_NAME).
header(CONTENT_TYPE, TEXT_XML).
body(getClass().getResourceAsStream("the.wsdl"), true).
build());
Expand Down Expand Up @@ -107,7 +107,7 @@ private Response createResponse(Throwable e, boolean useSoap11) {
String body = useSoap11 ? HttpUtil.getFaultSOAPBody(title, message) : HttpUtil.getFaultSOAP12Body(title,
message);
return Response.internalServerError().
header(SERVER, PRODUCT_NAME + " " + VERSION).
header(SERVER, PRODUCT_NAME).
header(HttpUtil.createHeaders(TEXT_XML_UTF8)).
body(body.getBytes(UTF_8)).
build();
Expand Down Expand Up @@ -272,7 +272,7 @@ private Response respondBank(String bezeichnung, String bic, String ort, String
"</ns1:ort><ns1:plz>" + escape(plz) +
"</ns1:plz></ns1:details></ns1:getBankResponse></soapenv:Body></soapenv:Envelope>";
return Response.ok().
header(SERVER, PRODUCT_NAME + " " + VERSION).
header(SERVER, PRODUCT_NAME).
header(CONTENT_TYPE, TEXT_XML_UTF8).
body(body.getBytes(UTF_8)).
build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,18 @@

public class OpenAPIProxyServiceKey extends ServiceProxyKey {

private static Logger log = LoggerFactory.getLogger(OpenAPIProxyServiceKey.class.getName());
private static final Logger log = LoggerFactory.getLogger(OpenAPIProxyServiceKey.class.getName());

ArrayList<String> basePaths = new ArrayList<>();

public OpenAPIProxyServiceKey(String ip, String host, int port) {
super(host, "*", null, port, ip);

// Add basePaths of OpenAPIPublisherInterceptor to accept them also
basePaths.add(OpenAPIPublisherInterceptor.PATH);
basePaths.add(OpenAPIPublisherInterceptor.PATH_UI);
basePaths.add(OpenAPIPublisherInterceptor.PATH); // new path
basePaths.add(OpenAPIPublisherInterceptor.PATH_UI); // "
basePaths.add("/api-doc"); // old to stay compatible
basePaths.add("/api-doc/ui"); // "
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public void run() {
};

private Exchange createResolveExchange(String url) throws URISyntaxException {
return new Builder().method(METHOD_GET).url(uriFactory, url).header(USER_AGENT, PRODUCT_NAME + " " + VERSION).buildExchange();
return new Builder().method(METHOD_GET).url(uriFactory, url).header(USER_AGENT, PRODUCT_NAME).buildExchange();
}

public HTTPSchemaResolver(@Nullable HttpClientFactory httpClientFactory) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,6 @@ public class HttpTransport extends Transport {

private static final Logger log = LoggerFactory.getLogger(HttpTransport.class.getName());

public static final String SOURCE_HOSTNAME = "com.predic8.membrane.transport.http.source.Hostname";
public static final String HEADER_HOST = "com.predic8.membrane.transport.http.header.Host";
public static final String SOURCE_IP = "com.predic8.membrane.transport.http.source.Ip";

private int socketTimeout = 30000;
private int forceSocketCloseOnHotDeployAfter = 30000;
private boolean tcpNoDelay = true;
Expand Down Expand Up @@ -271,7 +267,7 @@ public int getForceSocketCloseOnHotDeployAfter() {

/**
* @description When proxies.xml is changed and &lt;router hotDeploy="true"&gt;, the Spring Context is automatically refreshed,
* which restarts the {@link Router} object (=Membrane Service Proxy). Before the context refresh, all open socket connections
* which restarts the {@link Router} object (=Membrane API Gateway). Before the context refresh, all open socket connections
* have to be closed. Exchange objects which are still running might delay this process. Setting forceSocketCloseOnHotDeployAfter
* to a non-zero number of milliseconds forces connections to be closed after this time.
* @default 30000
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ public static Header createHeaders(String contentType, String... headers) {
synchronized (GMT_DATE_FORMAT) {
header.add("Date", GMT_DATE_FORMAT.format(new Date()));
}
header.add("Server", PRODUCT_NAME + " " + VERSION + ". See http://membrane-soa.org");
header.add("Server", PRODUCT_NAME);
header.add("Connection", Header.CLOSE);
for (int i = 0; i<headers.length; i+=2) {
header.add(headers[i],headers[i+1]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,18 @@
limitations under the License. */
package com.predic8.membrane.core.interceptor.rewrite;

import static com.predic8.membrane.core.interceptor.Outcome.CONTINUE;
import static org.junit.jupiter.api.Assertions.*;

import java.util.ArrayList;
import java.util.List;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import com.predic8.membrane.core.HttpRouter;
import com.predic8.membrane.core.exchange.Exchange;
import com.predic8.membrane.core.interceptor.DispatchingInterceptor;
import com.predic8.membrane.core.interceptor.Outcome;
import com.predic8.membrane.core.interceptor.rewrite.RewriteInterceptor.Mapping;
import com.predic8.membrane.core.rules.ServiceProxy;
import com.predic8.membrane.core.rules.ServiceProxyKey;
Expand All @@ -34,6 +33,7 @@ public class RewriteInterceptorTest {

private RewriteInterceptor rewriter;
private Exchange exc;

private DispatchingInterceptor di;
private ServiceProxy sp;

Expand All @@ -48,29 +48,40 @@ public void setUp() throws Exception {
sp.init(router);

exc = new Exchange(null);
exc.setRequest(MessageUtil.getGetRequest("/buy/banana/3"));


rewriter = new RewriteInterceptor();
List<Mapping> mappings = new ArrayList<>();
mappings.add( new Mapping("/buy/(.*)/(.*)", "/buy?item=$1&amount=$2", null));
mappings.add( new Mapping("^/store/(.*)", "/shop/v2/$1",null));
rewriter.setMappings(mappings);
rewriter.init(router);
}

@Test
public void testRewriteWithoutTarget() throws Exception {
assertEquals(Outcome.CONTINUE, di.handleRequest(exc));
assertEquals(Outcome.CONTINUE, rewriter.handleRequest(exc));
void testRewriteWithoutTarget() throws Exception {
exc.setRequest(MessageUtil.getGetRequest("/buy/banana/3"));
assertEquals(CONTINUE, di.handleRequest(exc));
assertEquals(CONTINUE, rewriter.handleRequest(exc));
assertEquals("/buy?item=banana&amount=3", exc.getDestinations().get(0));
}

@Test
public void testRewrite() throws Exception {
void testRewrite() throws Exception {
exc.setRequest(MessageUtil.getGetRequest("/buy/banana/3"));
exc.setRule(sp);

assertEquals(Outcome.CONTINUE, di.handleRequest(exc));
assertEquals(Outcome.CONTINUE, rewriter.handleRequest(exc));
assertEquals(CONTINUE, di.handleRequest(exc));
assertEquals(CONTINUE, rewriter.handleRequest(exc));
assertEquals("http://www.predic8.de:80/buy?item=banana&amount=3", exc.getDestinations().get(0));
}

@Test
void storeSample() throws Exception {
exc.setRequest(MessageUtil.getGetRequest("https://api.predic8.de/store/products/"));
assertEquals(CONTINUE, di.handleRequest(exc));
assertEquals(CONTINUE, rewriter.handleRequest(exc));
assertEquals("https://api.predic8.de/shop/v2/products/", exc.getDestinations().get(0));
}

}
Loading

0 comments on commit 3e20594

Please sign in to comment.