This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch docs
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/docs by this push:
new 2a78845917 Add Session Options via HTTP documentation
2a78845917 is described below
commit 2a78845917a9f2a6f987c98eafcb8281285a8ebc
Author: James Bognar <[email protected]>
AuthorDate: Sat Apr 4 14:58:30 2026 -0400
Add Session Options via HTTP documentation
- New 10.21a.SessionOptions.md covering HTTP-based session property override
- Updated 02.03.SerializersAndParsers.md with REST integration and HTTP
options section
- Updated 12.02.PojoMarshalling.md with client-side session options API
examples
Made-with: Cursor
---
pages/topics/02.03.SerializersAndParsers.md | 40 +++++-
pages/topics/10.21a.SessionOptions.md | 184 ++++++++++++++++++++++++++++
pages/topics/12.02.PojoMarshalling.md | 30 +++++
3 files changed, 253 insertions(+), 1 deletion(-)
diff --git a/pages/topics/02.03.SerializersAndParsers.md
b/pages/topics/02.03.SerializersAndParsers.md
index 977797ecea..c1a7df4445 100644
--- a/pages/topics/02.03.SerializersAndParsers.md
+++ b/pages/topics/02.03.SerializersAndParsers.md
@@ -375,4 +375,42 @@ public void put(RestRequest req, @Body MyBean body) {
req.setParserSessionProperty("trimStrings", true);
// body is then parsed with trimStrings=true
}
-```
\ No newline at end of file
+```
+
+#### HTTP-Based Session Options
+
+Clients can also pass session properties via HTTP headers or query parameters
when the server has enabled them. The server controls which properties are
allowed using `@Rest(allowedSerializerOptions, allowedParserOptions)` or
`@RestOp(allowedSerializerOptions, allowedParserOptions)`:
+
+```java
+// Allow clients to override these specific serializer properties
+@Rest(
+ allowedSerializerOptions={"useWhitespace", "addBeanTypes"},
+ allowedParserOptions={"trimStrings"}
+)
+public class MyResource extends BasicRestServlet {
+ ...
+}
+```
+
+Clients send options using the `X-Juneau-Serializer-Options` header (JSON5
format) or `juneauSerializerOptions` query parameter (UON format):
+
+```java
+// Client using Juneau REST client
+RestClient client = RestClient.create()
+ .rootUrl("http://localhost:8080/myresource")
+ .build();
+
+// Via header (JSON5 format)
+client.get("/mybean")
+ .serializerSessionOptionsHeader("{useWhitespace:true,addBeanTypes:false}")
+ .run()
+ .getContent().as(MyBean.class);
+
+// Via query parameter (UON format)
+client.get("/mybean")
+ .serializerSessionOptionsQuery("(useWhitespace=true)")
+ .run()
+ .getContent().as(MyBean.class);
+```
+
+See [Session Options via HTTP](SessionOptions) for complete documentation.
\ No newline at end of file
diff --git a/pages/topics/10.21a.SessionOptions.md
b/pages/topics/10.21a.SessionOptions.md
new file mode 100644
index 0000000000..201b380ca0
--- /dev/null
+++ b/pages/topics/10.21a.SessionOptions.md
@@ -0,0 +1,184 @@
+---
+title: "Session Options via HTTP"
+slug: SessionOptions
+---
+
+Juneau REST supports overriding serializer and parser session properties on a
per-request basis via HTTP headers or query parameters. This allows clients to
control aspects of marshalling (such as whitespace formatting, bean type
annotations, etc.) without server-side code changes.
+
+## Overview
+
+The feature works at two levels:
+
+1. **Server-side**: Configure which properties clients are allowed to override
using `@Rest` or `@RestOp` annotations.
+2. **Client-side**: Send the allowed properties via HTTP headers or query
parameters.
+
+## Server Configuration
+
+### `@Rest` Level (applies to all operations in the class)
+
+```java
+@Rest(
+ serializers=JsonSerializer.class,
+ parsers=JsonParser.class,
+ allowedSerializerOptions={"useWhitespace", "addBeanTypes",
"sortCollections"},
+ allowedParserOptions={"trimStrings", "validateEnd"}
+)
+public class MyResource extends BasicRestServlet {
+ @RestGet
+ public MyBean get() { ... }
+}
+```
+
+### `@RestOp` Level (applies to a specific operation)
+
+```java
+@RestGet(
+ allowedSerializerOptions={"useWhitespace"},
+ allowedParserOptions={"trimStrings"}
+)
+public MyBean get() { ... }
+```
+
+### Overriding Inheritance with `noInherit`
+
+By default, operation-level `allowedSerializerOptions` and
`allowedParserOptions` are merged with class-level values. Use `noInherit` to
override and replace the parent values:
+
+```java
+@Rest(allowedSerializerOptions={"useWhitespace", "addBeanTypes"})
+public class MyResource extends BasicRestServlet {
+
+ // Only allows "sortCollections" - ignores parent "useWhitespace" and
"addBeanTypes"
+ @RestGet(
+ allowedSerializerOptions={"sortCollections"},
+ noInherit={"allowedSerializerOptions"}
+ )
+ public MyBean get() { ... }
+}
+```
+
+### `BasicUniversalConfig`
+
+Resources using `BasicUniversalConfig` have a comprehensive default allowlist
that covers the most common and safe session properties for all supported
serializers and parsers.
+
+## Client Usage
+
+### Juneau REST Client
+
+The `RestClient` and `RestRequest` APIs provide dedicated methods for setting
session options:
+
+```java
+RestClient client = RestClient.create()
+ .rootUrl("http://localhost:8080/myresource")
+ .build();
+```
+
+#### Via HTTP Headers (JSON5 format)
+
+```java
+// Builder-level (applies to all requests)
+RestClient client = RestClient.create()
+ .rootUrl("http://localhost:8080/myresource")
+ .serializerSessionOptionsHeader("{useWhitespace:true,addBeanTypes:false}")
+ .build();
+
+// Request-level
+client.get("/mybean")
+ .serializerSessionOptionsHeader("{useWhitespace:true}")
+ .run()
+ .getContent().as(MyBean.class);
+
+// Map form (serialized as JSON5)
+client.get("/mybean")
+ .serializerSessionOptionsHeader(Map.of("useWhitespace", true))
+ .run()
+ .getContent().as(MyBean.class);
+```
+
+#### Via Query Parameters (UON format)
+
+```java
+// Builder-level (applies to all requests via default query params)
+RestClient client = RestClient.create()
+ .rootUrl("http://localhost:8080/myresource")
+ .serializerSessionOptionsQueryDefault("(useWhitespace=true)")
+ .build();
+
+// Request-level
+client.get("/mybean")
+ .serializerSessionOptionsQuery("(useWhitespace=true)")
+ .run()
+ .getContent().as(MyBean.class);
+```
+
+#### Parser Options
+
+```java
+// Parser options work the same way
+client.post("/mybean", body)
+ .parserSessionOptionsHeader("{trimStrings:true}")
+ .run();
+```
+
+### Raw HTTP
+
+Without the Juneau client, you can send options via raw HTTP:
+
+**Header format** (JSON5/JSON map):
+```
+X-Juneau-Serializer-Options: {useWhitespace:true,addBeanTypes:false}
+X-Juneau-Parser-Options: {trimStrings:true}
+```
+
+**Query parameter format** (UON map):
+```
+GET /myresource/mybean?juneauSerializerOptions=(useWhitespace=true)
+```
+
+## Programmatic Override
+
+Server-side code can also set session properties programmatically via
`RestRequest`:
+
+```java
+@RestGet
+public MyBean get(RestRequest req) {
+ // These are applied regardless of allowedSerializerOptions
+ req.setSerializerSessionProperty("addBeanTypes", true);
+ req.setSerializerSessionProperty("maxIndent", 2);
+ return myBean;
+}
+```
+
+Programmatic values and HTTP-provided values are merged, with programmatic
values taking precedence.
+
+## Safe Properties
+
+Not all session properties are safe to expose via HTTP. Properties that
control internal server behavior (like `javaMethod`, `resolver`, `schema`,
`outer`) should never be in the allowlist.
+
+Safe properties to expose include formatting and output control properties:
+
+| Property | Applies To | Description |
+|---|---|---|
+| `useWhitespace` | Writers | Enable whitespace in output |
+| `maxIndent` | Writers | Maximum indentation level |
+| `quoteChar` | Writers | Quote character for strings |
+| `keepNullProperties` | Serializers | Include null-valued properties |
+| `trimStrings` | Serializers/Parsers | Trim string values |
+| `addBeanTypes` | Serializers | Add `_type` annotations |
+| `addRootType` | Serializers | Add root type annotation |
+| `sortCollections` | Serializers | Sort collections before serializing |
+| `sortMaps` | Serializers | Sort maps before serializing |
+| `trimEmptyCollections` | Serializers | Remove empty collections |
+| `trimEmptyMaps` | Serializers | Remove empty maps |
+| `binaryFormat` | Binary serializers | Binary encoding format (`BASE64`,
`HEX`, etc.) |
+| `escapeSolidus` | JSON | Escape forward slashes (`/`) |
+| `encoding` | UON | URL-encode special characters |
+| `validateEnd` | JSON/UON parsers | Validate end of input |
+| `expandedParams` | URL-encoding parser | Use expanded parameter format |
+| `preserveRootElement` | XML parser | Preserve root XML element |
+
+## Security Considerations
+
+- Only add properties to the allowlist that clients should be permitted to
change.
+- Properties controlling server internals (e.g., `javaMethod`, `schema`) must
never be exposed.
+- The allowlist is enforced on the server; clients cannot override the
enforcement.
+- If a client sends a disallowed property, the server returns a `400 Bad
Request`.
diff --git a/pages/topics/12.02.PojoMarshalling.md
b/pages/topics/12.02.PojoMarshalling.md
index b4f5847cd9..ebdc8e731b 100644
--- a/pages/topics/12.02.PojoMarshalling.md
+++ b/pages/topics/12.02.PojoMarshalling.md
@@ -97,3 +97,33 @@ These can be overridden using the following methods:
<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/rest/client/RestClient.Builder.html#partSerializer(java.lang.Class)"
target="_blank">partSerializer(Class<? extends
HttpPartSerializer>)</a></java-method></node-1>
<node-1><java-method><a
href="/site/apidocs/org/apache/juneau/rest/client/RestClient.Builder.html#partParser(java.lang.Class)"
target="_blank">partParser(Class<? extends
HttpPartParser>)</a></java-method></node-1>
</tree>
+
+## Session Options via HTTP
+
+The Juneau REST client supports sending serializer and parser session
properties via HTTP headers or query parameters. This allows controlling
per-request marshalling behavior when the server has enabled it:
+
+```java
+RestClient client = RestClient.create()
+ .rootUrl("http://localhost:8080/myapi")
+ .build();
+
+// Send serializer options via header (JSON5 format)
+client.get("/mybean")
+ .serializerSessionOptionsHeader("{useWhitespace:true}")
+ .run()
+ .getContent().as(MyBean.class);
+
+// Send parser options via query parameter (UON format)
+client.post("/mybean", body)
+ .parserSessionOptionsQuery("(trimStrings=true)")
+ .run();
+
+// Set default options for all requests via builder
+RestClient clientWithDefaults = RestClient.create()
+ .rootUrl("http://localhost:8080/myapi")
+ .serializerSessionOptionsHeader("{addBeanTypes:false}")
+ .parserSessionOptionsQueryDefault("(trimStrings=true)")
+ .build();
+```
+
+See [Session Options via HTTP](SessionOptions) for complete documentation on
server configuration and security.