diff --git a/CHANGELOG.md b/CHANGELOG.md index 582b98174c..a305cf24d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Add explicit keep rules for RxJava `Result` types to prevent their generic information from being removed. - Add `allowoptimization` flags for most kept types. - Add `Invocation.annotationUrl` which returns the original URL from the method annotation. + - Support `QUERY` method. **Changed** diff --git a/retrofit/build.gradle b/retrofit/build.gradle index 4e83fe8e03..280fea55c8 100644 --- a/retrofit/build.gradle +++ b/retrofit/build.gradle @@ -31,21 +31,31 @@ def addMultiReleaseSourceSet(int version) { addMultiReleaseSourceSet(14) addMultiReleaseSourceSet(16) +def extra = sourceSets.create('extra') { + java.srcDir('src/main/extra') +} + dependencies { api libs.okhttp.client + api extra.output compileOnly libs.android compileOnly libs.kotlinx.coroutines compileOnly libs.animalSnifferAnnotations compileOnly libs.findBugsAnnotations + + // Can't extend extraCompileOnly from compileOnly due to the circular dependencies. + extraCompileOnly libs.okhttp.client } javadoc { exclude('retrofit2/internal/**') } -jar { +tasks.named('jar', Jar) { + from(extra.output) + manifest { attributes 'Automatic-Module-Name': 'retrofit2' attributes 'Multi-Release': 'true' diff --git a/retrofit/java-test/src/test/java/retrofit2/RequestFactoryTest.java b/retrofit/java-test/src/test/java/retrofit2/RequestFactoryTest.java index b4eae2ce2d..8e9f10e281 100644 --- a/retrofit/java-test/src/test/java/retrofit2/RequestFactoryTest.java +++ b/retrofit/java-test/src/test/java/retrofit2/RequestFactoryTest.java @@ -60,6 +60,7 @@ import retrofit2.http.Part; import retrofit2.http.PartMap; import retrofit2.http.Path; +import retrofit2.http.QUERY; import retrofit2.http.Query; import retrofit2.http.QueryMap; import retrofit2.http.QueryName; @@ -1005,6 +1006,22 @@ Call method() { assertThat(request.body()).isNull(); } + @Test + public void query() { + class Example { + @QUERY("/foo/bar/") // + Call method(@Body RequestBody body) { + return null; + } + } + RequestBody body = RequestBody.create(TEXT_PLAIN, "hi"); + Request request = buildRequest(Example.class, body); + assertThat(request.method()).isEqualTo("QUERY"); + assertThat(request.headers().size()).isEqualTo(0); + assertThat(request.url().toString()).isEqualTo("http://example.com/foo/bar/"); + assertBody(request.body(), "hi"); + } + @Test public void getWithPathParam() { class Example { diff --git a/retrofit/src/main/extra/retrofit2/http/QUERY.java b/retrofit/src/main/extra/retrofit2/http/QUERY.java new file mode 100644 index 0000000000..55fbb9522c --- /dev/null +++ b/retrofit/src/main/extra/retrofit2/http/QUERY.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2025 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package retrofit2.http; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import okhttp3.HttpUrl; + +/** Make a QUERY request. */ +@Documented +@Target(METHOD) +@Retention(RUNTIME) +public @interface QUERY { + /** + * A relative or absolute path, or full URL of the endpoint. This value is optional if the first + * parameter of the method is annotated with {@link Url @Url}. + * + *

See {@linkplain retrofit2.Retrofit.Builder#baseUrl(HttpUrl) base URL} for details of how + * this is resolved against a base URL to create the full endpoint URL. + */ + String value() default ""; +} diff --git a/retrofit/src/main/java/retrofit2/RequestFactory.java b/retrofit/src/main/java/retrofit2/RequestFactory.java index 55444e7a89..eeae27de39 100644 --- a/retrofit/src/main/java/retrofit2/RequestFactory.java +++ b/retrofit/src/main/java/retrofit2/RequestFactory.java @@ -56,6 +56,7 @@ import retrofit2.http.Part; import retrofit2.http.PartMap; import retrofit2.http.Path; +import retrofit2.http.QUERY; import retrofit2.http.Query; import retrofit2.http.QueryMap; import retrofit2.http.QueryName; @@ -244,6 +245,8 @@ private void parseMethodAnnotation(Annotation annotation) { parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true); } else if (annotation instanceof OPTIONS) { parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false); + } else if (annotation instanceof QUERY) { + parseHttpMethodAndPath("QUERY", ((QUERY) annotation).value(), true); } else if (annotation instanceof HTTP) { HTTP http = (HTTP) annotation; parseHttpMethodAndPath(http.method(), http.path(), http.hasBody()); diff --git a/retrofit/src/main/java/retrofit2/Retrofit.java b/retrofit/src/main/java/retrofit2/Retrofit.java index 9e5a5bd561..323a5404ad 100644 --- a/retrofit/src/main/java/retrofit2/Retrofit.java +++ b/retrofit/src/main/java/retrofit2/Retrofit.java @@ -111,8 +111,9 @@ public final class Retrofit { *

The relative path for a given method is obtained from an annotation on the method describing * the request type. The built-in methods are {@link retrofit2.http.GET GET}, {@link * retrofit2.http.PUT PUT}, {@link retrofit2.http.POST POST}, {@link retrofit2.http.PATCH PATCH}, - * {@link retrofit2.http.HEAD HEAD}, {@link retrofit2.http.DELETE DELETE} and {@link - * retrofit2.http.OPTIONS OPTIONS}. You can use a custom HTTP method with {@link HTTP @HTTP}. For + * {@link retrofit2.http.HEAD HEAD}, {@link retrofit2.http.DELETE DELETE}, + * {@link retrofit2.http.OPTIONS OPTIONS}, and {@link retrofit2.http.QUERY QUERY}. + * You can use a custom HTTP method with {@link HTTP @HTTP}. For * a dynamic URL, omit the path on the annotation and annotate the first parameter with {@link * Url @Url}. *