Skip to content

Commit e58d337

Browse files
committed
Add support for the detailed error model
Motivation: A common extension to gRPC is a the detailed error model. While not a standard gRPC feature it is widely used. The standard error model only allows for a status code and message to be propagated to the client. The detailed error model allows users to use a common set of structured errors and send them to the client in metadata. The model uses the 'google.rpc.Status' protobuf message to describe the error and any error details. Modifications: - Update the fetch and generate protobuf scripts to get and build the relevant standard protobuf messages. - Add `ErrorDetails` which is a container for common error types. Each of the error types maps to one a standard error detail from the detailed error model. - Add a `GoogleRPCStatus` error which maps to the 'google.rpc.Status' protobuf. This also conforms to `RPCErrorConvertible` so gRPC will automaticlly turn it into an appropriate status and metadata. - Add a helper for unpacking the `GoogleRPCStatus` from an `RPCError`. Result: Support for the detailed error mode.
1 parent 405d74c commit e58d337

File tree

2 files changed

+112
-1
lines changed

2 files changed

+112
-1
lines changed

dev/protos/fetch.sh

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/bin/bash
2+
## Copyright 2024, gRPC Authors All rights reserved.
3+
##
4+
## Licensed under the Apache License, Version 2.0 (the "License");
5+
## you may not use this file except in compliance with the License.
6+
## You may obtain a copy of the License at
7+
##
8+
## http://www.apache.org/licenses/LICENSE-2.0
9+
##
10+
## Unless required by applicable law or agreed to in writing, software
11+
## distributed under the License is distributed on an "AS IS" BASIS,
12+
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
## See the License for the specific language governing permissions and
14+
## limitations under the License.
15+
16+
set -eu
17+
18+
here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
19+
upstream="$here/upstream"
20+
21+
# Create a temporary directory for the repo checkouts.
22+
checkouts="$(mktemp -d)"
23+
24+
# Clone the google protos into the staging area.
25+
git clone --depth 1 https://github.com/googleapis/googleapis.git "$checkouts/googleapis"
26+
27+
# Remove the old protos.
28+
rm -rf "$upstream"
29+
30+
# Copy over the googleapis protos.
31+
mkdir -p "$upstream/google/rpc"
32+
cp -rp "$checkouts/googleapis/google/rpc/error_details.proto" "$upstream/google/rpc/error_details.proto"
33+
cp -rp "$checkouts/googleapis/google/rpc/code.proto" "$upstream/google/rpc/code.proto"
34+
cp -rp "$checkouts/googleapis/google/rpc/status.proto" "$upstream/google/rpc/status.proto"

dev/protos/generate.sh

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,84 @@ here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
1919
root="$here/../.."
2020
protoc=$(which protoc)
2121

22+
# Checkout and build the plugins.
23+
swift build --package-path "$root" --product protoc-gen-swift
24+
swift build --package-path "$root" --product protoc-gen-grpc-swift
25+
26+
# Grab the plugin paths.
27+
bin_path=$(swift build --package-path "$root" --show-bin-path)
28+
protoc_gen_swift="$bin_path/protoc-gen-swift"
29+
protoc_gen_grpc_swift="$bin_path/protoc-gen-grpc-swift"
30+
31+
# Generates gRPC by invoking protoc with the gRPC Swift plugin.
32+
# Parameters:
33+
# - $1: .proto file
34+
# - $2: proto path
35+
# - $3: output path
36+
# - $4 onwards: options to forward to the plugin
37+
function generate_grpc {
38+
local proto=$1
39+
local args=("--plugin=$protoc_gen_grpc_swift" "--proto_path=${2}" "--grpc-swift_out=${3}")
40+
41+
for option in "${@:4}"; do
42+
args+=("--grpc-swift_opt=$option")
43+
done
44+
45+
invoke_protoc "${args[@]}" "$proto"
46+
}
47+
48+
# Generates messages by invoking protoc with the Swift plugin.
49+
# Parameters:
50+
# - $1: .proto file
51+
# - $2: proto path
52+
# - $3: output path
53+
# - $4 onwards: options to forward to the plugin
54+
function generate_message {
55+
local proto=$1
56+
local args=("--plugin=$protoc_gen_swift" "--proto_path=$2" "--swift_out=$3")
57+
58+
for option in "${@:4}"; do
59+
args+=("--swift_opt=$option")
60+
done
61+
62+
invoke_protoc "${args[@]}" "$proto"
63+
}
64+
2265
function invoke_protoc {
2366
# Setting -x when running the script produces a lot of output, instead boil
2467
# just echo out the protoc invocations.
2568
echo "$protoc" "$@"
2669
"$protoc" "$@"
2770
}
2871

72+
#- DETAILED ERROR -------------------------------------------------------------
73+
74+
function generate_rpc_error_details {
75+
local protos output
76+
77+
protos=(
78+
"$here/upstream/google/rpc/status.proto"
79+
"$here/upstream/google/rpc/code.proto"
80+
"$here/upstream/google/rpc/error_details.proto"
81+
)
82+
output="$root/Sources/GRPCProtobuf/Errors/Generated"
83+
84+
for proto in "${protos[@]}"; do
85+
generate_message "$proto" "$(dirname "$proto")" "$output" "Visibility=Internal" "UseAccessLevelOnImports=true"
86+
done
87+
}
88+
89+
#- DETAILED ERROR Tests -------------------------------------------------------
90+
91+
function generate_error_service {
92+
local proto output
93+
proto="$here/local/error-service.proto"
94+
output="$root/Tests/GRPCProtobufTests/Errors/Generated"
95+
96+
generate_message "$proto" "$(dirname "$proto")" "$output" "Visibility=Internal" "UseAccessLevelOnImports=true"
97+
generate_grpc "$proto" "$(dirname "$proto")" "$output" "Visibility=Internal" "UseAccessLevelOnImports=true"
98+
}
99+
29100
#- DESCRIPTOR SETS ------------------------------------------------------------
30101

31102
function generate_test_service_descriptor_set {
@@ -72,7 +143,13 @@ function generate_wkt_service_descriptor_set {
72143

73144
#------------------------------------------------------------------------------
74145

75-
# Descriptor sets
146+
# Detailed error model
147+
generate_rpc_error_details
148+
149+
# Service for testing error details
150+
generate_error_service
151+
152+
# Descriptor sets for tests
76153
generate_test_service_descriptor_set
77154
generate_foo_service_descriptor_set
78155
generate_bar_service_descriptor_set

0 commit comments

Comments
 (0)