• Stars
    star
    459
  • Rank 95,377 (Top 2 %)
  • Language
    Java
  • License
    Apache License 2.0
  • Created about 12 years ago
  • Updated about 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

API gateway for REST, OpenAPI, GraphQL and SOAP written in Java.

Membrane Logo

API Gateway

GitHub release Hex.pm

API Gateway for REST, WebSockets and legacy Web Services written in Java. Featuring:

OpenAPI:

API Security:

Legacy Web Services:

Other:

Getting Started

Java

  1. Make sure Java 17 or newer is installed.

  2. Download the binary and unzip it.

  3. Run service-proxy.sh or service-proxy.bat in a terminal

  4. Open http://localhost:2000 to access https://api.predic8.de over the gateway.

  5. Change the configuration in conf/proxies.xml

Docker

$ docker run -p 2000:2000 predic8/membrane

Browse to http://localhost:2000 or use curl:

curl http://localhost:2000

This should yield the same response as calling https://api.predic8.de does.

More about setting up Membrane for Docker.

Next Steps

See the snippets below, run the samples, follow the REST or SOAP tutorial or have a look at the documentation.

Configuration

Try the following snippets by copying them into the conf/proxies.xml file.

Using OpenAPI for Configuration & Validation

Configures APIs from OpenAPI and validates messages against the definitions. Needed data like backend addresses are taken from the OpenAPI description. See the example

This configuration is all you need to deploy from OpenAPI:

<api port="2000">
    <openapi location="fruitshop-api.yml" validateRequests="yes"/>
</api>

A list of deployed APIs is available at http://localhost:2000/api-docs

List of OpenAPI Deployments

Click on the API title to get the Swagger UI.

Swagger UI

REST and HTTP APIs

Routing requests from port 2000 to api.predic8.de when the path starts with /shop/v2/.

<api port="2000">
    <path>/shop/v2/</path>
    <target url="https://api.predic8.de"/>
</api>

Call the API by opening http://localhost:2000/shop/v2/ in the browser.

Instrumentation

Open Telemetry

Using the openTelemetry plugin and the W3C propagation standard, we can integrate Membrane into OpenTelemetry traces. otel_example

Membrane together with a backend with database connection.

    <api port="2000">
        <openTelemetry sampleRate="1.0">
            <otlpExporter host="localhost" port="4317"/>
        </openTelemetry>
        <target host="localhost" port="3000"/>
    </api>

See the opentelemetry example

Message Transformation

Create JSON from Query Parameters

<api port="2000" method="GET">
    <request>
        <template contentType="application/json" pretty="yes">
            { "answer": ${params.answer} }
        </template>
    </request>
    <return statusCode="200"/>
</api>

Call this API with http://localhost:2000?answer=42 . Replace <return.../> with your <target url="backend-server"/>.

Transform JSON into TEXT, JSON or XML with Templates

Call the following APIs with this request:

curl -d '{"city":"Berlin"}' -H "Content-Type: application/json" "http://localhost:2000"

This template will transform the JSON input into plain text:

<api port="2000" method="POST">
    <request>
        <template contentType="text/plain">
            City: ${json.city}
        </template>
    </request>
    <return statusCode="200"/>
</api>

...into JSON:

<template contentType="application/json" pretty="true">
    {
    "destination": "${json.city}"
    }
</template>

...and into XML:

<template contentType="application/xml">
    <![CDATA[
    <places>
        <place>${json.city}</place>
    </places>
    ]]>
</template>

Transform XML into Text or JSON

Using the xpathExtractor you can extract values from XML request or response bodies and store it in properties. The properties are then available as variables in the template plugin.

<api port="2000">
    <request>
        <xpathExtractor>
            <property name="fn" xpath="person/@firstname"/>
        </xpathExtractor>
        <template>Buenas Noches, ${fn}sito!</template>
    </request>
    <return statusCode="200" contentType="text/plain"/>
</api>

See: message-transformation examples

Complex Transformations using Javascript or Groovy

Use the Javascript or Groovy plugin for more powerful yet simple transformations.

<api port="2000">
    <request>
        <javascript>
            ({ id:7, place: json.city })
        </javascript>
    </request>
    <return contentType="application/json"/>
</api>

Call the API with this curl command:

curl -d '{"city":"Berlin"}' -H "Content-Type: application/json" "http://localhost:2000"

Transformation with Computations

This script transforms the input and adds some calculations.

<api port="2000">
    <request>
        <javascript>

            function convertDate(d) {
            return d.getFullYear() + "-" + ("0"+(d.getMonth()+1)).slice(-2) + "-" + ("0"+d.getDate()).slice(-2);
            }

            ({
            id: json.id,
            date: convertDate(new Date(json.date)),
            client: json.customer,
            total: json.items.map(i => i.quantity * i.price).reduce((a,b) => a+b),
            positions: json.items.map(i => ({
            pieces: i.quantity,
            price: i.price,
            article: i.description
            }))
            })
        </javascript>
    </request>
    <return/>
</api>

See examples/javascript for a detailed explanation. The same transformation can also be realized with Groovy

Beautifier

You can beautify a JSON or XML using the <beautifier/> plugin.

<api port="2000">
    <template contentType="application/xml"><![CDATA[
        <foo><bar>baz</bar></foo>
    ]]></template>

    <beautifier/>

    <return statusCode="200"/>
</api>

Returns:

<foo>
    <bar>baz</bar>
</foo>

Branching and Conditionals

Conditionally modify response:

<api port="2000">
  <if test="header.contains('X-Demo')">
    <response>
      <groovy>
        exc.getResponse().setBodyContent("Example".getBytes())
      </groovy>
    </response>
  </if>
  <return/>
</api>

Check if certain scopes/roles are provided:

<api port="2000">
    <if test="hasScopes({'admin', 'webmaster'})" language="SpEL">
      <target url="https://localhost:2000/admin" />
    </if>
    <target host="localhost" port="1001" />
</api>

Writing Extensions with Groovy or Javascript

Dynamically manipulate and monitor messages with Groovy:

<api port="2000">
    <response>
        <groovy>
            header.add("X-Groovy", "Hello from Groovy!")
            println("Status: ${message.statusCode}")
            CONTINUE
        </groovy>
    </response>
    <target url="https://api.predic8.de"/>
</api>

Create a response with Javascript:

<api port="2000">
    <response>
        <javascript>
            var body = JSON.stringify({
            foo: 7,
            bar: 42
            });

            Response.ok(body).contentType("application/json").build();
        </javascript>
    </response>
    <return/> <!-- Do not forward, return immediately -->
</api>

Also try the Groovy and Javascript example.

Security

Membrane offers lots of security features to protect backend servers.

JSON Web Tokens

The API below only allows requests with valid tokens from Microsoft's Azure AD. You can also use the JWT validator for other identity providers.

<api port="8080">
    <jwtAuth expectedAud="api://2axxxx16-xxxx-xxxx-xxxx-faxxxxxxxxf0">
        <jwks jwksUris="https://login.microsoftonline.com/common/discovery/keys"/>
    </jwtAuth>
    <target url="https://your-backend"/>
</api>

OAuth2

Secure an API with OAuth2

Use OAuth2/OpenID to secure endpoints against Google, Azure AD, GitHub, Keycloak or Membrane authentication servers.

<api port="2001">
    <oauth2Resource>
        <membrane src="https://accounts.google.com"
                  clientId="INSERT_CLIENT_ID"
                  clientSecret="INSERT_CLIENT_SECRET"
                  scope="email profile"
                  subject="sub"/>
    </oauth2Resource>
    <groovy>
        // Get email from OAuth2 and forward it to the backend
        def oauth2 = exc.properties.oauth2
        header.setValue('X-EMAIL',oauth2.userinfo.email)
        CONTINUE
    </groovy>
    <target url="https://backend"/>
</api>

Try the tutorial OAuth2 with external OpenID Providers

Membrane as Authorization Server

Operate your own identity provider:

<api port="2000">
    <oauth2authserver location="logindialog" issuer="http://localhost:2000" consentFile="consentFile.json">
        <staticUserDataProvider>
            <user username="john" password="password" email="[email protected]"/>
        </staticUserDataProvider>
        <staticClientList>
            <client clientId="abc" clientSecret="def" callbackUrl="http://localhost:2001/oauth2callback"/>
        </staticClientList>
        <bearerToken/>
        <claims value="aud email iss sub username">
            <scope id="username" claims="username"/>
            <scope id="profile" claims="username email password"/>
        </claims>
    </oauth2authserver>
</api>

See the OAuth2 Authorization Server example.

Basic Authentication

<api port="2000">
    <basicAuthentication>
        <user name="bob" password="secret"/>
    </basicAuthentication>
    <target host="localhost" port="8080"/>
</api>

SSL/TLS

Route to SSL/TLS secured endpoints:

<api port="8080">
    <target url="https://api.predic8.de"/>
</api>

Secure endpoints with SSL/TLS:

<api port="443">
  <ssl>
    <keystore location="membrane.p12" password="secret" keyPassword="secret" />
    <truststore location="membrane.p12" password="secret" />
  </ssl>
  <target host="localhost" port="8080"  />
</api>

Rate Limiting

Limit the number of incoming requests:

<api port="2000">
    <rateLimiter requestLimit="3" requestLimitDuration="PT30S"/>
    <target host="localhost" port="8080"/>
</api>

Load balancing

Distribute workload to multiple backend nodes. See the example

<api port="8080">
    <balancer name="balancer">
        <clusters>
            <cluster name="Default">
                <node host="my.backend-1" port="4000"/>
                <node host="my.backend-2" port="4000"/>
                <node host="my.backend-3" port="4000"/>
            </cluster>
        </clusters>
    </balancer>
</api>

Rewrite URLs

<api port="2000">
    <rewriter>
        <map from="^/good-looking-path/(.*)" to="/backend-path/$1"/>
    </rewriter>
    <target host="my.backend.server"/>
</api>

Log HTTP

Log data about requests and responses to a file or database as CSV or JSON file.

<api port="2000">
    <log/> <!-- Logs to the console -->
    <statisticsCSV file="./log.csv"/> <!-- Logs fine-grained CSV -->
    <target url="https://api.predic8.de"/>
</api>

Websockets

Route and intercept WebSocket traffic:

<api port="2000">
    <webSocket url="http://my.websocket.server:1234">
        <wsLog/>
    </webSocket>
    <target port="8080" host="localhost"/>
</api>

See documentation

SOAP Web Services

Integrate legacy services.

API configuration from WSDL

SOAP proxies configure themselves by analysing WSDL:

<soapProxy wsdl="http://thomas-bayer.com/axis2/services/BLZService?wsdl"/>

Message Validation against WSDL and XSD

The validator checks SOAP messages against a WSDL document including referenced XSD schemas.

<soapProxy wsdl="http://thomas-bayer.com/axis2/services/BLZService?wsdl">
    <validator/>
</soapProxy>

See configuration reference for much more.

More Repositories

1

soa-model

Toolkit and Java API for WSDL, WADL and XML Schema.
Groovy
93
star
2

monitor

GUI for Service Proxy, that allows you to capture, analyze and manipulate HTTP and SOAP messages.
Java
26
star
3

servicemesh-demo

Begleitendes Material zum Youtube Video "Servicemesh: Istio".
Java
12
star
4

membrane-spring-boot-starter

A Spring Boot Starter for Membrane Service Proxy.
Java
10
star
5

api-management

API Management for Membrane Service Proxy
JavaScript
9
star
6

camel-introduction

Begleitmaterial zur Youtubeserie "Einfรผhrung Apache Camel"
JavaScript
7
star
7

kubernetes-client

Extension of the official Kubernetes Java client library.
Java
6
star
8

jenkins-git-tag-builder

Jenkins plugin which builds every tag pushed to a git repo
Java
6
star
9

jmediator

Mediator implementation for Java
Java
4
star
10

iot-remote-control

Python scripts to control cheap remotes using MQTT and Raspberry PI
Python
4
star
11

remote-control-iot-app

iOS app for controlling lights over cheap remotes
Swift
3
star
12

msa-catalogue

Microservices Workshop Catalogue Service
Java
3
star
13

client

Generic SOAP Client GUI
Java
3
star
14

msa-utils

Microservices Workshop Utilities und Skripte
Shell
3
star
15

msa-stock

Java
2
star
16

spring-boot-vertical-slice-architecture

Sample project for the Vertical Slice Architecture with Java and Spring Boot
Java
1
star
17

openapi-catalog

Membrane OpenAPI Catalog
Kotlin
1
star
18

spring-boot-security-jwt-sample

Java
1
star
19

msa-checkout

Java
1
star
20

library

A sample REST service using JAX-RS.
Java
1
star
21

xmlbeautifier

XML Pretty Printer for plain Text and HTML
Java
1
star