Components Reference

Overview

Complete reference of all available GoCamel components. Components provide connectivity to various systems and services.

Core Components

Direct

In-memory synchronous routing between routes in the same context.

// Consumer: receives from direct endpoint
// Producer: sends to direct endpoint
builder.From("direct:start").To("direct:process")

Endpoints are identified by name only β€” query parameters are ignored for identity, so direct:start and direct:start?x=1 resolve to the same endpoint. Only one consumer per endpoint is allowed.


Timer

Simple periodic triggering.

builder.From("timer:tick?period=5s")
OptionTypeDefaultDescription
periodDuration1sPeriod between triggers
repeatCountint0Number of repetitions (0=infinite)
fixedRateboolfalseFixed-rate vs fixed-delay mode

File Transfer Components

File

Local file system operations.

// Consumer (read)
builder.From("file://input?delete=true")

// Producer (write)
builder.To("file://output")
OptionTypeDefaultDescription
deleteboolfalseDelete after processing
noopboolfalseDo not move/delete file
includestring""Include file pattern
excludestring""Exclude file pattern
preMovestring""Move file before processing
movestring""Move file after processing
moveFailedstring""Move file on failure
readLockstringchangedRead lock strategy (none, changed, rename, markerFile)
readLockTimeoutDuration10sTimeout waiting to acquire read lock
readLockCheckIntervalDuration100msInterval between read lock checks
readLockMinLengthint640Minimum file size in bytes
readLockMinAgeDuration0Minimum file age
fileExiststringOverrideBehavior if destination file exists (Override, Append, Fail, Ignore)

Headers

Set on Consumer Exchanges
  • CamelFileName: The relative file name
  • CamelFilePath: The full path of the file
  • CamelFileLength: The file size in bytes
  • CamelFileLastModified: Last modification timestamp (time.Time)
Consumed by Producer
  • CamelFileName: Overrides destination file name when the producer URI points to a directory. Must be a relative path: empty names, absolute paths, Windows volume names, and .. components that escape the endpoint directory are rejected.

The consumer skips symbolic links and refuses files larger than 32 MiB (DefaultMaxBodySize).

Read lock

GoCamel provides multiple read lock strategies to ensure files are fully written and exclusive before processing:

  • readLock=changed: The consumer samples file size and modification time over readLockCheckInterval and reads once two consecutive samples match within readLockTimeout.
  • readLock=rename: Renames the file to an exclusive temporary name (.camelExclusiveReadLock) during processing.
  • readLock=markerFile: Creates a .camelLock marker file while processing and deletes it upon completion.
  • readLock=none: Disables read lock verification.
Prefer an atomic handoff

The changed read lock is a heuristic: a writer that stalls for longer than the sampling interval mid-write can still be observed as stable. For a guaranteed handoff, have the producer write to a temporary name and rename it into the watched directory β€” rename is atomic.


FTP / FTPS

File transfer via FTP protocol.

// Consumer
builder.From("ftp://host:21/incoming?username=admin&readLock=changed")

// Producer
builder.To("ftp://host:21/outgoing?binary=true")

Environment Variables:

  • FTP_USERNAME - Username
  • FTP_PASSWORD - Password
OptionTypeDefaultDescription
usernamestring""FTP username
passwordstring""FTP password
binarybooltrueBinary transfer mode
passiveModebooltrueUse passive mode
maxMessageSizeint0Max bytes a polled file may hold (0 = unlimited)
readLockstringnoneRead lock strategy (none, changed, rename, markerFile)
readLockTimeoutDuration10sTimeout waiting to acquire read lock
readLockCheckIntervalDuration1sInterval between read lock checks
readLockMinLengthint640Minimum file size in bytes
readLockMinAgeDuration0Minimum file age

With fileExist=Append, the producer downloads the existing remote file and uploads the concatenation. A partial download fails the send instead of silently re-uploading truncated content.

When the URI path is a directory, CamelFileName is joined with JoinRemotePath: absolute names and directory traversal are rejected.


SFTP

Secure file transfer via SSH.

builder.From("sftp://host:22/data?username=scott&readLock=changed&readLockTimeout=15s")

Authentication Methods:

  • Password: via password parameter or SFTP_PASSWORD env var
  • Key-based: via privateKeyFile parameter or SFTP_PRIVATE_KEY_FILE
OptionTypeDefaultDescription
usernamestring""SSH username
passwordstring""SSH password
privateKeyFilestring""Path to private key
privateKeyPassphrasestring""Private key passphrase
maxMessageSizeint0Max bytes a polled file may hold (0 = unlimited)
readLockstringnoneRead lock strategy (none, changed, rename, markerFile)
readLockTimeoutDuration10sTimeout waiting to acquire read lock
readLockCheckIntervalDuration1sInterval between read lock checks
readLockMinLengthint640Minimum file size in bytes
readLockMinAgeDuration0Minimum file age

As with FTP, fileExist=Append concatenates onto the existing remote file and aborts the send if reading it fails partway. CamelFileName is confined the same way as FTP (JoinRemotePath).


SMB

Windows/Samba share access.

builder.From("smb://server/share/folder?username=user&readLock=changed")
OptionTypeDefaultDescription
usernamestring""Domain username
passwordstring""Domain password
sharestringrequiredShare name
maxMessageSizeint0Max bytes a polled file may hold (0 = unlimited)
readLockstringnoneRead lock strategy (none, changed, rename, markerFile)
readLockTimeoutDuration10sTimeout waiting to acquire read lock
readLockCheckIntervalDuration1sInterval between read lock checks
readLockMinLengthint640Minimum file size in bytes
readLockMinAgeDuration0Minimum file age

The same fileExist=Append semantics as FTP/SFTP apply. CamelFileName is confined with JoinRemotePath (absolute names and .. are rejected; the producer does not use filepath.Join, which would discard the share path when the header is absolute).


Network Components

HTTP

HTTP server and client support.

// Consumer (HTTP server) β€” plaintext listen only
builder.From("http://localhost:8080/api")

// Producer (HTTP client)
builder.To("http://example.com/webhook")

The https scheme is producer-only. From("https://...") fails when creating the consumer: the listener is plaintext HTTP. Terminate TLS in front of an http:// consumer (reverse proxy, HTTPComponent.SetMiddleware, or similar).

Headers set on the consumer

HeaderSource
CamelHttpMethodRequest method (GET, POST, …)
CamelHttpPathRequest URL path
CamelHttpQueryRaw query string
CamelHttpUrlurl.URL.String() of the request

The producer sends POST unless CamelHttpMethod is set on the exchange (a From(http).To(http) proxy therefore forwards the inbound method).

Inbound request headers are also copied onto the exchange (see response headers below).

Authentication, TLS, rate limiting (consumer middleware)

The HTTP consumer ships with no authentication. Expose it to an untrusted network only behind a middleware that enforces the security model you need (token check, mTLS, OAuth, IP allowlist, rate limit, …). Install the middleware on the HTTPComponent before the route starts:

http := gocamel.NewHTTPComponent()
http.SetMiddleware(func(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        if r.Header.Get("Authorization") != "Bearer "+os.Getenv("API_TOKEN") {
            http.Error(w, "unauthorized", http.StatusUnauthorized)
            return
        }
        next.ServeHTTP(w, r)
    })
})
ctx.AddComponent("http", http)

The middleware wraps every handler installed by an http:// consumer in this context.

Outbound header sanitisation

Both the HTTP producer (To) and the consumer response path reject header names and values containing \r or \n (CRLF) to prevent HTTP response splitting (CWE-113). An exchange that tries to set such a header gets an error back from Send().

Response headers

The response body is taken from Out (or In when no Out was set, per Camel InOut semantics). []byte and string bodies are written as-is; any other non-nil body is written using its %v string representation.

Because the consumer copies every inbound request header onto the exchange, a route that does not set Out would answer with the request’s own headers. Two filters prevent that:

  • Unchanged inbound headers are not echoed. A header that comes back identical to the one received is dropped, so Cookie and Authorization are never reflected to the client. A header the route sets or modifies is always sent.
  • Hop-by-hop and framing headers are never emitted (Connection, Keep-Alive, Transfer-Encoding, Content-Length, Host, …). Echoing the request’s Content-Length corrupted the response framing.

The same hop-by-hop filter applies to the producer, so a From(http://...) β†’ To(http://...) bridge does not forward the inbound Content-Length or Host to the upstream.

The producer forwards every other inbound header by default, including Cookie and Authorization β€” the normal behaviour for a generic HTTP client that calls an authenticated upstream. In a proxy/bridge scenario where that would leak a downstream client’s credentials to a third-party upstream, strip them explicitly:

http := gocamel.NewHTTPComponent()
http.SetSkipAuthorizationHeaders(true)

When enabled, Authorization and Cookie are dropped from every outbound request produced by this component.

Response status

A route sets the status code with the CamelHttpResponseCode header on the response message (the legacy Status-Code header is still honoured). Values outside 100–599 are ignored:

builder.From("http://localhost:8080/api").
    ProcessFunc(func(e *gocamel.Exchange) error {
        e.GetOut().SetHeader(gocamel.CamelHttpResponseCode, 201)
        e.GetOut().SetHeader("Content-Type", "application/json")
        e.GetOut().SetBody(`{"created":true}`)
        return nil
    })

Producer error handling

An upstream response with status β‰₯ 300 is an error (the Apache Camel default). The error wraps gocamel.ErrHTTPStatus, and the response body and headers are still published on Out so the route can inspect them:

if errors.Is(err, gocamel.ErrHTTPStatus) {
    code, _ := exchange.GetOut().GetHeader(gocamel.CamelHttpResponseCode)
    // code is an int; the body holds the upstream error payload
}

To treat every response as a success and branch on the status yourself:

http := gocamel.NewHTTPComponent()
http.SetThrowExceptionOnFailure(false)

The producer also sets CamelHttpResponseCode (int) and CamelHttpResponseText (e.g. "500 Internal Server Error") on Out.

Hardening

  • The embedded server sets a 10-second ReadHeaderTimeout (slow header attacks), a 60-second ReadTimeout (slow body attacks) and a 60-second IdleTimeout (idle keep-alive connections).

  • Request and response bodies are read through a size limit β€” DefaultMaxBodySize (32 MiB) β€” so a single oversized payload cannot exhaust process memory (CWE-400). An oversized request is answered with 413 Request Entity Too Large. Adjust or disable it per component:

    http := gocamel.NewHTTPComponent()
    http.SetMaxBodySize(256 << 20) // 256 MiB; <= 0 disables the limit
  • Route errors are not returned to the client: the handler answers with a generic 500 internal server error and logs the detail, which may carry SQL text, file paths or driver messages.

Shutdown

The consumer goroutine is tracked by an internal WaitGroup and Stop() waits for http.Server.Shutdown to complete (bounded by a 30-second internal deadline) before returning. Stop() is idempotent.


Net (TCP/UDP)

Raw TCP and UDP sockets, built on the standard library β€” the Go equivalent of Apache Camel’s netty/mina components. The consumer listens and feeds inbound messages into the route; the producer dials and sends the message body.

// Consumer (server): request-reply over TCP
builder.From("net:tcp://localhost:9090")

// Consumer (server): fire-and-forget UDP
builder.From("net:udp://localhost:9090?sync=false")

// Producer (client)
builder.To("net:tcp://localhost:9090")
OptionTypeDefaultDescription
syncbooltrueRequest-reply: the consumer writes the route’s response back to the peer; the producer waits for a reply
textlinebooltrueNewline-delimited messages (TCP only). false = one message per read
bufferSizeint8192Maximum message/datagram size in bytes
timeoutint30000Producer dial/reply timeout in ms (0 = none)
keepAliveboolfalseTCP keepalive on connections
readTimeoutint60000Consumer read deadline in ms (0 = none)

URI forms β€” both net:tcp://host:port and net:tcp:host:port are accepted; the same applies to udp. An omitted host defaults to localhost. Port 0 asks the OS for an ephemeral port: read the actual bound address from NetConsumer.Address().

Framing. TCP is a byte stream, so the component needs a message boundary. With textline=true (default) each newline-terminated line is one message (the trailing \r\n or \n is stripped). With textline=false each read is one message. UDP datagrams need no framing: each datagram is one message.

// Request-reply echo server
builder.From("net:tcp://localhost:9090").
    ProcessFunc(func(e *gocamel.Exchange) error {
        body, _ := e.GetIn().GetBody().([]byte)
        e.GetOut().SetBody([]byte("echo: " + string(body)))
        return nil
    })

Headers. The consumer sets CamelNetRemoteAddress and CamelNetLocalAddress (host:port) on the In message.

Hardening

  • Message reads are bounded by bufferSize. A textline message longer than the limit is a protocol error: the connection is dropped rather than buffering unbounded data (CWE-400). UDP datagrams larger than the limit are truncated.
  • The producer’s reply read in sync mode is bounded by bufferSize and by the timeout read deadline, so a silent peer cannot hang the route forever.
  • The consumer sets a readTimeout (default 60 s) on each connection so a slowloris-style client cannot pin a goroutine open indefinitely; set it to 0 to disable.
  • Panics in route processors are contained (ProcessSafely): a misbehaving route fails its exchange, never the consumer.

Messaging Components

Telegram

Telegram Bot API integration for receiving and sending messages.

// Required: Set TELEGRAM_AUTHORIZATIONTOKEN env variable
ctx.AddComponent("telegram", gocamel.NewTelegramComponent())

// Consumer (webhook/polling mode)
builder.From("telegram:bots").Log("${body}")

// Producer (send messages)
builder.To("telegram:bots")

Environment Variables:

  • TELEGRAM_AUTHORIZATIONTOKEN - Bot API token
OptionTypeDefaultDescription
authorizationTokenstringenv varBot API token

NATS

Asynchronous event-driven messaging with NATS. High performance publisher and subscriber with Go NATS client.

ctx.AddComponent("nats", gocamel.NewNATSComponent())

// Consumer: reactive asynchronous subscription
builder.From("nats://orders?servers=nats://localhost:4222").
    ProcessFunc(func(e *gocamel.Exchange) error {
        // NATS payload is received as a byte slice
        payload := e.GetIn().GetBody().([]byte)
        fmt.Printf("Received order: %s\n", string(payload))
        return nil
    })

// Producer: publish to subject
builder.To("nats://orders?servers=nats://localhost:4222")

// Dynamically override subject in header
exchange.In.SetHeader(gocamel.CamelNATSSubject, "urgent-orders")
Warning

When writing URIs, always use double slashes (e.g. nats://orders) instead of nats:orders, otherwise url.Parse treats it as an Opaque URI, which contaminates the subject string with query parameters.

OptionTypeDefaultDescription
serversstringnats://127.0.0.1:4222NATS server addresses (comma-separated)
subjectstringparsed from pathNATS subject to subscribe/publish to

Exchange Headers:

  • CamelNATSSubject - Subject of the received message or target subject for publishing.

Kafka

High-throughput distributed event streaming with Apache Kafka via segmentio/kafka-go (pure Go).

import "gitlab.com/tranchida/gocamel/components/kafka"

ctx.AddComponent("kafka", kafka.NewKafkaComponent())

// Consumer with consumer group
builder.From("kafka:orders?brokers=localhost:9092&groupId=billing-service").
    Log("Received message: ${body}")

// Producer with dynamic partition key (requires allowHeaderOverride=true)
builder.From("direct:publish").
    SetHeader("CamelKafkaPartitionKey", "key-123").
    To("kafka:orders?brokers=localhost:9092&allowHeaderOverride=true")
OptionTypeDefaultDescription
brokersstringlocalhost:9092Comma-separated list of Kafka broker addresses
groupIdstring""Kafka consumer group ID
partitionint-1Target partition (when not using consumer group)
clientIdstring""Client identifier
allowHeaderOverrideboolfalseAllow CamelKafkaTopic, CamelKafkaPartitionKey and CamelKafkaKey to override the URI when producing
forwardHeadersstring""Comma-separated allowlist of exchange headers forwarded as Kafka record headers; when set, ONLY those headers are propagated

Headers:

  • CamelKafkaTopic - Overrides (with allowHeaderOverride=true) or reads the target topic.
  • CamelKafkaPartitionKey / CamelKafkaKey - Partition key for Kafka partitioning (honored with allowHeaderOverride=true).
  • CamelKafkaPartition - Partition index.
  • CamelKafkaOffset - Message offset.
  • CamelKafkaTimestamp - Message timestamp.

⚠️ Security: the topic and key configured in the URI are trusted configuration. Header overrides are ignored unless the endpoint opts in with allowHeaderOverride=true. Enable it only where headers cannot be influenced by untrusted input.

Outbound exchange headers are filtered before they reach the broker: Authorization, Cookie, Proxy-Authorization, Set-Cookie and WWW-Authenticate (case-insensitive) are never forwarded, so a producer sitting downstream of the HTTP consumer does not leak client credentials. Set forwardHeaders for an explicit allowlist when you want stricter control.

When a groupId is configured, each successfully processed message is committed to the consumer group. A failed commit is logged (with topic/partition/offset) rather than silently swallowed: the message will be redelivered after a rebalance or restart, and the log line is the only signal of that duplicated processing.


gRPC

High-performance RPC client and server integration powered by google.golang.org/grpc.

import "gitlab.com/tranchida/gocamel/components/grpc"

ctx.AddComponent("grpc", grpc.NewGRPCComponent())

// Server Consumer: routes RPC calls through GoCamel
builder.From("grpc://0.0.0.0:50051/helloworld.Greeter/SayHello").
    SetBody("Hello from GoCamel gRPC Server")

// Client Producer: invokes remote RPC methods
builder.From("direct:invoke").
    To("grpc://localhost:50051/helloworld.Greeter/SayHello?insecure=true")
OptionTypeDefaultDescription
servicestringparsed from pathFull gRPC service name
methodstringparsed from pathMethod name to call or expose
insecurebooltrueUse plaintext transport without TLS; when false, TLS 1.2+ is used with the system CA pool
caCertstring""Path to a PEM CA certificate trusted for server verification when insecure=false (e.g. self-signed server)
forwardHeadersstring""Comma-separated allowlist of exchange headers forwarded as outgoing RPC metadata; when set, ONLY those headers are propagated

Headers:

  • CamelGrpcMethod - Method name invoked.
  • CamelGrpcStatusCode - gRPC status code (e.g. 0 for OK).
  • CamelGrpcStatusDescription - gRPC client status description message.

⚠️ Security: outbound exchange headers are filtered before they are sent as RPC metadata: Authorization, Cookie, Proxy-Authorization, Set-Cookie and WWW-Authenticate (case-insensitive) are never forwarded, so a producer sitting downstream of the HTTP consumer does not leak client credentials. Set forwardHeaders for an explicit allowlist when you want stricter control.


Redis

Send commands (SET, GET, DEL, PUBLISH) or subscribe to Redis Pub/Sub channels.

ctx.AddComponent("redis", gocamel.NewRedisComponent())

// Consumer: Subscribe to Pub/Sub channel
builder.From("redis://localhost:6379?subscribe=true&channel=mychannel").
    Log("Received Pub/Sub message: ${body}")

// Producer: Execute commands
builder.To("redis://localhost:6379?command=SET&key=mykey")

Supported Commands:

  • SET: Saves the exchange body as the value of key.
  • GET: Retrieves the value of key and writes it to Out.Body.
  • DEL: Deletes key and writes the number of affected keys to Out.Body.
  • PUBLISH: Publishes the exchange body to the specified channel/key.

Exchange Headers (Override URI parameters):

  • CamelRedisCommand - The Redis command to execute (e.g. "GET").
  • CamelRedisKey - The target Redis key.
  • CamelRedisChannel - Target Pub/Sub channel for publish or source channel for subscribe.
OptionTypeDefaultDescription
commandstringSETRedis command for producer
keystring""Redis key to operate on
channelstring""Redis Pub/Sub channel
subscribeboolfalseIf true, acts as a Pub/Sub consumer

Redis Idempotent Repository

The Redis Idempotent Repository provides a distributed implementation of the IdempotentRepository interface, allowing multiple GoCamel instances in a cluster to coordinate and avoid processing duplicate messages.

import (
    "time"
    "github.com/redis/go-redis/v9"
)

rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})
// Key prefix "idempotent:" with 24-hour expiration TTL
repo := gocamel.NewRedisIdempotentRepository(rdb, "idempotent:", 24*time.Hour)

builder.From("direct:start").
    IdempotentConsumer("${header.MessageId}", repo).
    To("direct:process")

Go Channel

A native, ultra-fast intra-process integration component utilizing native Go channels. It enables decoupling route segments asynchronously inside the same process.

ctx.AddComponent("chan", gocamel.NewChanComponent())

// Consumer: processes exchanges asynchronously from channel
builder.From("chan:orders?bufferSize=500").
    To("direct:process-order")

// Producer: writes a copy of the exchange to the channel asynchronously
builder.To("chan:orders")
OptionTypeDefaultDescription
bufferSizeint100Capacity of the internal buffered channel

Notes:

  • Endpoints are cached by channel name: every producer and consumer using the same name shares one endpoint, and only one consumer per channel is allowed (a second From("chan:orders") fails at startup).
  • URI options are applied when the endpoint is first created; later references with different options log a warning and reuse the existing endpoint.

AI Components

OpenAI

OpenAI API integration for ChatGPT/GPT-4. Any OpenAI-compatible endpoint is supported via the baseURL option (OpenRouter, Groq, Together, Mistral, vLLM, LM Studio, Ollama’s OpenAI compatibility layer, …).

ctx.AddComponent("openai", gocamel.NewOpenAIComponent())

// Producer only - send chat completion request
endpoint, _ := ctx.CreateEndpoint("openai:chat?model=gpt-4")
producer, _ := endpoint.CreateProducer()

exchange := gocamel.NewExchange(context.Background())
exchange.GetIn().SetBody("Hello, how are you?")
producer.Send(exchange)

fmt.Println(exchange.GetOut().GetBody()) // AI response

Use a custom OpenAI-compatible provider:

// OpenRouter example: route to openai/gpt-4o via OpenRouter's gateway
endpoint, _ := ctx.CreateEndpoint(
    "openai:chat?model=openai/gpt-4o" +
        "&baseURL=https://openrouter.ai/api/v1" +
        "&apiKey=$OPENROUTER_API_KEY")

Environment Variables:

  • OPENAI_AUTHORIZATIONTOKEN or OPENAI_API_KEY - API key
OptionTypeDefaultDescription
modelstringgpt-3.5-turboModel to use
authorizationTokenstringenv varAPI key (alias: apiKey)
baseURLstringhttps://api.openai.com/v1Custom OpenAI-compatible base URL (OpenRouter, Groq, …)

The SDK HTTP client timeout is 60 seconds. Bound long-running calls further with exchange.Context.

Anthropic

Native integration with the Anthropic Messages API (Claude). Unlike the OpenAI component, this is a dedicated connector for Claude’s native API shape β€” separate system parameter, content blocks, prompt caching headers, and stop reasons.

ctx.AddComponent("anthropic", gocamel.NewAnthropicComponent())

// Producer only - send a Messages request
endpoint, _ := ctx.CreateEndpoint(
    "anthropic:messages?model=claude-sonnet-4-5" +
        "&apiKey=$ANTHROPIC_API_KEY" +
        "&maxTokens=1024" +
        "&system=You are a concise assistant")
producer, _ := endpoint.CreateProducer()

exchange := gocamel.NewExchange(context.Background())
exchange.GetIn().SetBody("Explain EIP in one sentence.")
producer.Send(exchange)

fmt.Println(exchange.GetOut().GetBody()) // Claude response

Environment Variables:

  • ANTHROPIC_API_KEY - API key (recommended over embedding it in the URI)
OptionTypeDefaultDescription
apiKeystringenv varAPI key (alias: authorizationToken). Masked by RedactURI.
modelstringrequiredModel name, e.g. claude-sonnet-4-5
maxTokensint1024Maximum tokens to generate
systemstring""System prompt
temperaturefloatunsetSampling temperature (0.0-1.0)
baseURLstringAnthropic APIOverride API base URL (proxies, gateways). Must be http(s).

The SDK HTTP client timeout is 60 seconds.

Per-message override headers (In message):

HeaderTypeDescription
AnthropicSystemstringOverrides the URI system
AnthropicModelstringOverrides the URI model
AnthropicMaxTokensstringOverrides the URI maxTokens
AnthropicTemperaturestringOverrides the URI temperature

Out headers (set on the response):

HeaderTypeDescription
AnthropicUsageInputTokensint64Input tokens billed
AnthropicUsageOutputTokensint64Output tokens billed
AnthropicStopReasonstringend_turn, max_tokens, …
AnthropicModelstringModel that produced the response

Ollama

Native integration with a local Ollama server via its Go client (github.com/ollama/ollama/api). Three modes are selected by the URI path:

  • ollama:chat (default) β€” multi-turn chat API (/api/chat)
  • ollama:generate β€” one-shot generation (/api/generate)
  • ollama:embed β€” embeddings (/api/embed)
ctx.AddComponent("ollama", gocamel.NewOllamaComponent())

// Chat with a local model
endpoint, _ := ctx.CreateEndpoint(
    "ollama:chat?model=llama3.1&host=http://localhost:11434")
producer, _ := endpoint.CreateProducer()

exchange := gocamel.NewExchange(context.Background())
exchange.GetIn().SetBody("Summarize EIP in one sentence.")
producer.Send(exchange)

fmt.Println(exchange.GetOut().GetBody()) // Local model response

Generate embeddings locally:

endpoint, _ := ctx.CreateEndpoint(
    "ollama:embed?model=nomic-embed-text&host=http://localhost:11434")
// exchange.GetOut().GetBody() returns []float32

Environment Variables:

  • OLLAMA_HOST - default host when the host URI option is omitted
OptionTypeDefaultDescription
modelstringrequired (chat/generate)Model name
hoststringhttp://localhost:11434Ollama server base URL (must be http(s))
systemstring""System prompt (generate mode only)
keepAlivedurationunsetModel retention in memory (e.g. 5m, 30s)
thinkstringunsetReasoning effort: true/false/low/medium/high/max
formatstringunsetStructured output format (e.g. json)

Per-message override headers (In message):

HeaderTypeDescription
OllamaModelstringOverrides the URI model
OllamaSystemstringOverrides the URI system (chat/generate)

Out headers (set on the response):

HeaderTypeDescription (chat/generate)
OllamaModelstringModel that produced the response
OllamaDoneReasonstringstop, length, …
OllamaTotalDurationint64Total duration (ns)
OllamaPromptEvalCountintInput tokens evaluated
OllamaEvalCountintOutput tokens generated

The Ollama component does not expose model lifecycle operations (Pull/List/Delete). Use the ollama CLI or HTTP API directly for model management; the GoCamel producer is scoped to inference.


Scheduling Components

Cron

Advanced scheduling with cron expressions or simple intervals.

ctx.AddComponent("cron", gocamel.NewCronComponent())

// Cron trigger (6 fields, including seconds)
builder.From("cron://group/job?cron=0+*+*+*+*+*")

// Simple interval trigger
builder.From("cron://poller?trigger.repeatInterval=5000")

Cron Expression Format (6 fields):

second minute hour day month dayOfWeek
0 * * * * *  # Every minute
0 */5 * * * * # Every 5 minutes
cron=0 0 12 * * *  # Every day at noon
OptionTypeDefaultDescription
cronstring""6-field cron expression
trigger.repeatIntervalint""Interval in ms (simple trigger)
trigger.repeatCountint-1Max repetitions
triggerStartDelayint500Initial delay in ms
statefulboolfalsePrevent concurrent execution

Exchange Headers:

  • fireTime - Trigger execution time
  • nextFireTime - Next scheduled time
  • triggerName - Trigger identifier

On Stop(), a job whose triggerStartDelay has not elapsed yet is never registered on the shared scheduler: the stop request wins the race with the delayed registration, so no orphan job is left firing forever.


Mail Components

SMTP/SMTPS (Send)

Send emails via SMTP.

builder.To("smtps://smtp.gmail.com:465?to=recipient@example.com&subject=Hello")
OptionTypeDefaultDescription
usernamestring""SMTP username
passwordstring""SMTP password
tostring""Recipient(s)
subjectstring""Email subject
contentTypestring"text/plain"MIME type

IMAP/IMAPS (Receive)

Receive emails via IMAP with IDLE support.

builder.From("imaps://imap.gmail.com:993?folderName=INBOX&idle=true")
OptionTypeDefaultDescription
usernamestring""IMAP username
passwordstring""IMAP password
folderNamestring"INBOX"Folder to poll
unseenbooltrueOnly unread messages
idleboolfalseUse IMAP IDLE mode
deleteboolfalseDelete after processing
fetchSizeint-1Messages per poll
pollDelayint60000Poll interval (ms)
maxMessageSizeint0Max message size in bytes (0 = unlimited)

POP3/POP3S (Receive)

Receive emails via POP3.

builder.From("pop3s://pop.gmail.com:995?username=user&password=pass")

The POP3 consumer honours the same maxMessageSize option as IMAP (default 0 = unlimited) to bound the size of a downloaded message.

With disconnect=false (default), the POP3 connection is kept between polls, like the IMAP consumer. Set disconnect=true to re-authenticate for each poll (useful with servers that drop idle connections).


Database Components

SQL

SQL query execution via database/sql.

import (
    "database/sql"
    _ "modernc.org/sqlite"
)

db, _ := sql.Open("sqlite", "./app.db")

sqlComp := gocamel.NewSQLComponent()
sqlComp.RegisterDataSource("appdb", db)
ctx.AddComponent("sql", sqlComp)

// SELECT -> Out.Body = []map[string]any
builder.From("direct:list").
    To("sql://appdb?query=SELECT+id,name+FROM+users").
    Log("${body}")

// SELECT single row -> Out.Body = map[string]any
builder.From("direct:one").
    SetHeader(gocamel.SqlParameters, []any{42}).
    To("sql://appdb?query=SELECT+*+FROM+users+WHERE+id=?&outputType=SelectOne")

// INSERT/UPDATE/DELETE -> Out.Body = affected rows (int64)
builder.From("direct:insert").
    SetHeader(gocamel.SqlParameters, []any{"alice", "alice@example.com"}).
    To("sql://appdb?query=INSERT+INTO+users(name,email)+VALUES(?,?)")

URI Format:

sql://<datasourceName>?query=<SQL>
sql://logical?dataSourceRef=<datasourceName>&query=<SQL>
OptionTypeDefaultDescription
querystringrequiredSQL query string
dataSourceRefstringhost pathDatasource name
outputTypestringSelectListSelectList or SelectOne
batchboolfalseBatch execution mode
transactedboolfalseWrap in transaction
allowHeaderOverrideboolfalseAllow CamelSqlQuery to replace the statement

Query Parameters:

Provide via CamelSqlParameters header or body as []any.

The query is trusted configuration

The statement is never interpolated with Exchange data β€” substituting ${header.X} into the SQL string would defeat parameterised queries and enable SQL injection. Always bind dynamic values through CamelSqlParameters (positional ? placeholders) or a []any body.

The CamelSqlQuery header replaces the statement wholesale, so since v0.2 it is ignored unless the endpoint opts in with allowHeaderOverride=true. Enable it only where headers cannot be influenced by untrusted input: any component that maps external metadata onto headers would otherwise hand a caller full control of the statement.

// Statement fixed by configuration (default, recommended)
builder.To("sql://appdb?query=SELECT+*+FROM+users+WHERE+id=?")

// Statement supplied per message β€” only with trusted headers
builder.To("sql://appdb?allowHeaderOverride=true&query=SELECT+1")

Output Headers:

  • CamelSqlRowCount - Rows returned/affected
  • CamelSqlColumnNames - Column names (SELECT)

Result Body:

CaseOut.Body Type
SELECT + SelectList[]map[string]any
SELECT + SelectOnemap[string]any or nil
INSERT/UPDATE/DELETEint64 (affected rows)

Statement classification:

Whether a statement is run as a query (result set) or an update (affected rows) is decided from its leading keyword, ignoring leading comments and parentheses. SELECT, WITH (CTE), VALUES, TABLE, SHOW, EXPLAIN, DESCRIBE and PRAGMA return rows, as does any statement carrying a RETURNING clause:

WITH recent AS (SELECT * FROM orders WHERE ts > ?)
SELECT id, total FROM recent          -- result set
INSERT INTO users(name) VALUES (?) RETURNING id   -- result set

SQL-Stored

Stored procedure execution with IN, OUT, and INOUT parameter support.

import (
    "database/sql"
    _ "modernc.org/sqlite"
)

db, _ := sql.Open("mysql", "user:pass@/mydb")

sqlStored := gocamel.NewSQLStoredComponent()
sqlStored.RegisterDataSource("mydb", db)
ctx.AddComponent("sql-stored", sqlStored)

// Simple call with IN parameters
builder.From("direct:call").
    SetBody([]gocamel.StoredProcedureParam{
        {Name: "userId", Direction: gocamel.ParamDirectionIn, Value: 42},
    }).
    To("sql-stored://mydb?procedure=GET_USER_BY_ID").
    Log("${body}")

URI Format:

sql-stored://datasourceName?procedure=NAME
sql-stored://logical?dataSourceRef=dsName&procedure=NAME
OptionTypeDefaultDescription
procedurestringrequiredStored procedure name
dataSourceRefstringhost pathDatasource name
outputTypestringSelectListSelectList or SelectOne
transactedboolfalseExecute in transaction
noopboolfalseTest mode (no execution)
allowHeaderOverrideboolfalseAllow CamelSqlStoredProcedureName to replace the name
Procedure name is a trusted identifier

The procedure name is spliced into the CALL statement and is never interpolated with exchange data. The CamelSqlStoredProcedureName header is ignored unless the endpoint opts in with allowHeaderOverride=true; when it is enabled, the header value is validated against a strict identifier pattern ([A-Za-z_][A-Za-z0-9_.]*). Only enable the override where headers cannot be influenced by untrusted input.

Parameter Directions:

DirectionDescription
ParamDirectionInInput only
ParamDirectionOutOutput only
ParamDirectionInOutBoth input and output

Example:

params := []gocamel.StoredProcedureParam{
    {Name: "inParam", Direction: gocamel.ParamDirectionIn, Value: "input"},
    {Name: "outParam", Direction: gocamel.ParamDirectionOut},
    {Name: "inOutParam", Direction: gocamel.ParamDirectionInOut, Value: 123},
}

MongoDB

MongoDB integration for CRUD operations. Producer-only.

URI Format

mongodb://connectionName?database=mydb&collection=mycoll&operation=find

Options

OptionTypeRequiredDescription
databasestringYesDatabase name
collectionstringYesCollection name
operationstringYesOperation: find, findOne, insert, insertOne, save, update, remove, count
connectionRefstringNoRegistered connection reference
allowDeleteAllboolNoAllow remove with an empty filter (default: false)
allowUpdateAllboolNoAllow update with an empty filter, i.e. mass-update the whole collection (default: false)
allowHeaderOverrideboolNoAllow CamelMongoDbDatabase, CamelMongoDbCollection, CamelMongoDbOperation and CamelMongoDbCriteria to override the URI configuration (default: false)

For safety, remove rejects nil and empty filters. Set allowDeleteAll=true explicitly only when deleting the entire collection is intentional. Likewise, update rejects a missing or empty filter (nil, {}, empty bson.M / bson.D, empty string): any of those would mass-update every document. Set allowUpdateAll=true explicitly only when that is intentional.

⚠️ Security: the database, collection and operation configured in the URI are trusted configuration. The CamelMongoDbDatabase, CamelMongoDbCollection, CamelMongoDbOperation and CamelMongoDbCriteria headers are ignored unless the endpoint opts in with allowHeaderOverride=true. Enable it only where headers cannot be influenced by untrusted input.

Input Headers

HeaderModeDescription
CamelMongoDbDatabaseR/WDatabase name
CamelMongoDbCollectionR/WCollection name
CamelMongoDbOperationR/WOperation to execute
CamelMongoDbCriteriaWriteFilter/criteria (map[string]any or JSON)
CamelMongoDbLimitWriteResult limit
CamelMongoDbSkipWriteSkip N documents
CamelMongoDbSortWriteSort order (json: {“field”: 1})

Output Headers

HeaderDescription
CamelMongoDbResultTotalTotal documents found/affected
CamelMongoDbOidObjectID of inserted document

Example

import (
    "context"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

// Create component
mongoComp := gocamel.NewMongoDBComponent()

// Connect
client, _ := mongo.Connect(context.Background(), options.Client().ApplyURI("mongodb://localhost:27017"))
conn := gocamel.CreateMongoDBConnection(client, "mongodb://localhost:27017", "mydb")
mongoComp.RegisterConnection("myconn", conn)

builder.WithComponent("mongodb", mongoComp)

// Insert
builder.From("timer:tick?period=5s").
    SetBody(map[string]any{"name": "test", "value": 123}).
    To("mongodb://myconn?database=mydb&collection=items&operation=insert")

// Query with filter
builder.From("direct:search").
    SetHeader(gocamel.CamelMongoDbCriteria, map[string]any{"status": "active"}).
    SetHeader(gocamel.CamelMongoDbLimit, 10).
    To("mongodb://myconn?database=mydb&collection=items&operation=find")

Transformation Components

XSLT

XML transformation using XSL stylesheets.

builder.To("xslt:file://transform.xsl")
OptionTypeDefaultDescription
transformerFactorystring""Custom transformer class

XSD

XML Schema validation.

builder.To("xsd:file://schema.xsd")
OptionTypeDefaultDescription
schemaResourcestringrequiredXSD schema path

Template

Go template processing (inspired by Apache Camel Velocity).

// Basic template
builder.To("template:templates/email.tmpl")

// With caching
builder.To("template:templates/item.tmpl?contentCache=true")

// Dynamic template from header
builder.To("template:default.tmpl?allowTemplateFromHeader=true")
OptionTypeDefaultDescription
contentCacheboolfalseCache template in memory
allowTemplateFromHeaderboolfalseAllow CamelTemplatePath header override
startDelimiterstring{{Template start delimiter
endDelimiterstring}}Template end delimiter

Template Variables:

{{.Body}}              # Message body
{{.Headers.name}}      # Header value
{{.Exchange.ID}}         # Exchange ID
{{.Exchange.Created}}    # Creation timestamp

Template Functions:

{{.Body | upper}}
{{.Body | lower}}
{{.Body | trim}}
{{now | formatDate "2006-01-02 15:04:05"}}
{{"hello" | contains "ell"}}

Execution Components

Exec

Execute system commands.

builder.To("exec:ls -la")
OptionTypeDefaultDescription
argsstring""Command arguments
workingDirstring""Working directory
timeoutint0Timeout in ms (0=no timeout)
outFilestring""Read the result from this file instead of stdout
useStderrOnEmptyboolfalseUse stderr as body when stdout is empty
allowHeaderOverrideboolfalseAllow CamelExecCommand* headers to override the URI

Per-message overrides (opt-in):

When allowHeaderOverride=true, these headers override the URI settings for a single message:

HeaderOverrides
CamelExecCommandExecutableExecutable
CamelExecCommandArgsArguments
CamelExecCommandWorkingDirWorking directory
CamelExecCommandTimeoutTimeout (ms)
Security

Header overrides let a message choose which binary is executed. They are disabled by default; only enable allowHeaderOverride=true when message headers cannot be influenced by untrusted input (e.g. headers coming from an HTTP or mail consumer).

The executable and the working directory are validated against shell metacharacters and path traversal. A header-supplied executable must additionally be a bare command name (no path) β€” it is resolved via PATH, never an absolute path β€” so an attacker cannot smuggle /bin/sh plus arbitrary arguments. Arguments are not validated: commands run through execve without a shell, so |, &, $, < and > carry no special meaning and reach the child process verbatim β€” which is the intent. Rejecting them blocked legitimate values (a JSON document, a password containing $, a relative path) without preventing any injection. NUL and other control characters are still rejected.

Output:

  • Out.Body = command stdout (also mirrored on In for backward compatibility, so an InOut route sees the command output)
  • Header CamelExecExitValue = exit code
  • Headers CamelExecStdout / CamelExecStderr = raw command output

Component Configuration

Authentication

Credentials can be provided via environment variables:

// FTP with env var
builder.From("ftp://host?username=${env:FTP_USER}")

// Or parameter  
builder.From("ftp://host?username=admin&password=${env:FTP_PASS}")

Common Options

Many components share common polling options:

// File polling
builder.From("file://data?delay=10s&delete=true")

// FTP polling
builder.From("ftp://host/incoming?delay=30s&include=*.xml")
OptionTypeDefaultDescription
delayDurationvariesPoll interval
includestring""Include pattern
excludestring""Exclude pattern

Component Summary Table

ComponentCategoryConsumerProducerURI Pattern
DirectCoreβœ…βœ…direct:name
TimerCoreβœ…βŒtimer:name
FileFileβœ…βœ…file://path
FTPFileβœ…βœ…ftp://host/path
SFTPFileβœ…βœ…sftp://host/path
SMBFileβœ…βœ…smb://host/share
HTTPNetworkβœ…βœ…http://host:port/path
NetNetworkβœ…βœ…net:tcp://host:port
KafkaMessagingβœ…βœ…kafka:topic
gRPCNetworkβœ…βœ…grpc://host:port/Service/Method
TelegramMessagingβœ…βœ…telegram:bots
OpenAIAIβŒβœ…openai:chat
AnthropicAIβŒβœ…anthropic:messages
OllamaAIβŒβœ…ollama:chat/generate/embed
CronSchedulingβœ…βŒcron://group/job
SMTPMailβŒβœ…smtp://host:port
IMAPMailβœ…βŒimap://host:port
POP3Mailβœ…βŒpop3://host:port
SQLDatabaseβŒβœ…sql://datasource
SQL-StoredDatabaseβŒβœ…sql-stored://datasource
MongoDBDatabaseβŒβœ…mongodb:connectionName
XSLTTransformβŒβœ…xslt:template
XSDTransformβŒβœ…xsd:schema
TemplateTransformβŒβœ…template:template
ExecExecutionβŒβœ…exec:command
NATSMessagingβœ…βœ…nats://subject
RedisMessagingβœ…βœ…redis://host:port
Go ChannelCoreβœ…βœ…chan:channelName

Delivery and lifecycle details

  • Kafka: the resolved topic is set on each message, so configured and header-overridden topics work together. Failed processing is retried with a fresh exchange before fetching the next record. Commit failures retry the commit without repeating successful processing. Retries wait 100 ms and stop on cancellation. A permanent failure blocks this consumer until handled by the route or stopped; this preserves cumulative offset safety.
  • FTP: each producer leases its connection exclusively for the complete transfer. Concurrent sends and Stop cannot interleave FTP commands; a sender waiting for the lease can cancel.
  • MongoDB: save preserves the input document’s _id, including when replacement fails, so retry keeps targeting the same document.
  • Mail: IMAP IDLE reacts to mailbox notifications by ending IDLE, searching for messages and re-entering IDLE. Existing messages are searched before the first IDLE.
  • Cron: Stop prevents new executions and waits for active jobs before returning, including when pausing a job.
  • Redis: clients are shared by active producers and consumers and closed when the last owner stops. Stopping one producer leaves other owners usable; stopped route consumers release their registration so the route can restart.
  • File: a URI ending in / denotes a directory even before it exists; CamelFileName selects the file inside it.
  • Net: the configured timeout bounds established writes as well as reply reads. Cancelling the exchange closes its connection and interrupts either operation.
  • Prometheus: repeated Metrics() or MetricsWith(registry) calls reuse compatible registered collectors, allowing separate interceptors on multiple routes. Incompatible collector definitions still fail registration.