-
Notifications
You must be signed in to change notification settings - Fork 921
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support camelcase for HttpJsonTranscodingService Query Parameters (#4428
) Motivation: fixes #4401 Modifications: - Add HttpJsonTranscodingOptions and HttpJsonTranscodingOptionsBuilder - add GrpcServiceBuilder Api that consumes HttpJsonTranscodingOptions when setting enableHttpJsonTranscoding - check HttpJsonTranscodingOptions in HttpJsonTranscodingService, then add fields with camelCase keys in buildField function if camelCaseQueryParam option is set to true Result: - Closes #4401 - No breaking changes: changes are only applied when the new camelCaseQueryParam option is set to true - HttpJsonTranscoding endpoint can handle both snake_case and camelCase form of query parameters when option is set ```java HttpJsonTranscodingOptions options = HttpJsonTranscodingOptions.builder() .queryParamMatchRules(LOWER_CAMEL_CASE) ... .build(); GrpcService.builder() // Enable HttpJsonTranscoding and use the specified HttpJsonTranscodingOption .enableHttpJsonTranscoding(options) .build(); ```
- Loading branch information
1 parent
ec7c425
commit c888c86
Showing
9 changed files
with
609 additions
and
44 deletions.
There are no files selected for viewing
72 changes: 72 additions & 0 deletions
72
grpc/src/main/java/com/linecorp/armeria/server/grpc/DefaultHttpJsonTranscodingOptions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* | ||
* Copyright 2022 LINE Corporation | ||
* | ||
* LINE Corporation licenses this file to you 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: | ||
* | ||
* https://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 com.linecorp.armeria.server.grpc; | ||
|
||
import java.util.Objects; | ||
import java.util.Set; | ||
|
||
import com.google.common.base.MoreObjects; | ||
|
||
final class DefaultHttpJsonTranscodingOptions implements HttpJsonTranscodingOptions { | ||
|
||
static final HttpJsonTranscodingOptions DEFAULT = HttpJsonTranscodingOptions.builder().build(); | ||
|
||
private final Set<HttpJsonTranscodingQueryParamMatchRule> queryParamMatchRules; | ||
private final UnframedGrpcErrorHandler errorHandler; | ||
|
||
DefaultHttpJsonTranscodingOptions(Set<HttpJsonTranscodingQueryParamMatchRule> queryParamMatchRules, | ||
UnframedGrpcErrorHandler errorHandler) { | ||
this.queryParamMatchRules = queryParamMatchRules; | ||
this.errorHandler = errorHandler; | ||
} | ||
|
||
@Override | ||
public Set<HttpJsonTranscodingQueryParamMatchRule> queryParamMatchRules() { | ||
return queryParamMatchRules; | ||
} | ||
|
||
@Override | ||
public UnframedGrpcErrorHandler errorHandler() { | ||
return errorHandler; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) { | ||
return true; | ||
} | ||
if (!(o instanceof HttpJsonTranscodingOptions)) { | ||
return false; | ||
} | ||
final HttpJsonTranscodingOptions that = (HttpJsonTranscodingOptions) o; | ||
return queryParamMatchRules.equals(that.queryParamMatchRules()) && | ||
errorHandler.equals(that.errorHandler()); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(queryParamMatchRules, errorHandler); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return MoreObjects.toStringHelper(this) | ||
.add("queryParamMatchRules", queryParamMatchRules) | ||
.add("errorHandler", errorHandler) | ||
.toString(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
grpc/src/main/java/com/linecorp/armeria/server/grpc/HttpJsonTranscodingOptions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/* | ||
* Copyright 2022 LINE Corporation | ||
* | ||
* LINE Corporation licenses this file to you 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: | ||
* | ||
* https://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 com.linecorp.armeria.server.grpc; | ||
|
||
import java.util.Set; | ||
|
||
import com.google.protobuf.Message; | ||
|
||
import com.linecorp.armeria.common.annotation.UnstableApi; | ||
|
||
/** | ||
* User provided options for customizing {@link HttpJsonTranscodingService}. | ||
*/ | ||
@UnstableApi | ||
public interface HttpJsonTranscodingOptions { | ||
|
||
/** | ||
* Returns a new {@link HttpJsonTranscodingOptionsBuilder}. | ||
*/ | ||
static HttpJsonTranscodingOptionsBuilder builder() { | ||
return new HttpJsonTranscodingOptionsBuilder(); | ||
} | ||
|
||
/** | ||
* Returns the default {@link HttpJsonTranscodingOptions}. | ||
*/ | ||
static HttpJsonTranscodingOptions of() { | ||
return DefaultHttpJsonTranscodingOptions.DEFAULT; | ||
} | ||
|
||
/** | ||
* Returns the {@link HttpJsonTranscodingQueryParamMatchRule}s which is used to match fields in a | ||
* {@link Message} with query parameters. | ||
*/ | ||
Set<HttpJsonTranscodingQueryParamMatchRule> queryParamMatchRules(); | ||
|
||
/** | ||
* Return the {@link UnframedGrpcErrorHandler} which handles an exception raised while serving a gRPC | ||
* request transcoded from an HTTP/JSON request. | ||
*/ | ||
UnframedGrpcErrorHandler errorHandler(); | ||
} |
102 changes: 102 additions & 0 deletions
102
grpc/src/main/java/com/linecorp/armeria/server/grpc/HttpJsonTranscodingOptionsBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* | ||
* Copyright 2022 LINE Corporation | ||
* | ||
* LINE Corporation licenses this file to you 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: | ||
* | ||
* https://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 com.linecorp.armeria.server.grpc; | ||
|
||
import static com.google.common.base.Preconditions.checkArgument; | ||
import static java.util.Objects.requireNonNull; | ||
|
||
import java.util.EnumSet; | ||
import java.util.Set; | ||
|
||
import com.google.common.collect.ImmutableList; | ||
import com.google.common.collect.Iterables; | ||
import com.google.common.collect.Sets; | ||
import com.google.protobuf.Message; | ||
|
||
import com.linecorp.armeria.common.HttpRequest; | ||
import com.linecorp.armeria.common.QueryParams; | ||
import com.linecorp.armeria.common.annotation.Nullable; | ||
import com.linecorp.armeria.common.annotation.UnstableApi; | ||
|
||
/** | ||
* A builder for {@link HttpJsonTranscodingOptions}. | ||
*/ | ||
@UnstableApi | ||
public final class HttpJsonTranscodingOptionsBuilder { | ||
|
||
private static final EnumSet<HttpJsonTranscodingQueryParamMatchRule> DEFAULT_QUERY_PARAM_MATCH_RULES = | ||
EnumSet.of(HttpJsonTranscodingQueryParamMatchRule.ORIGINAL_FIELD); | ||
|
||
private UnframedGrpcErrorHandler errorHandler = UnframedGrpcErrorHandler.ofJson(); | ||
|
||
@Nullable | ||
private Set<HttpJsonTranscodingQueryParamMatchRule> queryParamMatchRules; | ||
|
||
HttpJsonTranscodingOptionsBuilder() {} | ||
|
||
/** | ||
* Adds the specified {@link HttpJsonTranscodingQueryParamMatchRule} which is used | ||
* to match {@link QueryParams} of an {@link HttpRequest} with fields in a {@link Message}. | ||
* If not set, {@link HttpJsonTranscodingQueryParamMatchRule#ORIGINAL_FIELD} is used by default. | ||
*/ | ||
public HttpJsonTranscodingOptionsBuilder queryParamMatchRules( | ||
HttpJsonTranscodingQueryParamMatchRule... queryParamMatchRules) { | ||
requireNonNull(queryParamMatchRules, "queryParamMatchRules"); | ||
queryParamMatchRules(ImmutableList.copyOf(queryParamMatchRules)); | ||
return this; | ||
} | ||
|
||
/** | ||
* Adds the specified {@link HttpJsonTranscodingQueryParamMatchRule} which is used | ||
* to match {@link QueryParams} of an {@link HttpRequest} with fields in a {@link Message}. | ||
* If not set, {@link HttpJsonTranscodingQueryParamMatchRule#ORIGINAL_FIELD} is used by default. | ||
*/ | ||
public HttpJsonTranscodingOptionsBuilder queryParamMatchRules( | ||
Iterable<HttpJsonTranscodingQueryParamMatchRule> queryParamMatchRules) { | ||
requireNonNull(queryParamMatchRules, "queryParamMatchRules"); | ||
checkArgument(!Iterables.isEmpty(queryParamMatchRules), "Can't set an empty queryParamMatchRules"); | ||
if (this.queryParamMatchRules == null) { | ||
this.queryParamMatchRules = EnumSet.noneOf(HttpJsonTranscodingQueryParamMatchRule.class); | ||
} | ||
this.queryParamMatchRules.addAll(ImmutableList.copyOf(queryParamMatchRules)); | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets an error handler which handles an exception raised while serving a gRPC request transcoded from | ||
* an HTTP/JSON request. By default, {@link UnframedGrpcErrorHandler#ofJson()} would be set. | ||
*/ | ||
@UnstableApi | ||
public HttpJsonTranscodingOptionsBuilder errorHandler(UnframedGrpcErrorHandler errorHandler) { | ||
requireNonNull(errorHandler, "errorHandler"); | ||
this.errorHandler = errorHandler; | ||
return this; | ||
} | ||
|
||
/** | ||
* Returns a newly created {@link HttpJsonTranscodingOptions}. | ||
*/ | ||
public HttpJsonTranscodingOptions build() { | ||
final Set<HttpJsonTranscodingQueryParamMatchRule> matchRules; | ||
if (queryParamMatchRules == null) { | ||
matchRules = DEFAULT_QUERY_PARAM_MATCH_RULES; | ||
} else { | ||
matchRules = Sets.immutableEnumSet(queryParamMatchRules); | ||
} | ||
return new DefaultHttpJsonTranscodingOptions(matchRules, errorHandler); | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
...rc/main/java/com/linecorp/armeria/server/grpc/HttpJsonTranscodingQueryParamMatchRule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* | ||
* Copyright 2022 LINE Corporation | ||
* | ||
* LINE Corporation licenses this file to you 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: | ||
* | ||
* https://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 com.linecorp.armeria.server.grpc; | ||
|
||
import com.google.protobuf.Message; | ||
|
||
import com.linecorp.armeria.common.HttpRequest; | ||
import com.linecorp.armeria.common.QueryParams; | ||
import com.linecorp.armeria.common.annotation.UnstableApi; | ||
|
||
/** | ||
* A naming rule to map {@link QueryParams} of an {@link HttpRequest} to fields in a {@link Message} for | ||
* HTTP-JSON transcoding endpoint. | ||
*/ | ||
@UnstableApi | ||
public enum HttpJsonTranscodingQueryParamMatchRule { | ||
/** | ||
* Converts field names that are | ||
* <a href="https://developers.google.com/protocol-buffers/docs/style#message_and_field_names">underscore_separated</a> | ||
* into lowerCamelCase before matching with {@link QueryParams} of an {@link HttpRequest}. | ||
* | ||
* <p>Note that field names which aren't {@code underscore_separated} may fail to | ||
* convert correctly to lowerCamelCase. Therefore, don't use this option if you aren't following | ||
* Protocol Buffer's | ||
* <a href="https://developers.google.com/protocol-buffers/docs/style">naming conventions</a>. | ||
*/ | ||
LOWER_CAMEL_CASE, | ||
/** | ||
* Uses the original fields in .proto files to match {@link QueryParams} of an {@link HttpRequest}. | ||
*/ | ||
ORIGINAL_FIELD | ||
} |
Oops, something went wrong.