mirror of
https://github.com/go-micro/go-micro.git
synced 2024-11-24 08:02:32 +02:00
Add examples
This commit is contained in:
parent
273bab5dd7
commit
a34c70de0e
@ -72,6 +72,10 @@ See the [docs](https://github.com/micro/micro/tree/master/docs/v2) for detailed
|
||||
|
||||
See [cmd/protoc-gen-micro](https://github.com/micro/go-micro/tree/master/cmd/protoc-gen-micro) for protobuf code generation.
|
||||
|
||||
## Examples
|
||||
|
||||
See [examples](https://github.com/micro/go-micro/tree/master/examples) directory for usage examples.
|
||||
|
||||
## License
|
||||
|
||||
Go Micro is Apache 2.0 licensed.
|
||||
|
51
examples/.github/workflows/tests.yml
vendored
Normal file
51
examples/.github/workflows/tests.yml
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
name: Run tests
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
|
||||
test:
|
||||
name: Test repo
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Set up Go 1.13
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.13
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Get dependencies
|
||||
run: |
|
||||
go get -v -t -d ./...
|
||||
|
||||
- name: Run tests
|
||||
id: tests
|
||||
env:
|
||||
IN_TRAVIS_CI: yes
|
||||
run: go test -v ./...
|
||||
|
||||
- name: Notify of test failure
|
||||
if: failure()
|
||||
uses: rtCamp/action-slack-notify@v2.0.0
|
||||
env:
|
||||
SLACK_CHANNEL: build
|
||||
SLACK_COLOR: '#BF280A'
|
||||
SLACK_ICON: https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png
|
||||
SLACK_TITLE: Tests Failed
|
||||
SLACK_USERNAME: GitHub Actions
|
||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
|
||||
- name: Notify of test success
|
||||
if: success()
|
||||
uses: rtCamp/action-slack-notify@v2.0.0
|
||||
env:
|
||||
SLACK_CHANNEL: build
|
||||
SLACK_COLOR: '#1FAD2B'
|
||||
SLACK_ICON: https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png
|
||||
SLACK_TITLE: Tests Passed
|
||||
SLACK_USERNAME: GitHub Actions
|
||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
|
191
examples/LICENSE
Normal file
191
examples/LICENSE
Normal file
@ -0,0 +1,191 @@
|
||||
|
||||
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
|
||||
|
||||
Copyright 2015 Asim Aslam.
|
||||
|
||||
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.
|
63
examples/README.md
Normal file
63
examples/README.md
Normal file
@ -0,0 +1,63 @@
|
||||
# Examples
|
||||
|
||||
This is a repository for micro examples. Feel free to contribute.
|
||||
|
||||
## Contents
|
||||
|
||||
- [api](api) - Provides API usage examples
|
||||
- [booking](booking) - A booking.com demo application
|
||||
- [broker](broker) - A example of using Broker for Publish and Subscribing.
|
||||
- [client](client) - Usage of the Client package to call a service.
|
||||
- [command](command) - An example of bot commands as micro services
|
||||
- [config](config) - Using Go Config for dynamic config
|
||||
- [event](event) - Using the API Gateway event handler
|
||||
- [filter](filter) - Filter nodes of a service when requesting
|
||||
- [flags](flags) - Using command line flags with a service
|
||||
- [form](form) - How to parse a form behind the micro api
|
||||
- [function](function) - Example of using Function programming model
|
||||
- [getip](getip) - Get the local and remote ip from metadata
|
||||
- [graceful](graceful) - Demonstrates graceful shutdown of a service
|
||||
- [greeter](greeter) - A complete greeter example (includes python, ruby examples)
|
||||
- [heartbeat](heartbeat) - Make services heartbeat with discovery for high availability
|
||||
- [helloworld](helloworld) - Hello world using micro
|
||||
- [kubernetes](kubernetes) - Examples of using the k8s registry and grpc
|
||||
- [metadata](metadata) - Extracting metadata from context of a request
|
||||
- [mocking](mocking) - Demonstrate mocking helloworld service
|
||||
- [noproto](noproto) - Use micro without protobuf or code generation, only go types
|
||||
- [options](options) - Setting options in the go-micro framework
|
||||
- [plugins](plugins) - How to use plugins
|
||||
- [pubsub](pubsub) - Example of using pubsub at the client/server level
|
||||
- [grpc](grpc) - Examples of how to use [go-micro/service/grpc](https://github.com/micro/go-micro/service/grpc)
|
||||
- [redirect](redirect) - An example of how to http redirect using an API service
|
||||
- [roundrobin](roundrobin) - A stateful client wrapper for true round robin of requests
|
||||
- [secure](secure) - Demonstrates use of transport secure option for self signed certs
|
||||
- [server](server) - Use of the Server package directly to server requests.
|
||||
- [service](service) - Example of the top level Service in go-micro.
|
||||
- [sharding](sharding) - An example of how to shard requests or use session affinity
|
||||
- [shutdown](shutdown) - Demonstrates graceful shutdown via context cancellation
|
||||
- [stream](stream) - An example of a streaming service and client
|
||||
- [template](template) - Api, web and srv service templates generated with the 'micro new' command
|
||||
- [tunnel](tunnel) - How to use connection tunneling with the tunnel package
|
||||
- [waitgroup](waitgroup) - Demonstrates how to use a waitgroup with a service
|
||||
- [wrapper](wrapper) - A simple example of using a log wrapper
|
||||
|
||||
## Community
|
||||
|
||||
Find contributions from the community via the [explorer](https://micro.mu/projects/)
|
||||
|
||||
## Install
|
||||
|
||||
Install [protoc](https://github.com/google/protobuf) for your environment. Then:
|
||||
|
||||
```shell
|
||||
# install protoc-gen-go
|
||||
go get github.com/golang/protobuf/{proto,protoc-gen-go}
|
||||
# install protoc-gen-micro
|
||||
go get github.com/micro/micro/v2/cmd/protoc-gen-micro@master
|
||||
```
|
||||
|
||||
To recompile any proto after changes:
|
||||
|
||||
```shell
|
||||
protoc --proto_path=$GOPATH/src:. --micro_out=. --go_out=. path/to/proto
|
||||
```
|
1
examples/_config.yml
Normal file
1
examples/_config.yml
Normal file
@ -0,0 +1 @@
|
||||
theme: jekyll-theme-architect
|
57
examples/api/README.md
Normal file
57
examples/api/README.md
Normal file
@ -0,0 +1,57 @@
|
||||
# API
|
||||
|
||||
This repo contains examples for using the micro api.
|
||||
|
||||
## Overview
|
||||
|
||||
The [micro api](https://github.com/micro/micro/tree/master/api) is an API gateway which serves HTTP and routes dynamically based on service discovery.
|
||||
|
||||
The micro api by default serves the namespace go.micro.api. Our service names include this plus a unique name e.g go.micro.api.example.
|
||||
You can change the namespace via the flag `--namespace=`.
|
||||
|
||||
The micro api has a number of different handlers which lets you define what kind of API services you want. See examples below. The handler
|
||||
can be set via the flag `--handler=`. The default handler is "rpc".
|
||||
|
||||
## Contents
|
||||
|
||||
- api - an rpc handler that provides the entire http headers and request
|
||||
- proxy - use the api as a http reverse proxy
|
||||
- rpc - make an rpc request to a go-micro app
|
||||
- meta - specify which handler to use via configuration in code
|
||||
|
||||
## Request Mapping
|
||||
|
||||
### API/RPC
|
||||
|
||||
Micro maps http paths to rpc services. The mapping table can be seen below.
|
||||
|
||||
The default namespace for the api is **go.micro.api** but you can set your own namespace via `--namespace`.
|
||||
|
||||
URLs are mapped as follows:
|
||||
|
||||
Path | Service | Method
|
||||
---- | ---- | ----
|
||||
/foo/bar | go.micro.api.foo | Foo.Bar
|
||||
/foo/bar/baz | go.micro.api.foo | Bar.Baz
|
||||
/foo/bar/baz/cat | go.micro.api.foo.bar | Baz.Cat
|
||||
|
||||
Versioned API URLs can easily be mapped to service names:
|
||||
|
||||
Path | Service | Method
|
||||
---- | ---- | ----
|
||||
/foo/bar | go.micro.api.foo | Foo.Bar
|
||||
/v1/foo/bar | go.micro.api.v1.foo | Foo.Bar
|
||||
/v1/foo/bar/baz | go.micro.api.v1.foo | Bar.Baz
|
||||
/v2/foo/bar | go.micro.api.v2.foo | Foo.Bar
|
||||
/v2/foo/bar/baz | go.micro.api.v2.foo | Bar.Baz
|
||||
|
||||
### Proxy Mapping
|
||||
|
||||
Starting the API with `--handler=http` will reverse proxy requests to backend services within the served API namespace (default: go.micro.api).
|
||||
|
||||
Example
|
||||
|
||||
Path | Service | Service Path
|
||||
--- | --- | ---
|
||||
/greeter | go.micro.api.greeter | /greeter
|
||||
/greeter/:name | go.micro.api.greeter | /greeter/:name
|
58
examples/api/api/README.md
Normal file
58
examples/api/api/README.md
Normal file
@ -0,0 +1,58 @@
|
||||
# API
|
||||
|
||||
This example makes use of the "api" handler.
|
||||
|
||||
The api expects you use the [api.Request/Response](https://github.com/micro/go-api/blob/master/proto/api.proto) protos.
|
||||
|
||||
The micro api request handler gives you full control over the http request and response while still leveraging RPC and
|
||||
any transport plugins that use other protocols beyond http in your stack such as grpc, nats, kafka.
|
||||
|
||||
## Usage
|
||||
|
||||
Run the micro API
|
||||
|
||||
```
|
||||
micro api --handler=api
|
||||
```
|
||||
|
||||
Run this example
|
||||
|
||||
```
|
||||
go run api.go
|
||||
```
|
||||
|
||||
|
||||
## Calling the service
|
||||
|
||||
Make a GET request to /example/call which will call go.micro.api.example Example.Call
|
||||
|
||||
```
|
||||
curl "http://localhost:8080/example/call?name=john"
|
||||
```
|
||||
|
||||
Make a POST request to /example/foo/bar which will call go.micro.api.example Foo.Bar
|
||||
|
||||
```
|
||||
curl -H 'Content-Type: application/json' -d '{}' http://localhost:8080/example/foo/bar
|
||||
```
|
||||
|
||||
## Set Namespace
|
||||
|
||||
Run the micro API with custom namespace
|
||||
|
||||
```
|
||||
micro api --handler=api --namespace=com.foobar.api
|
||||
```
|
||||
|
||||
or
|
||||
```
|
||||
MICRO_API_NAMESPACE=com.foobar.api micro api --handler=api
|
||||
```
|
||||
|
||||
Set service name with the namespace
|
||||
|
||||
```
|
||||
service := micro.NewService(
|
||||
micro.Name("com.foobar.api.example"),
|
||||
)
|
||||
```
|
91
examples/api/api/api.go
Normal file
91
examples/api/api/api.go
Normal file
@ -0,0 +1,91 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
proto "github.com/micro/examples/api/api/proto"
|
||||
"github.com/micro/go-micro/v2"
|
||||
api "github.com/micro/go-micro/v2/api/proto"
|
||||
"github.com/micro/go-micro/v2/errors"
|
||||
)
|
||||
|
||||
type Example struct{}
|
||||
|
||||
type Foo struct{}
|
||||
|
||||
// Example.Call is a method which will be served by http request /example/call
|
||||
// In the event we see /[service]/[method] the [service] is used as part of the method
|
||||
// E.g /example/call goes to go.micro.api.example Example.Call
|
||||
func (e *Example) Call(ctx context.Context, req *api.Request, rsp *api.Response) error {
|
||||
log.Print("Received Example.Call request")
|
||||
|
||||
// parse values from the get request
|
||||
name, ok := req.Get["name"]
|
||||
|
||||
if !ok || len(name.Values) == 0 {
|
||||
return errors.BadRequest("go.micro.api.example", "no content")
|
||||
}
|
||||
|
||||
// set response status
|
||||
rsp.StatusCode = 200
|
||||
|
||||
// respond with some json
|
||||
b, _ := json.Marshal(map[string]string{
|
||||
"message": "got your request " + strings.Join(name.Values, " "),
|
||||
})
|
||||
|
||||
// set json body
|
||||
rsp.Body = string(b)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Foo.Bar is a method which will be served by http request /example/foo/bar
|
||||
// Because Foo is not the same as the service name it is mapped beyond /example/
|
||||
func (f *Foo) Bar(ctx context.Context, req *api.Request, rsp *api.Response) error {
|
||||
log.Print("Received Foo.Bar request")
|
||||
|
||||
// check method
|
||||
if req.Method != "POST" {
|
||||
return errors.BadRequest("go.micro.api.example", "require post")
|
||||
}
|
||||
|
||||
// let's make sure we get json
|
||||
ct, ok := req.Header["Content-Type"]
|
||||
if !ok || len(ct.Values) == 0 {
|
||||
return errors.BadRequest("go.micro.api.example", "need content-type")
|
||||
}
|
||||
|
||||
if ct.Values[0] != "application/json" {
|
||||
return errors.BadRequest("go.micro.api.example", "expect application/json")
|
||||
}
|
||||
|
||||
// parse body
|
||||
var body map[string]interface{}
|
||||
json.Unmarshal([]byte(req.Body), &body)
|
||||
|
||||
// do something with parsed body
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
service := micro.NewService(
|
||||
micro.Name("go.micro.api.example"),
|
||||
)
|
||||
|
||||
service.Init()
|
||||
|
||||
// register example handler
|
||||
proto.RegisterExampleHandler(service.Server(), new(Example))
|
||||
|
||||
// register foo handler
|
||||
proto.RegisterFooHandler(service.Server(), new(Foo))
|
||||
|
||||
if err := service.Run(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
151
examples/api/api/proto/api.micro.go
Normal file
151
examples/api/api/proto/api.micro.go
Normal file
@ -0,0 +1,151 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: proto/api.proto
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
proto1 "github.com/micro/go-micro/v2/api/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
import (
|
||||
context "context"
|
||||
client "github.com/micro/go-micro/v2/client"
|
||||
server "github.com/micro/go-micro/v2/server"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ client.Option
|
||||
var _ server.Option
|
||||
|
||||
// Client API for Example service
|
||||
|
||||
type ExampleService interface {
|
||||
Call(ctx context.Context, in *proto1.Request, opts ...client.CallOption) (*proto1.Response, error)
|
||||
}
|
||||
|
||||
type exampleService struct {
|
||||
c client.Client
|
||||
name string
|
||||
}
|
||||
|
||||
func NewExampleService(name string, c client.Client) ExampleService {
|
||||
if c == nil {
|
||||
c = client.NewClient()
|
||||
}
|
||||
if len(name) == 0 {
|
||||
name = "example"
|
||||
}
|
||||
return &exampleService{
|
||||
c: c,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *exampleService) Call(ctx context.Context, in *proto1.Request, opts ...client.CallOption) (*proto1.Response, error) {
|
||||
req := c.c.NewRequest(c.name, "Example.Call", in)
|
||||
out := new(proto1.Response)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Example service
|
||||
|
||||
type ExampleHandler interface {
|
||||
Call(context.Context, *proto1.Request, *proto1.Response) error
|
||||
}
|
||||
|
||||
func RegisterExampleHandler(s server.Server, hdlr ExampleHandler, opts ...server.HandlerOption) error {
|
||||
type example interface {
|
||||
Call(ctx context.Context, in *proto1.Request, out *proto1.Response) error
|
||||
}
|
||||
type Example struct {
|
||||
example
|
||||
}
|
||||
h := &exampleHandler{hdlr}
|
||||
return s.Handle(s.NewHandler(&Example{h}, opts...))
|
||||
}
|
||||
|
||||
type exampleHandler struct {
|
||||
ExampleHandler
|
||||
}
|
||||
|
||||
func (h *exampleHandler) Call(ctx context.Context, in *proto1.Request, out *proto1.Response) error {
|
||||
return h.ExampleHandler.Call(ctx, in, out)
|
||||
}
|
||||
|
||||
// Client API for Foo service
|
||||
|
||||
type FooService interface {
|
||||
Bar(ctx context.Context, in *proto1.Request, opts ...client.CallOption) (*proto1.Response, error)
|
||||
}
|
||||
|
||||
type fooService struct {
|
||||
c client.Client
|
||||
name string
|
||||
}
|
||||
|
||||
func NewFooService(name string, c client.Client) FooService {
|
||||
if c == nil {
|
||||
c = client.NewClient()
|
||||
}
|
||||
if len(name) == 0 {
|
||||
name = "foo"
|
||||
}
|
||||
return &fooService{
|
||||
c: c,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *fooService) Bar(ctx context.Context, in *proto1.Request, opts ...client.CallOption) (*proto1.Response, error) {
|
||||
req := c.c.NewRequest(c.name, "Foo.Bar", in)
|
||||
out := new(proto1.Response)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Foo service
|
||||
|
||||
type FooHandler interface {
|
||||
Bar(context.Context, *proto1.Request, *proto1.Response) error
|
||||
}
|
||||
|
||||
func RegisterFooHandler(s server.Server, hdlr FooHandler, opts ...server.HandlerOption) error {
|
||||
type foo interface {
|
||||
Bar(ctx context.Context, in *proto1.Request, out *proto1.Response) error
|
||||
}
|
||||
type Foo struct {
|
||||
foo
|
||||
}
|
||||
h := &fooHandler{hdlr}
|
||||
return s.Handle(s.NewHandler(&Foo{h}, opts...))
|
||||
}
|
||||
|
||||
type fooHandler struct {
|
||||
FooHandler
|
||||
}
|
||||
|
||||
func (h *fooHandler) Bar(ctx context.Context, in *proto1.Request, out *proto1.Response) error {
|
||||
return h.FooHandler.Bar(ctx, in, out)
|
||||
}
|
37
examples/api/api/proto/api.pb.go
Normal file
37
examples/api/api/proto/api.pb.go
Normal file
@ -0,0 +1,37 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: proto/api.proto
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
_ "github.com/micro/go-micro/v2/api/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
func init() { proto.RegisterFile("proto/api.proto", fileDescriptor_ecf0878b123623e2) }
|
||||
|
||||
var fileDescriptor_ecf0878b123623e2 = []byte{
|
||||
// 135 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2f, 0x28, 0xca, 0x2f,
|
||||
0xc9, 0xd7, 0x4f, 0x2c, 0xc8, 0xd4, 0x03, 0xb3, 0xa4, 0x74, 0xd3, 0x33, 0x4b, 0x32, 0x4a, 0x93,
|
||||
0xf4, 0x92, 0xf3, 0x73, 0xf5, 0x73, 0x33, 0x93, 0x8b, 0xf2, 0xf5, 0xd3, 0xf3, 0x75, 0x21, 0x8c,
|
||||
0xc4, 0x82, 0x4c, 0x7d, 0x34, 0xe5, 0x46, 0x66, 0x5c, 0xec, 0xae, 0x15, 0x89, 0xb9, 0x05, 0x39,
|
||||
0xa9, 0x42, 0xda, 0x5c, 0x2c, 0xce, 0x89, 0x39, 0x39, 0x42, 0xfc, 0x7a, 0xe9, 0xf9, 0x7a, 0x20,
|
||||
0x15, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x52, 0x02, 0x08, 0x81, 0xe2, 0x82, 0xfc, 0xbc,
|
||||
0xe2, 0x54, 0x25, 0x06, 0x23, 0x43, 0x2e, 0x66, 0xb7, 0xfc, 0x7c, 0x21, 0x2d, 0x2e, 0x66, 0xa7,
|
||||
0xc4, 0x22, 0xa2, 0xb4, 0x24, 0xb1, 0x81, 0x6d, 0x34, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xf4,
|
||||
0x92, 0x9f, 0xad, 0xb3, 0x00, 0x00, 0x00,
|
||||
}
|
11
examples/api/api/proto/api.proto
Normal file
11
examples/api/api/proto/api.proto
Normal file
@ -0,0 +1,11 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "github.com/micro/go-micro/v2/api/proto/api.proto";
|
||||
|
||||
service Example {
|
||||
rpc Call(go.api.Request) returns(go.api.Response) {};
|
||||
}
|
||||
|
||||
service Foo {
|
||||
rpc Bar(go.api.Request) returns(go.api.Response) {};
|
||||
}
|
31
examples/api/meta/README.md
Normal file
31
examples/api/meta/README.md
Normal file
@ -0,0 +1,31 @@
|
||||
# Meta API
|
||||
|
||||
This example makes use of the micro API metadata handler.
|
||||
|
||||
This will allow us to write standard go-micro services and set the handler/endpoint via service discovery metadata.
|
||||
|
||||
## Usage
|
||||
|
||||
Run the micro API
|
||||
|
||||
```
|
||||
micro api
|
||||
```
|
||||
|
||||
Run this example. Note endpoint metadata when registering the handler
|
||||
|
||||
```
|
||||
go run meta.go
|
||||
```
|
||||
|
||||
Make a POST request to /example which will call go.micro.api.example Example.Call
|
||||
|
||||
```
|
||||
curl -H 'Content-Type: application/json' -d '{"name": "john"}' "http://localhost:8080/example"
|
||||
```
|
||||
|
||||
Make a POST request to /foo/bar which will call go.micro.api.example Foo.Bar
|
||||
|
||||
```
|
||||
curl -H 'Content-Type: application/json' -d '{}' http://localhost:8080/foo/bar
|
||||
```
|
78
examples/api/meta/meta.go
Normal file
78
examples/api/meta/meta.go
Normal file
@ -0,0 +1,78 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
proto "github.com/micro/examples/api/rpc/proto"
|
||||
"github.com/micro/go-micro/v2"
|
||||
"github.com/micro/go-micro/v2/api"
|
||||
rapi "github.com/micro/go-micro/v2/api/handler/api"
|
||||
"github.com/micro/go-micro/v2/api/handler/rpc"
|
||||
"github.com/micro/go-micro/v2/errors"
|
||||
|
||||
"context"
|
||||
)
|
||||
|
||||
type Example struct{}
|
||||
|
||||
type Foo struct{}
|
||||
|
||||
// Example.Call is a method which will be served by http request /example/call
|
||||
// In the event we see /[service]/[method] the [service] is used as part of the method
|
||||
// E.g /example/call goes to go.micro.api.example Example.Call
|
||||
func (e *Example) Call(ctx context.Context, req *proto.CallRequest, rsp *proto.CallResponse) error {
|
||||
log.Print("Received Example.Call request")
|
||||
|
||||
if len(req.Name) == 0 {
|
||||
return errors.BadRequest("go.micro.api.example", "no content")
|
||||
}
|
||||
|
||||
rsp.Message = "got your request " + req.Name
|
||||
return nil
|
||||
}
|
||||
|
||||
// Foo.Bar is a method which will be served by http request /example/foo/bar
|
||||
// Because Foo is not the same as the service name it is mapped beyond /example/
|
||||
func (f *Foo) Bar(ctx context.Context, req *proto.EmptyRequest, rsp *proto.EmptyResponse) error {
|
||||
log.Print("Received Foo.Bar request")
|
||||
|
||||
// noop
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
service := micro.NewService(
|
||||
micro.Name("go.micro.api.example"),
|
||||
)
|
||||
|
||||
service.Init()
|
||||
|
||||
// register example handler
|
||||
proto.RegisterExampleHandler(service.Server(), new(Example), api.WithEndpoint(&api.Endpoint{
|
||||
// The RPC method
|
||||
Name: "Example.Call",
|
||||
// The HTTP paths. This can be a POSIX regex
|
||||
Path: []string{"/example"},
|
||||
// The HTTP Methods for this endpoint
|
||||
Method: []string{"POST"},
|
||||
// The API handler to use
|
||||
Handler: rpc.Handler,
|
||||
}))
|
||||
|
||||
// register foo handler
|
||||
proto.RegisterFooHandler(service.Server(), new(Foo), api.WithEndpoint(&api.Endpoint{
|
||||
// The RPC method
|
||||
Name: "Foo.Bar",
|
||||
// The HTTP paths. This can be a POSIX regex
|
||||
Path: []string{"/foo/bar"},
|
||||
// The HTTP Methods for this endpoint
|
||||
Method: []string{"POST"},
|
||||
// The API handler to use
|
||||
Handler: rapi.Handler,
|
||||
}))
|
||||
|
||||
if err := service.Run(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
160
examples/api/meta/proto/api.micro.go
Normal file
160
examples/api/meta/proto/api.micro.go
Normal file
@ -0,0 +1,160 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: github.com/micro/examples/api/meta/proto/api.proto
|
||||
|
||||
/*
|
||||
Package api is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
github.com/micro/examples/api/meta/proto/api.proto
|
||||
|
||||
It has these top-level messages:
|
||||
CallRequest
|
||||
CallResponse
|
||||
EmptyRequest
|
||||
EmptyResponse
|
||||
*/
|
||||
package api
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "context"
|
||||
client "github.com/micro/go-micro/v2/client"
|
||||
server "github.com/micro/go-micro/v2/server"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ client.Option
|
||||
var _ server.Option
|
||||
|
||||
// Client API for Example service
|
||||
|
||||
type ExampleService interface {
|
||||
Call(ctx context.Context, in *CallRequest, opts ...client.CallOption) (*CallResponse, error)
|
||||
}
|
||||
|
||||
type exampleService struct {
|
||||
c client.Client
|
||||
serviceName string
|
||||
}
|
||||
|
||||
func NewExampleService(serviceName string, c client.Client) ExampleService {
|
||||
if c == nil {
|
||||
c = client.NewClient()
|
||||
}
|
||||
if len(serviceName) == 0 {
|
||||
serviceName = "example"
|
||||
}
|
||||
return &exampleService{
|
||||
c: c,
|
||||
serviceName: serviceName,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *exampleService) Call(ctx context.Context, in *CallRequest, opts ...client.CallOption) (*CallResponse, error) {
|
||||
req := c.c.NewRequest(c.serviceName, "Example.Call", in)
|
||||
out := new(CallResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Example service
|
||||
|
||||
type ExampleHandler interface {
|
||||
Call(context.Context, *CallRequest, *CallResponse) error
|
||||
}
|
||||
|
||||
func RegisterExampleHandler(s server.Server, hdlr ExampleHandler, opts ...server.HandlerOption) {
|
||||
type example interface {
|
||||
Call(ctx context.Context, in *CallRequest, out *CallResponse) error
|
||||
}
|
||||
type Example struct {
|
||||
example
|
||||
}
|
||||
h := &exampleHandler{hdlr}
|
||||
s.Handle(s.NewHandler(&Example{h}, opts...))
|
||||
}
|
||||
|
||||
type exampleHandler struct {
|
||||
ExampleHandler
|
||||
}
|
||||
|
||||
func (h *exampleHandler) Call(ctx context.Context, in *CallRequest, out *CallResponse) error {
|
||||
return h.ExampleHandler.Call(ctx, in, out)
|
||||
}
|
||||
|
||||
// Client API for Foo service
|
||||
|
||||
type FooService interface {
|
||||
Bar(ctx context.Context, in *EmptyRequest, opts ...client.CallOption) (*EmptyResponse, error)
|
||||
}
|
||||
|
||||
type fooService struct {
|
||||
c client.Client
|
||||
serviceName string
|
||||
}
|
||||
|
||||
func NewFooService(serviceName string, c client.Client) FooService {
|
||||
if c == nil {
|
||||
c = client.NewClient()
|
||||
}
|
||||
if len(serviceName) == 0 {
|
||||
serviceName = "foo"
|
||||
}
|
||||
return &fooService{
|
||||
c: c,
|
||||
serviceName: serviceName,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *fooService) Bar(ctx context.Context, in *EmptyRequest, opts ...client.CallOption) (*EmptyResponse, error) {
|
||||
req := c.c.NewRequest(c.serviceName, "Foo.Bar", in)
|
||||
out := new(EmptyResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Foo service
|
||||
|
||||
type FooHandler interface {
|
||||
Bar(context.Context, *EmptyRequest, *EmptyResponse) error
|
||||
}
|
||||
|
||||
func RegisterFooHandler(s server.Server, hdlr FooHandler, opts ...server.HandlerOption) {
|
||||
type foo interface {
|
||||
Bar(ctx context.Context, in *EmptyRequest, out *EmptyResponse) error
|
||||
}
|
||||
type Foo struct {
|
||||
foo
|
||||
}
|
||||
h := &fooHandler{hdlr}
|
||||
s.Handle(s.NewHandler(&Foo{h}, opts...))
|
||||
}
|
||||
|
||||
type fooHandler struct {
|
||||
FooHandler
|
||||
}
|
||||
|
||||
func (h *fooHandler) Bar(ctx context.Context, in *EmptyRequest, out *EmptyResponse) error {
|
||||
return h.FooHandler.Bar(ctx, in, out)
|
||||
}
|
246
examples/api/meta/proto/api.pb.go
Normal file
246
examples/api/meta/proto/api.pb.go
Normal file
@ -0,0 +1,246 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: github.com/micro/examples/api/meta/proto/api.proto
|
||||
|
||||
/*
|
||||
Package api is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
github.com/micro/examples/api/meta/proto/api.proto
|
||||
|
||||
It has these top-level messages:
|
||||
CallRequest
|
||||
CallResponse
|
||||
EmptyRequest
|
||||
EmptyResponse
|
||||
*/
|
||||
package api
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type CallRequest struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
}
|
||||
|
||||
func (m *CallRequest) Reset() { *m = CallRequest{} }
|
||||
func (m *CallRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*CallRequest) ProtoMessage() {}
|
||||
func (*CallRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func (m *CallRequest) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type CallResponse struct {
|
||||
Message string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"`
|
||||
}
|
||||
|
||||
func (m *CallResponse) Reset() { *m = CallResponse{} }
|
||||
func (m *CallResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*CallResponse) ProtoMessage() {}
|
||||
func (*CallResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *CallResponse) GetMessage() string {
|
||||
if m != nil {
|
||||
return m.Message
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type EmptyRequest struct {
|
||||
}
|
||||
|
||||
func (m *EmptyRequest) Reset() { *m = EmptyRequest{} }
|
||||
func (m *EmptyRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*EmptyRequest) ProtoMessage() {}
|
||||
func (*EmptyRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
|
||||
type EmptyResponse struct {
|
||||
}
|
||||
|
||||
func (m *EmptyResponse) Reset() { *m = EmptyResponse{} }
|
||||
func (m *EmptyResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*EmptyResponse) ProtoMessage() {}
|
||||
func (*EmptyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*CallRequest)(nil), "CallRequest")
|
||||
proto.RegisterType((*CallResponse)(nil), "CallResponse")
|
||||
proto.RegisterType((*EmptyRequest)(nil), "EmptyRequest")
|
||||
proto.RegisterType((*EmptyResponse)(nil), "EmptyResponse")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// 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.SupportPackageIsVersion4
|
||||
|
||||
// Client API for Example service
|
||||
|
||||
type ExampleClient interface {
|
||||
Call(ctx context.Context, in *CallRequest, opts ...grpc.CallOption) (*CallResponse, error)
|
||||
}
|
||||
|
||||
type exampleClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewExampleClient(cc *grpc.ClientConn) ExampleClient {
|
||||
return &exampleClient{cc}
|
||||
}
|
||||
|
||||
func (c *exampleClient) Call(ctx context.Context, in *CallRequest, opts ...grpc.CallOption) (*CallResponse, error) {
|
||||
out := new(CallResponse)
|
||||
err := grpc.Invoke(ctx, "/Example/Call", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Example service
|
||||
|
||||
type ExampleServer interface {
|
||||
Call(context.Context, *CallRequest) (*CallResponse, error)
|
||||
}
|
||||
|
||||
func RegisterExampleServer(s *grpc.Server, srv ExampleServer) {
|
||||
s.RegisterService(&_Example_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Example_Call_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(CallRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ExampleServer).Call(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Example/Call",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ExampleServer).Call(ctx, req.(*CallRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Example_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "Example",
|
||||
HandlerType: (*ExampleServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Call",
|
||||
Handler: _Example_Call_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "github.com/micro/examples/api/meta/proto/api.proto",
|
||||
}
|
||||
|
||||
// Client API for Foo service
|
||||
|
||||
type FooClient interface {
|
||||
Bar(ctx context.Context, in *EmptyRequest, opts ...grpc.CallOption) (*EmptyResponse, error)
|
||||
}
|
||||
|
||||
type fooClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewFooClient(cc *grpc.ClientConn) FooClient {
|
||||
return &fooClient{cc}
|
||||
}
|
||||
|
||||
func (c *fooClient) Bar(ctx context.Context, in *EmptyRequest, opts ...grpc.CallOption) (*EmptyResponse, error) {
|
||||
out := new(EmptyResponse)
|
||||
err := grpc.Invoke(ctx, "/Foo/Bar", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Foo service
|
||||
|
||||
type FooServer interface {
|
||||
Bar(context.Context, *EmptyRequest) (*EmptyResponse, error)
|
||||
}
|
||||
|
||||
func RegisterFooServer(s *grpc.Server, srv FooServer) {
|
||||
s.RegisterService(&_Foo_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Foo_Bar_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(EmptyRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(FooServer).Bar(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Foo/Bar",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(FooServer).Bar(ctx, req.(*EmptyRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Foo_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "Foo",
|
||||
HandlerType: (*FooServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Bar",
|
||||
Handler: _Foo_Bar_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "github.com/micro/examples/api/meta/proto/api.proto",
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("github.com/micro/examples/api/meta/proto/api.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 203 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x8f, 0xd1, 0x6a, 0x83, 0x30,
|
||||
0x14, 0x86, 0x75, 0xca, 0x64, 0x67, 0xea, 0x20, 0x57, 0xe2, 0xd5, 0x16, 0xd8, 0xf0, 0x66, 0xc9,
|
||||
0x70, 0x6f, 0xd0, 0x62, 0x1f, 0xc0, 0x37, 0x88, 0x72, 0xb0, 0x82, 0x31, 0xa9, 0x89, 0xd0, 0xbe,
|
||||
0x7d, 0x31, 0x5a, 0xb0, 0x77, 0xff, 0x07, 0x7f, 0xbe, 0x3f, 0x07, 0xca, 0xae, 0xb7, 0xe7, 0xb9,
|
||||
0x61, 0xad, 0x92, 0x5c, 0xf6, 0xed, 0xa4, 0x38, 0x5e, 0x85, 0xd4, 0x03, 0x1a, 0x2e, 0x74, 0xcf,
|
||||
0x25, 0x5a, 0xc1, 0xf5, 0xa4, 0xac, 0x5a, 0x90, 0xb9, 0x44, 0xbf, 0xe0, 0xfd, 0x28, 0x86, 0xa1,
|
||||
0xc6, 0xcb, 0x8c, 0xc6, 0x12, 0x02, 0xe1, 0x28, 0x24, 0x66, 0xfe, 0xa7, 0x5f, 0xbc, 0xd5, 0x2e,
|
||||
0xd3, 0x02, 0xe2, 0xb5, 0x62, 0xb4, 0x1a, 0x0d, 0x92, 0x0c, 0x22, 0x89, 0xc6, 0x88, 0x0e, 0xb3,
|
||||
0x17, 0x57, 0x7b, 0x20, 0x4d, 0x21, 0xae, 0xa4, 0xb6, 0xb7, 0xcd, 0x46, 0x3f, 0x20, 0xd9, 0x78,
|
||||
0x7d, 0x5a, 0xfe, 0x41, 0x54, 0xad, 0x5f, 0x22, 0xdf, 0x10, 0x2e, 0x56, 0x12, 0xb3, 0xdd, 0x7e,
|
||||
0x9e, 0xb0, 0xfd, 0x14, 0xf5, 0xca, 0x5f, 0x08, 0x4e, 0x4a, 0x91, 0x1f, 0x08, 0x0e, 0x62, 0x22,
|
||||
0x09, 0xdb, 0xfb, 0xf3, 0x94, 0x3d, 0xe9, 0xa9, 0xd7, 0xbc, 0xba, 0xab, 0xfe, 0xef, 0x01, 0x00,
|
||||
0x00, 0xff, 0xff, 0x14, 0x42, 0xb8, 0x1d, 0x0b, 0x01, 0x00, 0x00,
|
||||
}
|
23
examples/api/meta/proto/api.proto
Normal file
23
examples/api/meta/proto/api.proto
Normal file
@ -0,0 +1,23 @@
|
||||
syntax = "proto3";
|
||||
|
||||
service Example {
|
||||
rpc Call(CallRequest) returns(CallResponse) {};
|
||||
}
|
||||
|
||||
service Foo {
|
||||
rpc Bar(EmptyRequest) returns(EmptyResponse) {};
|
||||
}
|
||||
|
||||
message CallRequest {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message CallResponse {
|
||||
string message = 2;
|
||||
}
|
||||
|
||||
message EmptyRequest {
|
||||
}
|
||||
|
||||
message EmptyResponse {
|
||||
}
|
32
examples/api/proxy/README.md
Normal file
32
examples/api/proxy/README.md
Normal file
@ -0,0 +1,32 @@
|
||||
# Proxy API
|
||||
|
||||
This is an example of using the micro api as a http proxy.
|
||||
|
||||
Using the api as a http proxy gives you complete control over what languages or libraries to use
|
||||
at the API layer. In this case we're using go-web to easily register http services.
|
||||
|
||||
## Usage
|
||||
|
||||
Run micro api with http proxy handler
|
||||
|
||||
```
|
||||
micro api --handler=http
|
||||
```
|
||||
|
||||
Run this proxy service
|
||||
|
||||
```
|
||||
go run proxy.go
|
||||
```
|
||||
|
||||
Make a GET request to /example/call which will call go.micro.api.example Example.Call
|
||||
|
||||
```
|
||||
curl "http://localhost:8080/example/call?name=john"
|
||||
```
|
||||
|
||||
Make a POST request to /example/foo/bar which will call go.micro.api.example Foo.Bar
|
||||
|
||||
```
|
||||
curl -H 'Content-Type: application/json' -d '{}' http://localhost:8080/example/foo/bar
|
||||
```
|
84
examples/api/proxy/proxy.go
Normal file
84
examples/api/proxy/proxy.go
Normal file
@ -0,0 +1,84 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/micro/go-micro/v2/errors"
|
||||
"github.com/micro/go-micro/v2/web"
|
||||
)
|
||||
|
||||
// exampleCall will handle /example/call
|
||||
func exampleCall(w http.ResponseWriter, r *http.Request) {
|
||||
r.ParseForm()
|
||||
// get name
|
||||
name := r.Form.Get("name")
|
||||
|
||||
if len(name) == 0 {
|
||||
http.Error(
|
||||
w,
|
||||
errors.BadRequest("go.micro.api.example", "no content").Error(),
|
||||
400,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// marshal response
|
||||
b, _ := json.Marshal(map[string]interface{}{
|
||||
"message": "got your message " + name,
|
||||
})
|
||||
|
||||
// write response
|
||||
w.Write(b)
|
||||
}
|
||||
|
||||
// exampleFooBar will handle /example/foo/bar
|
||||
func exampleFooBar(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "POST" {
|
||||
http.Error(
|
||||
w,
|
||||
errors.BadRequest("go.micro.api.example", "require post").Error(),
|
||||
400,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if len(r.Header.Get("Content-Type")) == 0 {
|
||||
http.Error(
|
||||
w,
|
||||
errors.BadRequest("go.micro.api.example", "need content-type").Error(),
|
||||
400,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if r.Header.Get("Content-Type") != "application/json" {
|
||||
http.Error(
|
||||
w,
|
||||
errors.BadRequest("go.micro.api.example", "expect application/json").Error(),
|
||||
400,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// do something
|
||||
}
|
||||
|
||||
func main() {
|
||||
// we're using go-web for convenience since it registers with discovery
|
||||
service := web.NewService(
|
||||
web.Name("go.micro.api.example"),
|
||||
)
|
||||
|
||||
service.HandleFunc("/example/call", exampleCall)
|
||||
service.HandleFunc("/example/foo/bar", exampleFooBar)
|
||||
|
||||
if err := service.Init(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := service.Run(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
33
examples/api/rpc/README.md
Normal file
33
examples/api/rpc/README.md
Normal file
@ -0,0 +1,33 @@
|
||||
# RPC API
|
||||
|
||||
This example makes use of the micro API with the RPC handler.
|
||||
|
||||
The api in this mode lets you serve http while routing to standard go-micro services via RPC.
|
||||
|
||||
The micro api with rpc handler only supports POST method and expects content-type of application/json or application/protobuf.
|
||||
|
||||
## Usage
|
||||
|
||||
Run the micro API with the rpc handler
|
||||
|
||||
```
|
||||
micro api --handler=rpc
|
||||
```
|
||||
|
||||
Run this example
|
||||
|
||||
```
|
||||
go run rpc.go
|
||||
```
|
||||
|
||||
Make a POST request to /example/call which will call go.micro.api.example Example.Call
|
||||
|
||||
```
|
||||
curl -H 'Content-Type: application/json' -d '{"name": "john"}' "http://localhost:8080/example/call"
|
||||
```
|
||||
|
||||
Make a POST request to /example/foo/bar which will call go.micro.api.example Foo.Bar
|
||||
|
||||
```
|
||||
curl -H 'Content-Type: application/json' -d '{}' http://localhost:8080/example/foo/bar
|
||||
```
|
160
examples/api/rpc/proto/api.micro.go
Normal file
160
examples/api/rpc/proto/api.micro.go
Normal file
@ -0,0 +1,160 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: github.com/micro/examples/api/rpc/proto/api.proto
|
||||
|
||||
/*
|
||||
Package api is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
github.com/micro/examples/api/rpc/proto/api.proto
|
||||
|
||||
It has these top-level messages:
|
||||
CallRequest
|
||||
CallResponse
|
||||
EmptyRequest
|
||||
EmptyResponse
|
||||
*/
|
||||
package api
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "context"
|
||||
client "github.com/micro/go-micro/v2/client"
|
||||
server "github.com/micro/go-micro/v2/server"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ client.Option
|
||||
var _ server.Option
|
||||
|
||||
// Client API for Example service
|
||||
|
||||
type ExampleService interface {
|
||||
Call(ctx context.Context, in *CallRequest, opts ...client.CallOption) (*CallResponse, error)
|
||||
}
|
||||
|
||||
type exampleService struct {
|
||||
c client.Client
|
||||
serviceName string
|
||||
}
|
||||
|
||||
func NewExampleService(serviceName string, c client.Client) ExampleService {
|
||||
if c == nil {
|
||||
c = client.NewClient()
|
||||
}
|
||||
if len(serviceName) == 0 {
|
||||
serviceName = "example"
|
||||
}
|
||||
return &exampleService{
|
||||
c: c,
|
||||
serviceName: serviceName,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *exampleService) Call(ctx context.Context, in *CallRequest, opts ...client.CallOption) (*CallResponse, error) {
|
||||
req := c.c.NewRequest(c.serviceName, "Example.Call", in)
|
||||
out := new(CallResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Example service
|
||||
|
||||
type ExampleHandler interface {
|
||||
Call(context.Context, *CallRequest, *CallResponse) error
|
||||
}
|
||||
|
||||
func RegisterExampleHandler(s server.Server, hdlr ExampleHandler, opts ...server.HandlerOption) {
|
||||
type example interface {
|
||||
Call(ctx context.Context, in *CallRequest, out *CallResponse) error
|
||||
}
|
||||
type Example struct {
|
||||
example
|
||||
}
|
||||
h := &exampleHandler{hdlr}
|
||||
s.Handle(s.NewHandler(&Example{h}, opts...))
|
||||
}
|
||||
|
||||
type exampleHandler struct {
|
||||
ExampleHandler
|
||||
}
|
||||
|
||||
func (h *exampleHandler) Call(ctx context.Context, in *CallRequest, out *CallResponse) error {
|
||||
return h.ExampleHandler.Call(ctx, in, out)
|
||||
}
|
||||
|
||||
// Client API for Foo service
|
||||
|
||||
type FooService interface {
|
||||
Bar(ctx context.Context, in *EmptyRequest, opts ...client.CallOption) (*EmptyResponse, error)
|
||||
}
|
||||
|
||||
type fooService struct {
|
||||
c client.Client
|
||||
serviceName string
|
||||
}
|
||||
|
||||
func NewFooService(serviceName string, c client.Client) FooService {
|
||||
if c == nil {
|
||||
c = client.NewClient()
|
||||
}
|
||||
if len(serviceName) == 0 {
|
||||
serviceName = "foo"
|
||||
}
|
||||
return &fooService{
|
||||
c: c,
|
||||
serviceName: serviceName,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *fooService) Bar(ctx context.Context, in *EmptyRequest, opts ...client.CallOption) (*EmptyResponse, error) {
|
||||
req := c.c.NewRequest(c.serviceName, "Foo.Bar", in)
|
||||
out := new(EmptyResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Foo service
|
||||
|
||||
type FooHandler interface {
|
||||
Bar(context.Context, *EmptyRequest, *EmptyResponse) error
|
||||
}
|
||||
|
||||
func RegisterFooHandler(s server.Server, hdlr FooHandler, opts ...server.HandlerOption) {
|
||||
type foo interface {
|
||||
Bar(ctx context.Context, in *EmptyRequest, out *EmptyResponse) error
|
||||
}
|
||||
type Foo struct {
|
||||
foo
|
||||
}
|
||||
h := &fooHandler{hdlr}
|
||||
s.Handle(s.NewHandler(&Foo{h}, opts...))
|
||||
}
|
||||
|
||||
type fooHandler struct {
|
||||
FooHandler
|
||||
}
|
||||
|
||||
func (h *fooHandler) Bar(ctx context.Context, in *EmptyRequest, out *EmptyResponse) error {
|
||||
return h.FooHandler.Bar(ctx, in, out)
|
||||
}
|
246
examples/api/rpc/proto/api.pb.go
Normal file
246
examples/api/rpc/proto/api.pb.go
Normal file
@ -0,0 +1,246 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: github.com/micro/examples/api/rpc/proto/api.proto
|
||||
|
||||
/*
|
||||
Package api is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
github.com/micro/examples/api/rpc/proto/api.proto
|
||||
|
||||
It has these top-level messages:
|
||||
CallRequest
|
||||
CallResponse
|
||||
EmptyRequest
|
||||
EmptyResponse
|
||||
*/
|
||||
package api
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type CallRequest struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
}
|
||||
|
||||
func (m *CallRequest) Reset() { *m = CallRequest{} }
|
||||
func (m *CallRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*CallRequest) ProtoMessage() {}
|
||||
func (*CallRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func (m *CallRequest) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type CallResponse struct {
|
||||
Message string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"`
|
||||
}
|
||||
|
||||
func (m *CallResponse) Reset() { *m = CallResponse{} }
|
||||
func (m *CallResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*CallResponse) ProtoMessage() {}
|
||||
func (*CallResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *CallResponse) GetMessage() string {
|
||||
if m != nil {
|
||||
return m.Message
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type EmptyRequest struct {
|
||||
}
|
||||
|
||||
func (m *EmptyRequest) Reset() { *m = EmptyRequest{} }
|
||||
func (m *EmptyRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*EmptyRequest) ProtoMessage() {}
|
||||
func (*EmptyRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
|
||||
type EmptyResponse struct {
|
||||
}
|
||||
|
||||
func (m *EmptyResponse) Reset() { *m = EmptyResponse{} }
|
||||
func (m *EmptyResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*EmptyResponse) ProtoMessage() {}
|
||||
func (*EmptyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*CallRequest)(nil), "CallRequest")
|
||||
proto.RegisterType((*CallResponse)(nil), "CallResponse")
|
||||
proto.RegisterType((*EmptyRequest)(nil), "EmptyRequest")
|
||||
proto.RegisterType((*EmptyResponse)(nil), "EmptyResponse")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// 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.SupportPackageIsVersion4
|
||||
|
||||
// Client API for Example service
|
||||
|
||||
type ExampleClient interface {
|
||||
Call(ctx context.Context, in *CallRequest, opts ...grpc.CallOption) (*CallResponse, error)
|
||||
}
|
||||
|
||||
type exampleClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewExampleClient(cc *grpc.ClientConn) ExampleClient {
|
||||
return &exampleClient{cc}
|
||||
}
|
||||
|
||||
func (c *exampleClient) Call(ctx context.Context, in *CallRequest, opts ...grpc.CallOption) (*CallResponse, error) {
|
||||
out := new(CallResponse)
|
||||
err := grpc.Invoke(ctx, "/Example/Call", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Example service
|
||||
|
||||
type ExampleServer interface {
|
||||
Call(context.Context, *CallRequest) (*CallResponse, error)
|
||||
}
|
||||
|
||||
func RegisterExampleServer(s *grpc.Server, srv ExampleServer) {
|
||||
s.RegisterService(&_Example_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Example_Call_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(CallRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ExampleServer).Call(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Example/Call",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ExampleServer).Call(ctx, req.(*CallRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Example_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "Example",
|
||||
HandlerType: (*ExampleServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Call",
|
||||
Handler: _Example_Call_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "github.com/micro/examples/api/rpc/proto/api.proto",
|
||||
}
|
||||
|
||||
// Client API for Foo service
|
||||
|
||||
type FooClient interface {
|
||||
Bar(ctx context.Context, in *EmptyRequest, opts ...grpc.CallOption) (*EmptyResponse, error)
|
||||
}
|
||||
|
||||
type fooClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewFooClient(cc *grpc.ClientConn) FooClient {
|
||||
return &fooClient{cc}
|
||||
}
|
||||
|
||||
func (c *fooClient) Bar(ctx context.Context, in *EmptyRequest, opts ...grpc.CallOption) (*EmptyResponse, error) {
|
||||
out := new(EmptyResponse)
|
||||
err := grpc.Invoke(ctx, "/Foo/Bar", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Foo service
|
||||
|
||||
type FooServer interface {
|
||||
Bar(context.Context, *EmptyRequest) (*EmptyResponse, error)
|
||||
}
|
||||
|
||||
func RegisterFooServer(s *grpc.Server, srv FooServer) {
|
||||
s.RegisterService(&_Foo_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Foo_Bar_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(EmptyRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(FooServer).Bar(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/Foo/Bar",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(FooServer).Bar(ctx, req.(*EmptyRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Foo_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "Foo",
|
||||
HandlerType: (*FooServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Bar",
|
||||
Handler: _Foo_Bar_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "github.com/micro/examples/api/rpc/proto/api.proto",
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("github.com/micro/examples/api/rpc/proto/api.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 203 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x8f, 0x51, 0x6a, 0x84, 0x30,
|
||||
0x14, 0x45, 0xb5, 0x4a, 0xa5, 0xaf, 0x6a, 0x21, 0x5f, 0xe2, 0x57, 0x1b, 0x68, 0xf1, 0xa7, 0x49,
|
||||
0x6b, 0x77, 0xd0, 0x62, 0x17, 0xe0, 0x0e, 0xa2, 0x3c, 0xac, 0x60, 0x4c, 0x9a, 0x44, 0x98, 0xd9,
|
||||
0xfd, 0x60, 0x74, 0xc0, 0xf9, 0xbb, 0x07, 0x6e, 0xce, 0xcd, 0x83, 0xcf, 0x61, 0x74, 0x7f, 0x4b,
|
||||
0xc7, 0x7a, 0x25, 0xb9, 0x1c, 0x7b, 0xa3, 0x38, 0x9e, 0x84, 0xd4, 0x13, 0x5a, 0x2e, 0xf4, 0xc8,
|
||||
0x8d, 0xee, 0xb9, 0x36, 0xca, 0xa9, 0x95, 0x98, 0x4f, 0xf4, 0x05, 0x1e, 0x7f, 0xc4, 0x34, 0xb5,
|
||||
0xf8, 0xbf, 0xa0, 0x75, 0x84, 0x40, 0x3c, 0x0b, 0x89, 0x45, 0xf8, 0x1c, 0x56, 0x0f, 0xad, 0xcf,
|
||||
0xb4, 0x82, 0x74, 0xab, 0x58, 0xad, 0x66, 0x8b, 0xa4, 0x80, 0x44, 0xa2, 0xb5, 0x62, 0xc0, 0xe2,
|
||||
0xce, 0xd7, 0xae, 0x48, 0x73, 0x48, 0x1b, 0xa9, 0xdd, 0x79, 0xb7, 0xd1, 0x27, 0xc8, 0x76, 0xde,
|
||||
0x9e, 0xd6, 0x1f, 0x90, 0x34, 0xdb, 0x8f, 0xc8, 0x2b, 0xc4, 0xab, 0x95, 0xa4, 0xec, 0xb0, 0x5f,
|
||||
0x66, 0xec, 0x38, 0x45, 0x83, 0xfa, 0x1d, 0xa2, 0x5f, 0xa5, 0xc8, 0x1b, 0x44, 0xdf, 0xc2, 0x90,
|
||||
0x8c, 0x1d, 0xfd, 0x65, 0xce, 0x6e, 0xf4, 0x34, 0xe8, 0xee, 0xfd, 0x55, 0x5f, 0x97, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0x81, 0x2d, 0x74, 0x3d, 0x0a, 0x01, 0x00, 0x00,
|
||||
}
|
23
examples/api/rpc/proto/api.proto
Normal file
23
examples/api/rpc/proto/api.proto
Normal file
@ -0,0 +1,23 @@
|
||||
syntax = "proto3";
|
||||
|
||||
service Example {
|
||||
rpc Call(CallRequest) returns(CallResponse) {};
|
||||
}
|
||||
|
||||
service Foo {
|
||||
rpc Bar(EmptyRequest) returns(EmptyResponse) {};
|
||||
}
|
||||
|
||||
message CallRequest {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message CallResponse {
|
||||
string message = 2;
|
||||
}
|
||||
|
||||
message EmptyRequest {
|
||||
}
|
||||
|
||||
message EmptyResponse {
|
||||
}
|
57
examples/api/rpc/rpc.go
Normal file
57
examples/api/rpc/rpc.go
Normal file
@ -0,0 +1,57 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
proto "github.com/micro/examples/api/rpc/proto"
|
||||
"github.com/micro/go-micro/v2"
|
||||
"github.com/micro/go-micro/v2/errors"
|
||||
|
||||
"context"
|
||||
)
|
||||
|
||||
type Example struct{}
|
||||
|
||||
type Foo struct{}
|
||||
|
||||
// Example.Call is a method which will be served by http request /example/call
|
||||
// In the event we see /[service]/[method] the [service] is used as part of the method
|
||||
// E.g /example/call goes to go.micro.api.example Example.Call
|
||||
func (e *Example) Call(ctx context.Context, req *proto.CallRequest, rsp *proto.CallResponse) error {
|
||||
log.Print("Received Example.Call request")
|
||||
|
||||
if len(req.Name) == 0 {
|
||||
return errors.BadRequest("go.micro.api.example", "no content")
|
||||
}
|
||||
|
||||
rsp.Message = "got your request " + req.Name
|
||||
return nil
|
||||
}
|
||||
|
||||
// Foo.Bar is a method which will be served by http request /example/foo/bar
|
||||
// Because Foo is not the same as the service name it is mapped beyond /example/
|
||||
func (f *Foo) Bar(ctx context.Context, req *proto.EmptyRequest, rsp *proto.EmptyResponse) error {
|
||||
log.Print("Received Foo.Bar request")
|
||||
|
||||
// noop
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
service := micro.NewService(
|
||||
micro.Name("go.micro.api.example"),
|
||||
)
|
||||
|
||||
service.Init()
|
||||
|
||||
// register example handler
|
||||
proto.RegisterExampleHandler(service.Server(), new(Example))
|
||||
|
||||
// register foo handler
|
||||
proto.RegisterFooHandler(service.Server(), new(Foo))
|
||||
|
||||
if err := service.Run(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
22
examples/booking/Makefile
Normal file
22
examples/booking/Makefile
Normal file
@ -0,0 +1,22 @@
|
||||
.PHONY: proto data build
|
||||
|
||||
proto:
|
||||
for d in api srv; do \
|
||||
for f in $$d/**/proto/*.proto; do \
|
||||
protoc --proto_path=${GOPATH}/src:. --micro_out=. --go_out=. $$f; \
|
||||
echo compiled: $$f; \
|
||||
done \
|
||||
done
|
||||
|
||||
lint:
|
||||
./bin/lint.sh
|
||||
|
||||
build:
|
||||
./bin/build.sh
|
||||
|
||||
data:
|
||||
go-bindata -o data/bindata.go -pkg data data/*.json
|
||||
|
||||
run:
|
||||
docker-compose build
|
||||
docker-compose up
|
107
examples/booking/README.md
Normal file
107
examples/booking/README.md
Normal file
@ -0,0 +1,107 @@
|
||||
# Booking.com Example
|
||||
|
||||
This is [@harlow](https://github.com/harlow)'s [go-micro-services](https://github.com/harlow/go-micro-services) example converted to use Micro.
|
||||
|
||||
His README (with required changes):
|
||||
|
||||
The API Endpoint accepts HTTP requests at `localhost:8080` and then spawns a number of RPC requests to the backend services.
|
||||
|
||||
_Note:_ Data for each of the services is stored in JSON flat files under the `/data/` directory. In reality each of the services could choose their own specialty datastore. The Geo service for example could use PostGis or any other database specializing in geospacial queries.
|
||||
|
||||
### Setup
|
||||
|
||||
Docker is required for running the services https://docs.docker.com/engine/installation.
|
||||
|
||||
Protobuf v3 are required:
|
||||
|
||||
$ brew install protobuf
|
||||
|
||||
Install the protoc-gen libraries and other dependencies:
|
||||
|
||||
$ go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
|
||||
$ go get -u github.com/micro/protoc-gen-micro
|
||||
$ go get -u github.com/micro/go-micro
|
||||
$ go get -u github.com/hailocab/go-geoindex
|
||||
|
||||
Clone the repository:
|
||||
|
||||
$ git clone git@github.com:micro/micro.git
|
||||
|
||||
Change to examples dir
|
||||
|
||||
$ cd micro/examples/booking
|
||||
|
||||
### Protobufs
|
||||
|
||||
If changes are made to the Protocol Buffer files use the Makefile to regenerate:
|
||||
|
||||
$ make proto
|
||||
|
||||
### Run
|
||||
|
||||
To make the demo as straigforward as possible; [Docker Compose](https://docs.docker.com/compose/) is used to run all the services at once (In a production environment each of the services would be run (and scaled) independently).
|
||||
|
||||
$ make build
|
||||
$ make run
|
||||
|
||||
Curl the endpoint with an invalid auth token:
|
||||
|
||||
$ curl -H 'Content-Type: application/json' \
|
||||
-H "Authorization: Bearer INVALID_TOKEN" \
|
||||
-d '{"inDate": "2015-04-09"}' \
|
||||
http://localhost:8080/hotel/rates
|
||||
|
||||
{"id":"api.hotel.rates","code":401,"detail":"Unauthorized","status":"Unauthorized"}
|
||||
|
||||
Curl the endpoint without checkin or checkout dates:
|
||||
|
||||
$ curl -H 'Content-Type: application/json' \
|
||||
-H "Authorization: Bearer VALID_TOKEN" \
|
||||
-d '{"inDate": "2015-04-09"}' \
|
||||
http://localhost:8080/hotel/rates
|
||||
|
||||
{"id":"api.hotel.rates","code":400,"detail":"Please specify inDate/outDate params","status":"Bad Request"}
|
||||
|
||||
Curl the API endpoint with a valid auth token:
|
||||
|
||||
$ curl -H 'Content-Type: application/json' \
|
||||
-H "Authorization: Bearer VALID_TOKEN" \
|
||||
-d '{"inDate": "2015-04-09", "outDate": "2015-04-10"}' \
|
||||
http://localhost:8080/hotel/rates
|
||||
|
||||
The JSON response:
|
||||
|
||||
```json
|
||||
{
|
||||
"hotels": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Clift Hotel",
|
||||
"phoneNumber": "(415) 775-4700",
|
||||
"description": "A 6-minute walk from Union Square and 4 minutes from a Muni Metro station, this luxury hotel designed by Philippe Starck features an artsy furniture collection in the lobby, including work by Salvador Dali.",
|
||||
"address": {
|
||||
"streetNumber": "495",
|
||||
"streetName": "Geary St",
|
||||
"city": "San Francisco",
|
||||
"state": "CA",
|
||||
"country": "United States",
|
||||
"postalCode": "94102"
|
||||
}
|
||||
}
|
||||
],
|
||||
"ratePlans": [
|
||||
{
|
||||
"hotelId": 1,
|
||||
"code": "RACK",
|
||||
"inDate": "2015-04-09",
|
||||
"outDate": "2015-04-10",
|
||||
"roomType": {
|
||||
"bookableRate": 109,
|
||||
"totalRate": 109,
|
||||
"totalRateInclusive": 123.17,
|
||||
"code": "KNG"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
4
examples/booking/api/hotel/Dockerfile
Normal file
4
examples/booking/api/hotel/Dockerfile
Normal file
@ -0,0 +1,4 @@
|
||||
FROM alpine:3.2
|
||||
ADD . /app
|
||||
WORKDIR /app
|
||||
ENTRYPOINT [ "/app/hotel" ]
|
192
examples/booking/api/hotel/main.go
Normal file
192
examples/booking/api/hotel/main.go
Normal file
@ -0,0 +1,192 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
_ "expvar"
|
||||
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/net/trace"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/micro/examples/booking/api/hotel/proto"
|
||||
"github.com/micro/examples/booking/srv/auth/proto"
|
||||
"github.com/micro/examples/booking/srv/geo/proto"
|
||||
"github.com/micro/examples/booking/srv/profile/proto"
|
||||
"github.com/micro/examples/booking/srv/rate/proto"
|
||||
"github.com/micro/go-micro/v2"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
merr "github.com/micro/go-micro/v2/errors"
|
||||
"github.com/micro/go-micro/v2/metadata"
|
||||
)
|
||||
|
||||
const (
|
||||
BASIC_SCHEMA string = "Basic "
|
||||
BEARER_SCHEMA string = "Bearer "
|
||||
)
|
||||
|
||||
type profileResults struct {
|
||||
hotels []*profile.Hotel
|
||||
err error
|
||||
}
|
||||
|
||||
type rateResults struct {
|
||||
ratePlans []*rate.RatePlan
|
||||
err error
|
||||
}
|
||||
|
||||
type Hotel struct {
|
||||
Client client.Client
|
||||
}
|
||||
|
||||
func (s *Hotel) Rates(ctx context.Context, req *hotel.Request, rsp *hotel.Response) error {
|
||||
// tracing
|
||||
tr := trace.New("api.v1", "Hotel.Rates")
|
||||
defer tr.Finish()
|
||||
|
||||
// context
|
||||
ctx = trace.NewContext(ctx, tr)
|
||||
|
||||
md, ok := metadata.FromContext(ctx)
|
||||
if !ok {
|
||||
md = metadata.Metadata{}
|
||||
}
|
||||
|
||||
// add a unique request id to context
|
||||
traceID := uuid.New()
|
||||
// make copy
|
||||
tmd := metadata.Metadata{}
|
||||
for k, v := range md {
|
||||
tmd[k] = v
|
||||
}
|
||||
|
||||
tmd["traceID"] = traceID.String()
|
||||
tmd["fromName"] = "api.v1"
|
||||
ctx = metadata.NewContext(ctx, tmd)
|
||||
|
||||
// token from request headers
|
||||
token, err := getToken(md)
|
||||
if err != nil {
|
||||
return merr.Forbidden("api.hotel.rates", err.Error())
|
||||
}
|
||||
|
||||
// verify token w/ auth service
|
||||
authClient := auth.NewAuthService("go.micro.srv.auth", s.Client)
|
||||
if _, err = authClient.VerifyToken(ctx, &auth.Request{AuthToken: token}); err != nil {
|
||||
return merr.Unauthorized("api.hotel.rates", "Unauthorized")
|
||||
}
|
||||
|
||||
// checkin and checkout date query params
|
||||
inDate, outDate := req.InDate, req.OutDate
|
||||
if inDate == "" || outDate == "" {
|
||||
return merr.BadRequest("api.hotel.rates", "Please specify inDate/outDate params")
|
||||
}
|
||||
|
||||
// finds nearby hotels
|
||||
// TODO(hw): use lat/lon from request params
|
||||
geoClient := geo.NewGeoService("go.micro.srv.geo", s.Client)
|
||||
nearby, err := geoClient.Nearby(ctx, &geo.Request{
|
||||
Lat: 51.502973,
|
||||
Lon: -0.114723,
|
||||
})
|
||||
if err != nil {
|
||||
return merr.InternalServerError("api.hotel.rates", err.Error())
|
||||
}
|
||||
|
||||
// make requests for profiles and rates
|
||||
profileCh := getHotelProfiles(s.Client, ctx, nearby.HotelIds)
|
||||
rateCh := getRatePlans(s.Client, ctx, nearby.HotelIds, inDate, outDate)
|
||||
|
||||
// wait on profiles reply
|
||||
profileReply := <-profileCh
|
||||
if err := profileReply.err; err != nil {
|
||||
return merr.InternalServerError("api.hotel.rates", err.Error())
|
||||
}
|
||||
|
||||
// wait on rates reply
|
||||
rateReply := <-rateCh
|
||||
if err := rateReply.err; err != nil {
|
||||
return merr.InternalServerError("api.hotel.rates", err.Error())
|
||||
}
|
||||
|
||||
rsp.Hotels = profileReply.hotels
|
||||
rsp.RatePlans = rateReply.ratePlans
|
||||
return nil
|
||||
}
|
||||
|
||||
func getToken(md metadata.Metadata) (string, error) {
|
||||
// Grab the raw Authorization header
|
||||
authHeader := md["Authorization"]
|
||||
if authHeader == "" {
|
||||
return "", errors.New("Authorization header required")
|
||||
}
|
||||
|
||||
// Confirm the request is sending Basic Authentication credentials.
|
||||
if !strings.HasPrefix(authHeader, BASIC_SCHEMA) && !strings.HasPrefix(authHeader, BEARER_SCHEMA) {
|
||||
return "", errors.New("Authorization requires Basic/Bearer scheme")
|
||||
}
|
||||
|
||||
// Get the token from the request header
|
||||
// The first six characters are skipped - e.g. "Basic ".
|
||||
if strings.HasPrefix(authHeader, BASIC_SCHEMA) {
|
||||
str, err := base64.StdEncoding.DecodeString(authHeader[len(BASIC_SCHEMA):])
|
||||
if err != nil {
|
||||
return "", errors.New("Base64 encoding issue")
|
||||
}
|
||||
creds := strings.Split(string(str), ":")
|
||||
return creds[0], nil
|
||||
}
|
||||
|
||||
return authHeader[len(BEARER_SCHEMA):], nil
|
||||
}
|
||||
|
||||
func getRatePlans(c client.Client, ctx context.Context, hotelIDs []string, inDate string, outDate string) chan rateResults {
|
||||
rateClient := rate.NewRateService("go.micro.srv.rate", c)
|
||||
ch := make(chan rateResults, 1)
|
||||
|
||||
go func() {
|
||||
res, err := rateClient.GetRates(ctx, &rate.Request{
|
||||
HotelIds: hotelIDs,
|
||||
InDate: inDate,
|
||||
OutDate: outDate,
|
||||
})
|
||||
ch <- rateResults{res.RatePlans, err}
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
func getHotelProfiles(c client.Client, ctx context.Context, hotelIDs []string) chan profileResults {
|
||||
profileClient := profile.NewProfileService("go.micro.srv.profile", c)
|
||||
ch := make(chan profileResults, 1)
|
||||
|
||||
go func() {
|
||||
res, err := profileClient.GetProfiles(ctx, &profile.Request{
|
||||
HotelIds: hotelIDs,
|
||||
Locale: "en",
|
||||
})
|
||||
ch <- profileResults{res.Hotels, err}
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
func main() {
|
||||
// trace library patched for demo purposes.
|
||||
// https://github.com/golang/net/blob/master/trace/trace.go#L94
|
||||
trace.AuthRequest = func(req *http.Request) (any, sensitive bool) {
|
||||
return true, true
|
||||
}
|
||||
|
||||
service := micro.NewService(
|
||||
micro.Name("go.micro.api.hotel"),
|
||||
)
|
||||
|
||||
service.Init()
|
||||
hotel.RegisterHotelHandler(service.Server(), &Hotel{service.Client()})
|
||||
service.Run()
|
||||
}
|
101
examples/booking/api/hotel/proto/hotel.micro.go
Normal file
101
examples/booking/api/hotel/proto/hotel.micro.go
Normal file
@ -0,0 +1,101 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: github.com/micro/examples/booking/api/hotel/proto/hotel.proto
|
||||
|
||||
/*
|
||||
Package hotel is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
github.com/micro/examples/booking/api/hotel/proto/hotel.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Request
|
||||
Response
|
||||
*/
|
||||
package hotel
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import _ "github.com/micro/examples/booking/srv/profile/proto"
|
||||
import _ "github.com/micro/examples/booking/srv/rate/proto"
|
||||
|
||||
import (
|
||||
context "context"
|
||||
client "github.com/micro/go-micro/v2/client"
|
||||
server "github.com/micro/go-micro/v2/server"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ client.Option
|
||||
var _ server.Option
|
||||
|
||||
// Client API for Hotel service
|
||||
|
||||
type HotelService interface {
|
||||
Rates(ctx context.Context, in *Request, opts ...client.CallOption) (*Response, error)
|
||||
}
|
||||
|
||||
type hotelService struct {
|
||||
c client.Client
|
||||
serviceName string
|
||||
}
|
||||
|
||||
func NewHotelService(serviceName string, c client.Client) HotelService {
|
||||
if c == nil {
|
||||
c = client.NewClient()
|
||||
}
|
||||
if len(serviceName) == 0 {
|
||||
serviceName = "hotel"
|
||||
}
|
||||
return &hotelService{
|
||||
c: c,
|
||||
serviceName: serviceName,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *hotelService) Rates(ctx context.Context, in *Request, opts ...client.CallOption) (*Response, error) {
|
||||
req := c.c.NewRequest(c.serviceName, "Hotel.Rates", in)
|
||||
out := new(Response)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Hotel service
|
||||
|
||||
type HotelHandler interface {
|
||||
Rates(context.Context, *Request, *Response) error
|
||||
}
|
||||
|
||||
func RegisterHotelHandler(s server.Server, hdlr HotelHandler, opts ...server.HandlerOption) {
|
||||
type hotel interface {
|
||||
Rates(ctx context.Context, in *Request, out *Response) error
|
||||
}
|
||||
type Hotel struct {
|
||||
hotel
|
||||
}
|
||||
h := &hotelHandler{hdlr}
|
||||
s.Handle(s.NewHandler(&Hotel{h}, opts...))
|
||||
}
|
||||
|
||||
type hotelHandler struct {
|
||||
HotelHandler
|
||||
}
|
||||
|
||||
func (h *hotelHandler) Rates(ctx context.Context, in *Request, out *Response) error {
|
||||
return h.HotelHandler.Rates(ctx, in, out)
|
||||
}
|
185
examples/booking/api/hotel/proto/hotel.pb.go
Normal file
185
examples/booking/api/hotel/proto/hotel.pb.go
Normal file
@ -0,0 +1,185 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: github.com/micro/examples/booking/api/hotel/proto/hotel.proto
|
||||
|
||||
/*
|
||||
Package hotel is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
github.com/micro/examples/booking/api/hotel/proto/hotel.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Request
|
||||
Response
|
||||
*/
|
||||
package hotel
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import profile "github.com/micro/examples/booking/srv/profile/proto"
|
||||
import rate "github.com/micro/examples/booking/srv/rate/proto"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type Request struct {
|
||||
InDate string `protobuf:"bytes,1,opt,name=inDate" json:"inDate,omitempty"`
|
||||
OutDate string `protobuf:"bytes,2,opt,name=outDate" json:"outDate,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Request) Reset() { *m = Request{} }
|
||||
func (m *Request) String() string { return proto.CompactTextString(m) }
|
||||
func (*Request) ProtoMessage() {}
|
||||
func (*Request) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func (m *Request) GetInDate() string {
|
||||
if m != nil {
|
||||
return m.InDate
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Request) GetOutDate() string {
|
||||
if m != nil {
|
||||
return m.OutDate
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
Hotels []*profile.Hotel `protobuf:"bytes,1,rep,name=hotels" json:"hotels,omitempty"`
|
||||
RatePlans []*rate.RatePlan `protobuf:"bytes,2,rep,name=ratePlans" json:"ratePlans,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Response) Reset() { *m = Response{} }
|
||||
func (m *Response) String() string { return proto.CompactTextString(m) }
|
||||
func (*Response) ProtoMessage() {}
|
||||
func (*Response) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *Response) GetHotels() []*profile.Hotel {
|
||||
if m != nil {
|
||||
return m.Hotels
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Response) GetRatePlans() []*rate.RatePlan {
|
||||
if m != nil {
|
||||
return m.RatePlans
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Request)(nil), "hotel.Request")
|
||||
proto.RegisterType((*Response)(nil), "hotel.Response")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// 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.SupportPackageIsVersion4
|
||||
|
||||
// Client API for Hotel service
|
||||
|
||||
type HotelClient interface {
|
||||
Rates(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error)
|
||||
}
|
||||
|
||||
type hotelClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewHotelClient(cc *grpc.ClientConn) HotelClient {
|
||||
return &hotelClient{cc}
|
||||
}
|
||||
|
||||
func (c *hotelClient) Rates(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) {
|
||||
out := new(Response)
|
||||
err := grpc.Invoke(ctx, "/hotel.Hotel/Rates", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Hotel service
|
||||
|
||||
type HotelServer interface {
|
||||
Rates(context.Context, *Request) (*Response, error)
|
||||
}
|
||||
|
||||
func RegisterHotelServer(s *grpc.Server, srv HotelServer) {
|
||||
s.RegisterService(&_Hotel_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Hotel_Rates_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Request)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(HotelServer).Rates(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/hotel.Hotel/Rates",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(HotelServer).Rates(ctx, req.(*Request))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Hotel_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "hotel.Hotel",
|
||||
HandlerType: (*HotelServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Rates",
|
||||
Handler: _Hotel_Rates_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "github.com/micro/examples/booking/api/hotel/proto/hotel.proto",
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/micro/examples/booking/api/hotel/proto/hotel.proto", fileDescriptor0)
|
||||
}
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 246 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x50, 0xc1, 0x4a, 0xc3, 0x40,
|
||||
0x10, 0x35, 0x95, 0xa4, 0x76, 0x84, 0x0a, 0x7b, 0x90, 0x90, 0x53, 0xc9, 0x41, 0x8a, 0x48, 0x16,
|
||||
0xda, 0x63, 0xf1, 0x20, 0x78, 0xf0, 0x28, 0xfb, 0x05, 0x6e, 0xca, 0xd8, 0x2c, 0x26, 0x99, 0x98,
|
||||
0xdd, 0x88, 0x9f, 0x2f, 0x3b, 0xbb, 0xd1, 0xa3, 0xbd, 0xbd, 0x37, 0x6f, 0xde, 0xdb, 0x37, 0x0b,
|
||||
0x8f, 0x27, 0xe3, 0x9a, 0xa9, 0xae, 0x8e, 0xd4, 0xc9, 0xce, 0x1c, 0x47, 0x92, 0xf8, 0xad, 0xbb,
|
||||
0xa1, 0x45, 0x2b, 0x6b, 0xa2, 0x0f, 0xd3, 0x9f, 0xa4, 0x1e, 0x8c, 0x6c, 0xc8, 0x61, 0x2b, 0x87,
|
||||
0x91, 0x1c, 0x05, 0x5c, 0x31, 0x16, 0x29, 0x93, 0xe2, 0xe9, 0xff, 0x14, 0x3b, 0x7e, 0x79, 0xff,
|
||||
0xbb, 0x69, 0x31, 0xe6, 0x44, 0x16, 0x92, 0x8a, 0xc3, 0x79, 0x11, 0xa3, 0x76, 0xb3, 0xdf, 0xc3,
|
||||
0x60, 0x2e, 0x0f, 0xb0, 0x54, 0xf8, 0x39, 0xa1, 0x75, 0xe2, 0x16, 0x32, 0xd3, 0x3f, 0x6b, 0x87,
|
||||
0x79, 0xb2, 0x49, 0xb6, 0x2b, 0x15, 0x99, 0xc8, 0x61, 0x49, 0x93, 0x63, 0x61, 0xc1, 0xc2, 0x4c,
|
||||
0xcb, 0x37, 0xb8, 0x52, 0x68, 0x07, 0xea, 0x2d, 0x8a, 0x3b, 0xc8, 0xf8, 0x22, 0x9b, 0x27, 0x9b,
|
||||
0xcb, 0xed, 0xf5, 0x6e, 0x5d, 0xcd, 0x2d, 0x5f, 0xfc, 0x58, 0x45, 0x55, 0x3c, 0xc0, 0xca, 0x3f,
|
||||
0xff, 0xda, 0xea, 0xde, 0xe6, 0x8b, 0xb8, 0xca, 0x85, 0x54, 0x1c, 0xab, 0xbf, 0x85, 0xdd, 0x1e,
|
||||
0x52, 0xb6, 0x8b, 0x7b, 0x48, 0xbd, 0x6e, 0xc5, 0xba, 0x0a, 0xbf, 0x18, 0x5b, 0x17, 0x37, 0xbf,
|
||||
0x3c, 0x14, 0x29, 0x2f, 0xea, 0x8c, 0x4f, 0xdb, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x11, 0xa3,
|
||||
0x5e, 0xbd, 0xa2, 0x01, 0x00, 0x00,
|
||||
}
|
20
examples/booking/api/hotel/proto/hotel.proto
Normal file
20
examples/booking/api/hotel/proto/hotel.proto
Normal file
@ -0,0 +1,20 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package hotel;
|
||||
|
||||
import "github.com/micro/examples/booking/srv/profile/proto/profile.proto";
|
||||
import "github.com/micro/examples/booking/srv/rate/proto/rate.proto";
|
||||
|
||||
service Hotel {
|
||||
rpc Rates(Request) returns (Response) {};
|
||||
}
|
||||
|
||||
message Request {
|
||||
string inDate = 1;
|
||||
string outDate = 2;
|
||||
}
|
||||
|
||||
message Response {
|
||||
repeated profile.Hotel hotels = 1;
|
||||
repeated rate.RatePlan ratePlans = 2;
|
||||
}
|
15
examples/booking/bin/build.sh
Executable file
15
examples/booking/bin/build.sh
Executable file
@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
dir=`pwd`
|
||||
|
||||
build() {
|
||||
for d in $(ls ./$1); do
|
||||
echo "building $1/$d"
|
||||
pushd $dir/$1/$d >/dev/null
|
||||
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w'
|
||||
popd >/dev/null
|
||||
done
|
||||
}
|
||||
|
||||
build api
|
||||
build srv
|
16
examples/booking/bin/lint.sh
Executable file
16
examples/booking/bin/lint.sh
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
dir=`pwd`
|
||||
|
||||
check() {
|
||||
for d in $(ls ./$1); do
|
||||
echo "verifying $1/$d"
|
||||
pushd $dir/$1/$d >/dev/null
|
||||
go fmt
|
||||
golint
|
||||
popd >/dev/null
|
||||
done
|
||||
}
|
||||
|
||||
check api
|
||||
check srv
|
306
examples/booking/data/bindata.go
Normal file
306
examples/booking/data/bindata.go
Normal file
@ -0,0 +1,306 @@
|
||||
// Code generated by go-bindata.
|
||||
// sources:
|
||||
// data/customers.json
|
||||
// data/locations.json
|
||||
// data/profiles.json
|
||||
// data/rates.json
|
||||
// DO NOT EDIT!
|
||||
|
||||
package data
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func bindataRead(data []byte, name string) ([]byte, error) {
|
||||
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Read %q: %v", name, err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
_, err = io.Copy(&buf, gz)
|
||||
clErr := gz.Close()
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Read %q: %v", name, err)
|
||||
}
|
||||
if clErr != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
type asset struct {
|
||||
bytes []byte
|
||||
info os.FileInfo
|
||||
}
|
||||
|
||||
type bindataFileInfo struct {
|
||||
name string
|
||||
size int64
|
||||
mode os.FileMode
|
||||
modTime time.Time
|
||||
}
|
||||
|
||||
func (fi bindataFileInfo) Name() string {
|
||||
return fi.name
|
||||
}
|
||||
func (fi bindataFileInfo) Size() int64 {
|
||||
return fi.size
|
||||
}
|
||||
func (fi bindataFileInfo) Mode() os.FileMode {
|
||||
return fi.mode
|
||||
}
|
||||
func (fi bindataFileInfo) ModTime() time.Time {
|
||||
return fi.modTime
|
||||
}
|
||||
func (fi bindataFileInfo) IsDir() bool {
|
||||
return false
|
||||
}
|
||||
func (fi bindataFileInfo) Sys() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
var _dataCustomersJson = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x8a\xe6\x52\x00\x82\x6a\x30\x09\x02\x4a\x99\x29\x4a\x56\x0a\x86\x3a\x08\x81\xc4\xd2\x92\x8c\x90\xfc\xec\xd4\x3c\xa0\xb8\x52\x98\xa3\x8f\xa7\x4b\x7c\x88\xbf\xb7\xab\x9f\x12\x58\x49\x2d\x57\x2c\x17\x20\x00\x00\xff\xff\x2b\x28\xf3\x0d\x44\x00\x00\x00")
|
||||
|
||||
func dataCustomersJsonBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_dataCustomersJson,
|
||||
"data/customers.json",
|
||||
)
|
||||
}
|
||||
|
||||
func dataCustomersJson() (*asset, error) {
|
||||
bytes, err := dataCustomersJsonBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "data/customers.json", size: 68, mode: os.FileMode(420), modTime: time.Unix(1445724030, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _dataLocationsJson = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x8a\xe6\x52\x00\x82\x6a\x30\x09\x02\x4a\x19\xf9\x25\xa9\x39\x9e\x29\x4a\x56\x0a\x4a\x86\x4a\x3a\x08\xf1\x9c\xc4\x12\xa0\x98\xa9\xa1\x9e\xa9\x81\x91\xa5\xb9\x31\xb2\x4c\x7e\x1e\x50\x46\xd7\x40\xcf\xd0\xd0\xc4\xdc\xc8\x18\x2c\x51\xab\x83\xc7\x5c\x23\x1a\x99\x6b\x4c\x23\x73\x4d\x68\x64\xae\x29\x8d\xcc\x35\xa3\xc0\x5c\xae\x58\x2e\x40\x00\x00\x00\xff\xff\xab\x3a\x0e\xb4\x13\x02\x00\x00")
|
||||
|
||||
func dataLocationsJsonBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_dataLocationsJson,
|
||||
"data/locations.json",
|
||||
)
|
||||
}
|
||||
|
||||
func dataLocationsJson() (*asset, error) {
|
||||
bytes, err := dataLocationsJsonBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "data/locations.json", size: 531, mode: os.FileMode(420), modTime: time.Unix(1456591447, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _dataProfilesJson = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xd4\x56\xdd\x6e\x2b\x35\x10\xbe\xef\x53\x8c\x72\x05\x52\xb6\x4a\xb2\xbb\x6d\xc2\x5d\xd2\x43\x7b\x90\x08\xaa\x4e\x02\x08\x10\x17\xb3\xf6\x24\x6b\xea\xb5\x83\xed\x3d\x39\x11\x3a\x12\xaf\xc1\xeb\xf1\x24\x8c\x37\x29\x49\xdb\xfc\x94\x5c\x95\x5c\x54\xdd\xf5\xec\x78\x3c\xdf\xe7\x6f\xbe\x5f\x2e\x80\x7f\x7f\x34\x7f\xe3\xaf\xa5\x64\xeb\x2b\x68\x75\x5b\xed\xed\x2b\x83\x15\xc5\x97\x37\x5a\xcd\x02\xbc\xb7\x81\xf4\xee\xf2\xa2\xb4\x86\xbe\xab\xab\x82\x5c\x8c\xfa\x22\xeb\xe6\x5f\xc2\xf5\x75\x9e\x64\xd7\x9d\xce\x6e\xa0\x24\x2f\x9c\x5a\x04\x65\x4d\x0c\x1c\xc2\x55\x52\x29\x53\x07\x82\x25\xea\x07\x98\x39\x5b\xc1\xf7\x86\x57\x61\xf2\x7b\x8d\x8e\x00\x8d\x84\x0c\xd6\x31\x7e\xbd\x8e\x30\xae\x8d\x82\x31\x05\x67\xc1\x07\x8c\xc9\xda\x10\x4a\xe5\x41\xd7\x9f\x6a\xb7\x82\x32\xd6\x07\xbc\x97\x9a\x1b\x92\x50\xac\xe0\xbe\x54\x5a\x2d\x16\x04\x93\x80\x4e\xf0\x46\x84\xa1\x76\x9c\x11\x0d\xa0\x0b\x7e\x05\xb3\xda\x19\x15\xdf\x81\xb0\x5a\x93\x88\x59\x41\x19\xce\x4b\xa0\x6d\x51\xac\xda\xfc\x24\x74\x2d\x95\x99\xc3\xd2\xba\x87\x98\x76\x82\xfa\x23\x4a\xeb\xe0\x1d\x6a\x75\xb9\x7b\x50\x94\x92\xd3\x7b\x3e\xe4\xb6\xb1\xcd\x82\x0f\x8e\x28\x6c\x7b\x95\x0d\xf2\x9d\xef\x76\x43\x36\x2d\xbf\x23\xe4\x23\x4d\xc2\xf3\x28\xa1\xc2\x2a\xae\x4f\xf8\x08\xb7\x0e\x8d\x50\x5e\xd8\x97\xa9\x30\xac\x81\x1b\xbe\xf8\xde\xd6\x26\xb8\x26\x05\x77\x3c\x70\x9f\x26\x31\xd8\x3f\x8f\x5b\x58\x4e\xa2\x6f\xac\x6c\xf2\x0c\xb2\x6e\xa7\xd7\xfa\x37\xe2\x73\xf3\xdf\xe7\xf6\x7e\x0a\xf5\xf6\x51\xe8\x47\x38\x54\xf1\x21\x1a\x5d\x27\x79\x7a\x94\x46\xdf\x72\xa7\x19\xa8\x88\x25\x14\xda\x8a\x0d\x91\x22\x74\x3f\x91\x2b\x10\x46\x35\x19\x84\x1b\x32\x81\x1c\xcc\x18\xaf\xb8\x34\x64\xdc\x37\xbc\xe1\x86\x1b\xf9\xc8\x1b\x7e\x46\xe8\xf6\x8e\x13\xf3\x3c\xb0\xbb\xfd\xee\x71\xb0\x53\x27\xdf\x14\xd4\xe9\x6b\xa1\x4e\xf7\x41\xdd\xe8\x04\xfc\x4c\x21\xe0\x49\x98\xf3\x2c\x4d\xfa\x79\x9e\x1f\x55\x8b\xf4\x25\x28\x11\xc9\x7b\xbb\x24\xad\xf9\x50\xb1\x95\x20\xb0\xd0\x94\x08\x64\x94\xf9\x4e\xa3\xe3\xc3\xcb\x46\x47\x46\xc3\x0f\x53\x70\xa8\xf4\x33\xd5\x28\xd5\x62\x03\xfd\xe0\xa9\xd2\x3c\x51\x22\x61\xab\x42\x19\x8a\xe1\xf3\x32\x09\x24\x4a\xd6\x05\x39\x6f\xe4\x40\x85\x72\x23\x23\xc1\xd6\xa2\x24\x7f\x1e\x3d\xf2\x13\x52\x90\xf3\x36\xff\x4b\x76\x64\x87\xd9\xf1\x83\xe2\xa4\x74\x92\x1e\xbd\xeb\x7e\x92\x1e\x1f\x26\xd3\x88\xe5\x92\x2b\x77\x0c\x9e\x09\x1b\x48\x1b\x6c\x46\xb8\x82\x91\x53\x72\x4e\xf0\x51\xd1\xd2\xc7\x3b\x9e\xae\xa5\xc2\x6f\x69\x74\xab\x4c\xec\x1e\x6a\x78\xa7\xb8\xf1\x4a\x84\x86\x36\x08\xd9\x7e\xda\xdd\x92\x63\x65\x1e\xd5\x4a\xc7\xa1\x70\x1e\xe4\xfd\xe3\x88\x8f\x95\xf7\x0d\x07\xdf\x10\xea\xf9\x6b\x51\xcf\xf7\xa1\x7e\x5f\x5a\x32\xea\xd3\xab\x3d\xc4\x55\xd2\x4d\xfb\x47\xc5\xdf\x0a\x8c\xe5\x6f\x66\xf5\x94\x95\x9c\x9c\xb6\xfc\x68\x88\x6f\x6a\x61\x5d\x69\xad\x6c\x47\x4d\xef\xbc\xc4\x11\x0f\xaa\x82\x6b\xfc\x45\x65\x03\x8f\x8b\x78\xd1\x09\x4a\xe4\xcb\xcf\xed\xe0\xcd\x2a\x34\x2b\x70\x71\xd2\x54\xb5\x57\xcc\x19\xe3\x1b\xae\x58\x2e\xc1\x81\x20\x4d\x85\x53\x41\xb1\x5a\x78\x76\x0d\xd4\x54\xd6\x1d\xe4\x1d\x7f\x09\xdf\x84\xbf\xff\xfc\xcb\x1f\x66\x15\xef\xcd\x5b\x2a\x01\x77\x8e\x4d\x0a\x0c\x2b\xe2\x07\x06\x79\x1c\x37\x82\xf7\xc8\x42\x67\xf8\x5c\x81\xbd\x48\x71\x1e\xe7\xae\x3a\x27\xa6\xd0\xd7\x52\xbe\x2d\xc7\x31\x68\x5d\xbc\x92\x73\x57\xfb\x38\x37\x2d\xa3\xf1\xbb\x84\x0f\x34\x67\x60\xff\x9b\xfd\xe8\xf5\xb3\x24\xeb\x1c\x15\x9e\x6d\x6a\xc6\x88\xea\x0a\xa6\x3c\x8f\xdc\xda\x47\x64\xbd\x24\xc2\xc9\xee\x31\xeb\x67\xc0\xde\xd9\x3f\xac\xf8\x63\x5c\xc4\x80\x35\x63\x27\xb6\x66\x89\xb2\x33\x18\xa3\x7b\xe0\xf9\x25\x1f\xc5\x87\x5f\x3d\xa9\xb5\x0d\x37\x6c\x33\xd9\xbe\x18\x85\xcc\x67\xf9\x1b\x0a\x76\x34\x3c\x72\x9e\xb8\x9c\x3b\x74\x92\x0c\x3b\x9b\xb1\xe5\x6f\x0c\x6d\x6c\x4f\x1b\xee\x51\x8c\xe2\x98\x7c\x14\xac\x86\xb0\x4d\x01\xbb\x9b\x3c\x9e\x21\xd6\xc3\x08\x38\x13\x7d\xd2\x99\x6e\xa7\x77\x62\x9e\xb1\xdb\x79\x53\x1c\x7b\x46\xb1\x8b\x5f\x2f\xfe\x09\x00\x00\xff\xff\xf8\xbe\x11\x38\x1c\x0d\x00\x00")
|
||||
|
||||
func dataProfilesJsonBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_dataProfilesJson,
|
||||
"data/profiles.json",
|
||||
)
|
||||
}
|
||||
|
||||
func dataProfilesJson() (*asset, error) {
|
||||
bytes, err := dataProfilesJsonBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "data/profiles.json", size: 3356, mode: os.FileMode(420), modTime: time.Unix(1456591428, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _dataRatesJson = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x8a\xe6\x52\x00\x82\x6a\x30\x09\x02\x4a\x19\xf9\x25\xa9\x39\x9e\x29\x4a\x56\x0a\x4a\x86\x4a\x3a\x08\xf1\xe4\xfc\x94\x54\x90\x60\x90\xa3\xb3\x37\xb2\x78\x66\x9e\x4b\x62\x09\x58\xc6\xc8\xc0\xd0\x54\xd7\xc0\x44\xd7\xc0\x12\x59\x3e\xbf\xb4\x04\x5d\x81\xa1\x01\xb2\x82\xa2\xfc\xfc\xdc\x90\xca\x02\x90\x0a\x84\x33\x80\xe2\x49\xf9\xf9\xd9\x89\x49\x39\xa9\x41\x10\xdd\x86\x06\x96\x7a\x06\x06\x3a\xc8\x2a\x60\x4e\xf2\xf6\x73\x57\x42\x91\x48\x49\x2d\x4e\x2e\xca\x2c\x28\xc9\xcc\xcf\x03\xcb\x67\xe6\xa5\x2b\x14\x67\x56\xa5\xa6\x28\x24\xa5\xa6\xa0\x2a\x2d\xc9\x2f\x49\xcc\xc1\x6d\x05\x5c\xda\x33\x2f\x39\xa7\xb4\x38\xb3\x0c\xac\xce\xc8\x58\xcf\xd0\x1c\xae\xac\x96\x0b\x42\xc6\x72\x01\x02\x00\x00\xff\xff\xe0\xd7\xdf\xfa\x4d\x01\x00\x00")
|
||||
|
||||
func dataRatesJsonBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_dataRatesJson,
|
||||
"data/rates.json",
|
||||
)
|
||||
}
|
||||
|
||||
func dataRatesJson() (*asset, error) {
|
||||
bytes, err := dataRatesJsonBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "data/rates.json", size: 333, mode: os.FileMode(420), modTime: time.Unix(1456591432, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// Asset loads and returns the asset for the given name.
|
||||
// It returns an error if the asset could not be found or
|
||||
// could not be loaded.
|
||||
func Asset(name string) ([]byte, error) {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[cannonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
|
||||
}
|
||||
return a.bytes, nil
|
||||
}
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
|
||||
// MustAsset is like Asset but panics when Asset would return an error.
|
||||
// It simplifies safe initialization of global variables.
|
||||
func MustAsset(name string) []byte {
|
||||
a, err := Asset(name)
|
||||
if err != nil {
|
||||
panic("asset: Asset(" + name + "): " + err.Error())
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// AssetInfo loads and returns the asset info for the given name.
|
||||
// It returns an error if the asset could not be found or
|
||||
// could not be loaded.
|
||||
func AssetInfo(name string) (os.FileInfo, error) {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[cannonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
|
||||
}
|
||||
return a.info, nil
|
||||
}
|
||||
return nil, fmt.Errorf("AssetInfo %s not found", name)
|
||||
}
|
||||
|
||||
// AssetNames returns the names of the assets.
|
||||
func AssetNames() []string {
|
||||
names := make([]string, 0, len(_bindata))
|
||||
for name := range _bindata {
|
||||
names = append(names, name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||
var _bindata = map[string]func() (*asset, error){
|
||||
"data/customers.json": dataCustomersJson,
|
||||
"data/locations.json": dataLocationsJson,
|
||||
"data/profiles.json": dataProfilesJson,
|
||||
"data/rates.json": dataRatesJson,
|
||||
}
|
||||
|
||||
// AssetDir returns the file names below a certain
|
||||
// directory embedded in the file by go-bindata.
|
||||
// For example if you run go-bindata on data/... and data contains the
|
||||
// following hierarchy:
|
||||
// data/
|
||||
// foo.txt
|
||||
// img/
|
||||
// a.png
|
||||
// b.png
|
||||
// then AssetDir("data") would return []string{"foo.txt", "img"}
|
||||
// AssetDir("data/img") would return []string{"a.png", "b.png"}
|
||||
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
|
||||
// AssetDir("") will return []string{"data"}.
|
||||
func AssetDir(name string) ([]string, error) {
|
||||
node := _bintree
|
||||
if len(name) != 0 {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
pathList := strings.Split(cannonicalName, "/")
|
||||
for _, p := range pathList {
|
||||
node = node.Children[p]
|
||||
if node == nil {
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
if node.Func != nil {
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
rv := make([]string, 0, len(node.Children))
|
||||
for childName := range node.Children {
|
||||
rv = append(rv, childName)
|
||||
}
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
type bintree struct {
|
||||
Func func() (*asset, error)
|
||||
Children map[string]*bintree
|
||||
}
|
||||
|
||||
var _bintree = &bintree{nil, map[string]*bintree{
|
||||
"data": &bintree{nil, map[string]*bintree{
|
||||
"customers.json": &bintree{dataCustomersJson, map[string]*bintree{}},
|
||||
"locations.json": &bintree{dataLocationsJson, map[string]*bintree{}},
|
||||
"profiles.json": &bintree{dataProfilesJson, map[string]*bintree{}},
|
||||
"rates.json": &bintree{dataRatesJson, map[string]*bintree{}},
|
||||
}},
|
||||
}}
|
||||
|
||||
// RestoreAsset restores an asset under the given directory
|
||||
func RestoreAsset(dir, name string) error {
|
||||
data, err := Asset(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info, err := AssetInfo(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RestoreAssets restores an asset under the given directory recursively
|
||||
func RestoreAssets(dir, name string) error {
|
||||
children, err := AssetDir(name)
|
||||
// File
|
||||
if err != nil {
|
||||
return RestoreAsset(dir, name)
|
||||
}
|
||||
// Dir
|
||||
for _, child := range children {
|
||||
err = RestoreAssets(dir, filepath.Join(name, child))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func _filePath(dir, name string) string {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
||||
}
|
6
examples/booking/data/customers.json
Normal file
6
examples/booking/data/customers.json
Normal file
@ -0,0 +1,6 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"authToken": "VALID_TOKEN"
|
||||
}
|
||||
]
|
32
examples/booking/data/locations.json
Normal file
32
examples/booking/data/locations.json
Normal file
@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"hotelId": "1",
|
||||
"lat": 51.502973,
|
||||
"lon": -0.114723
|
||||
},
|
||||
{
|
||||
"hotelId": "2",
|
||||
"lat": 51.502973,
|
||||
"lon": -0.114723
|
||||
},
|
||||
{
|
||||
"hotelId": "3",
|
||||
"lat": 51.502973,
|
||||
"lon": -0.114723
|
||||
},
|
||||
{
|
||||
"hotelId": "4",
|
||||
"lat": 51.502973,
|
||||
"lon": -0.114723
|
||||
},
|
||||
{
|
||||
"hotelId": "5",
|
||||
"lat": 51.502973,
|
||||
"lon": -0.114723
|
||||
},
|
||||
{
|
||||
"hotelId": "6",
|
||||
"lat": 51.502973,
|
||||
"lon": -0.114723
|
||||
}
|
||||
]
|
87
examples/booking/data/profiles.json
Normal file
87
examples/booking/data/profiles.json
Normal file
@ -0,0 +1,87 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"name": "Clift Hotel",
|
||||
"phoneNumber": "(415) 775-4700",
|
||||
"description": "A 6-minute walk from Union Square and 4 minutes from a Muni Metro station, this luxury hotel designed by Philippe Starck features an artsy furniture collection in the lobby, including work by Salvador Dali.",
|
||||
"address": {
|
||||
"streetNumber": "495",
|
||||
"streetName": "Geary St",
|
||||
"city": "San Francisco",
|
||||
"state": "CA",
|
||||
"country": "United States",
|
||||
"postalCode": "94102"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"name": "W San Francisco",
|
||||
"phoneNumber": "(415) 777-5300",
|
||||
"description": "Less than a block from the Yerba Buena Center for the Arts, this trendy hotel is a 12-minute walk from Union Square.",
|
||||
"address": {
|
||||
"streetNumber": "181",
|
||||
"streetName": "3rd St",
|
||||
"city": "San Francisco",
|
||||
"state": "CA",
|
||||
"country": "United States",
|
||||
"postalCode": "94103"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"name": "Hotel Zetta",
|
||||
"phoneNumber": "(415) 543-8555",
|
||||
"description": "A 3-minute walk from the Powell Street cable-car turnaround and BART rail station, this hip hotel 9 minutes from Union Square combines high-tech lodging with artsy touches.",
|
||||
"address": {
|
||||
"streetNumber": "55",
|
||||
"streetName": "5th St",
|
||||
"city": "San Francisco",
|
||||
"state": "CA",
|
||||
"country": "United States",
|
||||
"postalCode": "94103"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"name": "Hotel Vitale",
|
||||
"phoneNumber": "(415) 278-3700",
|
||||
"description": "This waterfront hotel with Bay Bridge views is 3 blocks from the Financial District and a 4-minute walk from the Ferry Building.",
|
||||
"address": {
|
||||
"streetNumber": "8",
|
||||
"streetName": "Mission St",
|
||||
"city": "San Francisco",
|
||||
"state": "CA",
|
||||
"country": "United States",
|
||||
"postalCode": "94105"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"name": "Phoenix Hotel",
|
||||
"phoneNumber": "(415) 776-1380",
|
||||
"description": "Located in the Tenderloin neighborhood, a 10-minute walk from a BART rail station, this retro motor lodge has hosted many rock musicians and other celebrities since the 1950s. It’s a 4-minute walk from the historic Great American Music Hall nightclub.",
|
||||
"address": {
|
||||
"streetNumber": "601",
|
||||
"streetName": "Eddy St",
|
||||
"city": "San Francisco",
|
||||
"state": "CA",
|
||||
"country": "United States",
|
||||
"postalCode": "94109"
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"name": "The St. Regis San Francisco",
|
||||
"phoneNumber": "(415) 284-4000",
|
||||
"description": "St. Regis Museum Tower is a 42-story, 484 ft skyscraper in the South of Market district of San Francisco, California, adjacent to Yerba Buena Gardens, Moscone Center, PacBell Building and the San Francisco Museum of Modern Art.",
|
||||
"address": {
|
||||
"streetNumber": "125",
|
||||
"streetName": "3rd",
|
||||
"city": "San Francisco",
|
||||
"state": "CA",
|
||||
"country": "United States",
|
||||
"postalCode": "94109"
|
||||
}
|
||||
}
|
||||
]
|
15
examples/booking/data/rates.json
Normal file
15
examples/booking/data/rates.json
Normal file
@ -0,0 +1,15 @@
|
||||
[
|
||||
{
|
||||
"hotelId": "1",
|
||||
"code": "RACK",
|
||||
"inDate": "2015-04-09",
|
||||
"outDate": "2015-04-10",
|
||||
"roomType": {
|
||||
"bookableRate": 109.00,
|
||||
"code": "KNG",
|
||||
"description": "King sized bed",
|
||||
"totalRate": 109.00,
|
||||
"totalRateInclusive": 123.17
|
||||
}
|
||||
}
|
||||
]
|
45
examples/booking/docker-compose.yml
Normal file
45
examples/booking/docker-compose.yml
Normal file
@ -0,0 +1,45 @@
|
||||
consul:
|
||||
command: -server -bootstrap -rejoin
|
||||
image: progrium/consul:latest
|
||||
ports:
|
||||
- "8300:8300"
|
||||
- "8400:8400"
|
||||
- "8500:8500"
|
||||
- "8600:53/udp"
|
||||
micro:
|
||||
command: --registry_address=consul:8500 api --handler=rpc
|
||||
image: microhq/micro:latest
|
||||
links:
|
||||
- consul
|
||||
- api
|
||||
ports:
|
||||
- "8080:8080"
|
||||
api:
|
||||
build: ./api/hotel
|
||||
command: --registry_address=consul:8500
|
||||
links:
|
||||
- consul
|
||||
- auth
|
||||
- geo
|
||||
- profile
|
||||
- rate
|
||||
auth:
|
||||
build: ./srv/auth
|
||||
command: --registry_address=consul:8500
|
||||
links:
|
||||
- consul
|
||||
geo:
|
||||
build: ./srv/geo
|
||||
command: --registry_address=consul:8500
|
||||
links:
|
||||
- consul
|
||||
profile:
|
||||
build: ./srv/profile
|
||||
command: --registry_address=consul:8500
|
||||
links:
|
||||
- consul
|
||||
rate:
|
||||
build: ./srv/rate
|
||||
command: --registry_address=consul:8500
|
||||
links:
|
||||
- consul
|
4
examples/booking/srv/auth/Dockerfile
Normal file
4
examples/booking/srv/auth/Dockerfile
Normal file
@ -0,0 +1,4 @@
|
||||
FROM alpine:3.2
|
||||
ADD . /app
|
||||
WORKDIR /app
|
||||
ENTRYPOINT [ "/app/auth" ]
|
70
examples/booking/srv/auth/main.go
Normal file
70
examples/booking/srv/auth/main.go
Normal file
@ -0,0 +1,70 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
"github.com/micro/examples/booking/data"
|
||||
"github.com/micro/examples/booking/srv/auth/proto"
|
||||
|
||||
"context"
|
||||
"golang.org/x/net/trace"
|
||||
|
||||
"github.com/micro/go-micro/v2"
|
||||
"github.com/micro/go-micro/v2/metadata"
|
||||
)
|
||||
|
||||
type Auth struct {
|
||||
customers map[string]*auth.Customer
|
||||
}
|
||||
|
||||
// VerifyToken returns a customer from authentication token.
|
||||
func (s *Auth) VerifyToken(ctx context.Context, req *auth.Request, rsp *auth.Result) error {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
traceID := md["traceID"]
|
||||
|
||||
if tr, ok := trace.FromContext(ctx); ok {
|
||||
tr.LazyPrintf("traceID %s", traceID)
|
||||
}
|
||||
|
||||
customer := s.customers[req.AuthToken]
|
||||
if customer == nil {
|
||||
return errors.New("Invalid Token")
|
||||
}
|
||||
|
||||
rsp.Customer = customer
|
||||
return nil
|
||||
}
|
||||
|
||||
// loadCustomers loads customers from a JSON file.
|
||||
func loadCustomerData(path string) map[string]*auth.Customer {
|
||||
file := data.MustAsset(path)
|
||||
customers := []*auth.Customer{}
|
||||
|
||||
// unmarshal JSON
|
||||
if err := json.Unmarshal(file, &customers); err != nil {
|
||||
log.Fatalf("Failed to unmarshal json: %v", err)
|
||||
}
|
||||
|
||||
// create customer lookup map
|
||||
cache := make(map[string]*auth.Customer)
|
||||
for _, c := range customers {
|
||||
cache[c.AuthToken] = c
|
||||
}
|
||||
return cache
|
||||
}
|
||||
|
||||
func main() {
|
||||
service := micro.NewService(
|
||||
micro.Name("go.micro.srv.auth"),
|
||||
)
|
||||
|
||||
service.Init()
|
||||
|
||||
auth.RegisterAuthHandler(service.Server(), &Auth{
|
||||
customers: loadCustomerData("data/customers.json"),
|
||||
})
|
||||
|
||||
service.Run()
|
||||
}
|
100
examples/booking/srv/auth/proto/auth.micro.go
Normal file
100
examples/booking/srv/auth/proto/auth.micro.go
Normal file
@ -0,0 +1,100 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: github.com/micro/examples/booking/srv/auth/proto/auth.proto
|
||||
|
||||
/*
|
||||
Package auth is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
github.com/micro/examples/booking/srv/auth/proto/auth.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Request
|
||||
Result
|
||||
Customer
|
||||
*/
|
||||
package auth
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "context"
|
||||
client "github.com/micro/go-micro/v2/client"
|
||||
server "github.com/micro/go-micro/v2/server"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ client.Option
|
||||
var _ server.Option
|
||||
|
||||
// Client API for Auth service
|
||||
|
||||
type AuthService interface {
|
||||
VerifyToken(ctx context.Context, in *Request, opts ...client.CallOption) (*Result, error)
|
||||
}
|
||||
|
||||
type authService struct {
|
||||
c client.Client
|
||||
serviceName string
|
||||
}
|
||||
|
||||
func NewAuthService(serviceName string, c client.Client) AuthService {
|
||||
if c == nil {
|
||||
c = client.NewClient()
|
||||
}
|
||||
if len(serviceName) == 0 {
|
||||
serviceName = "auth"
|
||||
}
|
||||
return &authService{
|
||||
c: c,
|
||||
serviceName: serviceName,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *authService) VerifyToken(ctx context.Context, in *Request, opts ...client.CallOption) (*Result, error) {
|
||||
req := c.c.NewRequest(c.serviceName, "Auth.VerifyToken", in)
|
||||
out := new(Result)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Auth service
|
||||
|
||||
type AuthHandler interface {
|
||||
VerifyToken(context.Context, *Request, *Result) error
|
||||
}
|
||||
|
||||
func RegisterAuthHandler(s server.Server, hdlr AuthHandler, opts ...server.HandlerOption) {
|
||||
type auth interface {
|
||||
VerifyToken(ctx context.Context, in *Request, out *Result) error
|
||||
}
|
||||
type Auth struct {
|
||||
auth
|
||||
}
|
||||
h := &authHandler{hdlr}
|
||||
s.Handle(s.NewHandler(&Auth{h}, opts...))
|
||||
}
|
||||
|
||||
type authHandler struct {
|
||||
AuthHandler
|
||||
}
|
||||
|
||||
func (h *authHandler) VerifyToken(ctx context.Context, in *Request, out *Result) error {
|
||||
return h.AuthHandler.VerifyToken(ctx, in, out)
|
||||
}
|
191
examples/booking/srv/auth/proto/auth.pb.go
Normal file
191
examples/booking/srv/auth/proto/auth.pb.go
Normal file
@ -0,0 +1,191 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: github.com/micro/examples/booking/srv/auth/proto/auth.proto
|
||||
|
||||
/*
|
||||
Package auth is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
github.com/micro/examples/booking/srv/auth/proto/auth.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Request
|
||||
Result
|
||||
Customer
|
||||
*/
|
||||
package auth
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type Request struct {
|
||||
AuthToken string `protobuf:"bytes,1,opt,name=authToken" json:"authToken,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Request) Reset() { *m = Request{} }
|
||||
func (m *Request) String() string { return proto.CompactTextString(m) }
|
||||
func (*Request) ProtoMessage() {}
|
||||
func (*Request) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func (m *Request) GetAuthToken() string {
|
||||
if m != nil {
|
||||
return m.AuthToken
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
Customer *Customer `protobuf:"bytes,1,opt,name=customer" json:"customer,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Result) Reset() { *m = Result{} }
|
||||
func (m *Result) String() string { return proto.CompactTextString(m) }
|
||||
func (*Result) ProtoMessage() {}
|
||||
func (*Result) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *Result) GetCustomer() *Customer {
|
||||
if m != nil {
|
||||
return m.Customer
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Customer struct {
|
||||
Id int32 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
|
||||
AuthToken string `protobuf:"bytes,2,opt,name=authToken" json:"authToken,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Customer) Reset() { *m = Customer{} }
|
||||
func (m *Customer) String() string { return proto.CompactTextString(m) }
|
||||
func (*Customer) ProtoMessage() {}
|
||||
func (*Customer) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
|
||||
func (m *Customer) GetId() int32 {
|
||||
if m != nil {
|
||||
return m.Id
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Customer) GetAuthToken() string {
|
||||
if m != nil {
|
||||
return m.AuthToken
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Request)(nil), "auth.Request")
|
||||
proto.RegisterType((*Result)(nil), "auth.Result")
|
||||
proto.RegisterType((*Customer)(nil), "auth.Customer")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// 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.SupportPackageIsVersion4
|
||||
|
||||
// Client API for Auth service
|
||||
|
||||
type AuthClient interface {
|
||||
VerifyToken(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Result, error)
|
||||
}
|
||||
|
||||
type authClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewAuthClient(cc *grpc.ClientConn) AuthClient {
|
||||
return &authClient{cc}
|
||||
}
|
||||
|
||||
func (c *authClient) VerifyToken(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Result, error) {
|
||||
out := new(Result)
|
||||
err := grpc.Invoke(ctx, "/auth.Auth/VerifyToken", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Auth service
|
||||
|
||||
type AuthServer interface {
|
||||
VerifyToken(context.Context, *Request) (*Result, error)
|
||||
}
|
||||
|
||||
func RegisterAuthServer(s *grpc.Server, srv AuthServer) {
|
||||
s.RegisterService(&_Auth_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Auth_VerifyToken_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Request)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AuthServer).VerifyToken(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/auth.Auth/VerifyToken",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AuthServer).VerifyToken(ctx, req.(*Request))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Auth_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "auth.Auth",
|
||||
HandlerType: (*AuthServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "VerifyToken",
|
||||
Handler: _Auth_VerifyToken_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "github.com/micro/examples/booking/srv/auth/proto/auth.proto",
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/micro/examples/booking/srv/auth/proto/auth.proto", fileDescriptor0)
|
||||
}
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 213 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xb2, 0x4e, 0xcf, 0x2c, 0xc9,
|
||||
0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0xcf, 0xcd, 0x4c, 0x2e, 0xca, 0xd7, 0x4f, 0xad, 0x48,
|
||||
0xcc, 0x2d, 0xc8, 0x49, 0x2d, 0xd6, 0x4f, 0xca, 0xcf, 0xcf, 0xce, 0xcc, 0x4b, 0xd7, 0x2f, 0x2e,
|
||||
0x2a, 0xd3, 0x4f, 0x2c, 0x2d, 0xc9, 0xd0, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x07, 0x33, 0xf5, 0xc0,
|
||||
0x4c, 0x21, 0x16, 0x10, 0x5b, 0x49, 0x9d, 0x8b, 0x3d, 0x28, 0xb5, 0xb0, 0x34, 0xb5, 0xb8, 0x44,
|
||||
0x48, 0x86, 0x8b, 0x13, 0x24, 0x14, 0x92, 0x9f, 0x9d, 0x9a, 0x27, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1,
|
||||
0x19, 0x84, 0x10, 0x50, 0x32, 0xe1, 0x62, 0x0b, 0x4a, 0x2d, 0x2e, 0xcd, 0x29, 0x11, 0xd2, 0xe2,
|
||||
0xe2, 0x48, 0x2e, 0x2d, 0x2e, 0xc9, 0xcf, 0x4d, 0x2d, 0x02, 0x2b, 0xe3, 0x36, 0xe2, 0xd3, 0x03,
|
||||
0x9b, 0xeb, 0x0c, 0x15, 0x0d, 0x82, 0xcb, 0x2b, 0x59, 0x70, 0x71, 0xc0, 0x44, 0x85, 0xf8, 0xb8,
|
||||
0x98, 0x32, 0x53, 0xc0, 0x3a, 0x58, 0x83, 0x98, 0x32, 0x53, 0x50, 0xed, 0x63, 0x42, 0xb3, 0xcf,
|
||||
0xc8, 0x84, 0x8b, 0xc5, 0xb1, 0xb4, 0x24, 0x43, 0x48, 0x87, 0x8b, 0x3b, 0x2c, 0xb5, 0x28, 0x33,
|
||||
0xad, 0x12, 0x2c, 0x2c, 0xc4, 0x0b, 0xb1, 0x0a, 0xea, 0x66, 0x29, 0x1e, 0x18, 0x17, 0xe4, 0x32,
|
||||
0x25, 0x86, 0x24, 0x36, 0xb0, 0xdf, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xd7, 0x57, 0xa9,
|
||||
0xd9, 0x1a, 0x01, 0x00, 0x00,
|
||||
}
|
20
examples/booking/srv/auth/proto/auth.proto
Normal file
20
examples/booking/srv/auth/proto/auth.proto
Normal file
@ -0,0 +1,20 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package auth;
|
||||
|
||||
service Auth {
|
||||
rpc VerifyToken(Request) returns (Result) {}
|
||||
}
|
||||
|
||||
message Request {
|
||||
string authToken = 1;
|
||||
}
|
||||
|
||||
message Result {
|
||||
Customer customer = 1;
|
||||
}
|
||||
|
||||
message Customer {
|
||||
int32 id = 1;
|
||||
string authToken = 2;
|
||||
}
|
4
examples/booking/srv/geo/Dockerfile
Normal file
4
examples/booking/srv/geo/Dockerfile
Normal file
@ -0,0 +1,4 @@
|
||||
FROM alpine:3.2
|
||||
ADD . /app
|
||||
WORKDIR /app
|
||||
ENTRYPOINT [ "/app/geo" ]
|
95
examples/booking/srv/geo/main.go
Normal file
95
examples/booking/srv/geo/main.go
Normal file
@ -0,0 +1,95 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
|
||||
"github.com/hailocab/go-geoindex"
|
||||
"github.com/micro/examples/booking/data"
|
||||
"github.com/micro/examples/booking/srv/geo/proto"
|
||||
|
||||
"context"
|
||||
"golang.org/x/net/trace"
|
||||
|
||||
"github.com/micro/go-micro/v2"
|
||||
"github.com/micro/go-micro/v2/metadata"
|
||||
)
|
||||
|
||||
const (
|
||||
maxSearchRadius = 10
|
||||
maxSearchResults = 5
|
||||
)
|
||||
|
||||
type point struct {
|
||||
Pid string `json:"hotelId"`
|
||||
Plat float64 `json:"lat"`
|
||||
Plon float64 `json:"lon"`
|
||||
}
|
||||
|
||||
// Implement Point interface
|
||||
func (p *point) Lat() float64 { return p.Plat }
|
||||
func (p *point) Lon() float64 { return p.Plon }
|
||||
func (p *point) Id() string { return p.Pid }
|
||||
|
||||
type Geo struct {
|
||||
index *geoindex.ClusteringIndex
|
||||
}
|
||||
|
||||
// Nearby returns all hotels within a given distance.
|
||||
func (s *Geo) Nearby(ctx context.Context, req *geo.Request, rsp *geo.Result) error {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
traceID := md["traceID"]
|
||||
|
||||
if tr, ok := trace.FromContext(ctx); ok {
|
||||
tr.LazyPrintf("traceID %s", traceID)
|
||||
}
|
||||
|
||||
// create center point for query
|
||||
center := &geoindex.GeoPoint{
|
||||
Pid: "",
|
||||
Plat: float64(req.Lat),
|
||||
Plon: float64(req.Lon),
|
||||
}
|
||||
|
||||
// find points around center point
|
||||
points := s.index.KNearest(center, maxSearchResults, geoindex.Km(maxSearchRadius), func(p geoindex.Point) bool {
|
||||
return true
|
||||
})
|
||||
|
||||
for _, p := range points {
|
||||
rsp.HotelIds = append(rsp.HotelIds, p.Id())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// newGeoIndex returns a geo index with points loaded
|
||||
func newGeoIndex(path string) *geoindex.ClusteringIndex {
|
||||
file := data.MustAsset(path)
|
||||
|
||||
// unmarshal json points
|
||||
var points []*point
|
||||
if err := json.Unmarshal(file, &points); err != nil {
|
||||
log.Fatalf("Failed to load hotels: %v", err)
|
||||
}
|
||||
|
||||
// add points to index
|
||||
index := geoindex.NewClusteringIndex()
|
||||
for _, point := range points {
|
||||
index.Add(point)
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
func main() {
|
||||
service := micro.NewService(
|
||||
micro.Name("go.micro.srv.geo"),
|
||||
)
|
||||
|
||||
service.Init()
|
||||
|
||||
geo.RegisterGeoHandler(service.Server(), &Geo{
|
||||
index: newGeoIndex("data/locations.json"),
|
||||
})
|
||||
|
||||
service.Run()
|
||||
}
|
101
examples/booking/srv/geo/proto/geo.micro.go
Normal file
101
examples/booking/srv/geo/proto/geo.micro.go
Normal file
@ -0,0 +1,101 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: github.com/micro/examples/booking/srv/geo/proto/geo.proto
|
||||
|
||||
/*
|
||||
Package geo is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
github.com/micro/examples/booking/srv/geo/proto/geo.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Request
|
||||
Result
|
||||
*/
|
||||
package geo
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "context"
|
||||
client "github.com/micro/go-micro/v2/client"
|
||||
server "github.com/micro/go-micro/v2/server"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ client.Option
|
||||
var _ server.Option
|
||||
|
||||
// Client API for Geo service
|
||||
|
||||
type GeoService interface {
|
||||
// Finds the hotels contained nearby the current lat/lon.
|
||||
Nearby(ctx context.Context, in *Request, opts ...client.CallOption) (*Result, error)
|
||||
}
|
||||
|
||||
type geoService struct {
|
||||
c client.Client
|
||||
serviceName string
|
||||
}
|
||||
|
||||
func NewGeoService(serviceName string, c client.Client) GeoService {
|
||||
if c == nil {
|
||||
c = client.NewClient()
|
||||
}
|
||||
if len(serviceName) == 0 {
|
||||
serviceName = "geo"
|
||||
}
|
||||
return &geoService{
|
||||
c: c,
|
||||
serviceName: serviceName,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *geoService) Nearby(ctx context.Context, in *Request, opts ...client.CallOption) (*Result, error) {
|
||||
req := c.c.NewRequest(c.serviceName, "Geo.Nearby", in)
|
||||
out := new(Result)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Geo service
|
||||
|
||||
type GeoHandler interface {
|
||||
// Finds the hotels contained nearby the current lat/lon.
|
||||
Nearby(context.Context, *Request, *Result) error
|
||||
}
|
||||
|
||||
func RegisterGeoHandler(s server.Server, hdlr GeoHandler, opts ...server.HandlerOption) {
|
||||
type geo interface {
|
||||
Nearby(ctx context.Context, in *Request, out *Result) error
|
||||
}
|
||||
type Geo struct {
|
||||
geo
|
||||
}
|
||||
h := &geoHandler{hdlr}
|
||||
s.Handle(s.NewHandler(&Geo{h}, opts...))
|
||||
}
|
||||
|
||||
type geoHandler struct {
|
||||
GeoHandler
|
||||
}
|
||||
|
||||
func (h *geoHandler) Nearby(ctx context.Context, in *Request, out *Result) error {
|
||||
return h.GeoHandler.Nearby(ctx, in, out)
|
||||
}
|
174
examples/booking/srv/geo/proto/geo.pb.go
Normal file
174
examples/booking/srv/geo/proto/geo.pb.go
Normal file
@ -0,0 +1,174 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: github.com/micro/examples/booking/srv/geo/proto/geo.proto
|
||||
|
||||
/*
|
||||
Package geo is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
github.com/micro/examples/booking/srv/geo/proto/geo.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Request
|
||||
Result
|
||||
*/
|
||||
package geo
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// The latitude and longitude of the current location.
|
||||
type Request struct {
|
||||
Lat float32 `protobuf:"fixed32,1,opt,name=lat" json:"lat,omitempty"`
|
||||
Lon float32 `protobuf:"fixed32,2,opt,name=lon" json:"lon,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Request) Reset() { *m = Request{} }
|
||||
func (m *Request) String() string { return proto.CompactTextString(m) }
|
||||
func (*Request) ProtoMessage() {}
|
||||
func (*Request) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func (m *Request) GetLat() float32 {
|
||||
if m != nil {
|
||||
return m.Lat
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Request) GetLon() float32 {
|
||||
if m != nil {
|
||||
return m.Lon
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
HotelIds []string `protobuf:"bytes,1,rep,name=hotelIds" json:"hotelIds,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Result) Reset() { *m = Result{} }
|
||||
func (m *Result) String() string { return proto.CompactTextString(m) }
|
||||
func (*Result) ProtoMessage() {}
|
||||
func (*Result) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *Result) GetHotelIds() []string {
|
||||
if m != nil {
|
||||
return m.HotelIds
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Request)(nil), "geo.Request")
|
||||
proto.RegisterType((*Result)(nil), "geo.Result")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// 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.SupportPackageIsVersion4
|
||||
|
||||
// Client API for Geo service
|
||||
|
||||
type GeoClient interface {
|
||||
// Finds the hotels contained nearby the current lat/lon.
|
||||
Nearby(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Result, error)
|
||||
}
|
||||
|
||||
type geoClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewGeoClient(cc *grpc.ClientConn) GeoClient {
|
||||
return &geoClient{cc}
|
||||
}
|
||||
|
||||
func (c *geoClient) Nearby(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Result, error) {
|
||||
out := new(Result)
|
||||
err := grpc.Invoke(ctx, "/geo.Geo/Nearby", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Geo service
|
||||
|
||||
type GeoServer interface {
|
||||
// Finds the hotels contained nearby the current lat/lon.
|
||||
Nearby(context.Context, *Request) (*Result, error)
|
||||
}
|
||||
|
||||
func RegisterGeoServer(s *grpc.Server, srv GeoServer) {
|
||||
s.RegisterService(&_Geo_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Geo_Nearby_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Request)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(GeoServer).Nearby(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/geo.Geo/Nearby",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(GeoServer).Nearby(ctx, req.(*Request))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Geo_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "geo.Geo",
|
||||
HandlerType: (*GeoServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Nearby",
|
||||
Handler: _Geo_Nearby_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "github.com/micro/examples/booking/srv/geo/proto/geo.proto",
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/micro/examples/booking/srv/geo/proto/geo.proto", fileDescriptor0)
|
||||
}
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 184 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x3c, 0x8e, 0xb1, 0xae, 0x82, 0x30,
|
||||
0x14, 0x86, 0x03, 0x4d, 0xb8, 0xf7, 0x9e, 0xeb, 0x60, 0x3a, 0x11, 0x26, 0x82, 0x0e, 0xc4, 0x44,
|
||||
0x9a, 0xe8, 0xe4, 0x13, 0x18, 0x17, 0x87, 0xbe, 0x01, 0xc5, 0x93, 0x42, 0x2c, 0x1c, 0x6c, 0x8b,
|
||||
0xd1, 0xb7, 0x37, 0x25, 0xc4, 0xed, 0xfb, 0xbf, 0xe1, 0x7c, 0x07, 0x4e, 0xba, 0xf3, 0xed, 0xa4,
|
||||
0xaa, 0x86, 0x7a, 0xd1, 0x77, 0x8d, 0x25, 0x81, 0xaf, 0xba, 0x1f, 0x0d, 0x3a, 0xa1, 0x88, 0xee,
|
||||
0xdd, 0xa0, 0x85, 0xb3, 0x4f, 0xa1, 0x91, 0xc4, 0x68, 0xc9, 0x53, 0xa0, 0x6a, 0x26, 0xce, 0x34,
|
||||
0x52, 0xb1, 0x87, 0x1f, 0x89, 0x8f, 0x09, 0x9d, 0xe7, 0x6b, 0x60, 0xa6, 0xf6, 0x69, 0x94, 0x47,
|
||||
0x65, 0x2c, 0x03, 0xce, 0x86, 0x86, 0x34, 0x5e, 0x0c, 0x0d, 0xc5, 0x16, 0x12, 0x89, 0x6e, 0x32,
|
||||
0x9e, 0x67, 0xf0, 0xdb, 0x92, 0x47, 0x73, 0xb9, 0xb9, 0x34, 0xca, 0x59, 0xf9, 0x27, 0xbf, 0xfb,
|
||||
0xb0, 0x03, 0x76, 0x46, 0xe2, 0x1b, 0x48, 0xae, 0x58, 0x5b, 0xf5, 0xe6, 0xab, 0x2a, 0x64, 0x97,
|
||||
0x50, 0xf6, 0xbf, 0xac, 0x70, 0x47, 0x25, 0xf3, 0x33, 0xc7, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff,
|
||||
0x39, 0xe5, 0x14, 0x38, 0xc9, 0x00, 0x00, 0x00,
|
||||
}
|
18
examples/booking/srv/geo/proto/geo.proto
Normal file
18
examples/booking/srv/geo/proto/geo.proto
Normal file
@ -0,0 +1,18 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package geo;
|
||||
|
||||
service Geo {
|
||||
// Finds the hotels contained nearby the current lat/lon.
|
||||
rpc Nearby(Request) returns (Result);
|
||||
}
|
||||
|
||||
// The latitude and longitude of the current location.
|
||||
message Request {
|
||||
float lat = 1;
|
||||
float lon = 2;
|
||||
}
|
||||
|
||||
message Result {
|
||||
repeated string hotelIds = 1;
|
||||
}
|
4
examples/booking/srv/profile/Dockerfile
Normal file
4
examples/booking/srv/profile/Dockerfile
Normal file
@ -0,0 +1,4 @@
|
||||
FROM alpine:3.2
|
||||
ADD . /app
|
||||
WORKDIR /app
|
||||
ENTRYPOINT [ "/app/profile" ]
|
64
examples/booking/srv/profile/main.go
Normal file
64
examples/booking/srv/profile/main.go
Normal file
@ -0,0 +1,64 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
|
||||
"github.com/micro/examples/booking/data"
|
||||
"github.com/micro/examples/booking/srv/profile/proto"
|
||||
|
||||
"context"
|
||||
"golang.org/x/net/trace"
|
||||
|
||||
"github.com/micro/go-micro/v2"
|
||||
"github.com/micro/go-micro/v2/metadata"
|
||||
)
|
||||
|
||||
type Profile struct {
|
||||
hotels map[string]*profile.Hotel
|
||||
}
|
||||
|
||||
// GetProfiles returns hotel profiles for requested IDs
|
||||
func (s *Profile) GetProfiles(ctx context.Context, req *profile.Request, rsp *profile.Result) error {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
traceID := md["traceID"]
|
||||
if tr, ok := trace.FromContext(ctx); ok {
|
||||
tr.LazyPrintf("traceID %s", traceID)
|
||||
}
|
||||
|
||||
for _, i := range req.HotelIds {
|
||||
rsp.Hotels = append(rsp.Hotels, s.hotels[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// loadProfiles loads hotel profiles from a JSON file.
|
||||
func loadProfiles(path string) map[string]*profile.Hotel {
|
||||
file := data.MustAsset(path)
|
||||
|
||||
// unmarshal json profiles
|
||||
hotels := []*profile.Hotel{}
|
||||
if err := json.Unmarshal(file, &hotels); err != nil {
|
||||
log.Fatalf("Failed to load json: %v", err)
|
||||
}
|
||||
|
||||
profiles := make(map[string]*profile.Hotel)
|
||||
for _, hotel := range hotels {
|
||||
profiles[hotel.Id] = hotel
|
||||
}
|
||||
return profiles
|
||||
}
|
||||
|
||||
func main() {
|
||||
service := micro.NewService(
|
||||
micro.Name("go.micro.srv.profile"),
|
||||
)
|
||||
|
||||
service.Init()
|
||||
|
||||
profile.RegisterProfileHandler(service.Server(), &Profile{
|
||||
hotels: loadProfiles("data/profiles.json"),
|
||||
})
|
||||
|
||||
service.Run()
|
||||
}
|
102
examples/booking/srv/profile/proto/profile.micro.go
Normal file
102
examples/booking/srv/profile/proto/profile.micro.go
Normal file
@ -0,0 +1,102 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: github.com/micro/examples/booking/srv/profile/proto/profile.proto
|
||||
|
||||
/*
|
||||
Package profile is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
github.com/micro/examples/booking/srv/profile/proto/profile.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Request
|
||||
Result
|
||||
Hotel
|
||||
Address
|
||||
Image
|
||||
*/
|
||||
package profile
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "context"
|
||||
client "github.com/micro/go-micro/v2/client"
|
||||
server "github.com/micro/go-micro/v2/server"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ client.Option
|
||||
var _ server.Option
|
||||
|
||||
// Client API for Profile service
|
||||
|
||||
type ProfileService interface {
|
||||
GetProfiles(ctx context.Context, in *Request, opts ...client.CallOption) (*Result, error)
|
||||
}
|
||||
|
||||
type profileService struct {
|
||||
c client.Client
|
||||
serviceName string
|
||||
}
|
||||
|
||||
func NewProfileService(serviceName string, c client.Client) ProfileService {
|
||||
if c == nil {
|
||||
c = client.NewClient()
|
||||
}
|
||||
if len(serviceName) == 0 {
|
||||
serviceName = "profile"
|
||||
}
|
||||
return &profileService{
|
||||
c: c,
|
||||
serviceName: serviceName,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *profileService) GetProfiles(ctx context.Context, in *Request, opts ...client.CallOption) (*Result, error) {
|
||||
req := c.c.NewRequest(c.serviceName, "Profile.GetProfiles", in)
|
||||
out := new(Result)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Profile service
|
||||
|
||||
type ProfileHandler interface {
|
||||
GetProfiles(context.Context, *Request, *Result) error
|
||||
}
|
||||
|
||||
func RegisterProfileHandler(s server.Server, hdlr ProfileHandler, opts ...server.HandlerOption) {
|
||||
type profile interface {
|
||||
GetProfiles(ctx context.Context, in *Request, out *Result) error
|
||||
}
|
||||
type Profile struct {
|
||||
profile
|
||||
}
|
||||
h := &profileHandler{hdlr}
|
||||
s.Handle(s.NewHandler(&Profile{h}, opts...))
|
||||
}
|
||||
|
||||
type profileHandler struct {
|
||||
ProfileHandler
|
||||
}
|
||||
|
||||
func (h *profileHandler) GetProfiles(ctx context.Context, in *Request, out *Result) error {
|
||||
return h.ProfileHandler.GetProfiles(ctx, in, out)
|
||||
}
|
326
examples/booking/srv/profile/proto/profile.pb.go
Normal file
326
examples/booking/srv/profile/proto/profile.pb.go
Normal file
@ -0,0 +1,326 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: github.com/micro/examples/booking/srv/profile/proto/profile.proto
|
||||
|
||||
/*
|
||||
Package profile is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
github.com/micro/examples/booking/srv/profile/proto/profile.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Request
|
||||
Result
|
||||
Hotel
|
||||
Address
|
||||
Image
|
||||
*/
|
||||
package profile
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type Request struct {
|
||||
HotelIds []string `protobuf:"bytes,1,rep,name=hotelIds" json:"hotelIds,omitempty"`
|
||||
Locale string `protobuf:"bytes,2,opt,name=locale" json:"locale,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Request) Reset() { *m = Request{} }
|
||||
func (m *Request) String() string { return proto.CompactTextString(m) }
|
||||
func (*Request) ProtoMessage() {}
|
||||
func (*Request) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func (m *Request) GetHotelIds() []string {
|
||||
if m != nil {
|
||||
return m.HotelIds
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Request) GetLocale() string {
|
||||
if m != nil {
|
||||
return m.Locale
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
Hotels []*Hotel `protobuf:"bytes,1,rep,name=hotels" json:"hotels,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Result) Reset() { *m = Result{} }
|
||||
func (m *Result) String() string { return proto.CompactTextString(m) }
|
||||
func (*Result) ProtoMessage() {}
|
||||
func (*Result) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *Result) GetHotels() []*Hotel {
|
||||
if m != nil {
|
||||
return m.Hotels
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Hotel struct {
|
||||
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
|
||||
Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
|
||||
PhoneNumber string `protobuf:"bytes,3,opt,name=phoneNumber" json:"phoneNumber,omitempty"`
|
||||
Description string `protobuf:"bytes,4,opt,name=description" json:"description,omitempty"`
|
||||
Address *Address `protobuf:"bytes,5,opt,name=address" json:"address,omitempty"`
|
||||
Images []*Image `protobuf:"bytes,6,rep,name=images" json:"images,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Hotel) Reset() { *m = Hotel{} }
|
||||
func (m *Hotel) String() string { return proto.CompactTextString(m) }
|
||||
func (*Hotel) ProtoMessage() {}
|
||||
func (*Hotel) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
|
||||
func (m *Hotel) GetId() string {
|
||||
if m != nil {
|
||||
return m.Id
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Hotel) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Hotel) GetPhoneNumber() string {
|
||||
if m != nil {
|
||||
return m.PhoneNumber
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Hotel) GetDescription() string {
|
||||
if m != nil {
|
||||
return m.Description
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Hotel) GetAddress() *Address {
|
||||
if m != nil {
|
||||
return m.Address
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Hotel) GetImages() []*Image {
|
||||
if m != nil {
|
||||
return m.Images
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Address struct {
|
||||
StreetNumber string `protobuf:"bytes,1,opt,name=streetNumber" json:"streetNumber,omitempty"`
|
||||
StreetName string `protobuf:"bytes,2,opt,name=streetName" json:"streetName,omitempty"`
|
||||
City string `protobuf:"bytes,3,opt,name=city" json:"city,omitempty"`
|
||||
State string `protobuf:"bytes,4,opt,name=state" json:"state,omitempty"`
|
||||
Country string `protobuf:"bytes,5,opt,name=country" json:"country,omitempty"`
|
||||
PostalCode string `protobuf:"bytes,6,opt,name=postalCode" json:"postalCode,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Address) Reset() { *m = Address{} }
|
||||
func (m *Address) String() string { return proto.CompactTextString(m) }
|
||||
func (*Address) ProtoMessage() {}
|
||||
func (*Address) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||
|
||||
func (m *Address) GetStreetNumber() string {
|
||||
if m != nil {
|
||||
return m.StreetNumber
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Address) GetStreetName() string {
|
||||
if m != nil {
|
||||
return m.StreetName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Address) GetCity() string {
|
||||
if m != nil {
|
||||
return m.City
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Address) GetState() string {
|
||||
if m != nil {
|
||||
return m.State
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Address) GetCountry() string {
|
||||
if m != nil {
|
||||
return m.Country
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Address) GetPostalCode() string {
|
||||
if m != nil {
|
||||
return m.PostalCode
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Image struct {
|
||||
Url string `protobuf:"bytes,1,opt,name=url" json:"url,omitempty"`
|
||||
Default bool `protobuf:"varint,2,opt,name=default" json:"default,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Image) Reset() { *m = Image{} }
|
||||
func (m *Image) String() string { return proto.CompactTextString(m) }
|
||||
func (*Image) ProtoMessage() {}
|
||||
func (*Image) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
|
||||
|
||||
func (m *Image) GetUrl() string {
|
||||
if m != nil {
|
||||
return m.Url
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Image) GetDefault() bool {
|
||||
if m != nil {
|
||||
return m.Default
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Request)(nil), "profile.Request")
|
||||
proto.RegisterType((*Result)(nil), "profile.Result")
|
||||
proto.RegisterType((*Hotel)(nil), "profile.Hotel")
|
||||
proto.RegisterType((*Address)(nil), "profile.Address")
|
||||
proto.RegisterType((*Image)(nil), "profile.Image")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// 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.SupportPackageIsVersion4
|
||||
|
||||
// Client API for Profile service
|
||||
|
||||
type ProfileClient interface {
|
||||
GetProfiles(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Result, error)
|
||||
}
|
||||
|
||||
type profileClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewProfileClient(cc *grpc.ClientConn) ProfileClient {
|
||||
return &profileClient{cc}
|
||||
}
|
||||
|
||||
func (c *profileClient) GetProfiles(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Result, error) {
|
||||
out := new(Result)
|
||||
err := grpc.Invoke(ctx, "/profile.Profile/GetProfiles", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Profile service
|
||||
|
||||
type ProfileServer interface {
|
||||
GetProfiles(context.Context, *Request) (*Result, error)
|
||||
}
|
||||
|
||||
func RegisterProfileServer(s *grpc.Server, srv ProfileServer) {
|
||||
s.RegisterService(&_Profile_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Profile_GetProfiles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Request)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ProfileServer).GetProfiles(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/profile.Profile/GetProfiles",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ProfileServer).GetProfiles(ctx, req.(*Request))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Profile_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "profile.Profile",
|
||||
HandlerType: (*ProfileServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "GetProfiles",
|
||||
Handler: _Profile_GetProfiles_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "github.com/micro/examples/booking/srv/profile/proto/profile.proto",
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/micro/examples/booking/srv/profile/proto/profile.proto", fileDescriptor0)
|
||||
}
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 397 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x92, 0xc1, 0x6e, 0xd4, 0x30,
|
||||
0x10, 0x86, 0x95, 0xdd, 0x6e, 0xd2, 0x9d, 0x45, 0xa5, 0x1a, 0x21, 0x64, 0xf5, 0x80, 0x56, 0x39,
|
||||
0xa0, 0x15, 0x87, 0x4d, 0xb5, 0x3d, 0x22, 0x0e, 0x15, 0x07, 0xe8, 0x05, 0x21, 0xbf, 0x81, 0x13,
|
||||
0x4f, 0x77, 0x2d, 0x9c, 0x38, 0xd8, 0x0e, 0xa2, 0x8f, 0xc5, 0x33, 0xf0, 0x62, 0xc8, 0x8e, 0xd3,
|
||||
0x0d, 0x3d, 0x79, 0xfe, 0x6f, 0xc6, 0x9e, 0xf9, 0xad, 0x81, 0xfb, 0xa3, 0xf2, 0xa7, 0xa1, 0xde,
|
||||
0x37, 0xa6, 0xad, 0x5a, 0xd5, 0x58, 0x53, 0xd1, 0x6f, 0xd1, 0xf6, 0x9a, 0x5c, 0x55, 0x1b, 0xf3,
|
||||
0x43, 0x75, 0xc7, 0xca, 0xd9, 0x5f, 0x55, 0x6f, 0xcd, 0xa3, 0xd2, 0x14, 0x4e, 0x6f, 0x26, 0xb5,
|
||||
0x8f, 0x0a, 0x8b, 0x24, 0xcb, 0x4f, 0x50, 0x70, 0xfa, 0x39, 0x90, 0xf3, 0x78, 0x03, 0x97, 0x27,
|
||||
0xe3, 0x49, 0x3f, 0x48, 0xc7, 0xb2, 0xed, 0x72, 0xb7, 0xe6, 0xcf, 0x1a, 0xdf, 0x42, 0xae, 0x4d,
|
||||
0x23, 0x34, 0xb1, 0xc5, 0x36, 0xdb, 0xad, 0x79, 0x52, 0xe5, 0x2d, 0xe4, 0x9c, 0xdc, 0xa0, 0x3d,
|
||||
0xbe, 0x87, 0x3c, 0x56, 0x8f, 0x77, 0x37, 0x87, 0xab, 0xfd, 0xd4, 0xf1, 0x6b, 0xc0, 0x3c, 0x65,
|
||||
0xcb, 0xbf, 0x19, 0xac, 0x22, 0xc1, 0x2b, 0x58, 0x28, 0xc9, 0xb2, 0xf8, 0xde, 0x42, 0x49, 0x44,
|
||||
0xb8, 0xe8, 0x44, 0x3b, 0x75, 0x88, 0x31, 0x6e, 0x61, 0xd3, 0x9f, 0x4c, 0x47, 0xdf, 0x86, 0xb6,
|
||||
0x26, 0xcb, 0x96, 0x31, 0x35, 0x47, 0xa1, 0x42, 0x92, 0x6b, 0xac, 0xea, 0xbd, 0x32, 0x1d, 0xbb,
|
||||
0x18, 0x2b, 0x66, 0x08, 0x3f, 0x40, 0x21, 0xa4, 0xb4, 0xe4, 0x1c, 0x5b, 0x6d, 0xb3, 0xdd, 0xe6,
|
||||
0x70, 0xfd, 0x3c, 0xda, 0xfd, 0xc8, 0xf9, 0x54, 0x10, 0x5c, 0xa8, 0x56, 0x1c, 0xc9, 0xb1, 0xfc,
|
||||
0x85, 0x8b, 0x87, 0x80, 0x79, 0xca, 0x96, 0x7f, 0x32, 0x28, 0xd2, 0x65, 0x2c, 0xe1, 0x95, 0xf3,
|
||||
0x96, 0xc8, 0xa7, 0x21, 0x47, 0x47, 0xff, 0x31, 0x7c, 0x07, 0x90, 0xf4, 0xd9, 0xe1, 0x8c, 0x04,
|
||||
0xef, 0x8d, 0xf2, 0x4f, 0xc9, 0x60, 0x8c, 0xf1, 0x0d, 0xac, 0x9c, 0x17, 0x9e, 0x92, 0xa7, 0x51,
|
||||
0x20, 0x83, 0xa2, 0x31, 0x43, 0xe7, 0xed, 0x53, 0x74, 0xb3, 0xe6, 0x93, 0x0c, 0x3d, 0x7a, 0xe3,
|
||||
0xbc, 0xd0, 0x9f, 0x8d, 0x24, 0x96, 0x8f, 0x3d, 0xce, 0xa4, 0xbc, 0x83, 0x55, 0x34, 0x81, 0xd7,
|
||||
0xb0, 0x1c, 0xac, 0x4e, 0x73, 0x86, 0x30, 0x3c, 0x2a, 0xe9, 0x51, 0x0c, 0xda, 0xc7, 0xd9, 0x2e,
|
||||
0xf9, 0x24, 0x0f, 0x1f, 0xa1, 0xf8, 0x3e, 0xfe, 0x00, 0xde, 0xc2, 0xe6, 0x0b, 0xf9, 0xa4, 0x1c,
|
||||
0x9e, 0x7f, 0x31, 0x2d, 0xd0, 0xcd, 0xeb, 0x19, 0x09, 0x3b, 0x51, 0xe7, 0x71, 0xd9, 0xee, 0xfe,
|
||||
0x05, 0x00, 0x00, 0xff, 0xff, 0xf1, 0x00, 0x45, 0x96, 0xb1, 0x02, 0x00, 0x00,
|
||||
}
|
39
examples/booking/srv/profile/proto/profile.proto
Normal file
39
examples/booking/srv/profile/proto/profile.proto
Normal file
@ -0,0 +1,39 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package profile;
|
||||
|
||||
service Profile {
|
||||
rpc GetProfiles(Request) returns (Result);
|
||||
}
|
||||
|
||||
message Request {
|
||||
repeated string hotelIds = 1;
|
||||
string locale = 2;
|
||||
}
|
||||
|
||||
message Result {
|
||||
repeated Hotel hotels = 1;
|
||||
}
|
||||
|
||||
message Hotel {
|
||||
string id = 1;
|
||||
string name = 2;
|
||||
string phoneNumber = 3;
|
||||
string description = 4;
|
||||
Address address = 5;
|
||||
repeated Image images = 6;
|
||||
}
|
||||
|
||||
message Address {
|
||||
string streetNumber = 1;
|
||||
string streetName = 2;
|
||||
string city = 3;
|
||||
string state = 4;
|
||||
string country = 5;
|
||||
string postalCode = 6;
|
||||
}
|
||||
|
||||
message Image {
|
||||
string url = 1;
|
||||
bool default = 2;
|
||||
}
|
4
examples/booking/srv/rate/Dockerfile
Normal file
4
examples/booking/srv/rate/Dockerfile
Normal file
@ -0,0 +1,4 @@
|
||||
FROM alpine:3.2
|
||||
ADD . /app
|
||||
WORKDIR /app
|
||||
ENTRYPOINT [ "/app/rate" ]
|
82
examples/booking/srv/rate/main.go
Normal file
82
examples/booking/srv/rate/main.go
Normal file
@ -0,0 +1,82 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
|
||||
"github.com/micro/examples/booking/data"
|
||||
"github.com/micro/examples/booking/srv/rate/proto"
|
||||
|
||||
"context"
|
||||
"golang.org/x/net/trace"
|
||||
|
||||
"github.com/micro/go-micro/v2"
|
||||
"github.com/micro/go-micro/v2/metadata"
|
||||
)
|
||||
|
||||
type stay struct {
|
||||
HotelID string
|
||||
InDate string
|
||||
OutDate string
|
||||
}
|
||||
|
||||
type Rate struct {
|
||||
rateTable map[stay]*rate.RatePlan
|
||||
}
|
||||
|
||||
// GetRates gets rates for hotels for specific date range.
|
||||
func (s *Rate) GetRates(ctx context.Context, req *rate.Request, rsp *rate.Result) error {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
traceID := md["traceID"]
|
||||
|
||||
if tr, ok := trace.FromContext(ctx); ok {
|
||||
tr.LazyPrintf("traceID %s", traceID)
|
||||
}
|
||||
|
||||
for _, hotelID := range req.HotelIds {
|
||||
stay := stay{
|
||||
HotelID: hotelID,
|
||||
InDate: req.InDate,
|
||||
OutDate: req.OutDate,
|
||||
}
|
||||
if s.rateTable[stay] != nil {
|
||||
rsp.RatePlans = append(rsp.RatePlans, s.rateTable[stay])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// loadRates loads rate codes from JSON file.
|
||||
func loadRateTable(path string) map[stay]*rate.RatePlan {
|
||||
file := data.MustAsset("data/rates.json")
|
||||
|
||||
rates := []*rate.RatePlan{}
|
||||
if err := json.Unmarshal(file, &rates); err != nil {
|
||||
log.Fatalf("Failed to load json: %v", err)
|
||||
}
|
||||
|
||||
rateTable := make(map[stay]*rate.RatePlan)
|
||||
for _, ratePlan := range rates {
|
||||
stay := stay{
|
||||
HotelID: ratePlan.HotelId,
|
||||
InDate: ratePlan.InDate,
|
||||
OutDate: ratePlan.OutDate,
|
||||
}
|
||||
rateTable[stay] = ratePlan
|
||||
}
|
||||
return rateTable
|
||||
}
|
||||
|
||||
func main() {
|
||||
service := micro.NewService(
|
||||
micro.Name("go.micro.srv.rate"),
|
||||
)
|
||||
|
||||
service.Init()
|
||||
|
||||
rate.RegisterRateHandler(service.Server(), &Rate{
|
||||
rateTable: loadRateTable("data/rates.json"),
|
||||
})
|
||||
|
||||
service.Run()
|
||||
}
|
103
examples/booking/srv/rate/proto/rate.micro.go
Normal file
103
examples/booking/srv/rate/proto/rate.micro.go
Normal file
@ -0,0 +1,103 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: github.com/micro/examples/booking/srv/rate/proto/rate.proto
|
||||
|
||||
/*
|
||||
Package rate is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
github.com/micro/examples/booking/srv/rate/proto/rate.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Request
|
||||
Result
|
||||
RatePlan
|
||||
RoomType
|
||||
*/
|
||||
package rate
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "context"
|
||||
client "github.com/micro/go-micro/v2/client"
|
||||
server "github.com/micro/go-micro/v2/server"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ client.Option
|
||||
var _ server.Option
|
||||
|
||||
// Client API for Rate service
|
||||
|
||||
type RateService interface {
|
||||
// GetRates returns rate codes for hotels for a given date range
|
||||
GetRates(ctx context.Context, in *Request, opts ...client.CallOption) (*Result, error)
|
||||
}
|
||||
|
||||
type rateService struct {
|
||||
c client.Client
|
||||
serviceName string
|
||||
}
|
||||
|
||||
func NewRateService(serviceName string, c client.Client) RateService {
|
||||
if c == nil {
|
||||
c = client.NewClient()
|
||||
}
|
||||
if len(serviceName) == 0 {
|
||||
serviceName = "rate"
|
||||
}
|
||||
return &rateService{
|
||||
c: c,
|
||||
serviceName: serviceName,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *rateService) GetRates(ctx context.Context, in *Request, opts ...client.CallOption) (*Result, error) {
|
||||
req := c.c.NewRequest(c.serviceName, "Rate.GetRates", in)
|
||||
out := new(Result)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Rate service
|
||||
|
||||
type RateHandler interface {
|
||||
// GetRates returns rate codes for hotels for a given date range
|
||||
GetRates(context.Context, *Request, *Result) error
|
||||
}
|
||||
|
||||
func RegisterRateHandler(s server.Server, hdlr RateHandler, opts ...server.HandlerOption) {
|
||||
type rate interface {
|
||||
GetRates(ctx context.Context, in *Request, out *Result) error
|
||||
}
|
||||
type Rate struct {
|
||||
rate
|
||||
}
|
||||
h := &rateHandler{hdlr}
|
||||
s.Handle(s.NewHandler(&Rate{h}, opts...))
|
||||
}
|
||||
|
||||
type rateHandler struct {
|
||||
RateHandler
|
||||
}
|
||||
|
||||
func (h *rateHandler) GetRates(ctx context.Context, in *Request, out *Result) error {
|
||||
return h.RateHandler.GetRates(ctx, in, out)
|
||||
}
|
299
examples/booking/srv/rate/proto/rate.pb.go
Normal file
299
examples/booking/srv/rate/proto/rate.pb.go
Normal file
@ -0,0 +1,299 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: github.com/micro/examples/booking/srv/rate/proto/rate.proto
|
||||
|
||||
/*
|
||||
Package rate is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
github.com/micro/examples/booking/srv/rate/proto/rate.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Request
|
||||
Result
|
||||
RatePlan
|
||||
RoomType
|
||||
*/
|
||||
package rate
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type Request struct {
|
||||
HotelIds []string `protobuf:"bytes,1,rep,name=hotelIds" json:"hotelIds,omitempty"`
|
||||
InDate string `protobuf:"bytes,2,opt,name=inDate" json:"inDate,omitempty"`
|
||||
OutDate string `protobuf:"bytes,3,opt,name=outDate" json:"outDate,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Request) Reset() { *m = Request{} }
|
||||
func (m *Request) String() string { return proto.CompactTextString(m) }
|
||||
func (*Request) ProtoMessage() {}
|
||||
func (*Request) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func (m *Request) GetHotelIds() []string {
|
||||
if m != nil {
|
||||
return m.HotelIds
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Request) GetInDate() string {
|
||||
if m != nil {
|
||||
return m.InDate
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Request) GetOutDate() string {
|
||||
if m != nil {
|
||||
return m.OutDate
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
RatePlans []*RatePlan `protobuf:"bytes,1,rep,name=ratePlans" json:"ratePlans,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Result) Reset() { *m = Result{} }
|
||||
func (m *Result) String() string { return proto.CompactTextString(m) }
|
||||
func (*Result) ProtoMessage() {}
|
||||
func (*Result) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *Result) GetRatePlans() []*RatePlan {
|
||||
if m != nil {
|
||||
return m.RatePlans
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type RatePlan struct {
|
||||
HotelId string `protobuf:"bytes,1,opt,name=hotelId" json:"hotelId,omitempty"`
|
||||
Code string `protobuf:"bytes,2,opt,name=code" json:"code,omitempty"`
|
||||
InDate string `protobuf:"bytes,3,opt,name=inDate" json:"inDate,omitempty"`
|
||||
OutDate string `protobuf:"bytes,4,opt,name=outDate" json:"outDate,omitempty"`
|
||||
RoomType *RoomType `protobuf:"bytes,5,opt,name=roomType" json:"roomType,omitempty"`
|
||||
}
|
||||
|
||||
func (m *RatePlan) Reset() { *m = RatePlan{} }
|
||||
func (m *RatePlan) String() string { return proto.CompactTextString(m) }
|
||||
func (*RatePlan) ProtoMessage() {}
|
||||
func (*RatePlan) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
|
||||
func (m *RatePlan) GetHotelId() string {
|
||||
if m != nil {
|
||||
return m.HotelId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RatePlan) GetCode() string {
|
||||
if m != nil {
|
||||
return m.Code
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RatePlan) GetInDate() string {
|
||||
if m != nil {
|
||||
return m.InDate
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RatePlan) GetOutDate() string {
|
||||
if m != nil {
|
||||
return m.OutDate
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RatePlan) GetRoomType() *RoomType {
|
||||
if m != nil {
|
||||
return m.RoomType
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type RoomType struct {
|
||||
BookableRate float64 `protobuf:"fixed64,1,opt,name=bookableRate" json:"bookableRate,omitempty"`
|
||||
TotalRate float64 `protobuf:"fixed64,2,opt,name=totalRate" json:"totalRate,omitempty"`
|
||||
TotalRateInclusive float64 `protobuf:"fixed64,3,opt,name=totalRateInclusive" json:"totalRateInclusive,omitempty"`
|
||||
Code string `protobuf:"bytes,4,opt,name=code" json:"code,omitempty"`
|
||||
Currency string `protobuf:"bytes,5,opt,name=currency" json:"currency,omitempty"`
|
||||
RoomDescription string `protobuf:"bytes,6,opt,name=roomDescription" json:"roomDescription,omitempty"`
|
||||
}
|
||||
|
||||
func (m *RoomType) Reset() { *m = RoomType{} }
|
||||
func (m *RoomType) String() string { return proto.CompactTextString(m) }
|
||||
func (*RoomType) ProtoMessage() {}
|
||||
func (*RoomType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||
|
||||
func (m *RoomType) GetBookableRate() float64 {
|
||||
if m != nil {
|
||||
return m.BookableRate
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *RoomType) GetTotalRate() float64 {
|
||||
if m != nil {
|
||||
return m.TotalRate
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *RoomType) GetTotalRateInclusive() float64 {
|
||||
if m != nil {
|
||||
return m.TotalRateInclusive
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *RoomType) GetCode() string {
|
||||
if m != nil {
|
||||
return m.Code
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RoomType) GetCurrency() string {
|
||||
if m != nil {
|
||||
return m.Currency
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RoomType) GetRoomDescription() string {
|
||||
if m != nil {
|
||||
return m.RoomDescription
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Request)(nil), "rate.Request")
|
||||
proto.RegisterType((*Result)(nil), "rate.Result")
|
||||
proto.RegisterType((*RatePlan)(nil), "rate.RatePlan")
|
||||
proto.RegisterType((*RoomType)(nil), "rate.RoomType")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// 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.SupportPackageIsVersion4
|
||||
|
||||
// Client API for Rate service
|
||||
|
||||
type RateClient interface {
|
||||
// GetRates returns rate codes for hotels for a given date range
|
||||
GetRates(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Result, error)
|
||||
}
|
||||
|
||||
type rateClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewRateClient(cc *grpc.ClientConn) RateClient {
|
||||
return &rateClient{cc}
|
||||
}
|
||||
|
||||
func (c *rateClient) GetRates(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Result, error) {
|
||||
out := new(Result)
|
||||
err := grpc.Invoke(ctx, "/rate.Rate/GetRates", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Rate service
|
||||
|
||||
type RateServer interface {
|
||||
// GetRates returns rate codes for hotels for a given date range
|
||||
GetRates(context.Context, *Request) (*Result, error)
|
||||
}
|
||||
|
||||
func RegisterRateServer(s *grpc.Server, srv RateServer) {
|
||||
s.RegisterService(&_Rate_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Rate_GetRates_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Request)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(RateServer).GetRates(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rate.Rate/GetRates",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(RateServer).GetRates(ctx, req.(*Request))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Rate_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "rate.Rate",
|
||||
HandlerType: (*RateServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "GetRates",
|
||||
Handler: _Rate_GetRates_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "github.com/micro/examples/booking/srv/rate/proto/rate.proto",
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/micro/examples/booking/srv/rate/proto/rate.proto", fileDescriptor0)
|
||||
}
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 351 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0x4f, 0x4b, 0xfb, 0x30,
|
||||
0x18, 0xc7, 0xc9, 0x6f, 0xfd, 0x75, 0xed, 0xe3, 0x54, 0x78, 0x0e, 0x52, 0x86, 0x87, 0xd1, 0x8b,
|
||||
0x43, 0xa4, 0x85, 0x09, 0x5e, 0xbc, 0x0e, 0x64, 0x37, 0x09, 0x82, 0xe7, 0xb6, 0x0b, 0x5b, 0x31,
|
||||
0x6d, 0x6a, 0x92, 0x0e, 0xf7, 0x46, 0x7c, 0x69, 0xbe, 0x1e, 0x49, 0x9a, 0x76, 0x9b, 0xe8, 0xed,
|
||||
0xfb, 0x27, 0x3c, 0xfd, 0xe4, 0x69, 0xe0, 0x71, 0x53, 0xea, 0x6d, 0x9b, 0x27, 0x85, 0xa8, 0xd2,
|
||||
0xaa, 0x2c, 0xa4, 0x48, 0xd9, 0x47, 0x56, 0x35, 0x9c, 0xa9, 0x34, 0x17, 0xe2, 0xad, 0xac, 0x37,
|
||||
0xa9, 0x92, 0xbb, 0x54, 0x66, 0x9a, 0xa5, 0x8d, 0x14, 0x5a, 0x58, 0x99, 0x58, 0x89, 0x9e, 0xd1,
|
||||
0xf1, 0x2b, 0x8c, 0x29, 0x7b, 0x6f, 0x99, 0xd2, 0x38, 0x85, 0x60, 0x2b, 0x34, 0xe3, 0xab, 0xb5,
|
||||
0x8a, 0xc8, 0x6c, 0x34, 0x0f, 0xe9, 0xe0, 0xf1, 0x0a, 0xfc, 0xb2, 0x5e, 0x66, 0x9a, 0x45, 0xff,
|
||||
0x66, 0x64, 0x1e, 0x52, 0xe7, 0x30, 0x82, 0xb1, 0x68, 0xb5, 0x2d, 0x46, 0xb6, 0xe8, 0x6d, 0xfc,
|
||||
0x00, 0x3e, 0x65, 0xaa, 0xe5, 0x1a, 0xef, 0x20, 0x34, 0x9f, 0x7a, 0xe6, 0x59, 0xdd, 0x0d, 0x3e,
|
||||
0x5b, 0x5c, 0x24, 0x16, 0x84, 0xba, 0x98, 0x1e, 0x0e, 0xc4, 0x9f, 0x04, 0x82, 0x3e, 0x37, 0xe3,
|
||||
0x1d, 0x42, 0x44, 0xba, 0xf1, 0xce, 0x22, 0x82, 0x57, 0x88, 0x75, 0x8f, 0x63, 0xf5, 0x11, 0xe4,
|
||||
0xe8, 0x2f, 0x48, 0xef, 0x04, 0x12, 0x6f, 0x21, 0x90, 0x42, 0x54, 0x2f, 0xfb, 0x86, 0x45, 0xff,
|
||||
0x67, 0xe4, 0x88, 0xcc, 0xa5, 0x74, 0xe8, 0xe3, 0x2f, 0x03, 0xe6, 0x0c, 0xc6, 0x30, 0x31, 0x1b,
|
||||
0xce, 0x72, 0xce, 0x0c, 0xac, 0xa5, 0x23, 0xf4, 0x24, 0xc3, 0x6b, 0x08, 0xb5, 0xd0, 0x19, 0xa7,
|
||||
0xfd, 0xda, 0x08, 0x3d, 0x04, 0x98, 0x00, 0x0e, 0x66, 0x55, 0x17, 0xbc, 0x55, 0xe5, 0xae, 0x03,
|
||||
0x27, 0xf4, 0x97, 0x66, 0xb8, 0xb0, 0x77, 0x74, 0xe1, 0x29, 0x04, 0x45, 0x2b, 0x25, 0xab, 0x8b,
|
||||
0xbd, 0xc5, 0x0f, 0xe9, 0xe0, 0x71, 0x0e, 0x97, 0x06, 0x7d, 0xc9, 0x54, 0x21, 0xcb, 0x46, 0x97,
|
||||
0xa2, 0x8e, 0x7c, 0x7b, 0xe4, 0x67, 0xbc, 0x48, 0xc1, 0xb3, 0x44, 0x37, 0x10, 0x3c, 0x31, 0x6d,
|
||||
0xa4, 0xc2, 0x73, 0xb7, 0x86, 0xee, 0x69, 0x4c, 0x27, 0xbd, 0x35, 0x3f, 0x34, 0xf7, 0xed, 0x03,
|
||||
0xba, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xef, 0x8a, 0xc6, 0x91, 0x7f, 0x02, 0x00, 0x00,
|
||||
}
|
35
examples/booking/srv/rate/proto/rate.proto
Normal file
35
examples/booking/srv/rate/proto/rate.proto
Normal file
@ -0,0 +1,35 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package rate;
|
||||
|
||||
service Rate {
|
||||
// GetRates returns rate codes for hotels for a given date range
|
||||
rpc GetRates(Request) returns (Result);
|
||||
}
|
||||
|
||||
message Request {
|
||||
repeated string hotelIds = 1;
|
||||
string inDate = 2;
|
||||
string outDate = 3;
|
||||
}
|
||||
|
||||
message Result {
|
||||
repeated RatePlan ratePlans = 1;
|
||||
}
|
||||
|
||||
message RatePlan {
|
||||
string hotelId = 1;
|
||||
string code = 2;
|
||||
string inDate = 3;
|
||||
string outDate = 4;
|
||||
RoomType roomType = 5;
|
||||
}
|
||||
|
||||
message RoomType {
|
||||
double bookableRate = 1;
|
||||
double totalRate = 2;
|
||||
double totalRateInclusive = 3;
|
||||
string code = 4;
|
||||
string currency = 5;
|
||||
string roomDescription = 6;
|
||||
}
|
9
examples/broker/README.md
Normal file
9
examples/broker/README.md
Normal file
@ -0,0 +1,9 @@
|
||||
# Broker
|
||||
|
||||
The [broker](https://godoc.org/github.com/micro/go-micro/broker#Broker) is an interface for PubSub.
|
||||
|
||||
## Contents
|
||||
|
||||
- main.go - uns pub-sub as two go routines for 10 seconds.
|
||||
- producer - publishes messages to the broker every second
|
||||
- consumer - consumes any messages sent by the producer
|
51
examples/broker/consumer/consumer.go
Normal file
51
examples/broker/consumer/consumer.go
Normal file
@ -0,0 +1,51 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
"github.com/micro/go-micro/v2/config/cmd"
|
||||
// To enable rabbitmq plugin uncomment
|
||||
//_ "github.com/micro/go-plugins/broker/rabbitmq"
|
||||
)
|
||||
|
||||
var (
|
||||
topic = "go.micro.topic.foo"
|
||||
)
|
||||
|
||||
// Example of a shared subscription which receives a subset of messages
|
||||
func sharedSub() {
|
||||
_, err := broker.Subscribe(topic, func(p broker.Event) error {
|
||||
fmt.Println("[sub] received message:", string(p.Message().Body), "header", p.Message().Header)
|
||||
return nil
|
||||
}, broker.Queue("consumer"))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Example of a subscription which receives all the messages
|
||||
func sub() {
|
||||
_, err := broker.Subscribe(topic, func(p broker.Event) error {
|
||||
fmt.Println("[sub] received message:", string(p.Message().Body), "header", p.Message().Header)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
cmd.Init()
|
||||
|
||||
if err := broker.Init(); err != nil {
|
||||
log.Fatalf("Broker Init error: %v", err)
|
||||
}
|
||||
if err := broker.Connect(); err != nil {
|
||||
log.Fatalf("Broker Connect error: %v", err)
|
||||
}
|
||||
|
||||
sub()
|
||||
select {}
|
||||
}
|
59
examples/broker/main.go
Normal file
59
examples/broker/main.go
Normal file
@ -0,0 +1,59 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
"github.com/micro/go-micro/v2/config/cmd"
|
||||
)
|
||||
|
||||
var (
|
||||
topic = "go.micro.topic.foo"
|
||||
)
|
||||
|
||||
func pub() {
|
||||
tick := time.NewTicker(time.Second)
|
||||
i := 0
|
||||
for _ = range tick.C {
|
||||
msg := &broker.Message{
|
||||
Header: map[string]string{
|
||||
"id": fmt.Sprintf("%d", i),
|
||||
},
|
||||
Body: []byte(fmt.Sprintf("%d: %s", i, time.Now().String())),
|
||||
}
|
||||
if err := broker.Publish(topic, msg); err != nil {
|
||||
log.Printf("[pub] failed: %v", err)
|
||||
} else {
|
||||
fmt.Println("[pub] pubbed message:", string(msg.Body))
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
func sub() {
|
||||
_, err := broker.Subscribe(topic, func(p broker.Event) error {
|
||||
fmt.Println("[sub] received message:", string(p.Message().Body), "header", p.Message().Header)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
cmd.Init()
|
||||
|
||||
if err := broker.Init(); err != nil {
|
||||
log.Fatalf("Broker Init error: %v", err)
|
||||
}
|
||||
if err := broker.Connect(); err != nil {
|
||||
log.Fatalf("Broker Connect error: %v", err)
|
||||
}
|
||||
|
||||
go pub()
|
||||
go sub()
|
||||
|
||||
<-time.After(time.Second * 10)
|
||||
}
|
49
examples/broker/producer/producer.go
Normal file
49
examples/broker/producer/producer.go
Normal file
@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
"github.com/micro/go-micro/v2/config/cmd"
|
||||
// To enable rabbitmq plugin uncomment
|
||||
//_ "github.com/micro/go-plugins/broker/rabbitmq"
|
||||
)
|
||||
|
||||
var (
|
||||
topic = "go.micro.topic.foo"
|
||||
)
|
||||
|
||||
func pub() {
|
||||
tick := time.NewTicker(time.Second)
|
||||
i := 0
|
||||
for _ = range tick.C {
|
||||
msg := &broker.Message{
|
||||
Header: map[string]string{
|
||||
"id": fmt.Sprintf("%d", i),
|
||||
},
|
||||
Body: []byte(fmt.Sprintf("%d: %s", i, time.Now().String())),
|
||||
}
|
||||
if err := broker.Publish(topic, msg); err != nil {
|
||||
log.Printf("[pub] failed: %v", err)
|
||||
} else {
|
||||
fmt.Println("[pub] pubbed message:", string(msg.Body))
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
cmd.Init()
|
||||
|
||||
if err := broker.Init(); err != nil {
|
||||
log.Fatalf("Broker Init error: %v", err)
|
||||
}
|
||||
|
||||
if err := broker.Connect(); err != nil {
|
||||
log.Fatalf("Broker Connect error: %v", err)
|
||||
}
|
||||
|
||||
pub()
|
||||
}
|
12
examples/client/README.md
Normal file
12
examples/client/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# Client
|
||||
|
||||
## Contents
|
||||
|
||||
- main.go - calls each of the go.micro.srv.example handlers and includes the use of the streaming handler
|
||||
- codegen - demonstrates how to use code generation to remove boilerplate code
|
||||
- dc_filter - shows how to use Select filters inside a call wrapper for filtering to the local DC
|
||||
- dc_selector - is the same as dc_filter but as a Selector implementation itself
|
||||
- pub - publishes messages using the Publish method. By default encoding in protobuf
|
||||
- selector - shows how to write and load your own Selector
|
||||
- wrapper - provides examples for how to use client Wrappers (middleware)
|
||||
|
150
examples/client/codegen/README.md
Normal file
150
examples/client/codegen/README.md
Normal file
@ -0,0 +1,150 @@
|
||||
# Code Generation [Experimental]
|
||||
|
||||
We're experimenting with code generation to reduce the amount of boiler plate code written.
|
||||
|
||||
## Example
|
||||
|
||||
Going from this
|
||||
```golang
|
||||
req := client.NewRequest("go.micro.srv.example", "Example.Call", &example.Request{
|
||||
Name: "John",
|
||||
})
|
||||
|
||||
rsp := &example.Response{}
|
||||
|
||||
if err := client.Call(context.Background(), req, rsp); err != nil {
|
||||
return err
|
||||
}
|
||||
```
|
||||
|
||||
To
|
||||
|
||||
```golang
|
||||
rsp, err := cl.Call(context.Background(), &example.Request{Name: "John"})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
```
|
||||
|
||||
## Generation of stub code for the example service
|
||||
|
||||
```shell
|
||||
go get github.com/micro/protobuf/protoc-gen-go
|
||||
cd examples/server/proto/example
|
||||
protoc --go_out=plugins=micro:. example.proto
|
||||
```
|
||||
|
||||
Look at examples/server/proto/example/example.pb.go
|
||||
to see the generated code.
|
||||
|
||||
## Guide
|
||||
|
||||
### Download the protoc-gen-go code
|
||||
|
||||
```shell
|
||||
go get github.com/micro/protobuf/protoc-gen-go
|
||||
```
|
||||
|
||||
### Define your proto service.
|
||||
|
||||
hello.proto
|
||||
```shell
|
||||
syntax = "proto3";
|
||||
|
||||
// package name is used as the service name for discovery
|
||||
// if service name is not passed in when initialising the
|
||||
// client
|
||||
package go.micro.srv.greeter;
|
||||
|
||||
service Say {
|
||||
rpc Hello(Request) returns (Response) {}
|
||||
}
|
||||
|
||||
message Request {
|
||||
optional string name = 1;
|
||||
}
|
||||
|
||||
message Response {
|
||||
optional string msg = 1;
|
||||
}
|
||||
```
|
||||
|
||||
**Note: Remember to set package name in the proto, it's used to generate
|
||||
the service for discovery.**
|
||||
|
||||
### Generate code
|
||||
|
||||
```shell
|
||||
protoc --go_out=plugins=micro:. hello.proto
|
||||
```
|
||||
|
||||
### Generated code
|
||||
|
||||
```shell
|
||||
// Client API for Say service
|
||||
|
||||
type SayClient interface {
|
||||
Hello(ctx context.Context, in *Request) (*Response, error)
|
||||
}
|
||||
|
||||
type sayClient struct {
|
||||
c client.Client
|
||||
serviceName string
|
||||
}
|
||||
|
||||
func NewSayClient(serviceName string, c client.Client) SayClient {
|
||||
if c == nil {
|
||||
c = client.NewClient()
|
||||
}
|
||||
if len(serviceName) == 0 {
|
||||
serviceName = "go.micro.srv.greeter"
|
||||
}
|
||||
return &sayClient{
|
||||
c: c,
|
||||
serviceName: serviceName,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *sayClient) Hello(ctx context.Context, in *Request) (*Response, error) {
|
||||
req := c.c.NewRequest(c.serviceName, "Say.Hello", in)
|
||||
out := new(Response)
|
||||
err := c.c.Call(ctx, req, out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Say service
|
||||
|
||||
type SayHandler interface {
|
||||
Hello(context.Context, *Request, *Response) error
|
||||
}
|
||||
|
||||
func RegisterSayHandler(s server.Server, hdlr SayHandler) {
|
||||
s.Handle(s.NewHandler(hdlr))
|
||||
}
|
||||
```
|
||||
|
||||
### Use the client
|
||||
```golang
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"context"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
hello "path/to/hello/proto"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cl := hello.NewSayClient("go.micro.srv.greeter", client.DefaultClient)
|
||||
// alternative initialisation
|
||||
// cl := hello.NewSayClient("", nil)
|
||||
|
||||
rsp, err := cl.Hello(contex.Background(), &hello.Request{"Name": "John"})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
79
examples/client/codegen/codegen.go
Normal file
79
examples/client/codegen/codegen.go
Normal file
@ -0,0 +1,79 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"context"
|
||||
example "github.com/micro/examples/server/proto/example"
|
||||
"github.com/micro/go-micro/v2/config/cmd"
|
||||
)
|
||||
|
||||
var (
|
||||
cl = example.NewExampleService("go.micro.srv.example", nil)
|
||||
)
|
||||
|
||||
func call(i int) {
|
||||
rsp, err := cl.Call(context.Background(), &example.Request{Name: "John"})
|
||||
if err != nil {
|
||||
fmt.Println("call err: ", err, rsp)
|
||||
return
|
||||
}
|
||||
fmt.Println("Call:", i, "rsp:", rsp.Msg)
|
||||
}
|
||||
|
||||
func stream(i int) {
|
||||
stream, err := cl.Stream(context.Background(), &example.StreamingRequest{Count: int64(i)})
|
||||
if err != nil {
|
||||
fmt.Println("err:", err)
|
||||
return
|
||||
}
|
||||
for j := 0; j < i; j++ {
|
||||
rsp, err := stream.Recv()
|
||||
if err != nil {
|
||||
fmt.Println("err:", err)
|
||||
break
|
||||
}
|
||||
fmt.Println("Stream: rsp:", rsp.Count)
|
||||
}
|
||||
if err := stream.Close(); err != nil {
|
||||
fmt.Println("stream close err:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func pingPong(i int) {
|
||||
stream, err := cl.PingPong(context.Background())
|
||||
if err != nil {
|
||||
fmt.Println("err:", err)
|
||||
return
|
||||
}
|
||||
for j := 0; j < i; j++ {
|
||||
if err := stream.Send(&example.Ping{Stroke: int64(j)}); err != nil {
|
||||
fmt.Println("err:", err)
|
||||
return
|
||||
}
|
||||
rsp, err := stream.Recv()
|
||||
if err != nil {
|
||||
fmt.Println("recv err", err)
|
||||
break
|
||||
}
|
||||
fmt.Printf("Sent ping %v got pong %v\n", j, rsp.Stroke)
|
||||
}
|
||||
if err := stream.Close(); err != nil {
|
||||
fmt.Println("stream close err:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
cmd.Init()
|
||||
|
||||
fmt.Println("\n--- Call example ---")
|
||||
for i := 0; i < 10; i++ {
|
||||
call(i)
|
||||
}
|
||||
|
||||
fmt.Println("\n--- Streamer example ---")
|
||||
stream(10)
|
||||
|
||||
fmt.Println("\n--- Ping Pong example ---")
|
||||
pingPong(10)
|
||||
}
|
88
examples/client/dc_filter/dc_filter.go
Normal file
88
examples/client/dc_filter/dc_filter.go
Normal file
@ -0,0 +1,88 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
"github.com/micro/go-micro/v2/config/cmd"
|
||||
"github.com/micro/go-micro/v2/metadata"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
|
||||
example "github.com/micro/examples/server/proto/example"
|
||||
)
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().Unix())
|
||||
}
|
||||
|
||||
// A Wrapper that creates a Datacenter Selector Option
|
||||
type dcWrapper struct {
|
||||
client.Client
|
||||
}
|
||||
|
||||
func (dc *dcWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
|
||||
filter := func(services []*registry.Service) []*registry.Service {
|
||||
for _, service := range services {
|
||||
var nodes []*registry.Node
|
||||
for _, node := range service.Nodes {
|
||||
if node.Metadata["datacenter"] == md["datacenter"] {
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
}
|
||||
service.Nodes = nodes
|
||||
}
|
||||
return services
|
||||
}
|
||||
|
||||
callOptions := append(opts, client.WithSelectOption(
|
||||
selector.WithFilter(filter),
|
||||
))
|
||||
|
||||
fmt.Printf("[DC Wrapper] filtering for datacenter %s\n", md["datacenter"])
|
||||
return dc.Client.Call(ctx, req, rsp, callOptions...)
|
||||
}
|
||||
|
||||
func NewDCWrapper(c client.Client) client.Client {
|
||||
return &dcWrapper{c}
|
||||
}
|
||||
|
||||
func call(i int) {
|
||||
// Create new request to service go.micro.srv.example, method Example.Call
|
||||
req := client.NewRequest("go.micro.srv.example", "Example.Call", &example.Request{
|
||||
Name: "John",
|
||||
})
|
||||
|
||||
// create context with metadata
|
||||
ctx := metadata.NewContext(context.Background(), map[string]string{
|
||||
"datacenter": "local",
|
||||
})
|
||||
|
||||
rsp := &example.Response{}
|
||||
|
||||
// Call service
|
||||
if err := client.Call(ctx, req, rsp); err != nil {
|
||||
fmt.Println("call err: ", err, rsp)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Call:", i, "rsp:", rsp.Msg)
|
||||
}
|
||||
|
||||
func main() {
|
||||
cmd.Init()
|
||||
|
||||
client.DefaultClient = client.NewClient(
|
||||
client.Wrap(NewDCWrapper),
|
||||
)
|
||||
|
||||
fmt.Println("\n--- Call example ---")
|
||||
for i := 0; i < 10; i++ {
|
||||
call(i)
|
||||
}
|
||||
}
|
134
examples/client/dc_selector/dc_selector.go
Normal file
134
examples/client/dc_selector/dc_selector.go
Normal file
@ -0,0 +1,134 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
"github.com/micro/go-micro/v2/config/cmd"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
|
||||
example "github.com/micro/examples/server/proto/example"
|
||||
)
|
||||
|
||||
// Built in random hashed node selector
|
||||
type dcSelector struct {
|
||||
opts selector.Options
|
||||
}
|
||||
|
||||
var (
|
||||
datacenter = "local"
|
||||
)
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().Unix())
|
||||
}
|
||||
|
||||
func (n *dcSelector) Init(opts ...selector.Option) error {
|
||||
for _, o := range opts {
|
||||
o(&n.opts)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *dcSelector) Options() selector.Options {
|
||||
return n.opts
|
||||
}
|
||||
|
||||
func (n *dcSelector) Select(service string, opts ...selector.SelectOption) (selector.Next, error) {
|
||||
services, err := n.opts.Registry.GetService(service)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(services) == 0 {
|
||||
return nil, selector.ErrNotFound
|
||||
}
|
||||
|
||||
var nodes []*registry.Node
|
||||
|
||||
// Filter the nodes for datacenter
|
||||
for _, service := range services {
|
||||
for _, node := range service.Nodes {
|
||||
if node.Metadata["datacenter"] == datacenter {
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(nodes) == 0 {
|
||||
return nil, selector.ErrNotFound
|
||||
}
|
||||
|
||||
var i int
|
||||
var mtx sync.Mutex
|
||||
|
||||
return func() (*registry.Node, error) {
|
||||
mtx.Lock()
|
||||
defer mtx.Unlock()
|
||||
i++
|
||||
return nodes[i%len(nodes)], nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (n *dcSelector) Mark(service string, node *registry.Node, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (n *dcSelector) Reset(service string) {
|
||||
return
|
||||
}
|
||||
|
||||
func (n *dcSelector) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *dcSelector) String() string {
|
||||
return "dc"
|
||||
}
|
||||
|
||||
// Return a new first node selector
|
||||
func DCSelector(opts ...selector.Option) selector.Selector {
|
||||
var sopts selector.Options
|
||||
for _, opt := range opts {
|
||||
opt(&sopts)
|
||||
}
|
||||
if sopts.Registry == nil {
|
||||
sopts.Registry = registry.DefaultRegistry
|
||||
}
|
||||
return &dcSelector{sopts}
|
||||
}
|
||||
|
||||
func call(i int) {
|
||||
// Create new request to service go.micro.srv.example, method Example.Call
|
||||
req := client.NewRequest("go.micro.srv.example", "Example.Call", &example.Request{
|
||||
Name: "John",
|
||||
})
|
||||
|
||||
rsp := &example.Response{}
|
||||
|
||||
// Call service
|
||||
if err := client.Call(context.Background(), req, rsp); err != nil {
|
||||
fmt.Println("call err: ", err, rsp)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Call:", i, "rsp:", rsp.Msg)
|
||||
}
|
||||
|
||||
func main() {
|
||||
cmd.Init()
|
||||
|
||||
client.DefaultClient = client.NewClient(
|
||||
client.Selector(DCSelector()),
|
||||
)
|
||||
|
||||
fmt.Println("\n--- Call example ---")
|
||||
for i := 0; i < 10; i++ {
|
||||
call(i)
|
||||
}
|
||||
}
|
139
examples/client/main.go
Normal file
139
examples/client/main.go
Normal file
@ -0,0 +1,139 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"context"
|
||||
example "github.com/micro/examples/server/proto/example"
|
||||
"github.com/micro/go-micro/v2"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/metadata"
|
||||
)
|
||||
|
||||
// publishes a message
|
||||
func pub(p micro.Publisher) {
|
||||
msg := &example.Message{
|
||||
Say: "This is an async message",
|
||||
}
|
||||
|
||||
if err := p.Publish(context.TODO(), msg); err != nil {
|
||||
fmt.Println("pub err: ", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("Published: %v\n", msg)
|
||||
}
|
||||
|
||||
func call(i int, c client.Client) {
|
||||
// Create new request to service go.micro.srv.example, method Example.Call
|
||||
req := c.NewRequest("go.micro.srv.example", "Example.Call", &example.Request{
|
||||
Name: "John",
|
||||
})
|
||||
|
||||
// create context with metadata
|
||||
ctx := metadata.NewContext(context.Background(), map[string]string{
|
||||
"X-User-Id": "john",
|
||||
"X-From-Id": "script",
|
||||
})
|
||||
|
||||
rsp := &example.Response{}
|
||||
|
||||
// Call service
|
||||
if err := c.Call(ctx, req, rsp); err != nil {
|
||||
fmt.Println("call err: ", err, rsp)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Call:", i, "rsp:", rsp.Msg)
|
||||
}
|
||||
|
||||
func stream(i int, c client.Client) {
|
||||
// Create new request to service go.micro.srv.example, method Example.Call
|
||||
// Request can be empty as its actually ignored and merely used to call the handler
|
||||
req := c.NewRequest("go.micro.srv.example", "Example.Stream", &example.StreamingRequest{})
|
||||
|
||||
stream, err := c.Stream(context.Background(), req)
|
||||
if err != nil {
|
||||
fmt.Println("err:", err)
|
||||
return
|
||||
}
|
||||
if err := stream.Send(&example.StreamingRequest{Count: int64(i)}); err != nil {
|
||||
fmt.Println("err:", err)
|
||||
return
|
||||
}
|
||||
for stream.Error() == nil {
|
||||
rsp := &example.StreamingResponse{}
|
||||
err := stream.Recv(rsp)
|
||||
if err != nil {
|
||||
fmt.Println("recv err", err)
|
||||
break
|
||||
}
|
||||
fmt.Println("Stream: rsp:", rsp.Count)
|
||||
}
|
||||
|
||||
if stream.Error() != nil {
|
||||
fmt.Println("stream err:", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := stream.Close(); err != nil {
|
||||
fmt.Println("stream close err:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func pingPong(i int, c client.Client) {
|
||||
// Create new request to service go.micro.srv.example, method Example.Call
|
||||
// Request can be empty as its actually ignored and merely used to call the handler
|
||||
req := c.NewRequest("go.micro.srv.example", "Example.PingPong", &example.StreamingRequest{})
|
||||
|
||||
stream, err := c.Stream(context.Background(), req)
|
||||
if err != nil {
|
||||
fmt.Println("err:", err)
|
||||
return
|
||||
}
|
||||
|
||||
for j := 0; j < i; j++ {
|
||||
if err := stream.Send(&example.Ping{Stroke: int64(j + 1)}); err != nil {
|
||||
fmt.Println("err:", err)
|
||||
return
|
||||
}
|
||||
rsp := &example.Pong{}
|
||||
err := stream.Recv(rsp)
|
||||
if err != nil {
|
||||
fmt.Println("recv err", err)
|
||||
break
|
||||
}
|
||||
fmt.Printf("Sent ping %v got pong %v\n", j+1, rsp.Stroke)
|
||||
}
|
||||
|
||||
if stream.Error() != nil {
|
||||
fmt.Println("stream err:", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := stream.Close(); err != nil {
|
||||
fmt.Println("stream close err:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
service := micro.NewService()
|
||||
service.Init()
|
||||
|
||||
p := micro.NewPublisher("topic.example", service.Client())
|
||||
|
||||
fmt.Println("\n--- Publisher example ---")
|
||||
pub(p)
|
||||
|
||||
fmt.Println("\n--- Call example ---")
|
||||
for i := 0; i < 10; i++ {
|
||||
call(i, service.Client())
|
||||
}
|
||||
|
||||
fmt.Println("\n--- Streamer example ---")
|
||||
stream(10, service.Client())
|
||||
|
||||
fmt.Println("\n--- Ping Pong example ---")
|
||||
pingPong(10, service.Client())
|
||||
|
||||
}
|
36
examples/client/pub/pub.go
Normal file
36
examples/client/pub/pub.go
Normal file
@ -0,0 +1,36 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"context"
|
||||
example "github.com/micro/examples/server/proto/example"
|
||||
"github.com/micro/go-micro/v2"
|
||||
)
|
||||
|
||||
// publishes a message
|
||||
func pub(i int, p micro.Publisher) {
|
||||
msg := &example.Message{
|
||||
Say: fmt.Sprintf("This is an async message %d", i),
|
||||
}
|
||||
|
||||
if err := p.Publish(context.TODO(), msg); err != nil {
|
||||
fmt.Println("pub err: ", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("Published %d: %v\n", i, msg)
|
||||
}
|
||||
|
||||
func main() {
|
||||
service := micro.NewService()
|
||||
service.Init()
|
||||
|
||||
p := micro.NewPublisher("example", service.Client())
|
||||
|
||||
fmt.Println("\n--- Publisher example ---")
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
pub(i, p)
|
||||
}
|
||||
}
|
124
examples/client/selector/selector.go
Normal file
124
examples/client/selector/selector.go
Normal file
@ -0,0 +1,124 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
example "github.com/micro/examples/server/proto/example"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
"github.com/micro/go-micro/v2/config/cmd"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
)
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().Unix())
|
||||
}
|
||||
|
||||
// Built in random hashed node selector
|
||||
type firstNodeSelector struct {
|
||||
opts selector.Options
|
||||
}
|
||||
|
||||
func (n *firstNodeSelector) Init(opts ...selector.Option) error {
|
||||
for _, o := range opts {
|
||||
o(&n.opts)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *firstNodeSelector) Options() selector.Options {
|
||||
return n.opts
|
||||
}
|
||||
|
||||
func (n *firstNodeSelector) Select(service string, opts ...selector.SelectOption) (selector.Next, error) {
|
||||
services, err := n.opts.Registry.GetService(service)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(services) == 0 {
|
||||
return nil, selector.ErrNotFound
|
||||
}
|
||||
|
||||
var sopts selector.SelectOptions
|
||||
for _, opt := range opts {
|
||||
opt(&sopts)
|
||||
}
|
||||
|
||||
for _, filter := range sopts.Filters {
|
||||
services = filter(services)
|
||||
}
|
||||
|
||||
if len(services) == 0 {
|
||||
return nil, selector.ErrNotFound
|
||||
}
|
||||
|
||||
if len(services[0].Nodes) == 0 {
|
||||
return nil, selector.ErrNotFound
|
||||
}
|
||||
|
||||
return func() (*registry.Node, error) {
|
||||
return services[0].Nodes[0], nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (n *firstNodeSelector) Mark(service string, node *registry.Node, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (n *firstNodeSelector) Reset(service string) {
|
||||
return
|
||||
}
|
||||
|
||||
func (n *firstNodeSelector) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *firstNodeSelector) String() string {
|
||||
return "first"
|
||||
}
|
||||
|
||||
// Return a new first node selector
|
||||
func FirstNodeSelector(opts ...selector.Option) selector.Selector {
|
||||
var sopts selector.Options
|
||||
for _, opt := range opts {
|
||||
opt(&sopts)
|
||||
}
|
||||
if sopts.Registry == nil {
|
||||
sopts.Registry = registry.DefaultRegistry
|
||||
}
|
||||
return &firstNodeSelector{sopts}
|
||||
}
|
||||
|
||||
func call(i int) {
|
||||
// Create new request to service go.micro.srv.example, method Example.Call
|
||||
req := client.NewRequest("go.micro.srv.example", "Example.Call", &example.Request{
|
||||
Name: "John",
|
||||
})
|
||||
|
||||
rsp := &example.Response{}
|
||||
|
||||
// Call service
|
||||
if err := client.Call(context.Background(), req, rsp); err != nil {
|
||||
fmt.Println("call err: ", err, rsp)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Call:", i, "rsp:", rsp.Msg)
|
||||
}
|
||||
|
||||
func main() {
|
||||
cmd.Init()
|
||||
|
||||
client.DefaultClient = client.NewClient(
|
||||
client.Selector(FirstNodeSelector()),
|
||||
)
|
||||
|
||||
fmt.Println("\n--- Call example ---")
|
||||
for i := 0; i < 10; i++ {
|
||||
call(i)
|
||||
}
|
||||
}
|
110
examples/client/wrapper/wrapper.go
Normal file
110
examples/client/wrapper/wrapper.go
Normal file
@ -0,0 +1,110 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"context"
|
||||
example "github.com/micro/examples/server/proto/example"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/config/cmd"
|
||||
"github.com/micro/go-micro/v2/metadata"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
)
|
||||
|
||||
// wrapper example code
|
||||
|
||||
// log wrapper logs every time a request is made
|
||||
type logWrapper struct {
|
||||
client.Client
|
||||
}
|
||||
|
||||
func (l *logWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
|
||||
md, _ := metadata.FromContext(ctx)
|
||||
fmt.Printf("[Log Wrapper] ctx: %v service: %s method: %s\n", md, req.Service(), req.Endpoint())
|
||||
return l.Client.Call(ctx, req, rsp)
|
||||
}
|
||||
|
||||
// trace wrapper attaches a unique trace ID - timestamp
|
||||
type traceWrapper struct {
|
||||
client.Client
|
||||
}
|
||||
|
||||
func (t *traceWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
|
||||
ctx = metadata.NewContext(ctx, map[string]string{
|
||||
"X-Trace-Id": fmt.Sprintf("%d", time.Now().Unix()),
|
||||
})
|
||||
return t.Client.Call(ctx, req, rsp)
|
||||
}
|
||||
|
||||
// Implements client.Wrapper as logWrapper
|
||||
func logWrap(c client.Client) client.Client {
|
||||
return &logWrapper{c}
|
||||
}
|
||||
|
||||
// Implements client.Wrapper as traceWrapper
|
||||
func traceWrap(c client.Client) client.Client {
|
||||
return &traceWrapper{c}
|
||||
}
|
||||
|
||||
func metricsWrap(cf client.CallFunc) client.CallFunc {
|
||||
return func(ctx context.Context, node *registry.Node, req client.Request, rsp interface{}, opts client.CallOptions) error {
|
||||
t := time.Now()
|
||||
err := cf(ctx, node, req, rsp, opts)
|
||||
fmt.Printf("[Metrics Wrapper] called: %v %s.%s duration: %v\n", node, req.Service(), req.Endpoint(), time.Since(t))
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func call(i int) {
|
||||
// Create new request to service go.micro.srv.example, method Example.Call
|
||||
req := client.NewRequest("go.micro.srv.example", "Example.Call", &example.Request{
|
||||
Name: "John",
|
||||
})
|
||||
|
||||
// create context with metadata
|
||||
ctx := metadata.NewContext(context.Background(), map[string]string{
|
||||
"X-User-Id": "john",
|
||||
"X-From-Id": "script",
|
||||
})
|
||||
|
||||
rsp := &example.Response{}
|
||||
|
||||
// Call service
|
||||
if err := client.Call(ctx, req, rsp); err != nil {
|
||||
fmt.Println("call err: ", err, rsp)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Call:", i, "rsp:", rsp.Msg)
|
||||
}
|
||||
|
||||
func main() {
|
||||
cmd.Init()
|
||||
|
||||
fmt.Println("\n--- Log Wrapper example ---")
|
||||
|
||||
// Wrap the default client
|
||||
client.DefaultClient = logWrap(client.DefaultClient)
|
||||
|
||||
call(0)
|
||||
|
||||
fmt.Println("\n--- Log+Trace Wrapper example ---")
|
||||
|
||||
// Wrap using client.Wrap option
|
||||
client.DefaultClient = client.NewClient(
|
||||
client.Wrap(traceWrap),
|
||||
client.Wrap(logWrap),
|
||||
)
|
||||
|
||||
call(1)
|
||||
|
||||
fmt.Println("\n--- Metrics Wrapper example ---")
|
||||
|
||||
// Wrap using client.Wrap option
|
||||
client.DefaultClient = client.NewClient(
|
||||
client.WrapCall(metricsWrap),
|
||||
)
|
||||
|
||||
call(2)
|
||||
}
|
19
examples/command/README.md
Normal file
19
examples/command/README.md
Normal file
@ -0,0 +1,19 @@
|
||||
# Command
|
||||
|
||||
This is an example of a bot command as a microservice
|
||||
|
||||
## Contents
|
||||
|
||||
- main.go - is the main definition of the service and handler
|
||||
|
||||
## Run the example
|
||||
|
||||
Run the service
|
||||
|
||||
```shell
|
||||
go run main.go
|
||||
```
|
||||
|
||||
## Call the service
|
||||
|
||||
Run the [bot](https://micro.mu/docs/bot.html) and send message `command`
|
42
examples/command/main.go
Normal file
42
examples/command/main.go
Normal file
@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"context"
|
||||
"github.com/micro/go-micro/v2"
|
||||
|
||||
proto "github.com/micro/go-micro/v2/agent/proto"
|
||||
)
|
||||
|
||||
type Command struct{}
|
||||
|
||||
// Help returns the command usage
|
||||
func (c *Command) Help(ctx context.Context, req *proto.HelpRequest, rsp *proto.HelpResponse) error {
|
||||
rsp.Usage = "command"
|
||||
rsp.Description = "This is an example bot command as a micro service"
|
||||
return nil
|
||||
}
|
||||
|
||||
// Exec executes the command
|
||||
func (c *Command) Exec(ctx context.Context, req *proto.ExecRequest, rsp *proto.ExecResponse) error {
|
||||
rsp.Result = []byte(strings.Join(req.Args, " "))
|
||||
// rsp.Error could be set to return an error instead
|
||||
// the function error would only be used for service level issues
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
service := micro.NewService(
|
||||
micro.Name("go.micro.bot.command"),
|
||||
)
|
||||
|
||||
service.Init()
|
||||
|
||||
proto.RegisterCommandHandler(service.Server(), new(Command))
|
||||
|
||||
if err := service.Run(); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
4
examples/config/README.md
Normal file
4
examples/config/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Go Config
|
||||
|
||||
This example demonstrates how to use Go Config for dynamic configuration.
|
||||
|
12
examples/config/file/config.json
Normal file
12
examples/config/file/config.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"hosts": {
|
||||
"database": {
|
||||
"address": "10.0.0.1",
|
||||
"port": 3306
|
||||
},
|
||||
"cache": {
|
||||
"address": "10.0.0.2",
|
||||
"port": 6379
|
||||
}
|
||||
}
|
||||
}
|
34
examples/config/file/main.go
Normal file
34
examples/config/file/main.go
Normal file
@ -0,0 +1,34 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/micro/go-micro/v2/config"
|
||||
"github.com/micro/go-micro/v2/config/source/file"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// load the config from a file source
|
||||
if err := config.Load(file.NewSource(
|
||||
file.WithPath("./config.json"),
|
||||
)); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
// define our own host type
|
||||
type Host struct {
|
||||
Address string `json:"address"`
|
||||
Port int `json:"port"`
|
||||
}
|
||||
|
||||
var host Host
|
||||
|
||||
// read a database host
|
||||
if err := config.Get("hosts", "database").Scan(&host); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(host.Address, host.Port)
|
||||
}
|
43
examples/config/grpc/README.md
Normal file
43
examples/config/grpc/README.md
Normal file
@ -0,0 +1,43 @@
|
||||
# gRPC Config Server
|
||||
|
||||
This is an example implementation of a grpc config server
|
||||
|
||||
## Get Started
|
||||
|
||||
### Run Server
|
||||
|
||||
```bash
|
||||
go run srv/main.go
|
||||
```
|
||||
|
||||
### Run Client
|
||||
|
||||
```bash
|
||||
go run client/main.go
|
||||
```
|
||||
|
||||
### Edit Config
|
||||
|
||||
Change values in srv/conf/micro.yml
|
||||
|
||||
```bash
|
||||
micro:
|
||||
name: Micro
|
||||
version: 1.0.0
|
||||
message: hello
|
||||
```
|
||||
|
||||
to
|
||||
|
||||
```bash
|
||||
micro:
|
||||
name: Micro
|
||||
version: 1.0.0
|
||||
message: hello john
|
||||
```
|
||||
|
||||
The output from watching config after an edit
|
||||
|
||||
```bash
|
||||
2019/04/28 10:57:15 Watch changes: {"message":"hello john","name":"Micro","version":"1.0.0"}
|
||||
```
|
58
examples/config/grpc/client/main.go
Normal file
58
examples/config/grpc/client/main.go
Normal file
@ -0,0 +1,58 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/micro/go-micro/v2/config"
|
||||
"github.com/micro/go-micro/v2/util/log"
|
||||
grpcConfig "github.com/micro/go-plugins/config/source/grpc/v2"
|
||||
)
|
||||
|
||||
type Micro struct {
|
||||
Info
|
||||
}
|
||||
|
||||
type Info struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Age int `json:"age,omitempty"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
// create new source
|
||||
source := grpcConfig.NewSource(
|
||||
grpcConfig.WithAddress("127.0.0.1:8600"),
|
||||
grpcConfig.WithPath("/micro"),
|
||||
)
|
||||
|
||||
// create new config
|
||||
conf, _ := config.NewConfig()
|
||||
|
||||
// load the source into config
|
||||
if err := conf.Load(source); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
configs := &Micro{}
|
||||
if err := conf.Scan(configs); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Logf("Read config: %s", string(conf.Bytes()))
|
||||
|
||||
// watch the config for changes
|
||||
watcher, err := conf.Watch()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Logf("Watching for changes ...")
|
||||
|
||||
for {
|
||||
v, err := watcher.Next()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Logf("Watching for changes: %v", string(v.Bytes()))
|
||||
}
|
||||
}
|
4
examples/config/grpc/srv/conf/extra.yml
Normal file
4
examples/config/grpc/srv/conf/extra.yml
Normal file
@ -0,0 +1,4 @@
|
||||
other:
|
||||
name: Extra
|
||||
version: 1.0.0
|
||||
message: Ugh this sucks
|
4
examples/config/grpc/srv/conf/micro.yml
Normal file
4
examples/config/grpc/srv/conf/micro.yml
Normal file
@ -0,0 +1,4 @@
|
||||
micro:
|
||||
name: Micro
|
||||
version: 1.0.0
|
||||
message: hello
|
4
examples/config/grpc/srv/conf/other.yml
Normal file
4
examples/config/grpc/srv/conf/other.yml
Normal file
@ -0,0 +1,4 @@
|
||||
other:
|
||||
name: badBoy
|
||||
version: 1.0.0
|
||||
hi: Ah
|
130
examples/config/grpc/srv/main.go
Normal file
130
examples/config/grpc/srv/main.go
Normal file
@ -0,0 +1,130 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/config"
|
||||
"github.com/micro/go-micro/v2/config/source/file"
|
||||
"github.com/micro/go-micro/v2/util/log"
|
||||
proto "github.com/micro/go-plugins/config/source/grpc/v2/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
var (
|
||||
mux sync.RWMutex
|
||||
configMaps = make(map[string]*proto.ChangeSet)
|
||||
apps = []string{"micro", "extra"}
|
||||
)
|
||||
|
||||
type Service struct{}
|
||||
|
||||
func main() {
|
||||
// load config files
|
||||
err := loadConfigFile()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// new service
|
||||
service := grpc.NewServer()
|
||||
proto.RegisterSourceServer(service, new(Service))
|
||||
ts, err := net.Listen("tcp", ":8600")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Logf("configServer started")
|
||||
err = service.Serve(ts)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s Service) Read(ctx context.Context, req *proto.ReadRequest) (rsp *proto.ReadResponse, err error) {
|
||||
appName := parsePath(req.Path)
|
||||
switch appName {
|
||||
case "micro", "extra":
|
||||
rsp = &proto.ReadResponse{
|
||||
ChangeSet: getConfig(appName),
|
||||
}
|
||||
return
|
||||
default:
|
||||
err = fmt.Errorf("[Read] the first path is invalid")
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s Service) Watch(req *proto.WatchRequest, server proto.Source_WatchServer) (err error) {
|
||||
appName := parsePath(req.Path)
|
||||
rsp := &proto.WatchResponse{
|
||||
ChangeSet: getConfig(appName),
|
||||
}
|
||||
if err = server.Send(rsp); err != nil {
|
||||
log.Logf("[Watch] watch files error,%s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func loadConfigFile() (err error) {
|
||||
for _, app := range apps {
|
||||
if err := config.Load(file.NewSource(
|
||||
file.WithPath("./conf/" + app + ".yml"),
|
||||
)); err != nil {
|
||||
log.Fatalf("[loadConfigFile] load files error,%s", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// watch changes
|
||||
watcher, err := config.Watch()
|
||||
if err != nil {
|
||||
log.Fatalf("[loadConfigFile] start watching files error,%s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
v, err := watcher.Next()
|
||||
if err != nil {
|
||||
log.Fatalf("[loadConfigFile] watch files error,%s", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Logf("[loadConfigFile] file change, %s", string(v.Bytes()))
|
||||
}
|
||||
}()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getConfig(appName string) *proto.ChangeSet {
|
||||
bytes := config.Get(appName).Bytes()
|
||||
|
||||
log.Logf("[getConfig] appName,%s", string(bytes))
|
||||
return &proto.ChangeSet{
|
||||
Data: bytes,
|
||||
Checksum: fmt.Sprintf("%x", md5.Sum(bytes)),
|
||||
Format: "yml",
|
||||
Source: "file",
|
||||
Timestamp: time.Now().Unix()}
|
||||
}
|
||||
|
||||
func parsePath(path string) (appName string) {
|
||||
paths := strings.Split(path, "/")
|
||||
|
||||
if paths[0] == "" && len(paths) > 1 {
|
||||
return paths[1]
|
||||
}
|
||||
|
||||
return paths[0]
|
||||
}
|
14
examples/config/modify/README.md
Normal file
14
examples/config/modify/README.md
Normal file
@ -0,0 +1,14 @@
|
||||
# Modify Config
|
||||
|
||||
This is an example of modifying config in a file.
|
||||
|
||||
Note: We currently only support setting values in memory, not passing down to the source.
|
||||
|
||||
## Usage
|
||||
|
||||
- example.conf is a toml file format
|
||||
- modify.go - loads, modifies and writes back the file
|
||||
|
||||
```
|
||||
go run modify.go
|
||||
```
|
47
examples/config/modify/example.conf
Normal file
47
examples/config/modify/example.conf
Normal file
@ -0,0 +1,47 @@
|
||||
# This is a TOML document. Boom.
|
||||
|
||||
title = "TOML Example"
|
||||
|
||||
[owner]
|
||||
name = "Tom Preston-Werner"
|
||||
organization = "GitHub"
|
||||
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
|
||||
dob = 1979-05-27T07:32:00Z # First class dates? Why not?
|
||||
|
||||
[database]
|
||||
server = "192.168.1.1"
|
||||
ports = [ 8001, 8001, 8002 ]
|
||||
connection_max = 5000
|
||||
enabled = true
|
||||
|
||||
[servers]
|
||||
|
||||
# You can indent as you please. Tabs or spaces. TOML don't care.
|
||||
[servers.alpha]
|
||||
ip = "10.0.0.1"
|
||||
dc = "eqdc10"
|
||||
|
||||
[servers.beta]
|
||||
ip = "10.0.0.2"
|
||||
dc = "eqdc10"
|
||||
country = "中国" # This should be parsed as UTF-8
|
||||
|
||||
[clients]
|
||||
data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it
|
||||
|
||||
# Line breaks are OK when inside arrays
|
||||
hosts = [
|
||||
"alpha",
|
||||
"omega"
|
||||
]
|
||||
|
||||
# Products
|
||||
|
||||
[[products]]
|
||||
name = "Hammer"
|
||||
sku = 738594937
|
||||
|
||||
[[products]]
|
||||
name = "Nail"
|
||||
sku = 284758393
|
||||
color = "gray"
|
60
examples/config/modify/modify.go
Normal file
60
examples/config/modify/modify.go
Normal file
@ -0,0 +1,60 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/micro/go-micro/v2/config"
|
||||
"github.com/micro/go-micro/v2/config/encoder/toml"
|
||||
"github.com/micro/go-micro/v2/config/source"
|
||||
"github.com/micro/go-micro/v2/config/source/file"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// new toml encoder
|
||||
t := toml.NewEncoder()
|
||||
|
||||
// create a new config
|
||||
c, err := config.NewConfig(
|
||||
config.WithSource(
|
||||
// create a new file source
|
||||
file.NewSource(
|
||||
// path of file
|
||||
file.WithPath("./example.conf"),
|
||||
// specify the toml encoder
|
||||
source.WithEncoder(t),
|
||||
),
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
// load the config
|
||||
if err := c.Load(); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
// set a value
|
||||
c.Set("foo", "bar")
|
||||
|
||||
// now the hacks begin
|
||||
vals := c.Map()
|
||||
|
||||
// encode
|
||||
v, err := t.Encode(vals)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
// write the file
|
||||
if err := ioutil.WriteFile("./example.conf", v, 0644); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("wrote update to example.conf")
|
||||
}
|
71
examples/event/README.md
Normal file
71
examples/event/README.md
Normal file
@ -0,0 +1,71 @@
|
||||
# Event
|
||||
|
||||
This is an example of using the micro API as an event gateway with the event handler
|
||||
|
||||
A http request is formatted as an [event](https://github.com/micro/go-api/blob/master/proto/api.proto#L28L39) and published on the go-micro message broker.
|
||||
|
||||
## Contents
|
||||
|
||||
- srv - A service which subscribes to events
|
||||
|
||||
## Usage
|
||||
|
||||
Run the micro api with the event handler set and with a namespace which used as part of the topic name
|
||||
|
||||
```
|
||||
micro api --handler=event --namespace=go.micro.evt
|
||||
```
|
||||
|
||||
Run the service
|
||||
|
||||
```
|
||||
go run srv/main.go
|
||||
```
|
||||
|
||||
### Event format
|
||||
|
||||
On the receiving end the message will be formatted like so:
|
||||
|
||||
```
|
||||
// A HTTP event as RPC
|
||||
message Event {
|
||||
// e.g login
|
||||
string name = 1;
|
||||
// uuid
|
||||
string id = 2;
|
||||
// unix timestamp of event
|
||||
int64 timestamp = 3;
|
||||
// event headers
|
||||
map<string, Pair> header = 4;
|
||||
// the event data
|
||||
string data = 5;
|
||||
}
|
||||
```
|
||||
|
||||
### Publish Event
|
||||
|
||||
Publishing an event is as simple as making a http post request
|
||||
|
||||
```
|
||||
curl -d '{"name": "john"}' http://localhost:8080/user/login
|
||||
```
|
||||
|
||||
This request will be published to the topic `go.micro.evt.user` with event name `login`
|
||||
|
||||
### Receiving Event
|
||||
|
||||
A subscriber should be registered with the service for topic `go.micro.evt.user`
|
||||
|
||||
The subscriber should take the proto.Event type. See srv/main.go for the code.
|
||||
|
||||
The event received will look like the following
|
||||
|
||||
```
|
||||
{
|
||||
name: "user.login",
|
||||
id: "go.micro.evt.user-user.login-693116e7-f20c-11e7-96c7-f40f242f6897",
|
||||
timestamp:1515152077,
|
||||
header: {...},
|
||||
data: {"name": "john"}
|
||||
}
|
||||
```
|
33
examples/event/srv/main.go
Normal file
33
examples/event/srv/main.go
Normal file
@ -0,0 +1,33 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/micro/go-micro/v2"
|
||||
proto "github.com/micro/go-micro/v2/api/proto"
|
||||
"github.com/micro/go-micro/v2/util/log"
|
||||
)
|
||||
|
||||
// All methods of Event will be executed when a message is received
|
||||
type Event struct{}
|
||||
|
||||
// Method can be of any name
|
||||
func (e *Event) Process(ctx context.Context, event *proto.Event) error {
|
||||
log.Logf("Received event %+v\n", event)
|
||||
// do something with event
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
service := micro.NewService(
|
||||
micro.Name("user"),
|
||||
)
|
||||
service.Init()
|
||||
|
||||
// register subscriber
|
||||
micro.RegisterSubscriber("go.micro.evt.user", service.Server(), new(Event))
|
||||
|
||||
if err := service.Run(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
28
examples/event/srv/proto/pubsub.micro.go
Normal file
28
examples/event/srv/proto/pubsub.micro.go
Normal file
@ -0,0 +1,28 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: github.com/micro/examples/event/srv/proto/pubsub.proto
|
||||
|
||||
/*
|
||||
Package pubsub is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
github.com/micro/examples/event/srv/proto/pubsub.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Event
|
||||
*/
|
||||
package pubsub
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
85
examples/event/srv/proto/pubsub.pb.go
Normal file
85
examples/event/srv/proto/pubsub.pb.go
Normal file
@ -0,0 +1,85 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: github.com/micro/examples/event/srv/proto/pubsub.proto
|
||||
|
||||
/*
|
||||
Package pubsub is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
github.com/micro/examples/event/srv/proto/pubsub.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Event
|
||||
*/
|
||||
package pubsub
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// Example message
|
||||
type Event struct {
|
||||
// unique id
|
||||
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
|
||||
// unix timestamp
|
||||
Timestamp int64 `protobuf:"varint,2,opt,name=timestamp" json:"timestamp,omitempty"`
|
||||
// message
|
||||
Message string `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Event) Reset() { *m = Event{} }
|
||||
func (m *Event) String() string { return proto.CompactTextString(m) }
|
||||
func (*Event) ProtoMessage() {}
|
||||
func (*Event) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func (m *Event) GetId() string {
|
||||
if m != nil {
|
||||
return m.Id
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Event) GetTimestamp() int64 {
|
||||
if m != nil {
|
||||
return m.Timestamp
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Event) GetMessage() string {
|
||||
if m != nil {
|
||||
return m.Message
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Event)(nil), "Event")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/micro/examples/event/srv/proto/pubsub.proto", fileDescriptor0)
|
||||
}
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 143 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x32, 0x4b, 0xcf, 0x2c, 0xc9,
|
||||
0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0xcf, 0xcd, 0x4c, 0x2e, 0xca, 0xd7, 0x4f, 0xad, 0x48,
|
||||
0xcc, 0x2d, 0xc8, 0x49, 0x2d, 0xd6, 0x4f, 0x2d, 0x4b, 0xcd, 0x2b, 0xd1, 0x2f, 0x2e, 0x2a, 0xd3,
|
||||
0x2f, 0x28, 0xca, 0x2f, 0xc9, 0xd7, 0x2f, 0x28, 0x4d, 0x2a, 0x2e, 0x4d, 0xd2, 0x03, 0x73, 0x94,
|
||||
0xfc, 0xb9, 0x58, 0x5d, 0x41, 0xf2, 0x42, 0x7c, 0x5c, 0x4c, 0x99, 0x29, 0x12, 0x8c, 0x0a, 0x8c,
|
||||
0x1a, 0x9c, 0x41, 0x4c, 0x99, 0x29, 0x42, 0x32, 0x5c, 0x9c, 0x25, 0x99, 0xb9, 0xa9, 0xc5, 0x25,
|
||||
0x89, 0xb9, 0x05, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0xcc, 0x41, 0x08, 0x01, 0x21, 0x09, 0x2e, 0xf6,
|
||||
0xdc, 0xd4, 0xe2, 0xe2, 0xc4, 0xf4, 0x54, 0x09, 0x66, 0xb0, 0x16, 0x18, 0x37, 0x89, 0x0d, 0x6c,
|
||||
0xae, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x89, 0xbc, 0xdb, 0x74, 0x91, 0x00, 0x00, 0x00,
|
||||
}
|
11
examples/event/srv/proto/pubsub.proto
Normal file
11
examples/event/srv/proto/pubsub.proto
Normal file
@ -0,0 +1,11 @@
|
||||
syntax = "proto3";
|
||||
|
||||
// Example message
|
||||
message Event {
|
||||
// unique id
|
||||
string id = 1;
|
||||
// unix timestamp
|
||||
int64 timestamp = 2;
|
||||
// message
|
||||
string message = 3;
|
||||
}
|
15
examples/filter/README.md
Normal file
15
examples/filter/README.md
Normal file
@ -0,0 +1,15 @@
|
||||
# Filter
|
||||
|
||||
Filter demonstrates how to filter requests in the client
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
// Run the service example
|
||||
go run ../service/main.go
|
||||
```
|
||||
|
||||
```
|
||||
// Run the client
|
||||
go run main.go
|
||||
```
|
32
examples/filter/main.go
Normal file
32
examples/filter/main.go
Normal file
@ -0,0 +1,32 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/micro/examples/filter/version"
|
||||
proto "github.com/micro/examples/service/proto"
|
||||
"github.com/micro/go-micro/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
service := micro.NewService()
|
||||
service.Init()
|
||||
|
||||
greeter := proto.NewGreeterService("greeter", service.Client())
|
||||
|
||||
rsp, err := greeter.Hello(
|
||||
// provide a context
|
||||
context.TODO(),
|
||||
// provide the request
|
||||
&proto.Request{Name: "John"},
|
||||
// set the filter
|
||||
version.Filter("latest"),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(rsp.Greeting)
|
||||
}
|
25
examples/filter/version/version.go
Normal file
25
examples/filter/version/version.go
Normal file
@ -0,0 +1,25 @@
|
||||
// Package version provides a way of calling a version of a service
|
||||
package version
|
||||
|
||||
import (
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
)
|
||||
|
||||
// Filter will filter the version of the service
|
||||
func Filter(v string) client.CallOption {
|
||||
filter := func(services []*registry.Service) []*registry.Service {
|
||||
var filtered []*registry.Service
|
||||
|
||||
for _, service := range services {
|
||||
if service.Version == v {
|
||||
filtered = append(filtered, service)
|
||||
}
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
return client.WithSelectOption(selector.WithFilter(filter))
|
||||
}
|
11
examples/flags/README.md
Normal file
11
examples/flags/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Flags
|
||||
|
||||
This is an example of using command line flags
|
||||
|
||||
## Run the example
|
||||
|
||||
```shell
|
||||
go run main.go --string_flag="a string" --int_flag=10 --bool_flag=true
|
||||
```
|
||||
|
||||
And that's all there is to it.
|
51
examples/flags/main.go
Normal file
51
examples/flags/main.go
Normal file
@ -0,0 +1,51 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/micro/cli/v2"
|
||||
"github.com/micro/go-micro/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
service := micro.NewService(
|
||||
// Add runtime flags
|
||||
// We could do this below too
|
||||
micro.Flags(
|
||||
&cli.StringFlag{
|
||||
Name: "string_flag",
|
||||
Usage: "This is a string flag",
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "int_flag",
|
||||
Usage: "This is an int flag",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "bool_flag",
|
||||
Usage: "This is a bool flag",
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// Init will parse the command line flags. Any flags set will
|
||||
// override the above settings. Options defined here will
|
||||
// override anything set on the command line.
|
||||
service.Init(
|
||||
// Add runtime action
|
||||
// We could actually do this above
|
||||
micro.Action(func(c *cli.Context) error {
|
||||
fmt.Printf("The string flag is: %s\n", c.String("string_flag"))
|
||||
fmt.Printf("The int flag is: %d\n", c.Int("int_flag"))
|
||||
fmt.Printf("The bool flag is: %t\n", c.Bool("bool_flag"))
|
||||
// let's just exit because
|
||||
os.Exit(0)
|
||||
return nil
|
||||
}),
|
||||
)
|
||||
|
||||
// Run the server
|
||||
if err := service.Run(); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
36
examples/form/README.md
Normal file
36
examples/form/README.md
Normal file
@ -0,0 +1,36 @@
|
||||
# Form
|
||||
|
||||
This rudimentary example demonstrates how to access a form and multipart form when writing API services
|
||||
|
||||
## Contents
|
||||
|
||||
- web - is the web front end with the form
|
||||
- api - is the api service
|
||||
|
||||
## Usage
|
||||
|
||||
Run the micro api
|
||||
|
||||
```
|
||||
micro api --handler=api
|
||||
```
|
||||
|
||||
Run the micro web
|
||||
|
||||
```
|
||||
micro web
|
||||
```
|
||||
|
||||
Run the api service
|
||||
|
||||
```
|
||||
go run api/main.go
|
||||
```
|
||||
|
||||
Run the web service
|
||||
|
||||
```
|
||||
go run web/main.go
|
||||
```
|
||||
|
||||
Browse to localhost:8082/form
|
54
examples/form/api/main.go
Normal file
54
examples/form/api/main.go
Normal file
@ -0,0 +1,54 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
"strings"
|
||||
|
||||
proto "github.com/micro/examples/form/api/proto"
|
||||
"github.com/micro/go-micro/v2"
|
||||
api "github.com/micro/go-micro/v2/api/proto"
|
||||
"github.com/micro/go-micro/v2/util/log"
|
||||
)
|
||||
|
||||
type Form struct{}
|
||||
|
||||
func (f *Form) Submit(ctx context.Context, req *api.Request, rsp *api.Response) error {
|
||||
rsp.Body = fmt.Sprintf("got your values %+v", req.Post)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Form) Multipart(ctx context.Context, req *api.Request, rsp *api.Response) error {
|
||||
ct := strings.Join(req.Header["Content-Type"].Values, ",")
|
||||
mt, p, err := mime.ParseMediaType(ct)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !strings.HasPrefix(mt, "multipart/") {
|
||||
return fmt.Errorf("%v does not contain multipart", mt)
|
||||
}
|
||||
r := multipart.NewReader(bytes.NewReader([]byte(req.Body)), p["boundary"])
|
||||
form, err := r.ReadForm(32 << 20)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rsp.Body = fmt.Sprintf("got your values %+v", form)
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
service := micro.NewService(
|
||||
micro.Name("go.micro.api.form"),
|
||||
)
|
||||
|
||||
service.Init()
|
||||
|
||||
proto.RegisterFormHandler(service.Server(), new(Form))
|
||||
|
||||
if err := service.Run(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
113
examples/form/api/proto/api.micro.go
Normal file
113
examples/form/api/proto/api.micro.go
Normal file
@ -0,0 +1,113 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: proto/api.proto
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
proto1 "github.com/micro/go-micro/v2/api/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
import (
|
||||
context "context"
|
||||
client "github.com/micro/go-micro/v2/client"
|
||||
server "github.com/micro/go-micro/v2/server"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ client.Option
|
||||
var _ server.Option
|
||||
|
||||
// Client API for Form service
|
||||
|
||||
type FormService interface {
|
||||
// regular form
|
||||
Submit(ctx context.Context, in *proto1.Request, opts ...client.CallOption) (*proto1.Response, error)
|
||||
// multipart form
|
||||
Multipart(ctx context.Context, in *proto1.Request, opts ...client.CallOption) (*proto1.Response, error)
|
||||
}
|
||||
|
||||
type formService struct {
|
||||
c client.Client
|
||||
name string
|
||||
}
|
||||
|
||||
func NewFormService(name string, c client.Client) FormService {
|
||||
if c == nil {
|
||||
c = client.NewClient()
|
||||
}
|
||||
if len(name) == 0 {
|
||||
name = "form"
|
||||
}
|
||||
return &formService{
|
||||
c: c,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *formService) Submit(ctx context.Context, in *proto1.Request, opts ...client.CallOption) (*proto1.Response, error) {
|
||||
req := c.c.NewRequest(c.name, "Form.Submit", in)
|
||||
out := new(proto1.Response)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *formService) Multipart(ctx context.Context, in *proto1.Request, opts ...client.CallOption) (*proto1.Response, error) {
|
||||
req := c.c.NewRequest(c.name, "Form.Multipart", in)
|
||||
out := new(proto1.Response)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Form service
|
||||
|
||||
type FormHandler interface {
|
||||
// regular form
|
||||
Submit(context.Context, *proto1.Request, *proto1.Response) error
|
||||
// multipart form
|
||||
Multipart(context.Context, *proto1.Request, *proto1.Response) error
|
||||
}
|
||||
|
||||
func RegisterFormHandler(s server.Server, hdlr FormHandler, opts ...server.HandlerOption) error {
|
||||
type form interface {
|
||||
Submit(ctx context.Context, in *proto1.Request, out *proto1.Response) error
|
||||
Multipart(ctx context.Context, in *proto1.Request, out *proto1.Response) error
|
||||
}
|
||||
type Form struct {
|
||||
form
|
||||
}
|
||||
h := &formHandler{hdlr}
|
||||
return s.Handle(s.NewHandler(&Form{h}, opts...))
|
||||
}
|
||||
|
||||
type formHandler struct {
|
||||
FormHandler
|
||||
}
|
||||
|
||||
func (h *formHandler) Submit(ctx context.Context, in *proto1.Request, out *proto1.Response) error {
|
||||
return h.FormHandler.Submit(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *formHandler) Multipart(ctx context.Context, in *proto1.Request, out *proto1.Response) error {
|
||||
return h.FormHandler.Multipart(ctx, in, out)
|
||||
}
|
37
examples/form/api/proto/api.pb.go
Normal file
37
examples/form/api/proto/api.pb.go
Normal file
@ -0,0 +1,37 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: proto/api.proto
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
_ "github.com/micro/go-micro/v2/api/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
func init() { proto.RegisterFile("proto/api.proto", fileDescriptor_ecf0878b123623e2) }
|
||||
|
||||
var fileDescriptor_ecf0878b123623e2 = []byte{
|
||||
// 132 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2f, 0x28, 0xca, 0x2f,
|
||||
0xc9, 0xd7, 0x4f, 0x2c, 0xc8, 0xd4, 0x03, 0xb3, 0xa4, 0x74, 0xd3, 0x33, 0x4b, 0x32, 0x4a, 0x93,
|
||||
0xf4, 0x92, 0xf3, 0x73, 0xf5, 0x73, 0x33, 0x93, 0x8b, 0xf2, 0xf5, 0xd3, 0xf3, 0x75, 0x21, 0x8c,
|
||||
0xc4, 0x82, 0x4c, 0x7d, 0x34, 0xe5, 0x46, 0xe9, 0x5c, 0x2c, 0x6e, 0xf9, 0x45, 0xb9, 0x42, 0xba,
|
||||
0x5c, 0x6c, 0xc1, 0xa5, 0x49, 0xb9, 0x99, 0x25, 0x42, 0xfc, 0x7a, 0xe9, 0xf9, 0x7a, 0x20, 0x05,
|
||||
0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x52, 0x02, 0x08, 0x81, 0xe2, 0x82, 0xfc, 0xbc, 0xe2,
|
||||
0x54, 0x25, 0x06, 0x21, 0x03, 0x2e, 0x4e, 0xdf, 0xd2, 0x9c, 0x92, 0xcc, 0x82, 0xc4, 0x22, 0xe2,
|
||||
0x74, 0x24, 0xb1, 0x81, 0xed, 0x33, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x7e, 0x4f, 0x39, 0x8c,
|
||||
0xb1, 0x00, 0x00, 0x00,
|
||||
}
|
10
examples/form/api/proto/api.proto
Normal file
10
examples/form/api/proto/api.proto
Normal file
@ -0,0 +1,10 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "github.com/micro/go-micro/v2/api/proto/api.proto";
|
||||
|
||||
service Form {
|
||||
// regular form
|
||||
rpc Submit(go.api.Request) returns (go.api.Response) {};
|
||||
// multipart form
|
||||
rpc Multipart(go.api.Request) returns (go.api.Response) {};
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user