skip to content

In REST Assured, does a slash or a space inside a path-parameter value reach the server unescaped?

level: middleimportance: must knowfreq 51%

answer

  1. escaped per segment, after substitution
  2. a slash becomes %2F
  3. space is %20, never a plus
  4. charset from EncoderConfig, UTF-8 default

basics

~20 s

REST Assured percent-encodes each filled path segment by default, so a slash inside a value becomes %2F and a space becomes %20. The value cannot introduce an extra path segment, and other reserved characters are escaped as well.

solid answer

~40 s

By default REST Assured URL-encodes the path it builds. It substitutes each placeholder value into its path segment and then percent-encodes that whole segment, so `given().pathParam("clothCode", "MOROCCO/RED").when().get("/cloths/{clothCode}")` requests `/cloths/MOROCCO%2FRED` — one segment, not two. A space goes out as `%20` rather than `+`, because REST Assured rewrites the `+` that Java's `URLEncoder` produces; the charset comes from `EncoderConfig.defaultQueryParameterCharset()`, which is UTF-8 unless you change it. Since the escaping is applied to the segment *after* substitution, reserved characters that were literal in your template are escaped too — an `&` or an `=` written into the same segment comes out as `%26` or `%3D`. The practical upshot: a value can never smuggle in a segment separator, so if the bindery API really identifies a cloth as `MOROCCO/RED`, the server has to decode `%2F` itself.

code

java · 17 lines
java
import static io.restassured.RestAssured.given;

// A slash in the value is escaped into ONE segment:
// GET /cloths/MOROCCO%2FRED
given()
    .log().uri()
    .pathParam("clothCode", "MOROCCO/RED")
.when()
    .get("/cloths/{clothCode}");

// A space goes out as %20, never as "+":
// GET /cloths/buckram%20natural
given()
    .log().uri()
    .pathParam("clothCode", "buckram natural")
.when()
    .get("/cloths/{clothCode}");

go deeper

for a junior

Know that REST Assured escapes path values for you, so a space or a slash in a value is safe to pass. Do not hand-encode a value before giving it to pathParam.

for a middle

Explain that escaping happens per segment after substitution, name %2F and %20 as the results for slash and space, and say where the charset comes from.

for a senior

Diagnose from the wire: given a 404 on a path-parameterised call, show how you would print the built URI, spot a double escape or an unexpected %2F, and decide whether the fix belongs in the test or the API.

for a principal

Own the identifier policy. Decide whether resource ids in your APIs may contain separators at all, since a value that needs %2F constrains every client and gateway, not only this test suite.

## What REST Assured does to a placeholder value Filling a placeholder is not a plain string substitution. REST Assured splits the path template on `/`, fills the placeholders inside each resulting segment, and then percent-encodes the segment it has just produced. Two consequences follow directly from that order of operations, and together they explain almost everything people find surprising here: - The value is escaped, so characters that mean something in a URL lose their meaning. - The escaping covers the **whole segment**, not just the substituted value, so any literal reserved character you wrote into the template is escaped alongside it. The encoder itself is Java's `URLEncoder` with one adjustment, described below, and the charset it uses is `EncoderConfig.defaultQueryParameterCharset()` — UTF-8 out of the box. ## Slash, space and the rest On a bookbindery order API with the template `/cloths/{clothCode}`: | value passed | what goes on the wire | why it matters | |---|---|---| | `MOROCCO/RED` | `/cloths/MOROCCO%2FRED` | one segment, not two — the value cannot add depth to the path | | `buckram natural` | `/cloths/buckram%20natural` | a space is legal in a value and never in a raw URL | | `linen&board` | `/cloths/linen%26board` | the ampersand cannot start a query parameter | | `size=quarto` | `/cloths/size%3Dquarto` | the equals sign is escaped too | The first row is the one that changes how you design a test. Because `/` becomes `%2F`, you cannot use a path parameter to reach a deeper resource than the template describes. A value is always exactly one segment's worth of text, and a server that genuinely uses slashes inside an identifier must decode `%2F` before it can match a route — many web frameworks reject or normalise it by default. ## Why the space is %20 and not + `URLEncoder` was written for `application/x-www-form-urlencoded` bodies, where a space is encoded as `+`. That is wrong in a path: a `+` in a path segment is a literal plus sign to most servers, so the value would arrive corrupted. REST Assured therefore replaces the `+` that the encoder produces with `%20` before the path is assembled. It is a small detail with a large diagnostic payoff — if you ever see a `+` where a space should be, the escaping did not come from REST Assured's path handling. ## Which charset is used The charset for path and query escaping is `EncoderConfig.defaultQueryParameterCharset()`. Its default is UTF-8, deliberately, even though the URI syntax specification is stricter, because that is what most servers used for testing expect. The default charset for *content* is a different setting on the same config object, so changing one does not change the other. A non-ASCII value in a bindery order title is therefore escaped as UTF-8 bytes, each byte written as its own percent-escape. ## What this means when you write a test 1. Do not pre-escape values by hand while encoding is on. Passing `MOROCCO%2FRED` gets the `%` escaped in turn, so the server receives `MOROCCO%252FRED` and matches nothing. 2. Do not assemble a multi-segment fragment inside one placeholder. If you need `/cloths/MOROCCO/RED`, put two placeholders in the template, or write the literal segment into the path. 3. Expect literal reserved characters in a segment to be escaped along with the value. A path fragment written as `param1={a}&param2={b}` is one segment to the splitter, and the `=` and `&` in it come out as `%3D` and `%26`. 4. When a path-parameterised request 404s and the value looks fine in the source, print the built URI before blaming the server — the escaping is usually the answer. ## When the escaping is not what you want Three signatures in a logged request URI tell you what happened without any further reasoning: - A `%25` in a path segment means the value was escaped twice, so something pre-escaped it before REST Assured saw it. - A raw `/`, space or `&` in a segment means the escaping was switched off somewhere upstream. - A `+` where a space belongs means the text did not come from REST Assured's path handling, since it rewrites that `+`. There is exactly one lever, and it is a switch rather than a dial: `urlEncodingEnabled`. Set to `false` on a request (or statically), it turns REST Assured's escaping off for that whole request, and you take on the job of producing correct URL text yourself. That is the right choice when the value you hold has already been encoded upstream — a signed link, an id copied straight out of another response — and would otherwise be double-escaped. It is the wrong choice as a way to sneak a raw slash into a path, because the result is a URL whose shape no longer matches the template you wrote, and every other value on that request loses its escaping at the same time. The short version to remember: **REST Assured escapes for you, per segment, after substitution — and a value is always one segment.**

  • The bindery API really does key cloths as MOROCCO/RED. How would you test it?
    First establish what the server wants. If it decodes `%2F` itself, the default behaviour already works and the test needs no change. If it expects the raw slash, model the identifier as two placeholders — `/cloths/{family}/{shade}` — so the slash is part of the template rather than part of a value. Disabling encoding for the whole request is a last resort.
  • What happens to a non-ASCII character in a path-parameter value?
    It is encoded as its UTF-8 bytes, each written as a percent-escape, because `EncoderConfig.defaultQueryParameterCharset()` defaults to UTF-8. That is a deliberate choice in favour of what test servers commonly expect. If the service under test decodes paths with a different charset, change that setting rather than pre-encoding the value by hand.

saying these in an interview costs you the question

  • Says a slash in a value creates an extra path segment
  • Expects a space to be sent as a plus sign
  • Pre-encodes a value while encoding is still enabled
  • Thinks only the value is escaped, not the whole segment
  • Assumes the path charset is the same as the content charset