Downloads

Download Example CFHTTP REST Client Template for ColdFusion

Introduction

This downloadable resource is a production-ready ColdFusion/CFML template that wraps the cfhttp tag into a reusable REST client. It helps you create a reliable HTTP layer for calling REST APIs with consistent JSON handling, headers, Authentication, Error handling, timeouts, retries, logging hooks, and pagination helpers. If you’ve ever duplicated cfhttp blocks across .cfm pages or CFCs, this drop-in client centralizes those patterns so your app becomes easier to maintain, test, and scale.


What You’ll Get

  • Source code (CFML)
    • HttpClient.cfc: a low-level cfhttp wrapper with timeouts, retries, SSL options, proxy, and basic logging hooks.
    • RestClient.cfc: a higher-level REST convenience layer (GET/POST/PUT/PATCH/DELETE), JSON encode/decode, common headers, and pagination helpers.
  • Example Configuration
    • config/example.env.json: base URL, default headers, Authentication (Bearer token, Basic Auth, optional mTLS), timeouts, retry policy.
  • Quick-start examples
    • examples/demo-get.cfm: GET with query parameters and JSON response parsing.
    • examples/demo-post.cfm: POST JSON body and Error handling pattern.
    • examples/demo-upload.cfm: multipart/form-data File upload with cfhttpparam.
    • examples/demo-oauth.cfm: Client Credentials OAuth 2.0 token retrieval + use.
  • Documentation
    • README-setup.txt: short installation and Configuration guide.
    • CHANGELOG.txt: version notes and upgrade hints.
  • Optional utilities
    • utils/Json.cfm: safe JSON deserialize helper.
    • utils/RateLimit.cfc: simple wait logic based on response headers.

Each file is standalone and can be copied into existing projects. All examples use plain CFML so you can paste and run.


Overview

This template provides a consistent way to call REST APIs from Adobe ColdFusion or Lucee using cfhttp. It supports JSON serialization/deserialization, configurable timeouts, retry logic with backoff, SSL/TLS verification, proxies, multipart file uploads, and multiple authentication schemes. The goal is to replace one-off cfhttp snippets with a single, well-tested, configurable, and documented client.

See also  Download the ColdFusion Request Lifecycle Poster (PDF)

Key Features:

  • HTTP methods: GET, POST, PUT, PATCH, DELETE
  • JSON bodies and responses handled automatically
  • Headers and query parameters merged from defaults and overrides
  • Retry on transient errors (5xx) with exponential backoff
  • Timeouts and SSL verification flags
  • Basic Auth, Bearer tokens, and optional client certificate (mTLS)
  • Pagination and rate-limiting helpers
  • Lightweight logging hooks and structured error information

Supported Environments

  • Adobe ColdFusion: 2018, 2021, 2023
  • Lucee CFML: 5.3.x, 5.4.x

Minimum requirements:

  • CFML engine with cfhttp, cfhttpparam, and JSON functions (serializeJSON, deserializeJSON)
  • TLS 1.2+ recommended for secure endpoints

How to Install and Configure

Step 1: Add the files

  • Create a folder in your webroot or a CF mapping, for example:
    • /cfhttp-rest-client/
      • src/cfc/HttpClient.cfc
      • src/cfc/RestClient.cfc
      • config/example.env.json
      • examples/*.cfm
  • Optionally define a mapping in Application.cfc:
    • this.mappings[“/cfrest”] = expandPath(“/cfhttp-rest-client/src/cfc”);

Step 2: Configure the client

Copy config/example.env.json to config/app.env.json and adjust:

  • baseUrl: your API base URL (e.g., https://api.example.com)
  • defaultHeaders: Accept, User-Agent, etc.
  • auth:
    • bearerToken: “your-token” OR
    • basic: { “username”: “user”, “password”: “pass” }
    • clientCert, clientCertPassword for mTLS (optional)
  • timeout: seconds to wait for the request
  • retries, retryDelay: transient failure retry policy
  • verifySSL: true/false
  • proxy: host, port if required

Example (JSON):
{
“baseUrl”: “https://api.example.com“,
“defaultHeaders”: {
“Accept”: “application/json”,
“User-Agent”: “CFREST/1.0”
},
“auth”: {
“bearerToken”: “”
},
“timeout”: 30,
“retries”: 2,
“retryDelay”: 250,
“verifySSL”: true,
“proxy”: {}
}

Tip: Store secrets outside Version control and inject them at deploy time (environment variables or CF Admin passwords).

Step 3: Instantiate the client

Example Application.cfc or a service CFC:

  • Using mapping:
    • rest = new cfrest.RestClient(configPath=ExpandPath(“/cfhttp-rest-client/config/app.env.json”));
  • Or using relative path:
    • rest = new path.to.RestClient(configPath=ExpandPath(“./config/app.env.json”));

Step 4: Make a request

GET with query params:
response = rest.get(path=”/v1/users”, params={ active=true, limit=25 });
if (response.status >= 200 && response.status < 300) {
writeOutput( response.json ); // struct/array if JSON
} else {
writeDump(response); // includes status, headers, raw body
}


Usage Examples

GET with query parameters

response = rest.get(
path=”/v1/posts”,
params={ userId=1 },
headers={ “X-Trace-Id”=”abc-123” }
);

POST JSON body

payload = { title=”Hello”, body=”World”, userId=1 };
response = rest.post(path=”/v1/posts”, body=payload);
if (response.status == 201) {
writeOutput(“Created ID: ” & response.json.id);
}

File upload (multipart/form-data)

files = [
{ field=”file”, path=ExpandPath(“./data/report.pdf”), contentType=”application/pdf” }
];
response = rest.upload(path=”/v1/uploads”, files=files, fields={ folder=”docs” });

OAuth 2.0 Client Credentials

tokenResp = rest.oauthClientCredentials(
tokenUrl=”https://auth.example.com/oauth/token“,
clientId=variables.secrets.clientId,
clientSecret=variables.secrets.clientSecret,
scope=”read write”
);
rest.setBearerToken(tokenResp.json.access_token);
data = rest.get(“/v1/secure/resource”);

See also  Download the ColdFusion Disaster Recovery Checklist (PDF)

How to Use the Included CFCs

RestClient.cfc methods (high-level)

  • get(path, params={}, headers={})
  • post(path, body={}, headers={}, params={}, contentType=”application/json”)
  • put(path, body={}, headers={}, params={}, contentType=”application/json”)
  • patch(path, body={}, headers={}, params={}, contentType=”application/json”)
  • delete(path, params={}, headers={})
  • upload(path, files=[…], fields={}, headers={})
  • setBearerToken(token), setBasicAuth(username, password)
  • oauthClientCredentials(tokenUrl, clientId, clientSecret, scope=””)
  • withHeaders(struct) returns a cloned client with merged headers

Returns a response struct:

  • status: numeric HTTP code
  • headers: struct of response headers
  • body: raw response (string/binary)
  • json: parsed JSON (struct/array), if applicable
  • timings: optional timing info
  • request: echo of normalized request (useful for Debugging)

Error handling pattern

try {
resp = rest.get(“/v1/items”);
if (resp.status >= 400) {
// handle API errors
}
} catch (any e) {
// handle network/engine errors
}


Best practices

  • Prefer JSON: Use application/json for request/response; let the client serialize/deserialize automatically.
  • Timeouts and retries: Set a realistic timeout and enable retries for 5xx scenarios with backoff to improve resilience.
  • Validate TLS: Keep verifySSL=true; provide trusted certs and ensure TLS 1.2+.
  • Secure secrets: Put tokens and passwords in environment variables or CF Admin Password Manager; never hard-code secrets.
  • Do not log secrets: Mask Authorization headers and tokens in your logs.
  • Rate limiting: Respect Retry-After headers; use the included RateLimit helper to pause between calls.
  • Pagination: Use the pagination helpers (link headers or next-cursor patterns) to avoid partial datasets.
  • Idempotency: For POST operations that might be retried, include an Idempotency-Key header if the API supports it.

Benefits and Use Cases

  • Fast Onboarding: New services can call REST APIs with minimal boilerplate; no need to remember cfhttpparam quirks each time.
  • Fewer bugs: Centralized error handling, consistent headers, standardized JSON parsing, and predictable retry behavior reduce edge-case bugs.
  • Security posture: Built-in SSL verification, maskable logs, and support for Bearer, Basic, and mTLS give you a safer baseline.
  • Performance consistency: Timeouts, keep-alive headers (via defaults), and retry backoff help stabilize API integrations under load.
  • Cross-engine CFML: Works on Adobe ColdFusion and Lucee with no engine-specific code required.
  • Ideal for:

Troubleshooting and Tips

  • Unexpected HTML body: The server might return an HTML error page; check response.headers[“Content-Type”] and resp.body to log or parse safely.
  • SSL handshake errors: Verify TLS 1.2+, update cacerts, or set verifySSL=false only for local testing.
  • Timeouts: Increase timeout in config; test network reachability; avoid low readTimeout values for large downloads.
  • Proxy issues: Configure proxy host/port and credentials if your network requires a corporate proxy.
  • JSON parse errors: Some APIs return text/plain JSON; the client attempts to detect JSON but you can force deserialization manually if needed.
See also  Download ColdFusion Health Check & Status Endpoint Example

Security Considerations

  • Mask sensitive headers: Ensure logs never include Authorization, cookies, or PII.
  • mTLS for critical APIs: Supply clientCert and clientCertPassword for mutual TLS when required by the API.
  • Principle of least privilege: OAuth scopes should be minimal; rotate tokens regularly.
  • Input validation: Sanitize file paths and field values before uploads; avoid path traversal.
  • CSRF is not relevant for server-to-server calls, but ensure your outbound calls do not propagate unvalidated user input.

Key Takeaways

  • This template turns cfhttp into a clean, reusable REST client with JSON handling, retries, timeouts, auth, and uploads.
  • Works on both Adobe ColdFusion and Lucee with minimal configuration.
  • Encourages secure defaults (SSL verification, token masking) and operational resilience (backoff retries, rate limit helpers).
  • Saves time by eliminating repetitive cfhttp blocks and enforcing a consistent API-calling pattern across your codebase.

FAQ

How do I switch between Basic Auth and Bearer tokens?

Use rest.setBasicAuth(username, password) for Basic, or rest.setBearerToken(token) for Bearer. You can also set these in config/app.env.json under auth. The Authorization header is added automatically.

Does this work on both Adobe ColdFusion and Lucee?

Yes. The client is written in portable CFML and tested on Adobe ColdFusion 2018/2021/2023 and Lucee 5.3/5.4. If your engine has custom SSL/proxy requirements, adjust the config accordingly.

How do I upload files with multipart/form-data?

Call rest.upload(path=”/v1/upload”, files=[{field=”file”, path=ExpandPath(“./a.pdf”), contentType=”application/pdf”}], fields={…}). The client handles cfhttpparam(type=”file”) under the hood.

Can I handle paginated APIs?

Yes. Use the pagination helpers or inspect response.headers for Link or X-Next-Page. Call rest.get repeatedly using the returned next cursor or page token until no more results remain.

How do I set a corporate proxy or custom timeouts?

Provide proxy.host and proxy.port in config. Set timeout at the root of the config. You can also override per-request via method arguments if needed, or instantiate a second client instance with different settings.

About the author

Aaron Longnion

Aaron Longnion

Hey there! I'm Aaron Longnion — an Internet technologist, web software engineer, and ColdFusion expert with more than 24 years of experience. Over the years, I've had the privilege of working with some of the most exciting and fast-growing companies out there, including lynda.com, HomeAway, landsofamerica.com (CoStar Group), and Adobe.com.

I'm a full-stack developer at heart, but what really drives me is designing and building internet architectures that are highly scalable, cost-effective, and fault-tolerant — solutions built to handle rapid growth and stay ahead of the curve.