In REST Assured, how do you send a request through a proxy that requires a username and password?
answer
- only one overload carries credentials
- ProxySpecification statics host, port, auth
- withAuth after withScheme, not before
- host defaults to port 8888
basics
~20 sREST Assured's short proxy overloads take no credentials. Build a ProxySpecification instead, chaining host, withPort, withScheme and finally withAuth, and hand it to given().proxy(...). Order matters: withScheme rebuilds the specification and silently drops any username and password already set.
solid answer
~50 sFive of REST Assured's six `proxy(...)` overloads only fill in a host, port and scheme; the credentials-carrying one is `proxy(ProxySpecification)`. Build it with the statics on `io.restassured.specification.ProxySpecification` — `host("proxy.bakery.test")` defaults to port `8888` and scheme `http`, `port(3128)` defaults the host to `127.0.0.1`, and `auth(user, password)` gives you both defaults plus credentials — then refine with `withHost`, `withPort`, `withScheme` and `withAuth`. The trap is that `withScheme` delegates to the three-argument constructor, which resets username and password to null, so call it **before** `withAuth` or lose them silently. REST Assured turns the credentials into Apache `UsernamePasswordCredentials` under an `AuthScope` keyed by the proxy host's resolved IP address and port. The `proxy(URI)` overload reads only host, port and scheme, so user-info in the URI is discarded without a warning. Set the specification per request rather than on the static, so one suite can reach one target through a proxy and another directly.
code
java · 15 linesimport static io.restassured.RestAssured.given;
import static io.restassured.specification.ProxySpecification.host;
import static org.hamcrest.Matchers.equalTo;
given()
.proxy(host("proxy.bakery.test")
.withPort(3128)
.withScheme("http")
.withAuth("ci-runner", "s3cret"))
.baseUri("https://orders.bakery.example")
.when()
.get("/preorders/8412")
.then()
.statusCode(200)
.body("status", equalTo("READY"));go deeper
Be able to route a call through a local capture proxy with given().proxy(8888) and to say that the shorter overloads accept only host, port and scheme.
Explain that ProxySpecification is the only credential-carrying route, name its statics and their defaults, and describe the withScheme rebuild that drops the username and password.
Diagnose a 407 that appears only in CI: check the call order on the specification, whether the proxy was set statically or per request, and whether the JRE proxy selector is supplying a host nobody configured.
Decide where proxy configuration lives across a suite — per specification versus a shared static — and how proxy credentials are supplied and rotated without landing in source control or a request log.
## The six proxy overloads, and what each one can express `RequestSpecification` and the `RestAssured` statics both declare **six** `proxy(...)` overloads: `(int port)`, `(String host)`, `(String host, int port)`, `(String host, int port, String scheme)`, `(URI uri)` and `(ProxySpecification spec)`. Five of them are conveniences that fill in defaults; only the last can carry a username and password. | Overload | Host | Port | Scheme | Credentials | |---|---|---|---|---| | `proxy(8888)` | `127.0.0.1` | as given | `http` | none | | `proxy("proxy.bakery.test")` | as given | `8888` | `http` | none | | `proxy(host, port)` | as given | as given | `http` | none | | `proxy(host, port, scheme)` | as given | as given | as given | none | | `proxy(URI)` | from the URI | from the URI | from the URI | none | | `proxy(ProxySpecification)` | from the spec | from the spec | from the spec | **yes** | The `URI` overload is the one people expect to work for credentials, and it does not: REST Assured reads only `getHost()`, `getPort()` and `getScheme()` off the URI, so any user-info part is dropped without complaint. ## Building the specification `io.restassured.specification.ProxySpecification` is immutable, with three static factories and four `with...` methods that each return a new instance: - `ProxySpecification.host(String)` — the usual entry point, defaulting to port `8888`, scheme `http`. - `ProxySpecification.port(int)` — defaults the host to `127.0.0.1`. - `ProxySpecification.auth(String username, String password)` — defaults to `127.0.0.1:8888` over `http` with credentials attached. - `withHost`, `withPort`, `withScheme`, `withAuth` — each copies the specification with one field changed, plus `and()` as syntactic sugar. - A port below `1` is defaulted from the scheme, `80` for `http` and `443` for `https`, and any other scheme with no usable port throws `IllegalArgumentException` from the constructor. - Host and scheme are both trimmed to null and then asserted non-null, so a blank host fails immediately rather than producing a silently unroutable specification. A typical authenticated call therefore reads `given().proxy(host("proxy.bakery.test").withPort(3128).withAuth("ci-runner", "s3cret"))`, with `host` statically imported from `ProxySpecification`. ## The ordering trap in withScheme `withHost`, `withPort` and `withAuth` all copy every field including the credentials. `withScheme` does not: it delegates to the **public three-argument constructor** `ProxySpecification(host, port, scheme)`, which fills username and password with its own nulls. So this chain arrives at the wire with no credentials at all: ```java host("proxy.bakery.test").withAuth("ci-runner", "s3cret").withScheme("https") // credentials lost ``` while the same calls in the other order keep them: ```java host("proxy.bakery.test").withScheme("https").withAuth("ci-runner", "s3cret") // credentials kept ``` Nothing throws. The failure surfaces later as a `407` from the proxy on a request to `/preorders/8412` that you were sure was authenticated. Two details make it worth remembering: the port survives the rebuild, so a specification started with `host(...)` is still on `8888` rather than dropping to `443`; and the constructor only defaults a port from the scheme when the port it was handed is below `1`. ## What the credentials actually become When the specification has a username or a password, REST Assured builds an Apache `BasicCredentialsProvider`, registers `UsernamePasswordCredentials` under an `AuthScope`, and sets that provider on the HTTP client. The `AuthScope` is keyed by the proxy host's **resolved IP address** and port, not by the hostname you typed — the internal proxy selector works in addresses, so the library converts before registering. That is why a proxy host that resolves to more than one address, or that fails to resolve at all, produces a confusing failure rather than a clean authentication error. The scheme on the specification is applied to the proxy `HttpHost` itself, so `withScheme("https")` means the hop **to the proxy** is encrypted; it says nothing about the scheme of the target you are calling. ## What happens when you set no proxy Leaving the proxy unset is not the same as disabling proxying. REST Assured always installs its own route planner, and when no `ProxySpecification` is present that planner delegates to the JRE's default `ProxySelector`. Ordinary JVM proxy system properties therefore still apply, which explains the occasional report that a suite routes through a corporate proxy nobody configured in code. Three practical habits follow: 1. Set the proxy on a `RequestSpecification` or `RequestSpecBuilder` rather than on the static, so a single suite can call one target through a proxy and another directly. 2. Call `withScheme` before `withAuth`, or skip `withScheme` entirely when the default `http` hop is what you want. 3. Keep the proxy password out of the source file and out of the request log — `LogConfig`'s default sensitive-header blacklist covers `Proxy-Authorization` in the printed request.
- What does given().proxy(3128) resolve to, and when is that form useful?It becomes `ProxySpecification.port(3128)`, which defaults the host to `127.0.0.1` and the scheme to `http`. It is the shorthand for a capture proxy running on the same machine as the suite — handy while debugging a request locally, and useless in CI where the proxy is on another host.
- Your suite sets no proxy at all, yet requests still traverse one. Why?REST Assured always installs its own route planner and, with no `ProxySpecification` present, that planner delegates to the JRE's default `ProxySelector`. Standard JVM proxy system properties therefore still take effect. Setting an explicit `ProxySpecification` overrides the JRE selection for that request.
saying these in an interview costs you the question
- Puts credentials in the proxy URI and expects them to be sent
- Thinks proxy(host, port) accepts a username and password
- Calls withScheme after withAuth and loses the credentials
- Assumes withScheme sets the scheme of the target, not the proxy hop
- Believes no proxy call means no proxy is ever used