AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
네이티브 OpenAPI 지원, SOAP‑REST 변환, WSDL‑OpenAPI 생성, 깊은 XML 통합을 갖춘 현대적 경량 API 게이트웨이
Modern and lightweight API gateway with native OpenAPI support, SOAP-to-REST conversion, WSDL-to-OpenAPI generation, and deep XML integration.
개발 도구Java · ShellGitHub @membrane온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
API Gateway bridging modern and legacy APIs with WSDL-to-OpenAPI, SOAP-to-REST, XML, OAuth2, and GraphQL.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Open-source API gateway that speaks both REST and SOAP.
Deploy APIs directly from OpenAPI, secure them with OAuth2 and JWT, or turn legacy SOAP web services into JSON APIs, all with a few lines of YAML. Lightweight and easy to run as a single container or Java application. No database required.
docker run --rm -it -p 2000:2000 predic8/membrane
Explore the sample APIs in your browser:
Prefer Java instead of Docker? Follow the Java quickstart.
Create an apis.yaml file containing the following configuration:
api:
port: 2000
target:
url: https://apibin.io
Run a container with the apis.yaml file mounted:
Linux/macOS:
docker run --rm -p 2000:2000 -v "$(pwd)/apis.yaml:/opt/membrane/conf/apis.yaml" predic8/membrane
Windows PowerShell:
docker run --rm -p 2000:2000 -v "${PWD}/apis.yaml:/opt/membrane/conf/apis.yaml" predic8/membrane
Requests to http://localhost:2000 are now forwarded to https://apibin.io.
Deploy APIs from OpenAPI descriptions and use OpenAPI for message validation. Membrane supports OpenAPI 3.0, 3.1, and 3.2.
Expose existing SOAP web services as JSON APIs without changing the backend. Membrane’s wsdl2openapi generates OpenAPI descriptions from WSDL and uses it to convert between JSON and XML.
Use XPath and JSONPath to access message data for routing, filtering, and transformation. Templates and XSLT handle custom formats and more complex conversions.
Apply the same routing, transformation, and orchestration capabilities to legacy SOAP services and modern JSON APIs.
Validate messages against OpenAPI, JSON Schema, XSD, and WSDL to reject invalid requests before they reach your backend. Apply XML, JSON, and GraphQL protection to guard against malicious payloads.
Secure APIs with API keys, OAuth2, and JWT, and protect SOAP services with WS-Security, including XML signatures and encryption.
Combine calls to multiple APIs in a single flow. Process collections with loops and control execution with conditions.
Configure routing, security, and transformations with a few lines of YAML. Explore the examples below and the tutorials to get started.
For custom logic, use Groovy scripts or expressions with SpEL, JSONPath, and XPath. When you need deeper integration, write your own Java plugin. No need to learn Lua.
Membrane stays fast with security and validation enabled. In benchmarks on a 16-vCPU Azure VM, it achieved:
| Configuration | Requests/sec |
|---|---|
| Plain proxying | 216,000 |
| Basic Auth + rate limiting + TLS | 196,000 |
| OpenAPI validation of every request | 167,000 |
Membrane’s HTTP engine was built specifically for API gateway workloads. Its Java plugins run in the same process, keeping overhead low. This integrated architecture gives Membrane an edge over gateways built on general-purpose HTTP servers, helping it maintain high throughput even with demanding plugins enabled.
The distribution is approximately 55 MB, runs as a container or Java application, and requires no database.
See the benchmark setup and results, or run the tests yourself.
For a quick overview of what you can do with Membrane, the sections below provide a selection of short examples and configuration snippets.
OpenAPI is a native feature in Membrane. The gateway supports OpenAPI 3.0, 3.1, and 3.2, including the QUERY HTTP method.
Membrane can deploy an API directly from an OpenAPI description. It uses the defined paths, schemas, operations, and backend URLs to configure routing and, optionally, validate incoming requests and outgoing responses.
api:
port: 2000
openapi:
- location: openapi/fruitshop-v2-2-0.oas.yml
validateRequests: true
Membrane lets you explore APIs deployed from OpenAPI in a single overview page.
For documentation and testing, the gateway also hosts a Swagger UI for the deployed APIs.
See: OpenAPI tutorial
Integrate and modernize legacy SOAP web services.
Membrane can expose a SOAP web service described by WSDL as a REST API with an OpenAPI specification.
This configuration:
api:
port: 2000
flow:
- wsdl2openapi:
wsdl: mocks/partner.wsdl
operations:
getPartners:
method: GET
path: /partners
tag: Partner
getPartner:
method: GET
path: /partners/{id}
tag: Partner
createPartner:
method: POST
path: /partners
tag: Partner
updatePartner:
method: PUT
path: /partners/{id}
tag: Partner
deletePartner:
method: DELETE
path: /partners/{id}
tag: Partner
target:
url: http://localhost:3000/partner-service
turns this WSDL into an OpenAPI specification including JSON schemas derived from the WSDL's XSD schemas:
After deploying this configuration, clients can send JSON requests to the REST API. Membrane transforms them into SOAP requests for the backend Web Service and converts the XML responses back to JSON.
The conversion uses the XML Schema definitions from the WSDL to map data precisely between JSON and XML.
The easiest way to expose a SOAP Web Service as a REST API is to use the wsdl2openapi plugin described above.
For more control over the conversion, you can define the REST API manually and map individual REST endpoints to SOAP operations.
The following configuration accepts a request such as GET /cities/Nairobi, creates a SOAP request for the backend service, and transforms the SOAP response into JSON:
api:
port: 2000
method: GET
path:
uri: /cities/{city}
flow:
- request:
- soapBody:
src: |
<getCity xmlns="https://predic8.de/cities">
<name>${pathParam.city}</name>
</getCity>
- setHeader:
name: SOAPAction
value: https://predic8.de/cities/get
- response:
- template:
contentType: application/json
src: |
{
"country": ${xpath('//country')},
"population": ${xpath('//population')}
}
target:
# Change method to POST
method: POST
url: https://www.predic8.de/city-service
Note: Membrane automatically escapes expression values such as ${xpath(...)} for the specified content type.
See the SOAP to REST tutorial for more details.
Membrane can create a SOAP proxy directly from a WSDL:
soapProxy:
port: 2000
wsdl: https://www.predic8.de/city-service?wsdl
After startup, Membrane exposes:
The validator checks SOAP messages against a WSDL document including referenced XSD schemas.
soapProxy:
port: 2000
wsdl: https://www.predic8.de/city-service?wsdl
flow:
# Validates SOAP messages against the WSDL and XSDs
- validator: {}
Legacy SOAP services protected with Web Services Security (WS-Security) may require credentials and an XML Signature.
api:
port: 2000
flow:
- wsSecurity:
secure:
- usernameToken:
username: alice
password: secret
- signature:
references:
- by: BODY
- by: USERNAME_TOKEN
target:
url: http://localhost:2001
Membrane can create and validate WS-Security UsernameTokens and XML Signatures.
Membrane can act as a gateway for Large Language Models (LLMs) and Model Context Protocol (MCP) servers, providing centralized access control, usage policies, and API key management.
The mcpProtection plugin sits in front of an MCP server and controls which tools clients can discover and call.
api:
port: 2000
flow:
- mcpProtection:
tools:
- allow: getCustomers
- allow: getOrders
- deny: '.*'
target:
url: http://my-mcp-server
See the MCP protection tutorial.
The llmGateway plugin routes requests to LLM providers such as Anthropic Claude, OpenAI, and Google Gemini. It can centralize provider API keys and enforce policies for token usage and allowed models.
api:
port: 2000
flow:
- llmGateway:
claude: {}
apiKey: <<Replace with your API_KEY>>
policies:
maxOutputTokens: 100000
models:
- claude-opus-5-5
- claude-sonnet-5
simpleStore:
users:
- name: alice
apiKey: abc123
tokens: 2000000
- name: bob
apiKey: qwertz
tokens: 10000000
limitResetPeriod: 86400
target:
url: https://api.anthropic.com
Instead of handing the API key to every developer, keep it in the gateway and issue per-user keys. Membrane authenticates the user, enforces a per-user token budget, restricts the allowed models, and forwards the request using the shared provider key.
See: LLM key sharing tutorial.
Membrane provides flexible routing based on HTTP properties and custom expressions.
# Only GET to /products on port 2000
api:
port: 2000
method: GET
path: /products
flow:
- response:
- static:
src: Oui!
- return:
status: 200
There are many routing options:
| Option | Description |
|---|---|
port | Listening port |
method | HTTP method, e.g. GET, POST, QUERY |
path | Request path |
host | Hostname, e.g. api.predic8.de |
test | Custom expression, e.g. header['content-type'].startsWith('text/plain') |
See the API reference documentation.
Transform a POST request such as:
POST /products
Content-Type: application/json
{"limit": 100, "sort": "name"}
into a GET request like GET /products?limit=100&sort=name using a URI template with JSONPath expressions:
api:
port: 2000
target:
method: GET
url: https://api.predic8.de/shop/v2/products?sort=${$.sort}&limit=${$.limit}
language: jsonpath
Note: Membrane automatically escapes expression values such as ${$.sort} for the specified content type.
See the tutorial to transform from GET to POST.
Both converters use a heuristic mapping and do not require a JSON or XSD schema.
flow:
- xml2Json: {}
flow:
- json2Xml:
root: order
See transformation tutorials for other ways to transform between XML and JSON.
Templates can transform request and response bodies using data from the current message or the environment.
Membrane uses a Groovy-based template engine with dynamic constructs such as loops and conditionals. Its syntax is similar to template engines commonly used in web applications.
The example creates a JSON document containing the names and values of the request's HTTP headers.
- template:
contentType: application/json
pretty: true
src: |
{
<% header.eachWithIndex { e, i -> %>
<% if (i > 0) { %>,<% } %>
<%= e.key %>: <%= e.value %>
<% } %>
}
Templates can access message data using JSONPath, XPath, and Groovy.
Membrane can orchestrate calls to external APIs and process collections with loops and conditional flows.
The example iterates over a list of fruits and sends a POST request for each item:
api:
port: 2000
flow:
- for:
# Loops over a list of objects [{ "name": "Mango", "price": 1.23 }, ..]
in: $.fruits
language: jsonpath
flow:
- setBody:
# Serialize the current item to a JSON string
value: ${toJSON(it)}
# callout to an external API
- call:
method: POST
url: https://api.predic8.de/shop/v2/products
- log:
message: "Created product: ${it['name']}"
- return:
status: 200
Scripts can inspect and modify requests, responses, and extend gateway behavior. This makes it possible to implement custom API logic for use cases such as:
api:
port: 2000
flow:
- groovy:
src: |
println "I'm executed in the ${flow} flow"
println "HTTP Headers:\n${header}"
target:
url: https://api.predic8.de
You can write scripts in Groovy and JavaScript.
if-StatementA Membrane flow does not have to follow a fixed sequence. The if and choose plugins let you execute parts of a flow only when specific conditions are met. A common use case is error handling.
api:
port: 2000
flow:
- response:
- if:
test: statusCode >= 500
flow:
- static:
src: Failure!
target:
url: https://httpbin.org/status/500
Membrane provides security features for protecting APIs, services, and backend systems.
Incoming requests can be authenticated by validating an API key against keys stored in a file or database.
global:
- apiKey:
stores:
- simple:
- secret:
value: aed8bcc4-7c83-44d5-8789-21e4024ac873
- secret:
value: 08f121fa-3cda-49c6-90db-1f189ff80756
extractors:
- header: X-Api-Key
Membrane also supports:
See the API Key Tutorials
The API below only allows requests that present a valid JSON Web Token issued by Microsoft Azure Entra ID.
api:
port: 2000
flow:
- jwtAuth:
expectedAud: api://2axxxx16-xxxx-xxxx-xxxx-faxxxxxxxxf0
jwks:
jwksUris: https://login.microsoftonline.com/common/discovery/keys
target:
url: https://your-backend
See the JWT tutorials, including enforcing the scopes from an OpenAPI document.
Use OAuth2/OpenID to secure endpoints against Google, Azure Entra ID, GitHub, Keycloak or Membrane Authentication Servers.
api:
port: 2000
flow:
- oauth2Resource2:
membrane:
src: http://localhost:8000
clientId: abc
clientSecret: def
scope: openid profile
claims: username
claimsIdt: sub
- request:
# Forward the authenticated user’s email to the backend in an HTTP header.
- setHeader:
name: X-EMAIL
value: ${property['membrane.oauth2'].userinfo['email']}
target:
url: http://backend
Try the OAuth tutorial
The following example shows a minimal configuration for running Membrane as an OAuth 2.0 authorization server.
api:
port: 8000
flow:
- oauth2authserver:
issuer: http://localhost:8000
location: logindialog
consentFile: consentFile.json
staticUserDataProvider:
users:
- username: john
password: secret
email: [email protected]
staticClientList:
clients:
- clientId: abc
clientSecret: def
callbackUrl: http://localhost:2000/oauth2callback
bearerToken: {}
claims:
value: aud email iss sub username
scopes:
- id: username
claims: username
- id: profile
claims: username email
User accounts can be stored in a file, in an LDAP server or backed by a database.
This example enables TLS for connections from clients to the API Gateway:
api:
port: 443
ssl:
keystore:
location: keystore.p12
password: changeit
truststore:
location: keystore.p12
password: changeit
target:
url: http://backend
Membrane supports advanced TLS scenarios, including:
See the TLS/SSL tutorial
Membrane protects APIs from risks associated with XML, JSON, JSON-RPC and GraphQL payloads.
api:
port: 2000
flow:
- xmlProtection:
maxAttributeCount: 3
maxElementNameLength: 100
removeDTD: true
- return:
status: 200
See the XML protection, JSON protection, JSON-RPC protection, and GraphQL protection references.
Limit the number of incoming requests within a defined time period:
global:
- rateLimiter:
requestLimit: 1000
requestLimitDuration: PT1H
Distribute the workload across multiple API backend nodes.
api:
port: 8080
flow:
- balancer:
clusters:
- name: Default
nodes:
- host: my.backend-1
port: 4000
- host: my.backend-2
port: 4000
- host: my.backend-3
port: 4000
See the load balancing tutorial
Expose Membrane metrics for Prometheus:
api:
port: 2000
path:
uri: /metrics
flow:
- prometheus: {}
The collected metrics can be visualized in a Grafana dashboard:
Membrane supports integration with OpenTelemetry. This enables detailed tracing of requests across Membrane and backend services.
For working examples of Prometheus, Grafana and OpenTelemetry, see the operation tutorial.
To get support from our community, post your questions to our discussions page @GitHub.
If you find a bug, report it using GitHub Issues. Please provide a minimal example that reproduces the issue and the version of Membrane you are using.
See commercial support options and pricing.
Learn how API Gateways work through practical scenarios and real-world examples.
Download instantly. No registration required.
Meet other Membrane users online to discuss API gateway operation and architecture. Membrane developers answer questions and welcome your feedback and feature requests.