General
Conditional Requests at Runtime: Rendering Parts of a curl Command with XML `<if>`
paohaijiao DEV Community 周榜
5 views
HTTP requests are rarely static in production. A header should only be sent when a feature flag is on, verbose logging should appear only in debug sessions, and an endpoint variant should be selected by environment. JQuickCurl's XML mode solves this with conditional rendering: an <if test="..."> element whose enclosed curl text is included only when the expression evaluates to true — evaluated per request, at runtime.
This post shows:
How <if> composes with the XML catalog from Post 7.
Realistic conditions: headers, options, and body fragments.
A complete runnable demo with a toggled debug mode.
The Rule: Only What's True Gets Rendered
Inside a <curl> element you can wrap any curl fragment in <if test="expression">. If the expression holds, the fragment's text is spliced into the final command; otherwise it disappears as if never written.
<curl name="getUserByIdVariable" returnClass="com.example.model.User">
curl -X GET #{host} \
<if test="a == 1"> -H "Content-Type: application/json" </if>
</curl>
The expression reads values from the request context — which includes the @Param-annotated arguments you pass to the interface method (Post 7). Here, the extra header appears only when parameter a equals 1.
Practical Pattern 1: Toggle Debug Verbosity
Wrap the curl logging flag so that production traffic is silent while a debug flag on the interface adds -v:
<curls namespace="com.example.search.SearchApi">
<curl name="search" returnClass="java.lang.String">
curl -X GET 'https://api.example.com/search?q=#{keyword}&page=#{page}'
<if test="debug == true"> -v </if>
</curl>
</curls>
public interface SearchApi {
String search(@Param("keyword") String keyword,
@Param("page") int page,
@Param("debug") boolean debug);
}
Calling search("http", 1, true) adds -v to the command; calling it with false drops it. The same request shape, one conditional branch.
Practical Pattern 2: Conditional Header Injection
Environment-sensitive headers are a perfect <if> target. Inject a tracing header only when a traceId is actually present, and an API-key header only for the private environment:
<curl name="orders" returnClass="java.lang.String">
curl -X GET '#{host}/orders?status=#{status}'
<if test="traceId != null and traceId != ''"> -H "X-Trace-Id: #{traceId}" </if>
<if test="env == 'prd'"> -H "X-Env: prd" -H "Authorization: Bearer #{token}" </if>
</curl>
public interface OrderApi {
String orders(@Param("host") String host,
@Param("status") String status,
@Param("traceId") String traceId,
@Param("env") String env,
@Param("token") String token);
}
Same method, but the wire request differs with runtime state — no if/else in Java, no empty headers being sent.
Practical Pattern 3: Choose the Payload
Conditions can also select between body fragments. Sending a body only for methods that need one:
<curl name="report" returnClass="java.lang.String">
curl -X POST 'https://api.example.com/reports'
-H 'Content-Type: application/json'
-d '{"type":"#{kind}"}'
<if test="includeFilter == true"> ,"filter":{"min":#{min}} </if>
</curl>
When splicing JSON fragments, keep the result valid JSON after substitution. Several small <if> blocks are easier to reason about than one opaque mega-expression.
Runnable Demo
Put the catalog below on the classpath as search.xml and run the Java class.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE curls PUBLIC "-//PAOHAIJIAO//DTD API CURL 1.0//EN"
"classpath:paohaijiao/dtd/Jquick-curl.dtd">
<curls namespace="com.example.search.SearchApi">
<curl name="search" returnClass="java.lang.String">
curl -X GET 'https://httpbin.org/anything/search?q=#{q}'
<if test="verbose == true"> -v </if>
<if test="withHeader == true"> -H "X-Demo: conditional" </if>
</curl>
</curls>
import com.github.paohaijiao.xml.JQuickCurlXmlParseFactory;
import com.github.paohaijiao.xml.factory.JQuickXmlFactory;
import com.github.paohaijiao.xml.handler.JQuickParseHandler;
import com.github.paohaijiao.xml.param.Param;
public interface SearchApi {
String search(@Param("q") String q,
@Param("verbose") boolean verbose,
@Param("withHeader") boolean withHeader);
}
class ConditionalDemo {
public static void main(String[] args) {
JQuickParseHandler parser = new JQuickCurlXmlParseFactory();
SearchApi api = new JQuickXmlFactory(parser, "search.xml").createApi(SearchApi.class);
// Verbose + header enabled
System.out.println(api.search("curl", true, true));
// Both disabled — the request on the wire is different
System.out.println(api.search("curl", false, false));
}
}
Because the endpoint is httpbin.org/anything, the response echoes the headers and args the server actually received — you can visually confirm that X-Demo appears only in the first call.
Beyond <if>: The Full XML Control Set
The bundled DTD defines more than if. XML content may also use:
<foreach collection="..." item="..."> — repeat content over a collection with open, close, and separator.
<choose> / <when test="..."> / <otherwise> — multi-branch selection, similar to a switch.
Use them for the same goal: keeping the curl command truthful while letting runtime data shape it.
Summary
XML <if> turns a static curl catalog into a runtime decision graph. Headers, flags, and payload fragments are included only when their test expression is true, evaluated fresh on every invocation. The Java interface stays declarative and the request stays readable — the conditional logic lives where the request is defined, not sprinkled through callers.
Repository: dromara/jquick-curl. Post 9 covers the opposite end of HTTP payloads: binary and multipart file uploads through curl's -F flag.
java #springboot #httpclient #opensource #java-library
Read original: https://dev.to/paohaijiao/conditional-requests-at-runtime-rendering-parts-of-a-curl-command-with-xml--g61
← Previous
Sometimes, you have to be comfortable saying, “This working relationship isn’t working for me.
Next →
Building a Production-Style CI/CD Pipeline with Azure DevOps, ACR, Helm, AKS and PostgreSQL
Related
The Sky Becomes a Data Center: The Race to Put AI in Orbit
General
1
DEV Community 周榜
Nvidia เปิดสูตรเหรียญทอง IMO ทั้งชุด หลังนักคณิตศาสตร์เตือนเรื่อง AI
General
2
DEV Community 周榜
Stop Eating Free Scope: The Change Log Habit That Saved My Freelance Hours
General
0
DEV Community
The Workflow Ran With Four Personas Instead of Five and Looked Fine
General
1
DEV Community 周榜
Comments0
No comments yet — be the first