Technical — API Connect
RAGA's HTTP proxy service, built on Node.js + Express. Accepts API connection and endpoint configuration via the request body, handles authentication (Basic, Bearer, or JWT auto-login), then forwards the request to the external API and returns its response. Used by the Raga Engine (Text-to-API) in api-tarantula to call external APIs configured by the user without storing credentials on the server.
Note: this service is stateless — no API configuration is stored. All credentials and endpoint details are sent by the caller inside the request body every time.
Repository
| Key | Value |
|---|---|
| Git Remote | https://git.tlab.co.id/tarantula/service/api-connect.git |
| Active Branch | main |
git clone https://git.tlab.co.id/tarantula/service/api-connect.git
cd api-connectTech Stack
| Layer | Technology |
|---|---|
| Runtime | Node.js 18 |
| Framework | Express 4 |
| HTTP Client | axios |
| API Docs | swagger-ui-express + swagger-jsdoc (inline JSDoc) |
| Dev Runner | nodemon |
| Containerization | Docker (node:18) |
Folder Structure
api-connect/
├── index.js # Express app + all proxy & auth logic
├── package.json
├── Dockerfile
├── Dockerfile.stag
└── docker-compose.dev.ymlEnvironment Variables
This service does not use environment variables. All configuration (host, auth, endpoint) is sent per request by the caller inside the request body.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /health | Service health check |
POST | /proxy | Forward a request to an external API |
GET | /api-docs | Swagger UI (OpenAPI 3.0) |
POST /proxy
Forwards an HTTP request to an external API with automatic authentication handling.
Request body:
{
"connection": {
"host": "https://api.example.com",
"name": "Connection name (optional, for logging)",
"auth": { },
"endpoint": {
"path": "/v1/data",
"method": "get",
"params": [
{ "key": "search", "value": "query" }
],
"body": { }
},
"headers": {
"X-Custom-Header": "value"
}
}
}Response: The target API's response is passed through directly to the caller.
400 Response: If connection, host, or endpoint is missing from the body.
500 Response: If the proxy request fails or the JWT login step fails.
Operational note:
index.jscurrently writes the URL, method, body/params, and the full headers (including the resolvedAuthorizationheader for Basic/Bearer/JWT) toconsole.logfor every proxied request. Sinceauthis sent in full by the caller and never persisted, any external API credentials used through this service end up logged to the container's console as long as this log line is active — make sure logs aren't stored anywhere broadly accessible.
Authentication Modes (auth)
Basic Auth
{
"auth": {
"type": "basic",
"user": "username",
"password": "password"
}
}Header sent to the target API: Authorization: Basic <base64(user:password)>
Bearer Token
{
"auth": {
"type": "bearer",
"token": "your_access_token"
}
}Header sent to the target API: Authorization: Bearer <token>
JWT (Auto-login)
{
"auth": {
"type": "jwt",
"user": "username",
"password": "password",
"loginPath": "/auth/login"
}
}The service first does a POST {host}{loginPath} with { user, password }, extracts token from the response, then uses Bearer <token> for the main request.
Request Flow
Behavior per HTTP Method
| Method | Body sent as | Automatic Content-Type |
|---|---|---|
GET, HEAD | Query params (params) | — |
POST, PUT, PATCH, DELETE | Request body (data) | application/x-www-form-urlencoded |
If endpoint.body or connection.body is present, its value is used as the request body. Custom headers from connection.headers are always merged into every request.
Example Requests
GET with Basic Auth
curl -X POST http://localhost:3000/proxy \
-H "Content-Type: application/json" \
-d '{
"connection": {
"host": "https://api.example.com",
"auth": {
"type": "basic",
"user": "admin",
"password": "secret"
},
"endpoint": {
"path": "/v1/users",
"method": "get",
"params": [
{ "key": "page", "value": "1" }
]
}
}
}'POST with JWT Auto-login
curl -X POST http://localhost:3000/proxy \
-H "Content-Type: application/json" \
-d '{
"connection": {
"host": "https://api.internal.co.id",
"auth": {
"type": "jwt",
"user": "service_account",
"password": "pass123",
"loginPath": "/api/auth/login"
},
"endpoint": {
"path": "/api/v2/reports",
"method": "post",
"body": { "from": "2026-01-01", "to": "2026-06-30" }
}
}
}'GET /health
{ "status": "OK", "timestamp": "2026-06-30T10:00:00.000Z" }Build & Run
# Install dependencies
npm install
# Run development (nodemon)
npm start
# Run production (node directly)
npm run start_stag
# Docker Compose (dev)
docker compose -f docker-compose.dev.yml up --build
# Standalone Docker build & run
docker build -t api-connect .
docker run -p 3000:3000 api-connect