Skip to content

Add QUERY HTTP method #34993

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,16 @@ public static BaseBuilder<?> options(String urlTemplate, @Nullable Object... uri
return method(HttpMethod.OPTIONS, urlTemplate, uriVars);
}

/**
* HTTP POST variant. See {@link #get(String, Object...)} for general info.
* @param urlTemplate a URL template; the resulting URL will be encoded
* @param uriVars zero or more URI variables
* @return the created builder
*/
public static BodyBuilder query(String urlTemplate, @Nullable Object... uriVars) {
return method(HttpMethod.QUERY, urlTemplate, uriVars);
}

/**
* Create a builder with the given HTTP method and a {@link URI}.
* @param method the HTTP method (GET, POST, etc)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,11 @@ public RequestHeadersUriSpec<?> options() {
return methodInternal(HttpMethod.OPTIONS);
}

@Override
public RequestBodyUriSpec query() {
return methodInternal(HttpMethod.QUERY);
}

@Override
public RequestBodyUriSpec method(HttpMethod httpMethod) {
return methodInternal(httpMethod);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,12 @@ public interface WebTestClient {
*/
RequestHeadersUriSpec<?> options();

/**
* Prepare an HTTP QUERY request.
* @return a spec for specifying the target URL
*/
RequestBodyUriSpec query();

/**
* Prepare a request for the specified {@code HttpMethod}.
* @return a spec for specifying the target URL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,20 @@ public MockMvcRequestBuilder options() {
return method(HttpMethod.OPTIONS);
}

/**
* Prepare an HTTP QUERY request.
* <p>The returned builder can be wrapped in {@code assertThat} to enable
* assertions on the result. For multi-statements assertions, use
* {@link MockMvcRequestBuilder#exchange() exchange()} to assign the
* result. To control the time to wait for asynchronous request to complete
* on a per-request basis, use
* {@link MockMvcRequestBuilder#exchange(Duration) exchange(Duration)}.
* @return a request builder for specifying the target URI
*/
public MockMvcRequestBuilder query() {
return method(HttpMethod.QUERY);
}

/**
* Prepare a request for the specified {@code HttpMethod}.
* <p>The returned builder can be wrapped in {@code assertThat} to enable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,24 @@ public static MockHttpServletRequestBuilder head(URI uri) {
return new MockHttpServletRequestBuilder(HttpMethod.HEAD).uri(uri);
}

/**
* Create a {@link MockHttpServletRequestBuilder} for a QUERY request.
* @param uriTemplate a URI template; the resulting URI will be encoded
* @param uriVariables zero or more URI variables
*/
public static MockHttpServletRequestBuilder query(String uriTemplate, @Nullable Object... uriVariables) {
return new MockHttpServletRequestBuilder(HttpMethod.QUERY).uri(uriTemplate, uriVariables);
}

/**
* Create a {@link MockHttpServletRequestBuilder} for a QUERY request.
* @param uri the URI
* @since x.x.x
*/
public static MockHttpServletRequestBuilder query(URI uri) {
return new MockHttpServletRequestBuilder(HttpMethod.QUERY).uri(uri);
}

/**
* Create a {@link MockHttpServletRequestBuilder} for a request with the given HTTP method.
* @param method the HTTP method (GET, POST, etc.)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.assertj.core.api.ThrowingConsumer;
import org.junit.jupiter.api.Test;

import org.junit.jupiter.params.ParameterizedTest;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
Expand All @@ -53,6 +54,7 @@
import static org.assertj.core.api.Assertions.entry;
import static org.springframework.http.HttpMethod.GET;
import static org.springframework.http.HttpMethod.POST;
import static org.springframework.http.HttpMethod.QUERY;

/**
* Tests for building a {@link MockHttpServletRequest} with
Expand Down Expand Up @@ -391,17 +393,20 @@ void requestParameterFromMultiValueMap() {
}

@Test
@ParameterizedTest()
void requestParameterFromRequestBodyFormData() {
String contentType = "application/x-www-form-urlencoded;charset=UTF-8";
String body = "name+1=value+1&name+2=value+A&name+2=value+B&name+3";

MockHttpServletRequest request = new MockHttpServletRequestBuilder(POST).uri("/foo")
.contentType(contentType).content(body.getBytes(UTF_8))
.buildRequest(this.servletContext);
for (HttpMethod method : List.of(POST, QUERY)) {
MockHttpServletRequest request = new MockHttpServletRequestBuilder(method).uri("/foo")
.contentType(contentType).content(body.getBytes(UTF_8))
.buildRequest(this.servletContext);

assertThat(request.getParameterMap().get("name 1")).containsExactly("value 1");
assertThat(request.getParameterMap().get("name 2")).containsExactly("value A", "value B");
assertThat(request.getParameterMap().get("name 3")).containsExactly((String) null);
assertThat(request.getParameterMap().get("name 1")).containsExactly("value 1");
assertThat(request.getParameterMap().get("name 2")).containsExactly("value A", "value B");
assertThat(request.getParameterMap().get("name 3")).containsExactly((String) null);
}
}

@Test
Expand Down
27 changes: 27 additions & 0 deletions spring-web/src/main/java/org/springframework/http/HttpHeaders.java
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,12 @@ public class HttpHeaders implements Serializable {
* @see <a href="https://tools.ietf.org/html/rfc7233#section-2.3">Section 5.3.5 of RFC 7233</a>
*/
public static final String ACCEPT_RANGES = "Accept-Ranges";

/**
* The HTTP {@code Accept-Query} header field name.
* @see <a href="https://httpwg.org/http-extensions/draft-ietf-httpbis-safe-method-w-body.html">IETF Draft</a>
*/
public static final String ACCEPT_QUERY = "Accept-Query";
/**
* The CORS {@code Access-Control-Allow-Credentials} response header field name.
* @see <a href="https://www.w3.org/TR/cors/">CORS W3C recommendation</a>
Expand Down Expand Up @@ -635,6 +641,27 @@ public List<MediaType> getAcceptPatch() {
return MediaType.parseMediaTypes(get(ACCEPT_PATCH));
}

/**
* Set the list of acceptable {@linkplain MediaType media types} for
* {@code QUERY} methods, as specified by the {@code Accept-Query} header.
* @since x.x.x
*/
public void setAcceptQuery(List<MediaType> mediaTypes) {
set(ACCEPT_QUERY, MediaType.toString(mediaTypes));
}

/**
* Return the list of acceptable {@linkplain MediaType media types} for
* {@code QUERY} methods, as specified by the {@code Accept-Query} header.
* <p>Returns an empty list when the acceptable media types are unspecified.
* @since x.x.x
*/
public List<MediaType> getAcceptQuery() {
return MediaType.parseMediaTypes(get(ACCEPT_QUERY));
}



/**
* Set the (new) value of the {@code Access-Control-Allow-Credentials} response header.
*/
Expand Down
25 changes: 16 additions & 9 deletions spring-web/src/main/java/org/springframework/http/HttpMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,25 @@ public final class HttpMethod implements Comparable<HttpMethod>, Serializable {

/**
* The HTTP method {@code GET}.
* @see <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.3">HTTP 1.1, section 9.3</a>
* @see <a href="https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.1">HTTP Semantics, section 9.3.1</a>
*/
public static final HttpMethod GET = new HttpMethod("GET");

/**
* The HTTP method {@code HEAD}.
* @see <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4">HTTP 1.1, section 9.4</a>
* @see <a href="https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.2">HTTP Semantics, section 9.3.2</a>
*/
public static final HttpMethod HEAD = new HttpMethod("HEAD");

/**
* The HTTP method {@code POST}.
* @see <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5">HTTP 1.1, section 9.5</a>
* @see <a href="https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.3">HTTP Semantics, section 9.3.3</a>
*/
public static final HttpMethod POST = new HttpMethod("POST");

/**
* The HTTP method {@code PUT}.
* @see <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6">HTTP 1.1, section 9.6</a>
* @see <a href="https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.4">HTTP Semantics, section 9.3.4</a>
*/
public static final HttpMethod PUT = new HttpMethod("PUT");

Expand All @@ -67,23 +67,29 @@ public final class HttpMethod implements Comparable<HttpMethod>, Serializable {

/**
* The HTTP method {@code DELETE}.
* @see <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.7">HTTP 1.1, section 9.7</a>
* @see <a href="https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.5">HTTP Semantics, section 9.3.5</a>
*/
public static final HttpMethod DELETE = new HttpMethod("DELETE");

/**
* The HTTP method {@code OPTIONS}.
* @see <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.2">HTTP 1.1, section 9.2</a>
* @see <a href="https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.7">HTTP Semantics, section 9.3.7</a>
*/
public static final HttpMethod OPTIONS = new HttpMethod("OPTIONS");

/**
* The HTTP method {@code TRACE}.
* @see <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.8">HTTP 1.1, section 9.8</a>
* @see <a href="https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.8">HTTP Semantics, section 9.3.8</a>
*/
public static final HttpMethod TRACE = new HttpMethod("TRACE");

private static final HttpMethod[] values = new HttpMethod[] { GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE };
/**
* The HTTP method {@code QUERY}.
* @see <a href="https://httpwg.org/http-extensions/draft-ietf-httpbis-safe-method-w-body.html">IETF Draft</a>
*/
public static final HttpMethod QUERY = new HttpMethod("QUERY");

private static final HttpMethod[] values = new HttpMethod[] { GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE, QUERY };


private final String name;
Expand All @@ -97,7 +103,7 @@ private HttpMethod(String name) {
* Returns an array containing the standard HTTP methods. Specifically,
* this method returns an array containing {@link #GET}, {@link #HEAD},
* {@link #POST}, {@link #PUT}, {@link #PATCH}, {@link #DELETE},
* {@link #OPTIONS}, and {@link #TRACE}.
* {@link #OPTIONS}, {@link #TRACE}, and {@link #QUERY}.
*
* <p>Note that the returned value does not include any HTTP methods defined
* in WebDav.
Expand All @@ -124,6 +130,7 @@ public static HttpMethod valueOf(String method) {
case "DELETE" -> DELETE;
case "OPTIONS" -> OPTIONS;
case "TRACE" -> TRACE;
case "QUERY" -> QUERY;
default -> new HttpMethod(method);
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,26 @@ public static BodyBuilder post(String uriTemplate, @Nullable Object... uriVariab
return method(HttpMethod.POST, uriTemplate, uriVariables);
}

/**
* Create an HTTP QUERY builder with the given url.
* @param url the URL
* @return the created builder
*/
public static BodyBuilder query(URI url) {
return method(HttpMethod.QUERY, url);
}

/**
* Create an HTTP QUERY builder with the given string base uri template.
* @param uriTemplate the uri template to use
* @param uriVariables variables to expand the URI template with
* @return the created builder
* @since x.x.x
*/
public static BodyBuilder query(String uriTemplate, Object... uriVariables) {
return method(HttpMethod.QUERY, uriTemplate, uriVariables);
}

/**
* Create an HTTP PUT builder with the given url.
* @param url the URL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.classic.methods.HttpPut;
import org.apache.hc.client5.http.classic.methods.HttpTrace;
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
import org.apache.hc.client5.http.config.Configurable;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.HttpClients;
Expand Down Expand Up @@ -345,6 +346,9 @@ else if (HttpMethod.OPTIONS.equals(httpMethod)) {
else if (HttpMethod.TRACE.equals(httpMethod)) {
return new HttpTrace(uri);
}
else if (HttpMethod.QUERY.equals(httpMethod)) {
return new HttpUriRequestBase(HttpMethod.QUERY.name(), uri);
}
throw new IllegalArgumentException("Invalid HTTP method: " + httpMethod);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ public HttpHeaders getHeaders() {
if (HttpMethod.PATCH.equals(this.httpMethod)) {
headers.setAcceptPatch(getSupportedMediaTypes());
}
if (HttpMethod.QUERY.equals(this.httpMethod)) {
headers.setAcceptQuery(getSupportedMediaTypes());
}
return headers;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
* @see PostMapping
* @see PutMapping
* @see PatchMapping
* @see QueryMapping
* @see RequestMapping
*/
@Target(ElementType.METHOD)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
* @see PutMapping
* @see DeleteMapping
* @see PatchMapping
* @see QueryMapping
* @see RequestMapping
*/
@Target(ElementType.METHOD)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
* @see PostMapping
* @see PutMapping
* @see DeleteMapping
* @see QueryMapping
* @see RequestMapping
*/
@Target(ElementType.METHOD)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
* @see PutMapping
* @see DeleteMapping
* @see PatchMapping
* @see QueryMapping
* @see RequestMapping
*/
@Target(ElementType.METHOD)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
* @see PostMapping
* @see DeleteMapping
* @see PatchMapping
* @see QueryMapping
* @see RequestMapping
*/
@Target(ElementType.METHOD)
Expand Down
Loading