diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/go.mod b/go.mod index 64b8e9f..e5ad851 100644 --- a/go.mod +++ b/go.mod @@ -16,9 +16,10 @@ require ( github.com/unistack-org/micro-broker-http/v3 v3.2.2 github.com/unistack-org/micro-broker-memory/v3 v3.2.3 github.com/unistack-org/micro-client-grpc/v3 v3.2.3 - github.com/unistack-org/micro-client-http/v3 v3.2.2 + github.com/unistack-org/micro-client-http/v3 v3.2.3 github.com/unistack-org/micro-codec-grpc/v3 v3.1.1 github.com/unistack-org/micro-codec-json/v3 v3.1.1 + github.com/unistack-org/micro-codec-jsonpb/v3 v3.1.1 github.com/unistack-org/micro-codec-proto/v3 v3.1.1 github.com/unistack-org/micro-codec-segmentio/v3 v3.1.1 github.com/unistack-org/micro-config-env/v3 v3.2.4 @@ -27,14 +28,17 @@ require ( github.com/unistack-org/micro-register-memory/v3 v3.2.2 github.com/unistack-org/micro-router-register/v3 v3.2.2 github.com/unistack-org/micro-server-grpc/v3 v3.2.2 - github.com/unistack-org/micro-server-http/v3 v3.2.0 + github.com/unistack-org/micro-server-http/v3 v3.2.3 github.com/unistack-org/micro-server-tcp/v3 v3.2.2 github.com/unistack-org/micro-wrapper-trace-opentracing/v3 v3.1.1 - github.com/unistack-org/micro/v3 v3.2.4 + github.com/unistack-org/micro/v3 v3.2.8 google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f google.golang.org/grpc v1.35.0 google.golang.org/protobuf v1.25.0 ) +//replace github.com/unistack-org/micro-server-http/v3 => ../micro-server-http + //replace github.com/unistack-org/micro-client-http/v3 => ../micro-client-http + //replace github.com/unistack-org/micro/v3 => ../micro diff --git a/go.sum b/go.sum index 36f29b7..7f4d33e 100644 --- a/go.sum +++ b/go.sum @@ -351,6 +351,7 @@ github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.31 h1:sJFOl9BgwbYAWOGEwr61FU28pqsBNdpRBnhGXtO06Oo= github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= +github.com/miekg/dns v1.1.35 h1:oTfOaDH+mZkdcgdIjH6yBajRGtIwcwcaR+rt23ZSrJs= github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= @@ -526,12 +527,14 @@ github.com/unistack-org/micro-broker-memory/v3 v3.2.3 h1:01l0GqY8eG6Ln3E6VZ5GA9E github.com/unistack-org/micro-broker-memory/v3 v3.2.3/go.mod h1:63X6CabOKmRyxxwEVrDdzFDPOfvzkL+g5SNXft1YWDo= github.com/unistack-org/micro-client-grpc/v3 v3.2.3 h1:0X+PeAZuDYziROwRSuw7mVWsqzSEN8mVO1SSaWM/jNw= github.com/unistack-org/micro-client-grpc/v3 v3.2.3/go.mod h1:HcQuzli6tMTVrl7wHAqpyBZw5M4lUV0tk2WQFgyQ4LU= -github.com/unistack-org/micro-client-http/v3 v3.2.2 h1:9Fl/pJvMwsVgWaHPNOBRYGga/hBMFsjSek2g6L2/h28= -github.com/unistack-org/micro-client-http/v3 v3.2.2/go.mod h1:wlIrq+He9oPPG/NSr5kax/O47TS6RMaoI12xfWkNjNU= +github.com/unistack-org/micro-client-http/v3 v3.2.3 h1:+a9vwYGs1it/DAXpFbAuiUF/AzFt/4eHnTd/bJLXWU8= +github.com/unistack-org/micro-client-http/v3 v3.2.3/go.mod h1:wlIrq+He9oPPG/NSr5kax/O47TS6RMaoI12xfWkNjNU= github.com/unistack-org/micro-codec-grpc/v3 v3.1.1 h1:h+x6ny1UeMEqZWPx7vhkfczetnFh00lbCxdLl9Rr0EU= github.com/unistack-org/micro-codec-grpc/v3 v3.1.1/go.mod h1:2iY/1jF+gnRGwZZBz7PU9pN7DIERWh5mnz2xwQtwm1M= github.com/unistack-org/micro-codec-json/v3 v3.1.1 h1:1iILAzvT7XP7Dxae9yfZJwId0nVA9GZc3Ez+n2iF3tc= github.com/unistack-org/micro-codec-json/v3 v3.1.1/go.mod h1:pElZKyezgNLfVIvQK/rLsVpnsojRZA01OB/L+13l0aw= +github.com/unistack-org/micro-codec-jsonpb/v3 v3.1.1 h1:n+kJEtvuO6EQF+NqNRq6StAl1WPlHSGW2Wcv+raiXQE= +github.com/unistack-org/micro-codec-jsonpb/v3 v3.1.1/go.mod h1:Ann7PUsYjuzjrpUs7ddEjlJ9Flnl1xCnoLoXlGXyehM= github.com/unistack-org/micro-codec-proto/v3 v3.1.1 h1:97BVfeWjEL9nBCqGPWAYjxbSFKgPDtRx4UzeQLVB+UQ= github.com/unistack-org/micro-codec-proto/v3 v3.1.1/go.mod h1:c93m6EHNaDgnrOeFuzJRwYA4z/HCgit66It4XRR2DY8= github.com/unistack-org/micro-codec-segmentio/v3 v3.1.1 h1:WFVNcXNm58bEOKnubTztBu3zG8COiGN1giLSgA1Ju78= @@ -548,15 +551,14 @@ github.com/unistack-org/micro-router-register/v3 v3.2.2 h1:lYCymDHkJfhZWYQ4+Sb7F github.com/unistack-org/micro-router-register/v3 v3.2.2/go.mod h1:Y9Qtlg4NHqq5rR6X6Jm+04LoSJMi7/OOCm2mRueZYTE= github.com/unistack-org/micro-server-grpc/v3 v3.2.2 h1:LfjFdl5jYYGY2SgCEH2qObvlNZ6ENC4HSa36uvI/sx4= github.com/unistack-org/micro-server-grpc/v3 v3.2.2/go.mod h1:459FWPnuW56+gmI3R9ZbWsGEc/+nR70c3YyaI1nRwN8= -github.com/unistack-org/micro-server-http/v3 v3.2.0 h1:0gnriS8tykOT2vFDbNNWwr2RV02xmq+6xwW/7C+0+8Y= -github.com/unistack-org/micro-server-http/v3 v3.2.0/go.mod h1:JPmmEayerP3Zf7RQtHOjKjA5+EUynWV6yvpg0ftPFww= +github.com/unistack-org/micro-server-http/v3 v3.2.3 h1:zrot1162Elq3doCPi/OlcCrqL+QCLxHFlKn/lA0i8iU= +github.com/unistack-org/micro-server-http/v3 v3.2.3/go.mod h1:TOeb0O65cr+MYL1l+AAnaprhuSKqeqDoIEuEk5wepAg= github.com/unistack-org/micro-server-tcp/v3 v3.2.2 h1:2/Xn+4+dnzY/tpD3MgLO1wg3ect9Jx5CLSDfPBjdjT4= github.com/unistack-org/micro-server-tcp/v3 v3.2.2/go.mod h1:TQDIck2+RdEAGIRnwv+2a0OVBUTkL6OM7YUY4AjFFmY= github.com/unistack-org/micro-wrapper-trace-opentracing/v3 v3.1.1 h1:sEnPLn3BGt/t+ITsMJ8zHwtDUV9Qty3NIadOa099uHk= github.com/unistack-org/micro-wrapper-trace-opentracing/v3 v3.1.1/go.mod h1:iY0hsj7ul6sT4Zt2xkclVFpKHG4MZ9k1sllLv01P8vM= github.com/unistack-org/micro/v3 v3.1.1 h1:kWL0BVzUBdotjfDbl1qL9lNYmZqvebQWPNCyqrjUSAk= github.com/unistack-org/micro/v3 v3.1.1/go.mod h1:0DgOy4OdJxQCDER8YSKitZugd2+1bddrRSNfeooTHDc= -github.com/unistack-org/micro/v3 v3.2.0/go.mod h1:J8XxJj4Pqa3Ee0a4biRRtut7UwTlfBq8QRe+s4PKGS0= github.com/unistack-org/micro/v3 v3.2.1/go.mod h1:J8XxJj4Pqa3Ee0a4biRRtut7UwTlfBq8QRe+s4PKGS0= github.com/unistack-org/micro/v3 v3.2.2 h1:wli8jSMheABvEdU2tCdqeBEH4HlOCSmPxizud8DklNo= github.com/unistack-org/micro/v3 v3.2.2/go.mod h1:J8XxJj4Pqa3Ee0a4biRRtut7UwTlfBq8QRe+s4PKGS0= @@ -564,6 +566,8 @@ github.com/unistack-org/micro/v3 v3.2.3 h1:gzEQwXBp3aoGDKgNJOiMp5sSadBOK81IhR9FC github.com/unistack-org/micro/v3 v3.2.3/go.mod h1:J8XxJj4Pqa3Ee0a4biRRtut7UwTlfBq8QRe+s4PKGS0= github.com/unistack-org/micro/v3 v3.2.4 h1:V/QrzeSI/Bjd0j7uL8Lvvbbz8ky/0yj69srd1lE1RLI= github.com/unistack-org/micro/v3 v3.2.4/go.mod h1:J8XxJj4Pqa3Ee0a4biRRtut7UwTlfBq8QRe+s4PKGS0= +github.com/unistack-org/micro/v3 v3.2.8 h1:M1qgOz+qgSf/coFeIqDKa7Xc+b3s7du1Yin+i10o3aw= +github.com/unistack-org/micro/v3 v3.2.8/go.mod h1:J8XxJj4Pqa3Ee0a4biRRtut7UwTlfBq8QRe+s4PKGS0= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vultr/govultr v0.1.4/go.mod h1:9H008Uxr/C4vFNGLqKx232C206GL0PBHzOP0809bGNA= @@ -694,6 +698,7 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/server/grpc/grpc_test.go b/server/grpc/grpc_test.go index f2a5405..6d0dc89 100644 --- a/server/grpc/grpc_test.go +++ b/server/grpc/grpc_test.go @@ -2,6 +2,7 @@ package grpc_test import ( "context" + "fmt" "testing" bmemory "github.com/unistack-org/micro-broker-memory/v3" @@ -23,6 +24,15 @@ type testServer struct { pb.UnimplementedTestServer } +func NewServerHandlerWrapper() server.HandlerWrapper { + return func(fn server.HandlerFunc) server.HandlerFunc { + return func(ctx context.Context, req server.Request, rsp interface{}) error { + fmt.Printf("wrap ctx: %#+v req: %#+v\n", ctx, req) + return fn(ctx, req, rsp) + } + } +} + func (g *testServer) Call(ctx context.Context, req *pb.Request, rsp *pb.Response) error { if req.Name == "Error" { return &errors.Error{Id: "id", Code: 99, Detail: "detail"} @@ -38,7 +48,9 @@ func TestGRPCServer(t *testing.T) { r := rmemory.NewRegister() b := bmemory.NewBroker(broker.Register(r)) - s := gserver.NewServer(server.Codec("application/grpc+proto", protocodec.NewCodec()), server.Address(":12345"), server.Register(r), server.Name("helloworld"), gserver.Reflection(true)) + s := gserver.NewServer(server.Codec("application/grpc+proto", protocodec.NewCodec()), server.Address(":12345"), server.Register(r), server.Name("helloworld"), gserver.Reflection(true), + server.WrapHandler(NewServerHandlerWrapper()), + ) // create router rtr := regRouter.NewRouter(router.Register(r)) diff --git a/server/http/generate.go b/server/http/generate.go new file mode 100644 index 0000000..ea270fa --- /dev/null +++ b/server/http/generate.go @@ -0,0 +1,3 @@ +package http + +//go:generate protoc -I./proto -I. -I/home/vtolstov/.cache/go-path/pkg/mod/github.com/grpc-ecosystem/grpc-gateway/v2@v2.1.0 -I/home/vtolstov/.cache/go-path/pkg/mod/github.com/grpc-ecosystem/grpc-gateway/v2@v2.1.0/third_party/googleapis --go-grpc_out=paths=source_relative:./proto --go_out=paths=source_relative:./proto --micro_out=components=micro|http,debug=true,paths=source_relative:./proto proto/test.proto diff --git a/server/http/http_test.go b/server/http/http_test.go index 6872a6a..ec6c4cc 100644 --- a/server/http/http_test.go +++ b/server/http/http_test.go @@ -7,11 +7,199 @@ import ( "net/http" "testing" + wrapperpb "github.com/golang/protobuf/ptypes/wrappers" + httpcli "github.com/unistack-org/micro-client-http/v3" + jsoncodec "github.com/unistack-org/micro-codec-json/v3" + jsonpbcodec "github.com/unistack-org/micro-codec-jsonpb/v3" memory "github.com/unistack-org/micro-register-memory/v3" httpsrv "github.com/unistack-org/micro-server-http/v3" + pb "github.com/unistack-org/micro-tests/server/http/proto" + "github.com/unistack-org/micro/v3/client" + "github.com/unistack-org/micro/v3/metadata" "github.com/unistack-org/micro/v3/server" ) +type Handler struct { + t *testing.T +} + +func NewServerHandlerWrapper() server.HandlerWrapper { + return func(fn server.HandlerFunc) server.HandlerFunc { + return func(ctx context.Context, req server.Request, rsp interface{}) error { + fmt.Printf("wrap ctx: %#+v req: %#+v\n", ctx, req) + return fn(ctx, req, rsp) + } + } +} + +func (h *Handler) Call(ctx context.Context, req *pb.CallReq, rsp *pb.CallRsp) error { + if req.Nested == nil { + h.t.Fatalf("invalid reflect merging") + } + if len(req.Nested.Uint64Args) != 3 || req.Nested.Uint64Args[2].Value != 3 { + h.t.Fatalf("invalid reflect merging") + } + md, ok := metadata.FromContext(ctx) + if !ok { + h.t.Fatalf("context without metadata") + } + if _, ok := md.Get("User-Agent"); !ok { + h.t.Fatalf("context metadata does not have User-Agent header") + } + if req.Name != "my_name" { + h.t.Fatalf("invalid req received: %#+v", req) + } + rsp.Rsp = "name_my_name" + httpsrv.SetRspCode(ctx, http.StatusCreated) + return nil +} + +func (h *Handler) CallError(ctx context.Context, req *pb.CallReq1, rsp *pb.CallRsp1) error { + httpsrv.SetRspCode(ctx, http.StatusBadRequest) + return &pb.Error{Msg: "my_error"} + return nil +} + +func TestNativeClientServer(t *testing.T) { + reg := memory.NewRegister() + ctx := context.Background() + + // create server + srv := httpsrv.NewServer( + server.Name("helloworld"), + server.Register(reg), + server.Codec("application/json", jsonpbcodec.NewCodec()), + //server.WrapHandler(NewServerHandlerWrapper()), + ) + + h := &Handler{t: t} + pb.RegisterTestHandler(srv, h) + + // start server + if err := srv.Start(); err != nil { + t.Fatal(err) + } + + // lookup server + service, err := reg.LookupService(ctx, "helloworld") + if err != nil { + t.Fatal(err) + } + + if len(service) != 1 { + t.Fatalf("Expected 1 service got %d: %+v", len(service), service) + } + + if len(service[0].Nodes) != 1 { + t.Fatalf("Expected 1 node got %d: %+v", len(service[0].Nodes), service[0].Nodes) + } + + cli := client.NewClientCallOptions(httpcli.NewClient(client.ContentType("application/json"), client.Codec("application/json", jsonpbcodec.NewCodec())), client.WithAddress(fmt.Sprintf("http://%s", service[0].Nodes[0].Address))) + + svc := pb.NewTestService("helloworld", cli) + rsp, err := svc.Call(ctx, &pb.CallReq{ + Name: "my_name", + Nested: &pb.Nested{Uint64Args: []*wrapperpb.UInt64Value{ + &wrapperpb.UInt64Value{Value: 1}, + &wrapperpb.UInt64Value{Value: 2}, + &wrapperpb.UInt64Value{Value: 3}, + }}, + }) + if err != nil { + t.Fatal(err) + } + + if rsp.Rsp != "name_my_name" { + t.Fatalf("invalid response: %#+v\n", rsp) + } + // stop server + if err := srv.Stop(); err != nil { + t.Fatal(err) + } + +} + +func TestNativeServer(t *testing.T) { + reg := memory.NewRegister() + ctx := context.Background() + + // create server + srv := httpsrv.NewServer( + server.Name("helloworld"), + server.Register(reg), + server.Codec("application/json", jsoncodec.NewCodec()), + //server.WrapHandler(NewServerHandlerWrapper()), + ) + + h := &Handler{t: t} + pb.RegisterTestHandler(srv, h) + + // start server + if err := srv.Start(); err != nil { + t.Fatal(err) + } + + // lookup server + service, err := reg.LookupService(ctx, "helloworld") + if err != nil { + t.Fatal(err) + } + + if len(service) != 1 { + t.Fatalf("Expected 1 service got %d: %+v", len(service), service) + } + + if len(service[0].Nodes) != 1 { + t.Fatalf("Expected 1 node got %d: %+v", len(service[0].Nodes), service[0].Nodes) + } + + // make request + rsp, err := http.Post(fmt.Sprintf("http://%s/v1/test/call/my_name?req=key&arg1=arg1&arg2=12345&nested.string_args=str1,str2&nested.uint64_args=1,2,3", service[0].Nodes[0].Address), "application/json", nil) + if err != nil { + t.Fatal(err) + } + if rsp.StatusCode != http.StatusCreated { + t.Fatalf("invalid status received: %#+v\n", rsp) + } + + b, err := ioutil.ReadAll(rsp.Body) + rsp.Body.Close() + + if err != nil { + t.Fatal(err) + } + + if s := string(b); s != `{"rsp":"name_my_name"}` { + t.Fatalf("Expected response %s, got %s", `{"rsp":"name_my_name"}`, s) + } + + // make request with error + rsp, err = http.Post(fmt.Sprintf("http://%s/v1/test/callerror/my_name", service[0].Nodes[0].Address), "application/json", nil) + if err != nil { + t.Fatal(err) + } + if rsp.StatusCode != http.StatusBadRequest { + t.Fatalf("invalid status received: %#+v\n", rsp) + } + + b, err = ioutil.ReadAll(rsp.Body) + rsp.Body.Close() + + if err != nil { + t.Fatal(err) + } + + if s := string(b); s != `{"msg":"my_error"}` { + t.Fatalf("Expected response %s, got %s", `{"msg":"my_error"}`, s) + } + + // stop server + if err := srv.Stop(); err != nil { + t.Fatal(err) + } + +} + func TestHTTPServer(t *testing.T) { reg := memory.NewRegister() ctx := context.Background() diff --git a/server/http/proto/test.pb.go b/server/http/proto/test.pb.go new file mode 100644 index 0000000..0a0fcd8 --- /dev/null +++ b/server/http/proto/test.pb.go @@ -0,0 +1,552 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0-devel +// protoc v3.6.1 +// source: test.proto + +package pb + +import ( + proto "github.com/golang/protobuf/proto" + wrappers "github.com/golang/protobuf/ptypes/wrappers" + _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options" + _ "google.golang.org/genproto/googleapis/api/annotations" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type CallReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Req string `protobuf:"bytes,2,opt,name=req,proto3" json:"req,omitempty"` + Arg1 string `protobuf:"bytes,3,opt,name=arg1,proto3" json:"arg1,omitempty"` + Arg2 uint64 `protobuf:"varint,4,opt,name=arg2,proto3" json:"arg2,omitempty"` + Nested *Nested `protobuf:"bytes,5,opt,name=nested,proto3" json:"nested,omitempty"` +} + +func (x *CallReq) Reset() { + *x = CallReq{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CallReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CallReq) ProtoMessage() {} + +func (x *CallReq) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CallReq.ProtoReflect.Descriptor instead. +func (*CallReq) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{0} +} + +func (x *CallReq) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *CallReq) GetReq() string { + if x != nil { + return x.Req + } + return "" +} + +func (x *CallReq) GetArg1() string { + if x != nil { + return x.Arg1 + } + return "" +} + +func (x *CallReq) GetArg2() uint64 { + if x != nil { + return x.Arg2 + } + return 0 +} + +func (x *CallReq) GetNested() *Nested { + if x != nil { + return x.Nested + } + return nil +} + +type Nested struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + StringArgs []string `protobuf:"bytes,1,rep,name=string_args,json=stringArgs,proto3" json:"string_args,omitempty"` + Uint64Args []*wrappers.UInt64Value `protobuf:"bytes,2,rep,name=uint64_args,json=uint64Args,proto3" json:"uint64_args,omitempty"` +} + +func (x *Nested) Reset() { + *x = Nested{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Nested) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Nested) ProtoMessage() {} + +func (x *Nested) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Nested.ProtoReflect.Descriptor instead. +func (*Nested) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{1} +} + +func (x *Nested) GetStringArgs() []string { + if x != nil { + return x.StringArgs + } + return nil +} + +func (x *Nested) GetUint64Args() []*wrappers.UInt64Value { + if x != nil { + return x.Uint64Args + } + return nil +} + +type CallRsp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Rsp string `protobuf:"bytes,2,opt,name=rsp,proto3" json:"rsp,omitempty"` +} + +func (x *CallRsp) Reset() { + *x = CallRsp{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CallRsp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CallRsp) ProtoMessage() {} + +func (x *CallRsp) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CallRsp.ProtoReflect.Descriptor instead. +func (*CallRsp) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{2} +} + +func (x *CallRsp) GetRsp() string { + if x != nil { + return x.Rsp + } + return "" +} + +type CallReq1 struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Req string `protobuf:"bytes,2,opt,name=req,proto3" json:"req,omitempty"` +} + +func (x *CallReq1) Reset() { + *x = CallReq1{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CallReq1) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CallReq1) ProtoMessage() {} + +func (x *CallReq1) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CallReq1.ProtoReflect.Descriptor instead. +func (*CallReq1) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{3} +} + +func (x *CallReq1) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *CallReq1) GetReq() string { + if x != nil { + return x.Req + } + return "" +} + +type CallRsp1 struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Rsp string `protobuf:"bytes,2,opt,name=rsp,proto3" json:"rsp,omitempty"` +} + +func (x *CallRsp1) Reset() { + *x = CallRsp1{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CallRsp1) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CallRsp1) ProtoMessage() {} + +func (x *CallRsp1) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CallRsp1.ProtoReflect.Descriptor instead. +func (*CallRsp1) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{4} +} + +func (x *CallRsp1) GetRsp() string { + if x != nil { + return x.Rsp + } + return "" +} + +type Error struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Msg string `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"` +} + +func (x *Error) Reset() { + *x = Error{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Error) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Error) ProtoMessage() {} + +func (x *Error) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Error.ProtoReflect.Descriptor instead. +func (*Error) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{5} +} + +func (x *Error) GetMsg() string { + if x != nil { + return x.Msg + } + return "" +} + +var File_test_proto protoreflect.FileDescriptor + +var file_test_proto_rawDesc = []byte{ + 0x0a, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x74, 0x65, + 0x73, 0x74, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, + 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x6f, 0x70, 0x65, + 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x61, + 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x22, 0x7d, 0x0a, 0x07, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x10, 0x0a, 0x03, 0x72, 0x65, 0x71, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, + 0x71, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x31, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x61, 0x72, 0x67, 0x31, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x32, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x04, 0x61, 0x72, 0x67, 0x32, 0x12, 0x24, 0x0a, 0x06, 0x6e, 0x65, 0x73, + 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x74, 0x65, 0x73, 0x74, + 0x2e, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x52, 0x06, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x22, + 0x68, 0x0a, 0x06, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, + 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x41, 0x72, 0x67, 0x73, 0x12, 0x3d, 0x0a, 0x0b, 0x75, 0x69, + 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0a, 0x75, + 0x69, 0x6e, 0x74, 0x36, 0x34, 0x41, 0x72, 0x67, 0x73, 0x22, 0x1b, 0x0a, 0x07, 0x43, 0x61, 0x6c, + 0x6c, 0x52, 0x73, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x73, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x72, 0x73, 0x70, 0x22, 0x30, 0x0a, 0x08, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, + 0x71, 0x31, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x71, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x71, 0x22, 0x1c, 0x0a, 0x08, 0x43, 0x61, 0x6c, 0x6c, + 0x52, 0x73, 0x70, 0x31, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x73, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x72, 0x73, 0x70, 0x22, 0x19, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, + 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x73, + 0x67, 0x32, 0x94, 0x02, 0x0a, 0x04, 0x54, 0x65, 0x73, 0x74, 0x12, 0x7c, 0x0a, 0x04, 0x43, 0x61, + 0x6c, 0x6c, 0x12, 0x0d, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, + 0x71, 0x1a, 0x0d, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x73, 0x70, + 0x22, 0x56, 0x92, 0x41, 0x34, 0x2a, 0x04, 0x43, 0x61, 0x6c, 0x6c, 0x4a, 0x2c, 0x0a, 0x07, 0x64, + 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x21, 0x0a, 0x0e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x20, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0f, 0x0a, 0x0d, 0x1a, 0x0b, 0x2e, 0x74, + 0x65, 0x73, 0x74, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, + 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x63, 0x61, 0x6c, 0x6c, 0x2f, 0x7b, + 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x3a, 0x01, 0x2a, 0x12, 0x8d, 0x01, 0x0a, 0x09, 0x43, 0x61, 0x6c, + 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x0e, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x61, + 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x31, 0x1a, 0x0e, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x61, + 0x6c, 0x6c, 0x52, 0x73, 0x70, 0x31, 0x22, 0x60, 0x92, 0x41, 0x39, 0x2a, 0x09, 0x43, 0x61, 0x6c, + 0x6c, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x4a, 0x2c, 0x0a, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, + 0x74, 0x12, 0x21, 0x0a, 0x0e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x0f, 0x0a, 0x0d, 0x1a, 0x0b, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x22, 0x19, 0x2f, 0x76, 0x31, 0x2f, + 0x74, 0x65, 0x73, 0x74, 0x2f, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2f, 0x7b, + 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x3a, 0x01, 0x2a, 0x42, 0x3a, 0x5a, 0x38, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x6e, 0x69, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2d, + 0x6f, 0x72, 0x67, 0x2f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2f, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x3b, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_test_proto_rawDescOnce sync.Once + file_test_proto_rawDescData = file_test_proto_rawDesc +) + +func file_test_proto_rawDescGZIP() []byte { + file_test_proto_rawDescOnce.Do(func() { + file_test_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_proto_rawDescData) + }) + return file_test_proto_rawDescData +} + +var file_test_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_test_proto_goTypes = []interface{}{ + (*CallReq)(nil), // 0: test.CallReq + (*Nested)(nil), // 1: test.Nested + (*CallRsp)(nil), // 2: test.CallRsp + (*CallReq1)(nil), // 3: test.CallReq1 + (*CallRsp1)(nil), // 4: test.CallRsp1 + (*Error)(nil), // 5: test.Error + (*wrappers.UInt64Value)(nil), // 6: google.protobuf.UInt64Value +} +var file_test_proto_depIdxs = []int32{ + 1, // 0: test.CallReq.nested:type_name -> test.Nested + 6, // 1: test.Nested.uint64_args:type_name -> google.protobuf.UInt64Value + 0, // 2: test.Test.Call:input_type -> test.CallReq + 3, // 3: test.Test.CallError:input_type -> test.CallReq1 + 2, // 4: test.Test.Call:output_type -> test.CallRsp + 4, // 5: test.Test.CallError:output_type -> test.CallRsp1 + 4, // [4:6] is the sub-list for method output_type + 2, // [2:4] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_test_proto_init() } +func file_test_proto_init() { + if File_test_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_test_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CallReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Nested); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CallRsp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CallReq1); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CallRsp1); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Error); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_test_proto_rawDesc, + NumEnums: 0, + NumMessages: 6, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_test_proto_goTypes, + DependencyIndexes: file_test_proto_depIdxs, + MessageInfos: file_test_proto_msgTypes, + }.Build() + File_test_proto = out.File + file_test_proto_rawDesc = nil + file_test_proto_goTypes = nil + file_test_proto_depIdxs = nil +} diff --git a/server/http/proto/test.proto b/server/http/proto/test.proto new file mode 100644 index 0000000..4b4ac7a --- /dev/null +++ b/server/http/proto/test.proto @@ -0,0 +1,76 @@ +syntax = "proto3"; + +package test; +option go_package = "github.com/unistack-org/micro-tests/server/http/proto;pb"; +import "google/api/annotations.proto"; +import "protoc-gen-openapiv2/options/annotations.proto"; +import "google/protobuf/wrappers.proto"; + +service Test { + rpc Call(CallReq) returns (CallRsp) { + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + operation_id: "Call"; + responses: { + key: "default"; + value: { + description: "Error response"; + schema: { + json_schema: { + ref: ".test.Error"; + } + } + } + } + }; + option (google.api.http) = { post: "/v1/test/call/{name}"; body: "*"; }; + }; + rpc CallError(CallReq1) returns (CallRsp1) { + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + operation_id: "CallError"; + responses: { + key: "default"; + value: { + description: "Error response"; + schema: { + json_schema: { + ref: ".test.Error"; + } + } + } + } + }; + option (google.api.http) = { post: "/v1/test/callerror/{name}"; body: "*"; }; + }; + +}; + +message CallReq { + string name = 1; + string req = 2; + string arg1 = 3; + uint64 arg2 = 4; + Nested nested = 5; +}; + +message Nested { + repeated string string_args = 1; + repeated google.protobuf.UInt64Value uint64_args = 2; +} + +message CallRsp { + string rsp = 2; +}; + +message CallReq1 { + string name = 1; + string req = 2; +}; + +message CallRsp1 { + string rsp = 2; +}; + + +message Error { + string msg = 1; +}; diff --git a/server/http/proto/test_grpc.pb.go b/server/http/proto/test_grpc.pb.go new file mode 100644 index 0000000..d10e53c --- /dev/null +++ b/server/http/proto/test_grpc.pb.go @@ -0,0 +1,126 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. + +package pb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion6 + +// TestClient is the client API for Test service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type TestClient interface { + Call(ctx context.Context, in *CallReq, opts ...grpc.CallOption) (*CallRsp, error) + CallError(ctx context.Context, in *CallReq1, opts ...grpc.CallOption) (*CallRsp1, error) +} + +type testClient struct { + cc grpc.ClientConnInterface +} + +func NewTestClient(cc grpc.ClientConnInterface) TestClient { + return &testClient{cc} +} + +func (c *testClient) Call(ctx context.Context, in *CallReq, opts ...grpc.CallOption) (*CallRsp, error) { + out := new(CallRsp) + err := c.cc.Invoke(ctx, "/test.Test/Call", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *testClient) CallError(ctx context.Context, in *CallReq1, opts ...grpc.CallOption) (*CallRsp1, error) { + out := new(CallRsp1) + err := c.cc.Invoke(ctx, "/test.Test/CallError", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// TestServer is the server API for Test service. +// All implementations must embed UnimplementedTestServer +// for forward compatibility +type TestServer interface { + Call(context.Context, *CallReq) (*CallRsp, error) + CallError(context.Context, *CallReq1) (*CallRsp1, error) + mustEmbedUnimplementedTestServer() +} + +// UnimplementedTestServer must be embedded to have forward compatible implementations. +type UnimplementedTestServer struct { +} + +func (*UnimplementedTestServer) Call(context.Context, *CallReq) (*CallRsp, error) { + return nil, status.Errorf(codes.Unimplemented, "method Call not implemented") +} +func (*UnimplementedTestServer) CallError(context.Context, *CallReq1) (*CallRsp1, error) { + return nil, status.Errorf(codes.Unimplemented, "method CallError not implemented") +} +func (*UnimplementedTestServer) mustEmbedUnimplementedTestServer() {} + +func RegisterTestServer(s *grpc.Server, srv TestServer) { + s.RegisterService(&_Test_serviceDesc, srv) +} + +func _Test_Call_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CallReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestServer).Call(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/test.Test/Call", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestServer).Call(ctx, req.(*CallReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _Test_CallError_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CallReq1) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestServer).CallError(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/test.Test/CallError", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestServer).CallError(ctx, req.(*CallReq1)) + } + return interceptor(ctx, in, info, handler) +} + +var _Test_serviceDesc = grpc.ServiceDesc{ + ServiceName: "test.Test", + HandlerType: (*TestServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Call", + Handler: _Test_Call_Handler, + }, + { + MethodName: "CallError", + Handler: _Test_CallError_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "test.proto", +} diff --git a/server/http/proto/test_micro.pb.go b/server/http/proto/test_micro.pb.go new file mode 100644 index 0000000..0127c02 --- /dev/null +++ b/server/http/proto/test_micro.pb.go @@ -0,0 +1,47 @@ +// Code generated by protoc-gen-micro +// source: test.proto +package pb + +import ( + "context" + + micro_api "github.com/unistack-org/micro/v3/api" + micro_client "github.com/unistack-org/micro/v3/client" +) + +// NewTestEndpoints provides api endpoints metdata for Test service +func NewTestEndpoints() []*micro_api.Endpoint { + endpoints := make([]*micro_api.Endpoint, 0, 2) + var endpoint *micro_api.Endpoint + endpoint = µ_api.Endpoint{ + Name: "Test.Call", + Path: []string{"/v1/test/call/{name}"}, + Method: []string{"POST"}, + Body: "*", + Handler: "rpc", + } + endpoints = append(endpoints, endpoint) + endpoint = µ_api.Endpoint{ + Name: "Test.CallError", + Path: []string{"/v1/test/callerror/{name}"}, + Method: []string{"POST"}, + Body: "*", + Handler: "rpc", + } + endpoints = append(endpoints, endpoint) + return endpoints +} + +// TestService interface +type TestService interface { + Call(context.Context, *CallReq, ...micro_client.CallOption) (*CallRsp, error) + CallError(context.Context, *CallReq1, ...micro_client.CallOption) (*CallRsp1, error) +} + +// Micro server stuff + +// TestHandler server handler +type TestHandler interface { + Call(context.Context, *CallReq, *CallRsp) error + CallError(context.Context, *CallReq1, *CallRsp1) error +} diff --git a/server/http/proto/test_micro_http.pb.go b/server/http/proto/test_micro_http.pb.go new file mode 100644 index 0000000..3734c98 --- /dev/null +++ b/server/http/proto/test_micro_http.pb.go @@ -0,0 +1,117 @@ +// Code generated by protoc-gen-micro +// source: test.proto +package pb + +import ( + "context" + "fmt" + // "net/http" + + micro_client_http "github.com/unistack-org/micro-client-http/v3" + micro_api "github.com/unistack-org/micro/v3/api" + micro_client "github.com/unistack-org/micro/v3/client" + micro_server "github.com/unistack-org/micro/v3/server" +) + +var ( + _ micro_server.Option + _ micro_client.Option +) + +type testService struct { + c micro_client.Client + name string +} + +// Micro client stuff + +// NewTestService create new service client +func NewTestService(name string, c micro_client.Client) TestService { + return &testService{c: c, name: name} +} + +func (c *testService) Call(ctx context.Context, req *CallReq, opts ...micro_client.CallOption) (*CallRsp, error) { + errmap := make(map[string]interface{}, 1) + errmap["default"] = &Error{} + + nopts := append(opts, + micro_client_http.Method("POST"), + micro_client_http.Path("/v1/test/call/{name}"), + micro_client_http.Body("*"), + micro_client_http.ErrorMap(errmap), + ) + rsp := &CallRsp{} + err := c.c.Call(ctx, c.c.NewRequest(c.name, "Test.Call", req), rsp, nopts...) + if err != nil { + return nil, err + } + return rsp, nil +} + +func (c *testService) CallError(ctx context.Context, req *CallReq1, opts ...micro_client.CallOption) (*CallRsp1, error) { + errmap := make(map[string]interface{}, 1) + errmap["default"] = &Error{} + + nopts := append(opts, + micro_client_http.Method("POST"), + micro_client_http.Path("/v1/test/callerror/{name}"), + micro_client_http.Body("*"), + micro_client_http.ErrorMap(errmap), + ) + rsp := &CallRsp1{} + err := c.c.Call(ctx, c.c.NewRequest(c.name, "Test.CallError", req), rsp, nopts...) + if err != nil { + return nil, err + } + return rsp, nil +} + +// Micro server stuff + +type testHandler struct { + TestHandler +} + +func (h *testHandler) Call(ctx context.Context, req *CallReq, rsp *CallRsp) error { + return h.TestHandler.Call(ctx, req, rsp) +} + +/* +func (h *testHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + fmt.Printf("new request: %#+v\n", r) + // HANDLE ALL STUFF +} +*/ + +func (h *testHandler) CallError(ctx context.Context, req *CallReq1, rsp *CallRsp1) error { + return h.TestHandler.CallError(ctx, req, rsp) +} + +/* +func (h *testHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + fmt.Printf("new request: %#+v\n", r) + // HANDLE ALL STUFF +} +*/ + +// Error method to satisfy error interface +func (e *Error) Error() string { + return fmt.Sprintf("%#v", e) +} + +// RegisterTestHandler registers server handler +func RegisterTestHandler(s micro_server.Server, sh TestHandler, opts ...micro_server.HandlerOption) error { + type test interface { + Call(context.Context, *CallReq, *CallRsp) error + CallError(context.Context, *CallReq1, *CallRsp1) error + // ServeHTTP(http.ResponseWriter, *http.Request) + } + type Test struct { + test + } + h := &testHandler{sh} + for _, endpoint := range NewTestEndpoints() { + opts = append(opts, micro_api.WithEndpoint(endpoint)) + } + return s.Handle(s.NewHandler(&Test{h}, opts...)) +} diff --git a/wrapper/sql/wrapper_test.go b/wrapper/sql/wrapper_test.go new file mode 100644 index 0000000..f5c988d --- /dev/null +++ b/wrapper/sql/wrapper_test.go @@ -0,0 +1,52 @@ +// +build ignore + +package wrapper_test + +import ( + "context" + "fmt" + "testing" + + "github.com/jmoiron/sqlx" + //_ "github.com/mattn/go-sqlite3" + wrapper "github.com/unistack-org/micro-wrapper-sql" +) + +var ( + schema = ` + CREATE TABLE IF NOT EXISTS person ( + first_name text, + last_name text, + email text + );` +) + +type Person struct { + FirstName string `db:"first_name"` + LastName string `db:"last_name"` + Email string `db:"email"` +} + +func TestWrapper(t *testing.T) { + db, err := sqlx.Connect("sqlite3", "test.db") + if err != nil { + t.Fatal(err) + } + + w := wrapper.NewWrapper(db) + defer w.Close() + ctx := context.Background() + + db.MustExec(schema) + + tx := db.MustBegin() + //tx.NamedExec("INSERT OR REPLACE INTO person (first_name, last_name, email) VALUES (:first_name, :last_name, :email)", &Person{"Jane", "Citizen", "jane.citzen@example.com"}) + tx.Commit() + + people := &Person{} + if err := sqlx.GetContext(ctx, w, people, "SELECT * FROM person limit 1"); err != nil { + t.Fatal(err) + } + + fmt.Printf("%#+v\n", people) +}