Skip to content

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

KeyValue
Git Remotehttps://git.tlab.co.id/tarantula/service/api-connect.git
Active Branchmain
bash
git clone https://git.tlab.co.id/tarantula/service/api-connect.git
cd api-connect

Tech Stack

LayerTechnology
RuntimeNode.js 18
FrameworkExpress 4
HTTP Clientaxios
API Docsswagger-ui-express + swagger-jsdoc (inline JSDoc)
Dev Runnernodemon
ContainerizationDocker (node:18)

Folder Structure

api-connect/
├── index.js             # Express app + all proxy & auth logic
├── package.json
├── Dockerfile
├── Dockerfile.stag
└── docker-compose.dev.yml

Environment 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

MethodPathDescription
GET/healthService health check
POST/proxyForward a request to an external API
GET/api-docsSwagger UI (OpenAPI 3.0)

POST /proxy

Forwards an HTTP request to an external API with automatic authentication handling.

Request body:

json
{
  "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.js currently writes the URL, method, body/params, and the full headers (including the resolved Authorization header for Basic/Bearer/JWT) to console.log for every proxied request. Since auth is 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

json
{
  "auth": {
    "type": "basic",
    "user": "username",
    "password": "password"
  }
}

Header sent to the target API: Authorization: Basic <base64(user:password)>

Bearer Token

json
{
  "auth": {
    "type": "bearer",
    "token": "your_access_token"
  }
}

Header sent to the target API: Authorization: Bearer <token>

JWT (Auto-login)

json
{
  "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

MethodBody sent asAutomatic Content-Type
GET, HEADQuery params (params)
POST, PUT, PATCH, DELETERequest 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

bash
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

bash
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

json
{ "status": "OK", "timestamp": "2026-06-30T10:00:00.000Z" }

Build & Run

bash
# 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