Skip to content

Commit

Permalink
Merge pull request square#307 from square/jw/fix-encoded-path-cast
Browse files Browse the repository at this point in the history
Ensure @EncodedPath is not cast to @path when processing method.
  • Loading branch information
dnkoutso committed Aug 20, 2013
2 parents 1d77c0c + dea55b5 commit 27fd238
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 21 deletions.
41 changes: 23 additions & 18 deletions retrofit/src/main/java/retrofit/RestMethodInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -308,34 +308,25 @@ private void parseParameters() {
for (Annotation parameterAnnotation : parameterAnnotations) {
Class<? extends Annotation> annotationType = parameterAnnotation.annotationType();

if (annotationType == Path.class || annotationType == EncodedPath.class) {
if (annotationType == Path.class) {
String name = ((Path) parameterAnnotation).value();
validatePathName(name);

if (!PARAM_NAME_REGEX.matcher(name).matches()) {
throw new IllegalStateException("Path parameter name is not valid: "
+ name
+ ". Must match "
+ PARAM_URL_REGEX.pattern());
}
// Verify URL replacement name is actually present in the URL path.
if (!requestUrlParamNames.contains(name)) {
throw new IllegalStateException(
"Method URL \"" + requestUrl + "\" does not contain {" + name + "}.");
}
paramNames[i] = name;
paramUsage[i] = ParamUsage.PATH;
} else if (annotationType == EncodedPath.class) {
String name = ((EncodedPath) parameterAnnotation).value();
validatePathName(name);

paramNames[i] = name;
if (annotationType == EncodedPath.class) {
paramUsage[i] = ParamUsage.ENCODED_PATH;
} else {
paramUsage[i] = ParamUsage.PATH;
}
paramUsage[i] = ParamUsage.ENCODED_PATH;
} else if (annotationType == Query.class) {
String name = ((Query) parameterAnnotation).value();

paramNames[i] = name;
paramUsage[i] = ParamUsage.QUERY;
} else if (annotationType == EncodedQuery.class) {
String name = ((Query) parameterAnnotation).value();
String name = ((EncodedQuery) parameterAnnotation).value();

paramNames[i] = name;
paramUsage[i] = ParamUsage.ENCODED_QUERY;
Expand Down Expand Up @@ -402,6 +393,20 @@ private void parseParameters() {
}
}

private void validatePathName(String name) {
if (!PARAM_NAME_REGEX.matcher(name).matches()) {
throw new IllegalStateException("Path parameter name is not valid: "
+ name
+ ". Must match "
+ PARAM_URL_REGEX.pattern());
}
// Verify URL replacement name is actually present in the URL path.
if (!requestUrlParamNames.contains(name)) {
throw new IllegalStateException(
"Method URL \"" + requestUrl + "\" does not contain {" + name + "}.");
}
}

/**
* Gets the set of unique path parameters used in the given URI. If a parameter is used twice
* in the URI, it will only show up once in the set.
Expand Down
58 changes: 55 additions & 3 deletions retrofit/src/test/java/retrofit/RestMethodInfoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import org.junit.Test;
import retrofit.http.Body;
import retrofit.http.DELETE;
import retrofit.http.EncodedPath;
import retrofit.http.EncodedQuery;
import retrofit.http.Field;
import retrofit.http.FormUrlEncoded;
import retrofit.http.GET;
Expand All @@ -34,6 +36,8 @@
import static org.fest.assertions.api.Assertions.assertThat;
import static org.junit.Assert.fail;
import static retrofit.RestMethodInfo.ParamUsage.BODY;
import static retrofit.RestMethodInfo.ParamUsage.ENCODED_PATH;
import static retrofit.RestMethodInfo.ParamUsage.ENCODED_QUERY;
import static retrofit.RestMethodInfo.ParamUsage.HEADER;
import static retrofit.RestMethodInfo.ParamUsage.PATH;
import static retrofit.RestMethodInfo.ParamUsage.QUERY;
Expand Down Expand Up @@ -95,7 +99,7 @@ class Example {

@Test public void concreteCallbackTypesWithParams() {
class Example {
@GET("/foo") void a(@Path("id") String id, ResponseCallback cb) {
@GET("/foo") void a(@Query("id") String id, ResponseCallback cb) {
}
}

Expand All @@ -119,7 +123,7 @@ class Example {

@Test public void genericCallbackTypesWithParams() {
class Example {
@GET("/foo") void a(@Path("id") String id, Callback<Response> c) {
@GET("/foo") void a(@Query("id") String id, Callback<Response> c) {
}
}

Expand Down Expand Up @@ -203,7 +207,7 @@ class Example {
@Test(expected = IllegalArgumentException.class)
public void missingCallbackTypes() {
class Example {
@GET("/foo") void a(@Path("id") String id) {
@GET("/foo") void a(@Query("id") String id) {
}
}

Expand Down Expand Up @@ -408,6 +412,38 @@ class Example {
assertThat(methodInfo.requestType).isEqualTo(SIMPLE);
}

@Test public void singlePathParam() {
class Example {
@GET("/{a}") Response a(@Path("a") String a) {
return null;
}
}

Method method = TestingUtils.getMethod(Example.class, "a");
RestMethodInfo methodInfo = new RestMethodInfo(method);
methodInfo.init();

assertThat(methodInfo.requestParamNames).hasSize(1).containsExactly("a");
assertThat(methodInfo.requestParamUsage).hasSize(1).containsExactly(PATH);
assertThat(methodInfo.requestType).isEqualTo(SIMPLE);
}

@Test public void singleEncodedPathParam() {
class Example {
@GET("/{a}") Response a(@EncodedPath("a") String a) {
return null;
}
}

Method method = TestingUtils.getMethod(Example.class, "a");
RestMethodInfo methodInfo = new RestMethodInfo(method);
methodInfo.init();

assertThat(methodInfo.requestParamNames).hasSize(1).containsExactly("a");
assertThat(methodInfo.requestParamUsage).hasSize(1).containsExactly(ENCODED_PATH);
assertThat(methodInfo.requestType).isEqualTo(SIMPLE);
}

@Test public void singleQueryParam() {
class Example {
@GET("/") Response a(@Query("a") String a) {
Expand All @@ -424,6 +460,22 @@ class Example {
assertThat(methodInfo.requestType).isEqualTo(SIMPLE);
}

@Test public void singleEncodedQueryParam() {
class Example {
@GET("/") Response a(@EncodedQuery("a") String a) {
return null;
}
}

Method method = TestingUtils.getMethod(Example.class, "a");
RestMethodInfo methodInfo = new RestMethodInfo(method);
methodInfo.init();

assertThat(methodInfo.requestParamNames).hasSize(1).containsExactly("a");
assertThat(methodInfo.requestParamUsage).hasSize(1).containsExactly(ENCODED_QUERY);
assertThat(methodInfo.requestType).isEqualTo(SIMPLE);
}

@Test public void multipleQueryParams() {
class Example {
@GET("/") Response a(@Query("a") String a, @Query("b") String b, @Query("c") String c) {
Expand Down

0 comments on commit 27fd238

Please sign in to comment.