Skip to content
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

feat: convert grpc-status-details-bin in header to HTTP response body… #7639

Conversation

monkeyDluffy6017
Copy link
Contributor

Description

Convert grpc-status-details-bin in response header to response body, so that users could avoid parsing header to read error response.

Fixes #6996

Checklist

  • I have explained the need for this PR and the problem it solves
  • I have explained the changes or the new features added to this PR
  • I have added tests corresponding to this change
  • I have updated the documentation to reflect this change
  • I have verified that this change is backward compatible (If not, please discuss on the APISIX mailing list first)

type = "boolean",
default = false
},
-- https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto#L46
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean link after api7?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use GitHub's permalink feature, not a link to the master.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

local status_pb_state = grpc_proto.fetch_status_pb_state()
local old_pb_state = pb.state(status_pb_state)

local decoded_grpc_status = pb.decode("grpc.status.ErrorStatus", grpc_status)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be wrapped with pcall

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


local function handle_error_response(status_detail_type)
local headers = ngx.resp.get_headers()
local grpc_status = headers["grpc-status-details-bin"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use ngx.header will be better?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -44,6 +44,9 @@ APISIX takes in an HTTP request, transcodes it and forwards it to a gRPC service
| method | string | True | | Method name of the gRPC service. |
| deadline | number | False | 0 | Deadline for the gRPC service in ms. |
| pb_option | array[string([pb_option_def](#options-for-pb_option))] | False | | protobuf options. |
| show_status_in_body | boolean | False | False | Whether to display the parsed `grpc-status-details-bin` in the response body |
| status_detail_type | string | False | | The message type corresponding to the [details](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto#L46) part of `grpc-status-details-bin`, if not specified, this part will not be decoded |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to use permalink

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -44,6 +44,9 @@ APISIX takes in an HTTP request, transcodes it and forwards it to a gRPC service
| method | string | True | | Method name of the gRPC service. |
| deadline | number | False | 0 | Deadline for the gRPC service in ms. |
| pb_option | array[string([pb_option_def](#options-for-pb_option))] | False | | protobuf options. |
| show_status_in_body | boolean | False | False | Whether to display the parsed `grpc-status-details-bin` in the response body |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| show_status_in_body | boolean | False | False | Whether to display the parsed `grpc-status-details-bin` in the response body |
| show_status_in_body | boolean | False | false | Whether to display the parsed `grpc-status-details-bin` in the response body |

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

// GetErrResp implements helloworld.GreeterServer
func (s *server) GetErrResp(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
st := status.New(codes.Unavailable, "Out of service")
st, err := st.WithDetails(&pb.ErrorDetail{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use gofmt to format the code

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

ngx.say(body)
}
}
--- request
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These sections are defined at the top.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean? section 3 should be merge into section 1, or section 3 should be after section 1?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--- request is set in

$block->set_value("request", "GET /t");
. There is no need to set it again.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done




=== TEST 10: set routes (id: 1, show error details in body)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the difference between TEST 89 and TEST 1011?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are duplicated, deleted.




=== TEST 4: set routes (id: 1, get error response from rpc)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can merge TEST 3&4 into one, like the TEST 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@spacewander
Copy link
Member

Don't forget to install the proto file:

apisix/Makefile

Line 267 in ccc43ea

$(ENV_INSTALL) apisix/include/apisix/model/*.proto $(ENV_INST_LUADIR)/apisix/include/apisix/model/

@monkeyDluffy6017 monkeyDluffy6017 force-pushed the covert-grpc-status-details-bin-in-header-to-http-response-body branch from a2e935d to 0b2999a Compare August 10, 2022 15:03
@spacewander
Copy link
Member

Please make the CI pass, thanks!

@monkeyDluffy6017
Copy link
Contributor Author

Please make the CI pass, thanks!

I'm working on it.

-- initialize protoc compiler
protoc.reload()
local status_protoc = protoc.new()
-- do not use loadfile here, it can not load proto file when use relative address
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
-- do not use loadfile here, it can not load proto file when use relative address
-- do not use loadfile here, it can not load the proto file when using a relative address

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

grpc_status = ngx_decode_base64(grpc_status)
if grpc_status == nil then
ngx.arg[1] = "grpc-status-details-bin is not base64 format"
return "grpc-status-details-bin is not base64 format"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can exact the error message to a variable so we don't need to repeat them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

local status_pb_state = grpc_proto.fetch_status_pb_state()
local old_pb_state = pb.state(status_pb_state)

local ok, decoded_grpc_status = pcall(pb.decode, "grpc_status.ErrorStatus", grpc_status)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should restore the pb_state here so the error won't pollute the pb_state

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -248,6 +250,150 @@ Trailer: grpc-message
{"workflowKey":"#2251799813685260","workflowInstanceKey":"#2251799813688013","bpmnProcessId":"order-process","version":1}
```

## Show `grpc-status-details-bin` in response body

If the gRPC service returns an error, there may be a `grpc-status-details-bin` field in the return header describing the error, which you can decode and display in the return body.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If the gRPC service returns an error, there may be a `grpc-status-details-bin` field in the return header describing the error, which you can decode and display in the return body.
If the gRPC service returns an error, there may be a `grpc-status-details-bin` field in the response header describing the error, which you can decode and display in the response body.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}
--- response_body
passed
--- no_error_log
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The no_error_log is already set at the top of this file

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

-- do not use loadfile here, it can not load the proto file when using a relative address
-- after luarocks install apisix
local ok, err = status_protoc:load(grpc_status_proto, "grpc_status.proto")
if not ok then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should set the old_pb_state back when the error happened?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

for file_name in lfs.dir(ngx.config.prefix() .. "/../../apisix/plugins/") do
if string.match(file_name, ".lua$") then
local expected = file_name:sub(1, #file_name - 4)
--local lfs = require("lfs")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For debug?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, forget to recovery, i have checked that there is no same problem

@github-actions
Copy link

This pull request has been marked as stale due to 60 days of inactivity. It will be closed in 4 weeks if no further activity occurs. If you think that's incorrect or this pull request should instead be reviewed, please simply write any comment. Even if closed, you can still revive the PR at any time or discuss it on the dev@apisix.apache.org list. Thank you for your contributions.

@github-actions github-actions bot added the stale label Nov 12, 2022
@spacewander spacewander merged commit 02f9fa0 into apache:master Nov 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
4 participants