Compare commits
123 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
afe6861e2f | ||
|
962567ef42 | ||
|
e21ed3a183 | ||
64a5ce9607 | |||
|
d651b16acd | ||
|
1034837f69 | ||
|
80f2bfd5d0 | ||
|
6aaaf54275 | ||
|
603d37b135 | ||
|
53c3bff819 | ||
|
dcf859098b | ||
b4a743898e | |||
|
f1e7ea3020 | ||
|
5e8d5834eb | ||
|
ffdf986aac | ||
|
56f8115ea8 | ||
5b0175c2e5 | |||
|
01d88601c0 | ||
|
d467236f8f | ||
24d574ae71 | |||
cf0b39eaac | |||
1f767ba18c | |||
|
915c424213 | ||
117f56ebf7 | |||
|
ceed8942fc | ||
d1e25e7ead | |||
|
7e24c0c1cf | ||
|
ca251ba111 | ||
|
116855572b | ||
|
ee977acfef | ||
|
3fa7c26946 | ||
|
88457b812e | ||
|
78df154a4d | ||
|
c7eed618c2 | ||
|
36bcd3bd82 | ||
|
f4118dc357 | ||
58598d0fe0 | |||
6248f05f74 | |||
|
aa9a0a8d23 | ||
|
1e40c86dfe | ||
|
9696efde02 | ||
|
b3fc8be24e | ||
|
fc5339a368 | ||
|
964b7dee3f | ||
|
158949d0d0 | ||
|
eed8a0bf50 | ||
|
c691d116ab | ||
|
cbe8b7dd09 | ||
|
203486fd31 | ||
|
d9b3b17582 | ||
|
e080ecb43a | ||
|
ea70711dd3 | ||
6dc942bc19 | |||
|
d76baf59de | ||
79ad1e6fe3 | |||
2764de9a1a | |||
|
d1d6eada98 | ||
|
4a03183481 | ||
|
8ea84ac3eb | ||
|
4401c12e6c | ||
c706afcf04 | |||
|
ca1d0b94c3 | ||
67acd9288b | |||
0bf6c9fc08 | |||
99807a680c | |||
f0f7f860d6 | |||
|
ef537270ad | ||
|
c7f075d157 | ||
|
812ea78604 | ||
|
0755084a59 | ||
|
fe7f5a4134 | ||
|
19c454ec4b | ||
|
0e9b4c26a4 | ||
|
d40b13a045 | ||
|
4079b22c1e | ||
|
fdfb2bc4c1 | ||
|
dbeb7cfe9c | ||
|
512df2628f | ||
|
92571db693 | ||
|
16552620e0 | ||
|
5414195dc3 | ||
|
0591760932 | ||
|
48b9f3f5e9 | ||
|
e46278a766 | ||
|
2925b1615c | ||
|
fc4191c647 | ||
|
111126c780 | ||
|
54371bba6a | ||
|
c28737e88e | ||
|
c7d922fac2 | ||
|
f8e696bd30 | ||
|
6aef28dad2 | ||
7105e4099c | |||
|
f0762bbb6b | ||
|
243c6a4246 | ||
|
9983aea928 | ||
|
aa58a9749b | ||
|
d8110b70a3 | ||
a44dc90d45 | |||
|
12181bd441 | ||
|
8d44f7226f | ||
|
bf747a86f4 | ||
|
4333f00a43 | ||
7ab3a31ac4 | |||
|
a1d5d6831f | ||
|
1b9cabd654 | ||
|
d621548120 | ||
|
449bcb46fe | ||
|
079102ea59 | ||
|
a9d371e727 | ||
|
27efbc8779 | ||
efb59d9709 | |||
|
003f00b483 | ||
|
0be22c98c6 | ||
|
bafedf1aad | ||
|
98d55545fd | ||
|
5f6271b044 | ||
|
87753ad289 | ||
|
ffb9da0230 | ||
|
50ac642666 | ||
|
f6fcfcb8fc | ||
|
21e0932339 | ||
f23638c036 |
19
.github/workflows/docker.yml
vendored
Normal file
19
.github/workflows/docker.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
name: Docker
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
name: Check out repository
|
||||
- uses: elgohr/Publish-Docker-Github-Action@2.12
|
||||
name: Build and Push Docker Image
|
||||
with:
|
||||
name: micro/go-micro
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
28
.github/workflows/pr.yml
vendored
Normal file
28
.github/workflows/pr.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: PR Sanity Check
|
||||
on: pull_request
|
||||
|
||||
jobs:
|
||||
|
||||
prtest:
|
||||
name: PR sanity check
|
||||
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 ./...
|
51
.github/workflows/tests.yml
vendored
Normal file
51
.github/workflows/tests.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
name: Run tests
|
||||
on: [push]
|
||||
|
||||
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 }}
|
||||
|
17
.travis.yml
17
.travis.yml
@@ -1,17 +0,0 @@
|
||||
language: go
|
||||
go:
|
||||
- 1.13.x
|
||||
env:
|
||||
- GO111MODULE=on IN_TRAVIS_CI=yes
|
||||
before_script:
|
||||
- go install github.com/golangci/golangci-lint/cmd/golangci-lint
|
||||
script:
|
||||
- golangci-lint run || true
|
||||
- go test -v -race ./... || true
|
||||
- go test -v ./...
|
||||
notifications:
|
||||
slack:
|
||||
secure: aEvhLbhujaGaKSrOokiG3//PaVHTIrc3fBpoRbCRqfZpyq6WREoapJJhF+tIpWWOwaC9GmChbD6aHo/jMUgwKXVyPSaNjiEL87YzUUpL8B2zslNp1rgfTg/LrzthOx3Q1TYwpaAl3to0fuHUVFX4yMeC2vuThq7WSXgMMxFCtbc=
|
||||
cache:
|
||||
directories:
|
||||
- $GOPATH/pkg/mod
|
@@ -1,4 +1,4 @@
|
||||
# Go Micro [](https://opensource.org/licenses/Apache-2.0) [](https://godoc.org/github.com/micro/go-micro) [](https://travis-ci.org/micro/go-micro) [](https://goreportcard.com/report/github.com/micro/go-micro)
|
||||
# Go Micro [](https://opensource.org/licenses/Apache-2.0) [](https://pkg.go.dev/github.com/micro/go-micro?tab=doc) [](https://travis-ci.org/micro/go-micro) [](https://goreportcard.com/report/github.com/micro/go-micro)
|
||||
|
||||
Go Micro is a framework for microservice development.
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Go Micro [](https://opensource.org/licenses/Apache-2.0) [](https://godoc.org/github.com/micro/go-micro) [](https://travis-ci.org/micro/go-micro) [](https://goreportcard.com/report/github.com/micro/go-micro)
|
||||
# Go Micro [](https://opensource.org/licenses/Apache-2.0) [](https://pkg.go.dev/github.com/micro/go-micro?tab=doc) [](https://travis-ci.org/micro/go-micro) [](https://goreportcard.com/report/github.com/micro/go-micro)
|
||||
|
||||
Go Micro是基于Golang的微服务开发框架。
|
||||
|
||||
|
@@ -6,8 +6,8 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"github.com/micro/go-micro/agent/input"
|
||||
"github.com/micro/go-micro/util/log"
|
||||
"github.com/micro/go-micro/v2/agent/input"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
)
|
||||
|
||||
type discordConn struct {
|
||||
@@ -74,7 +74,7 @@ func (dc *discordConn) Send(e *input.Event) error {
|
||||
fields := strings.Split(e.To, ":")
|
||||
_, err := dc.master.session.ChannelMessageSend(fields[0], string(e.Data))
|
||||
if err != nil {
|
||||
log.Log("[bot][loop][send]", err)
|
||||
log.Error("[bot][loop][send]", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"github.com/micro/cli/v2"
|
||||
"github.com/micro/go-micro/agent/input"
|
||||
"github.com/micro/go-micro/v2/agent/input"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@@ -7,7 +7,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/agent/input"
|
||||
"github.com/micro/go-micro/v2/agent/input"
|
||||
"github.com/nlopes/slack"
|
||||
)
|
||||
|
||||
|
@@ -5,7 +5,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/micro/cli/v2"
|
||||
"github.com/micro/go-micro/agent/input"
|
||||
"github.com/micro/go-micro/v2/agent/input"
|
||||
"github.com/nlopes/slack"
|
||||
)
|
||||
|
||||
|
@@ -6,8 +6,8 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/forestgiant/sliceutil"
|
||||
"github.com/micro/go-micro/agent/input"
|
||||
"github.com/micro/go-micro/util/log"
|
||||
"github.com/micro/go-micro/v2/agent/input"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
tgbotapi "gopkg.in/telegram-bot-api.v4"
|
||||
)
|
||||
|
||||
@@ -104,7 +104,7 @@ func (tc *telegramConn) Send(event *input.Event) error {
|
||||
|
||||
if err != nil {
|
||||
// probably it could be because of nested HTML tags -- telegram doesn't allow nested tags
|
||||
log.Log("[telegram][Send] error:", err)
|
||||
log.Error("[telegram][Send] error:", err)
|
||||
msgConfig.Text = "This bot couldn't send the response (Internal error)"
|
||||
tc.input.api.Send(msgConfig)
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/micro/cli/v2"
|
||||
"github.com/micro/go-micro/agent/input"
|
||||
"github.com/micro/go-micro/v2/agent/input"
|
||||
tgbotapi "gopkg.in/telegram-bot-api.v4"
|
||||
)
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: github.com/micro/go-micro/agent/proto/bot.proto
|
||||
// source: github.com/micro/go-micro/v2/agent/proto/bot.proto
|
||||
|
||||
package go_micro_bot
|
||||
|
||||
@@ -192,7 +192,7 @@ func init() {
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/micro/go-micro/agent/proto/bot.proto", fileDescriptor_018e8d5b14a89d12)
|
||||
proto.RegisterFile("github.com/micro/go-micro/v2/agent/proto/bot.proto", fileDescriptor_018e8d5b14a89d12)
|
||||
}
|
||||
|
||||
var fileDescriptor_018e8d5b14a89d12 = []byte{
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: github.com/micro/go-micro/agent/proto/bot.proto
|
||||
// source: github.com/micro/go-micro/v2/agent/proto/bot.proto
|
||||
|
||||
package go_micro_bot
|
||||
|
||||
@@ -11,8 +11,8 @@ import (
|
||||
|
||||
import (
|
||||
context "context"
|
||||
client "github.com/micro/go-micro/client"
|
||||
server "github.com/micro/go-micro/server"
|
||||
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.
|
||||
|
@@ -5,8 +5,8 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/server"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/server"
|
||||
)
|
||||
|
||||
// Endpoint is a mapping between an RPC method and HTTP endpoint
|
||||
|
@@ -4,13 +4,13 @@ package api
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
goapi "github.com/micro/go-micro/api"
|
||||
"github.com/micro/go-micro/api/handler"
|
||||
api "github.com/micro/go-micro/api/proto"
|
||||
"github.com/micro/go-micro/client"
|
||||
"github.com/micro/go-micro/client/selector"
|
||||
"github.com/micro/go-micro/errors"
|
||||
"github.com/micro/go-micro/util/ctx"
|
||||
goapi "github.com/micro/go-micro/v2/api"
|
||||
"github.com/micro/go-micro/v2/api/handler"
|
||||
api "github.com/micro/go-micro/v2/api/proto"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
"github.com/micro/go-micro/v2/errors"
|
||||
"github.com/micro/go-micro/v2/util/ctx"
|
||||
)
|
||||
|
||||
type apiHandler struct {
|
||||
|
@@ -8,9 +8,9 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
api "github.com/micro/go-micro/api/proto"
|
||||
"github.com/micro/go-micro/client/selector"
|
||||
"github.com/micro/go-micro/registry"
|
||||
api "github.com/micro/go-micro/v2/api/proto"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
)
|
||||
|
||||
func requestToProto(r *http.Request) (*api.Request, error) {
|
||||
|
@@ -8,12 +8,13 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/micro/go-micro/api/handler"
|
||||
"github.com/micro/go-micro/broker"
|
||||
"github.com/micro/go-micro/util/log"
|
||||
"github.com/micro/go-micro/v2/api/handler"
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -26,6 +27,7 @@ const (
|
||||
)
|
||||
|
||||
type brokerHandler struct {
|
||||
once atomic.Value
|
||||
opts handler.Options
|
||||
u websocket.Upgrader
|
||||
}
|
||||
@@ -42,7 +44,6 @@ type conn struct {
|
||||
}
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
contentType = "text/plain"
|
||||
)
|
||||
|
||||
@@ -135,7 +136,7 @@ func (c *conn) writeLoop() {
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
log.Log(err.Error())
|
||||
log.Error(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -155,10 +156,15 @@ func (b *brokerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
br := b.opts.Service.Client().Options().Broker
|
||||
|
||||
// Setup the broker
|
||||
once.Do(func() {
|
||||
br.Init()
|
||||
br.Connect()
|
||||
})
|
||||
if !b.once.Load().(bool) {
|
||||
if err := br.Init(); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
}
|
||||
if err := br.Connect(); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
}
|
||||
b.once.Store(true)
|
||||
}
|
||||
|
||||
// Parse
|
||||
r.ParseForm()
|
||||
@@ -208,7 +214,7 @@ func (b *brokerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
ws, err := b.u.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
log.Log(err.Error())
|
||||
log.Error(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -235,7 +241,7 @@ func (b *brokerHandler) String() string {
|
||||
}
|
||||
|
||||
func NewHandler(opts ...handler.Option) handler.Handler {
|
||||
return &brokerHandler{
|
||||
h := &brokerHandler{
|
||||
u: websocket.Upgrader{
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
return true
|
||||
@@ -245,6 +251,8 @@ func NewHandler(opts ...handler.Option) handler.Handler {
|
||||
},
|
||||
opts: handler.NewOptions(opts...),
|
||||
}
|
||||
h.once.Store(true)
|
||||
return h
|
||||
}
|
||||
|
||||
func WithCors(cors map[string]bool, opts ...handler.Option) handler.Handler {
|
||||
|
@@ -7,8 +7,8 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/micro/go-micro/api/handler"
|
||||
"github.com/micro/go-micro/util/ctx"
|
||||
"github.com/micro/go-micro/v2/api/handler"
|
||||
"github.com/micro/go-micro/v2/util/ctx"
|
||||
)
|
||||
|
||||
type event struct {
|
||||
|
@@ -12,9 +12,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/micro/go-micro/api/handler"
|
||||
proto "github.com/micro/go-micro/api/proto"
|
||||
"github.com/micro/go-micro/util/ctx"
|
||||
"github.com/micro/go-micro/v2/api/handler"
|
||||
proto "github.com/micro/go-micro/v2/api/proto"
|
||||
"github.com/micro/go-micro/v2/util/ctx"
|
||||
)
|
||||
|
||||
type event struct {
|
||||
|
@@ -8,9 +8,9 @@ import (
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
|
||||
"github.com/micro/go-micro/api"
|
||||
"github.com/micro/go-micro/api/handler"
|
||||
"github.com/micro/go-micro/client/selector"
|
||||
"github.com/micro/go-micro/v2/api"
|
||||
"github.com/micro/go-micro/v2/api/handler"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@@ -6,11 +6,11 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/micro/go-micro/api/handler"
|
||||
"github.com/micro/go-micro/api/router"
|
||||
regRouter "github.com/micro/go-micro/api/router/registry"
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/registry/memory"
|
||||
"github.com/micro/go-micro/v2/api/handler"
|
||||
"github.com/micro/go-micro/v2/api/router"
|
||||
regRouter "github.com/micro/go-micro/v2/api/router/registry"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/registry/memory"
|
||||
)
|
||||
|
||||
func testHttp(t *testing.T, path, service, ns string) {
|
||||
|
@@ -1,8 +1,8 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"github.com/micro/go-micro"
|
||||
"github.com/micro/go-micro/api/router"
|
||||
"github.com/micro/go-micro/v2"
|
||||
"github.com/micro/go-micro/v2/api/router"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
|
@@ -9,8 +9,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/micro/go-micro/api/handler"
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/v2/api/handler"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@@ -10,17 +10,17 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/joncalhoun/qson"
|
||||
"github.com/micro/go-micro/api"
|
||||
"github.com/micro/go-micro/api/handler"
|
||||
proto "github.com/micro/go-micro/api/internal/proto"
|
||||
"github.com/micro/go-micro/client"
|
||||
"github.com/micro/go-micro/client/selector"
|
||||
"github.com/micro/go-micro/codec"
|
||||
"github.com/micro/go-micro/codec/jsonrpc"
|
||||
"github.com/micro/go-micro/codec/protorpc"
|
||||
"github.com/micro/go-micro/errors"
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/util/ctx"
|
||||
"github.com/micro/go-micro/v2/api"
|
||||
"github.com/micro/go-micro/v2/api/handler"
|
||||
proto "github.com/micro/go-micro/v2/api/internal/proto"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
"github.com/micro/go-micro/v2/codec"
|
||||
"github.com/micro/go-micro/v2/codec/jsonrpc"
|
||||
"github.com/micro/go-micro/v2/codec/protorpc"
|
||||
"github.com/micro/go-micro/v2/errors"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/util/ctx"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -202,8 +202,9 @@ func hasCodec(ct string, codecs []string) bool {
|
||||
func requestPayload(r *http.Request) ([]byte, error) {
|
||||
// we have to decode json-rpc and proto-rpc because we suck
|
||||
// well actually because there's no proxy codec right now
|
||||
switch r.Header.Get("Content-Type") {
|
||||
case "application/json-rpc":
|
||||
ct := r.Header.Get("Content-Type")
|
||||
switch {
|
||||
case strings.Contains(ct, "application/json-rpc"):
|
||||
msg := codec.Message{
|
||||
Type: codec.Request,
|
||||
Header: make(map[string]string),
|
||||
@@ -217,7 +218,7 @@ func requestPayload(r *http.Request) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
return ([]byte)(raw), nil
|
||||
case "application/proto-rpc", "application/octet-stream":
|
||||
case strings.Contains(ct, "application/proto-rpc"), strings.Contains(ct, "application/octet-stream"):
|
||||
msg := codec.Message{
|
||||
Type: codec.Request,
|
||||
Header: make(map[string]string),
|
||||
@@ -232,6 +233,19 @@ func requestPayload(r *http.Request) ([]byte, error) {
|
||||
}
|
||||
b, _ := raw.Marshal()
|
||||
return b, nil
|
||||
case strings.Contains(ct, "application/www-x-form-urlencoded"):
|
||||
r.ParseForm()
|
||||
|
||||
// generate a new set of values from the form
|
||||
vals := make(map[string]string)
|
||||
for k, v := range r.Form {
|
||||
vals[k] = strings.Join(v, ",")
|
||||
}
|
||||
|
||||
// marshal
|
||||
b, _ := json.Marshal(vals)
|
||||
return b, nil
|
||||
// TODO: application/grpc
|
||||
}
|
||||
|
||||
// otherwise as per usual
|
||||
|
@@ -7,7 +7,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
go_api "github.com/micro/go-micro/api/proto"
|
||||
go_api "github.com/micro/go-micro/v2/api/proto"
|
||||
)
|
||||
|
||||
func TestRequestPayloadFromRequest(t *testing.T) {
|
||||
|
@@ -11,9 +11,9 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/micro/go-micro/api"
|
||||
"github.com/micro/go-micro/api/handler"
|
||||
"github.com/micro/go-micro/client/selector"
|
||||
"github.com/micro/go-micro/v2/api"
|
||||
"github.com/micro/go-micro/v2/api/handler"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: github.com/micro/go-micro/api/proto/api.proto
|
||||
// source: github.com/micro/go-micro/v2/api/proto/api.proto
|
||||
|
||||
package go_api
|
||||
|
||||
@@ -304,7 +304,7 @@ func init() {
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/micro/go-micro/api/proto/api.proto", fileDescriptor_7b6696ef87ec1943)
|
||||
proto.RegisterFile("github.com/micro/go-micro/v2/api/proto/api.proto", fileDescriptor_7b6696ef87ec1943)
|
||||
}
|
||||
|
||||
var fileDescriptor_7b6696ef87ec1943 = []byte{
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: github.com/micro/go-micro/api/proto/api.proto
|
||||
// source: github.com/micro/go-micro/v2/api/proto/api.proto
|
||||
|
||||
package go_api
|
||||
|
||||
|
@@ -6,7 +6,7 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/micro/go-micro/api/resolver"
|
||||
"github.com/micro/go-micro/v2/api/resolver"
|
||||
)
|
||||
|
||||
type Resolver struct{}
|
||||
|
@@ -4,7 +4,7 @@ package host
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/micro/go-micro/api/resolver"
|
||||
"github.com/micro/go-micro/v2/api/resolver"
|
||||
)
|
||||
|
||||
type Resolver struct{}
|
||||
|
@@ -4,7 +4,7 @@ package micro
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/micro/go-micro/api/resolver"
|
||||
"github.com/micro/go-micro/v2/api/resolver"
|
||||
)
|
||||
|
||||
// default resolver for legacy purposes
|
||||
|
@@ -6,7 +6,7 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/micro/go-micro/api/resolver"
|
||||
"github.com/micro/go-micro/v2/api/resolver"
|
||||
)
|
||||
|
||||
type Resolver struct{}
|
||||
|
@@ -7,7 +7,7 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/micro/go-micro/api/resolver"
|
||||
"github.com/micro/go-micro/v2/api/resolver"
|
||||
)
|
||||
|
||||
type Resolver struct{}
|
||||
|
@@ -1,9 +1,9 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/micro/go-micro/api/resolver"
|
||||
"github.com/micro/go-micro/api/resolver/micro"
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/v2/api/resolver"
|
||||
"github.com/micro/go-micro/v2/api/resolver/micro"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
|
@@ -11,10 +11,10 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/api"
|
||||
"github.com/micro/go-micro/api/router"
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/registry/cache"
|
||||
"github.com/micro/go-micro/v2/api"
|
||||
"github.com/micro/go-micro/v2/api/router"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/registry/cache"
|
||||
)
|
||||
|
||||
// router is the default router
|
||||
|
@@ -6,7 +6,7 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/micro/go-micro/api"
|
||||
"github.com/micro/go-micro/v2/api"
|
||||
)
|
||||
|
||||
func TestSetNamespace(t *testing.T) {
|
||||
|
@@ -4,7 +4,7 @@ package router
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/micro/go-micro/api"
|
||||
"github.com/micro/go-micro/v2/api"
|
||||
)
|
||||
|
||||
// Router is used to determine an endpoint for a request
|
||||
|
@@ -2,6 +2,7 @@
|
||||
package acme
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net"
|
||||
)
|
||||
@@ -14,7 +15,10 @@ var (
|
||||
|
||||
// Provider is a ACME provider interface
|
||||
type Provider interface {
|
||||
NewListener(...string) (net.Listener, error)
|
||||
// Listen returns a new listener
|
||||
Listen(...string) (net.Listener, error)
|
||||
// TLSConfig returns a tls config
|
||||
TLSConfig(...string) (*tls.Config, error)
|
||||
}
|
||||
|
||||
// The Let's Encrypt ACME endpoints
|
||||
|
@@ -3,21 +3,42 @@
|
||||
package autocert
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/micro/go-micro/api/server/acme"
|
||||
"github.com/micro/go-micro/v2/api/server/acme"
|
||||
"golang.org/x/crypto/acme/autocert"
|
||||
)
|
||||
|
||||
// autoCertACME is the ACME provider from golang.org/x/crypto/acme/autocert
|
||||
type autocertProvider struct{}
|
||||
|
||||
// NewListener implements acme.Provider
|
||||
func (a *autocertProvider) NewListener(ACMEHosts ...string) (net.Listener, error) {
|
||||
return autocert.NewListener(ACMEHosts...), nil
|
||||
// Listen implements acme.Provider
|
||||
func (a *autocertProvider) Listen(hosts ...string) (net.Listener, error) {
|
||||
return autocert.NewListener(hosts...), nil
|
||||
}
|
||||
|
||||
// TLSConfig returns a new tls config
|
||||
func (a *autocertProvider) TLSConfig(hosts ...string) (*tls.Config, error) {
|
||||
// create a new manager
|
||||
m := &autocert.Manager{
|
||||
Prompt: autocert.AcceptTOS,
|
||||
}
|
||||
if len(hosts) > 0 {
|
||||
m.HostPolicy = autocert.HostWhitelist(hosts...)
|
||||
}
|
||||
dir := cacheDir()
|
||||
if err := os.MkdirAll(dir, 0700); err != nil {
|
||||
log.Printf("warning: autocert not using a cache: %v", err)
|
||||
} else {
|
||||
m.Cache = autocert.DirCache(dir)
|
||||
}
|
||||
return m.TLSConfig(), nil
|
||||
}
|
||||
|
||||
// New returns an autocert acme.Provider
|
||||
func New() acme.Provider {
|
||||
func NewProvider() acme.Provider {
|
||||
return &autocertProvider{}
|
||||
}
|
||||
|
@@ -5,9 +5,9 @@ import (
|
||||
)
|
||||
|
||||
func TestAutocert(t *testing.T) {
|
||||
l := New()
|
||||
l := NewProvider()
|
||||
if _, ok := l.(*autocertProvider); !ok {
|
||||
t.Error("New() didn't return an autocertProvider")
|
||||
t.Error("NewProvider() didn't return an autocertProvider")
|
||||
}
|
||||
// TODO: Travis CI doesn't let us bind :443
|
||||
// if _, err := l.NewListener(); err != nil {
|
||||
|
37
api/server/acme/autocert/cache.go
Normal file
37
api/server/acme/autocert/cache.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package autocert
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func homeDir() string {
|
||||
if runtime.GOOS == "windows" {
|
||||
return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
|
||||
}
|
||||
if h := os.Getenv("HOME"); h != "" {
|
||||
return h
|
||||
}
|
||||
return "/"
|
||||
}
|
||||
|
||||
func cacheDir() string {
|
||||
const base = "golang-autocert"
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
return filepath.Join(homeDir(), "Library", "Caches", base)
|
||||
case "windows":
|
||||
for _, ev := range []string{"APPDATA", "CSIDL_APPDATA", "TEMP", "TMP"} {
|
||||
if v := os.Getenv(ev); v != "" {
|
||||
return filepath.Join(v, base)
|
||||
}
|
||||
}
|
||||
// Worst case:
|
||||
return filepath.Join(homeDir(), base)
|
||||
}
|
||||
if xdg := os.Getenv("XDG_CACHE_HOME"); xdg != "" {
|
||||
return filepath.Join(xdg, base)
|
||||
}
|
||||
return filepath.Join(homeDir(), ".cache", base)
|
||||
}
|
@@ -2,6 +2,7 @@
|
||||
package certmagic
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
@@ -9,14 +10,15 @@ import (
|
||||
|
||||
"github.com/mholt/certmagic"
|
||||
|
||||
"github.com/micro/go-micro/api/server/acme"
|
||||
"github.com/micro/go-micro/v2/api/server/acme"
|
||||
)
|
||||
|
||||
type certmagicProvider struct {
|
||||
opts acme.Options
|
||||
}
|
||||
|
||||
func (c *certmagicProvider) NewListener(ACMEHosts ...string) (net.Listener, error) {
|
||||
// TODO: set self-contained options
|
||||
func (c *certmagicProvider) setup() {
|
||||
certmagic.Default.CA = c.opts.CA
|
||||
if c.opts.ChallengeProvider != nil {
|
||||
// Enabling DNS Challenge disables the other challenges
|
||||
@@ -34,12 +36,20 @@ func (c *certmagicProvider) NewListener(ACMEHosts ...string) (net.Listener, erro
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
randomDuration := (7 * 24 * time.Hour) + (time.Duration(rand.Intn(504)) * time.Hour)
|
||||
certmagic.Default.RenewDurationBefore = randomDuration
|
||||
}
|
||||
|
||||
return certmagic.Listen(ACMEHosts)
|
||||
func (c *certmagicProvider) Listen(hosts ...string) (net.Listener, error) {
|
||||
c.setup()
|
||||
return certmagic.Listen(hosts)
|
||||
}
|
||||
|
||||
func (c *certmagicProvider) TLSConfig(hosts ...string) (*tls.Config, error) {
|
||||
c.setup()
|
||||
return certmagic.TLS(hosts)
|
||||
}
|
||||
|
||||
// New returns a certmagic provider
|
||||
func New(options ...acme.Option) acme.Provider {
|
||||
func NewProvider(options ...acme.Option) acme.Provider {
|
||||
opts := acme.DefaultOptions()
|
||||
|
||||
for _, o := range options {
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package certmagic
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"reflect"
|
||||
@@ -10,17 +11,20 @@ import (
|
||||
|
||||
"github.com/go-acme/lego/v3/providers/dns/cloudflare"
|
||||
"github.com/mholt/certmagic"
|
||||
"github.com/micro/go-micro/api/server/acme"
|
||||
cfstore "github.com/micro/go-micro/store/cloudflare"
|
||||
"github.com/micro/go-micro/sync/lock/memory"
|
||||
"github.com/micro/go-micro/v2/api/server/acme"
|
||||
cfstore "github.com/micro/go-micro/v2/store/cloudflare"
|
||||
"github.com/micro/go-micro/v2/sync/lock/memory"
|
||||
)
|
||||
|
||||
func TestCertMagic(t *testing.T) {
|
||||
if len(os.Getenv("IN_TRAVIS_CI")) != 0 {
|
||||
t.Skip("Travis doesn't let us bind :443")
|
||||
}
|
||||
l, err := New().NewListener()
|
||||
l, err := NewProvider().Listen()
|
||||
if err != nil {
|
||||
if _, ok := err.(*net.OpError); ok {
|
||||
t.Skip("Run under non privileged user")
|
||||
}
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
l.Close()
|
||||
@@ -36,10 +40,10 @@ func TestCertMagic(t *testing.T) {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
l, err = New(acme.AcceptToS(true),
|
||||
l, err = NewProvider(acme.AcceptToS(true),
|
||||
acme.CA(acme.LetsEncryptStagingCA),
|
||||
acme.ChallengeProvider(p),
|
||||
).NewListener()
|
||||
).Listen()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
@@ -180,7 +184,7 @@ func TestStorageImplementation(t *testing.T) {
|
||||
|
||||
// New interface doesn't return an error, so call it in case any log.Fatal
|
||||
// happens
|
||||
New(acme.Cache(s))
|
||||
NewProvider(acme.Cache(s))
|
||||
}
|
||||
|
||||
// Full test with a real zone, with against LE staging
|
||||
@@ -207,7 +211,7 @@ func TestE2e(t *testing.T) {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
testProvider := New(
|
||||
testProvider := NewProvider(
|
||||
acme.AcceptToS(true),
|
||||
acme.Cache(testStorage),
|
||||
acme.CA(acme.LetsEncryptStagingCA),
|
||||
@@ -215,7 +219,7 @@ func TestE2e(t *testing.T) {
|
||||
acme.OnDemand(false),
|
||||
)
|
||||
|
||||
listener, err := testProvider.NewListener("*.micro.mu", "micro.mu")
|
||||
listener, err := testProvider.Listen("*.micro.mu", "micro.mu")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
@@ -10,8 +10,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/mholt/certmagic"
|
||||
"github.com/micro/go-micro/store"
|
||||
"github.com/micro/go-micro/sync/lock"
|
||||
"github.com/micro/go-micro/v2/store"
|
||||
"github.com/micro/go-micro/v2/sync/lock"
|
||||
)
|
||||
|
||||
// File represents a "File" that will be stored in store.Store - the contents and last modified time
|
||||
|
@@ -9,8 +9,8 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/micro/go-micro/api/server"
|
||||
"github.com/micro/go-micro/util/log"
|
||||
"github.com/micro/go-micro/v2/api/server"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
)
|
||||
|
||||
type httpServer struct {
|
||||
@@ -54,7 +54,7 @@ func (s *httpServer) Start() error {
|
||||
|
||||
if s.opts.EnableACME && s.opts.ACMEProvider != nil {
|
||||
// should we check the address to make sure its using :443?
|
||||
l, err = s.opts.ACMEProvider.NewListener(s.opts.ACMEHosts...)
|
||||
l, err = s.opts.ACMEProvider.Listen(s.opts.ACMEHosts...)
|
||||
} else if s.opts.EnableTLS && s.opts.TLSConfig != nil {
|
||||
l, err = tls.Listen("tcp", s.address, s.opts.TLSConfig)
|
||||
} else {
|
||||
@@ -65,7 +65,7 @@ func (s *httpServer) Start() error {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Logf("HTTP API Listening on %s", l.Addr().String())
|
||||
log.Infof("HTTP API Listening on %s", l.Addr().String())
|
||||
|
||||
s.mtx.Lock()
|
||||
s.address = l.Addr().String()
|
||||
|
@@ -3,7 +3,7 @@ package server
|
||||
import (
|
||||
"crypto/tls"
|
||||
|
||||
"github.com/micro/go-micro/api/server/acme"
|
||||
"github.com/micro/go-micro/v2/api/server/acme"
|
||||
)
|
||||
|
||||
type Option func(o *Options)
|
||||
|
55
auth/auth.go
55
auth/auth.go
@@ -7,34 +7,49 @@ import (
|
||||
|
||||
// Auth providers authentication and authorization
|
||||
type Auth interface {
|
||||
// Generate a new auth token
|
||||
Generate(string) (*Token, error)
|
||||
// Revoke an authorization token
|
||||
Revoke(*Token) error
|
||||
// Grant access to a resource
|
||||
Grant(*Token, *Service) error
|
||||
// Verify a token can access a resource
|
||||
Verify(*Token, *Service) error
|
||||
// Init the auth package
|
||||
Init(opts ...Option) error
|
||||
// Options returns the options set
|
||||
Options() Options
|
||||
// Generate a new auth Account
|
||||
Generate(id string, opts ...GenerateOption) (*Account, error)
|
||||
// Revoke an authorization Account
|
||||
Revoke(token string) error
|
||||
// Verify an account token
|
||||
Verify(token string) (*Account, error)
|
||||
// String returns the implementation
|
||||
String() string
|
||||
}
|
||||
|
||||
// Service is some thing to provide access to
|
||||
type Service struct {
|
||||
// Resource is an entity such as a user or
|
||||
type Resource struct {
|
||||
// Name of the resource
|
||||
Name string
|
||||
// Endpoint is the specific endpoint
|
||||
Endpoint string
|
||||
// Type of resource, e.g.
|
||||
Type string
|
||||
}
|
||||
|
||||
// Token providers by an auth provider
|
||||
type Token struct {
|
||||
// Unique token id
|
||||
Id string `json: "id"`
|
||||
// Time of token creation
|
||||
// Role an account has
|
||||
type Role struct {
|
||||
// Name of the role
|
||||
Name string
|
||||
// The resource it has access
|
||||
// TODO: potentially remove
|
||||
Resource *Resource
|
||||
}
|
||||
|
||||
// Account provided by an auth provider
|
||||
type Account struct {
|
||||
// ID of the account (UUID or email)
|
||||
Id string `json:"id"`
|
||||
// Token used to authenticate
|
||||
Token string `json:"token"`
|
||||
// Time of Account creation
|
||||
Created time.Time `json:"created"`
|
||||
// Time of token expiry
|
||||
// Time of Account expiry
|
||||
Expiry time.Time `json:"expiry"`
|
||||
// Roles associated with the token
|
||||
Roles []string `json:"roles"`
|
||||
// Roles associated with the Account
|
||||
Roles []*Role `json:"roles"`
|
||||
// Any other associated metadata
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
}
|
||||
|
122
auth/default.go
Normal file
122
auth/default.go
Normal file
@@ -0,0 +1,122 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"encoding/base32"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultAuth = NewAuth()
|
||||
)
|
||||
|
||||
func genAccount(id string) *Account {
|
||||
// return a pseudo account
|
||||
return &Account{
|
||||
Id: id,
|
||||
Token: base32.StdEncoding.EncodeToString([]byte(id)),
|
||||
Created: time.Now(),
|
||||
Expiry: time.Now().Add(time.Hour * 24),
|
||||
Metadata: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
// NewAuth returns a new default registry which is memory
|
||||
func NewAuth(opts ...Option) Auth {
|
||||
var options Options
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
|
||||
return &memory{
|
||||
accounts: make(map[string]*Account),
|
||||
opts: options,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: replace with https://github.com/nats-io/nkeys
|
||||
// We'll then register public key in registry to use
|
||||
type memory struct {
|
||||
opts Options
|
||||
// accounts
|
||||
sync.RWMutex
|
||||
accounts map[string]*Account
|
||||
}
|
||||
|
||||
func (n *memory) Init(opts ...Option) error {
|
||||
for _, o := range opts {
|
||||
o(&n.opts)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *memory) Options() Options {
|
||||
return n.opts
|
||||
}
|
||||
|
||||
func (n *memory) Generate(id string, opts ...GenerateOption) (*Account, error) {
|
||||
var options GenerateOptions
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
|
||||
// return a pseudo account
|
||||
acc := genAccount(id)
|
||||
|
||||
// set opts
|
||||
if len(options.Roles) > 0 {
|
||||
acc.Roles = options.Roles
|
||||
}
|
||||
if options.Metadata != nil {
|
||||
acc.Metadata = options.Metadata
|
||||
}
|
||||
|
||||
// TODO: don't overwrite
|
||||
n.Lock()
|
||||
// maybe save by account id?
|
||||
n.accounts[acc.Token] = acc
|
||||
n.Unlock()
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
func (n *memory) Revoke(token string) error {
|
||||
n.Lock()
|
||||
delete(n.accounts, token)
|
||||
n.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *memory) Verify(token string) (*Account, error) {
|
||||
n.RLock()
|
||||
defer n.RUnlock()
|
||||
|
||||
if len(token) == 0 {
|
||||
// pseudo account?
|
||||
return genAccount(""), nil
|
||||
}
|
||||
|
||||
// try get the local account if it exists
|
||||
if acc, ok := n.accounts[token]; ok {
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// decode the token otherwise
|
||||
b, err := base32.StdEncoding.DecodeString(token)
|
||||
if err != nil {
|
||||
return genAccount(""), nil
|
||||
}
|
||||
|
||||
// return a pseudo account based on token/id
|
||||
return &Account{
|
||||
Id: string(b),
|
||||
Token: token,
|
||||
Created: time.Now(),
|
||||
Expiry: time.Now().Add(time.Hour * 24),
|
||||
Metadata: make(map[string]string),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (n *memory) String() string {
|
||||
return "memory"
|
||||
}
|
135
auth/jwt/jwt.go
Normal file
135
auth/jwt/jwt.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrInvalidPrivateKey is returned when the service provided an invalid private key
|
||||
ErrInvalidPrivateKey = errors.New("An invalid private key was provided")
|
||||
|
||||
// ErrEncodingToken is returned when the service encounters an error during encoding
|
||||
ErrEncodingToken = errors.New("An error occured while encoding the JWT")
|
||||
|
||||
// ErrInvalidToken is returned when the token provided is not valid
|
||||
ErrInvalidToken = errors.New("An invalid token was provided")
|
||||
|
||||
// ErrMissingToken is returned when no token is provided
|
||||
ErrMissingToken = errors.New("A valid JWT is required")
|
||||
)
|
||||
|
||||
// NewAuth returns a new instance of the Auth service
|
||||
func NewAuth(opts ...auth.Option) auth.Auth {
|
||||
svc := new(svc)
|
||||
svc.Init(opts...)
|
||||
return svc
|
||||
}
|
||||
|
||||
// svc is the JWT implementation of the Auth interface
|
||||
type svc struct {
|
||||
options auth.Options
|
||||
}
|
||||
|
||||
func (s *svc) String() string {
|
||||
return "jwt"
|
||||
}
|
||||
|
||||
func (s *svc) Options() auth.Options {
|
||||
return s.options
|
||||
}
|
||||
|
||||
func (s *svc) Init(opts ...auth.Option) error {
|
||||
for _, o := range opts {
|
||||
o(&s.options)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AuthClaims to be encoded in the JWT
|
||||
type AuthClaims struct {
|
||||
Id string `json:"id"`
|
||||
Roles []*auth.Role `json:"roles"`
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
// Generate a new JWT
|
||||
func (s *svc) Generate(id string, ops ...auth.GenerateOption) (*auth.Account, error) {
|
||||
// decode the private key
|
||||
priv, err := base64.StdEncoding.DecodeString(s.options.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key, err := jwt.ParseRSAPrivateKeyFromPEM(priv)
|
||||
if err != nil {
|
||||
return nil, ErrEncodingToken
|
||||
}
|
||||
|
||||
options := auth.NewGenerateOptions(ops...)
|
||||
account := jwt.NewWithClaims(jwt.SigningMethodRS256, AuthClaims{
|
||||
id, options.Roles, options.Metadata, jwt.StandardClaims{
|
||||
Subject: id,
|
||||
ExpiresAt: time.Now().Add(time.Hour * 24).Unix(),
|
||||
},
|
||||
})
|
||||
|
||||
token, err := account.SignedString(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &auth.Account{
|
||||
Id: id,
|
||||
Token: token,
|
||||
Roles: options.Roles,
|
||||
Metadata: options.Metadata,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Revoke an authorization account
|
||||
func (s *svc) Revoke(token string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Verify a JWT
|
||||
func (s *svc) Verify(token string) (*auth.Account, error) {
|
||||
if token == "" {
|
||||
return nil, ErrMissingToken
|
||||
}
|
||||
|
||||
// decode the public key
|
||||
pub, err := base64.StdEncoding.DecodeString(s.options.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := jwt.ParseWithClaims(token, &AuthClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return jwt.ParseRSAPublicKeyFromPEM(pub)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !res.Valid {
|
||||
return nil, ErrInvalidToken
|
||||
}
|
||||
|
||||
claims, ok := res.Claims.(*AuthClaims)
|
||||
if !ok {
|
||||
return nil, ErrInvalidToken
|
||||
}
|
||||
|
||||
return &auth.Account{
|
||||
Id: claims.Id,
|
||||
Metadata: claims.Metadata,
|
||||
Roles: claims.Roles,
|
||||
}, nil
|
||||
}
|
75
auth/options.go
Normal file
75
auth/options.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package auth
|
||||
|
||||
type Options struct {
|
||||
// Token is an auth token
|
||||
Token string
|
||||
// Public key base64 encoded
|
||||
PublicKey string
|
||||
// Private key base64 encoded
|
||||
PrivateKey string
|
||||
// Endpoints to exclude
|
||||
Exclude []string
|
||||
}
|
||||
|
||||
type Option func(o *Options)
|
||||
|
||||
// Exclude ecludes a set of endpoints from authorization
|
||||
func Exclude(e ...string) Option {
|
||||
return func(o *Options) {
|
||||
o.Exclude = e
|
||||
}
|
||||
}
|
||||
|
||||
// PublicKey is the JWT public key
|
||||
func PublicKey(key string) Option {
|
||||
return func(o *Options) {
|
||||
o.PublicKey = key
|
||||
}
|
||||
}
|
||||
|
||||
// PrivateKey is the JWT private key
|
||||
func PrivateKey(key string) Option {
|
||||
return func(o *Options) {
|
||||
o.PrivateKey = key
|
||||
}
|
||||
}
|
||||
|
||||
// Token sets an auth token
|
||||
func Token(t string) Option {
|
||||
return func(o *Options) {
|
||||
o.Token = t
|
||||
}
|
||||
}
|
||||
|
||||
type GenerateOptions struct {
|
||||
// Metadata associated with the account
|
||||
Metadata map[string]string
|
||||
// Roles/scopes associated with the account
|
||||
Roles []*Role
|
||||
}
|
||||
|
||||
type GenerateOption func(o *GenerateOptions)
|
||||
|
||||
// Metadata for the generated account
|
||||
func Metadata(md map[string]string) func(o *GenerateOptions) {
|
||||
return func(o *GenerateOptions) {
|
||||
o.Metadata = md
|
||||
}
|
||||
}
|
||||
|
||||
// Roles for the generated account
|
||||
func Roles(rs []*Role) func(o *GenerateOptions) {
|
||||
return func(o *GenerateOptions) {
|
||||
o.Roles = rs
|
||||
}
|
||||
}
|
||||
|
||||
// NewGenerateOptions from a slice of options
|
||||
func NewGenerateOptions(opts ...GenerateOption) GenerateOptions {
|
||||
var options GenerateOptions
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
468
auth/service/proto/auth.pb.go
Normal file
468
auth/service/proto/auth.pb.go
Normal file
@@ -0,0 +1,468 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: micro/go-micro/auth/service/proto/auth.proto
|
||||
|
||||
package go_micro_auth
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/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
|
||||
|
||||
type Account struct {
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Token string `protobuf:"bytes,2,opt,name=token,proto3" json:"token,omitempty"`
|
||||
Created int64 `protobuf:"varint,3,opt,name=created,proto3" json:"created,omitempty"`
|
||||
Expiry int64 `protobuf:"varint,4,opt,name=expiry,proto3" json:"expiry,omitempty"`
|
||||
Roles []*Role `protobuf:"bytes,5,rep,name=roles,proto3" json:"roles,omitempty"`
|
||||
Metadata map[string]string `protobuf:"bytes,6,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Account) Reset() { *m = Account{} }
|
||||
func (m *Account) String() string { return proto.CompactTextString(m) }
|
||||
func (*Account) ProtoMessage() {}
|
||||
func (*Account) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_de609d4872dacc78, []int{0}
|
||||
}
|
||||
|
||||
func (m *Account) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Account.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Account) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Account.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Account) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Account.Merge(m, src)
|
||||
}
|
||||
func (m *Account) XXX_Size() int {
|
||||
return xxx_messageInfo_Account.Size(m)
|
||||
}
|
||||
func (m *Account) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Account.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Account proto.InternalMessageInfo
|
||||
|
||||
func (m *Account) GetId() string {
|
||||
if m != nil {
|
||||
return m.Id
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Account) GetToken() string {
|
||||
if m != nil {
|
||||
return m.Token
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Account) GetCreated() int64 {
|
||||
if m != nil {
|
||||
return m.Created
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Account) GetExpiry() int64 {
|
||||
if m != nil {
|
||||
return m.Expiry
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Account) GetRoles() []*Role {
|
||||
if m != nil {
|
||||
return m.Roles
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Account) GetMetadata() map[string]string {
|
||||
if m != nil {
|
||||
return m.Metadata
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Role struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Resource *Resource `protobuf:"bytes,2,opt,name=resource,proto3" json:"resource,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Role) Reset() { *m = Role{} }
|
||||
func (m *Role) String() string { return proto.CompactTextString(m) }
|
||||
func (*Role) ProtoMessage() {}
|
||||
func (*Role) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_de609d4872dacc78, []int{1}
|
||||
}
|
||||
|
||||
func (m *Role) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Role.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Role) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Role.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Role) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Role.Merge(m, src)
|
||||
}
|
||||
func (m *Role) XXX_Size() int {
|
||||
return xxx_messageInfo_Role.Size(m)
|
||||
}
|
||||
func (m *Role) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Role.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Role proto.InternalMessageInfo
|
||||
|
||||
func (m *Role) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Role) GetResource() *Resource {
|
||||
if m != nil {
|
||||
return m.Resource
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Resource struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Resource) Reset() { *m = Resource{} }
|
||||
func (m *Resource) String() string { return proto.CompactTextString(m) }
|
||||
func (*Resource) ProtoMessage() {}
|
||||
func (*Resource) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_de609d4872dacc78, []int{2}
|
||||
}
|
||||
|
||||
func (m *Resource) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Resource.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Resource) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Resource.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Resource) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Resource.Merge(m, src)
|
||||
}
|
||||
func (m *Resource) XXX_Size() int {
|
||||
return xxx_messageInfo_Resource.Size(m)
|
||||
}
|
||||
func (m *Resource) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Resource.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Resource proto.InternalMessageInfo
|
||||
|
||||
func (m *Resource) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Resource) GetType() string {
|
||||
if m != nil {
|
||||
return m.Type
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type GenerateRequest struct {
|
||||
Account *Account `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *GenerateRequest) Reset() { *m = GenerateRequest{} }
|
||||
func (m *GenerateRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*GenerateRequest) ProtoMessage() {}
|
||||
func (*GenerateRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_de609d4872dacc78, []int{3}
|
||||
}
|
||||
|
||||
func (m *GenerateRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GenerateRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *GenerateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_GenerateRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *GenerateRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GenerateRequest.Merge(m, src)
|
||||
}
|
||||
func (m *GenerateRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_GenerateRequest.Size(m)
|
||||
}
|
||||
func (m *GenerateRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GenerateRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GenerateRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *GenerateRequest) GetAccount() *Account {
|
||||
if m != nil {
|
||||
return m.Account
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type GenerateResponse struct {
|
||||
Account *Account `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *GenerateResponse) Reset() { *m = GenerateResponse{} }
|
||||
func (m *GenerateResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*GenerateResponse) ProtoMessage() {}
|
||||
func (*GenerateResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_de609d4872dacc78, []int{4}
|
||||
}
|
||||
|
||||
func (m *GenerateResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GenerateResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *GenerateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_GenerateResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *GenerateResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GenerateResponse.Merge(m, src)
|
||||
}
|
||||
func (m *GenerateResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_GenerateResponse.Size(m)
|
||||
}
|
||||
func (m *GenerateResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GenerateResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GenerateResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *GenerateResponse) GetAccount() *Account {
|
||||
if m != nil {
|
||||
return m.Account
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type VerifyRequest struct {
|
||||
Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *VerifyRequest) Reset() { *m = VerifyRequest{} }
|
||||
func (m *VerifyRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*VerifyRequest) ProtoMessage() {}
|
||||
func (*VerifyRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_de609d4872dacc78, []int{5}
|
||||
}
|
||||
|
||||
func (m *VerifyRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_VerifyRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *VerifyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_VerifyRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *VerifyRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_VerifyRequest.Merge(m, src)
|
||||
}
|
||||
func (m *VerifyRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_VerifyRequest.Size(m)
|
||||
}
|
||||
func (m *VerifyRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_VerifyRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_VerifyRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *VerifyRequest) GetToken() string {
|
||||
if m != nil {
|
||||
return m.Token
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type VerifyResponse struct {
|
||||
Account *Account `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *VerifyResponse) Reset() { *m = VerifyResponse{} }
|
||||
func (m *VerifyResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*VerifyResponse) ProtoMessage() {}
|
||||
func (*VerifyResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_de609d4872dacc78, []int{6}
|
||||
}
|
||||
|
||||
func (m *VerifyResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_VerifyResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *VerifyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_VerifyResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *VerifyResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_VerifyResponse.Merge(m, src)
|
||||
}
|
||||
func (m *VerifyResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_VerifyResponse.Size(m)
|
||||
}
|
||||
func (m *VerifyResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_VerifyResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_VerifyResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *VerifyResponse) GetAccount() *Account {
|
||||
if m != nil {
|
||||
return m.Account
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type RevokeRequest struct {
|
||||
Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *RevokeRequest) Reset() { *m = RevokeRequest{} }
|
||||
func (m *RevokeRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*RevokeRequest) ProtoMessage() {}
|
||||
func (*RevokeRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_de609d4872dacc78, []int{7}
|
||||
}
|
||||
|
||||
func (m *RevokeRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RevokeRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *RevokeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_RevokeRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *RevokeRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_RevokeRequest.Merge(m, src)
|
||||
}
|
||||
func (m *RevokeRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_RevokeRequest.Size(m)
|
||||
}
|
||||
func (m *RevokeRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_RevokeRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_RevokeRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *RevokeRequest) GetToken() string {
|
||||
if m != nil {
|
||||
return m.Token
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type RevokeResponse struct {
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *RevokeResponse) Reset() { *m = RevokeResponse{} }
|
||||
func (m *RevokeResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*RevokeResponse) ProtoMessage() {}
|
||||
func (*RevokeResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_de609d4872dacc78, []int{8}
|
||||
}
|
||||
|
||||
func (m *RevokeResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RevokeResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *RevokeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_RevokeResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *RevokeResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_RevokeResponse.Merge(m, src)
|
||||
}
|
||||
func (m *RevokeResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_RevokeResponse.Size(m)
|
||||
}
|
||||
func (m *RevokeResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_RevokeResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_RevokeResponse proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Account)(nil), "go.micro.auth.Account")
|
||||
proto.RegisterMapType((map[string]string)(nil), "go.micro.auth.Account.MetadataEntry")
|
||||
proto.RegisterType((*Role)(nil), "go.micro.auth.Role")
|
||||
proto.RegisterType((*Resource)(nil), "go.micro.auth.Resource")
|
||||
proto.RegisterType((*GenerateRequest)(nil), "go.micro.auth.GenerateRequest")
|
||||
proto.RegisterType((*GenerateResponse)(nil), "go.micro.auth.GenerateResponse")
|
||||
proto.RegisterType((*VerifyRequest)(nil), "go.micro.auth.VerifyRequest")
|
||||
proto.RegisterType((*VerifyResponse)(nil), "go.micro.auth.VerifyResponse")
|
||||
proto.RegisterType((*RevokeRequest)(nil), "go.micro.auth.RevokeRequest")
|
||||
proto.RegisterType((*RevokeResponse)(nil), "go.micro.auth.RevokeResponse")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("micro/go-micro/auth/service/proto/auth.proto", fileDescriptor_de609d4872dacc78)
|
||||
}
|
||||
|
||||
var fileDescriptor_de609d4872dacc78 = []byte{
|
||||
// 432 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0x4b, 0x6f, 0xd3, 0x40,
|
||||
0x10, 0xae, 0x1d, 0xe7, 0xc1, 0x44, 0x09, 0xd1, 0x80, 0x8a, 0x15, 0xf1, 0x88, 0x56, 0x20, 0x05,
|
||||
0x09, 0x1c, 0xe4, 0x5e, 0x10, 0x5c, 0x28, 0x0f, 0xf5, 0x54, 0x21, 0xed, 0x81, 0xfb, 0xe2, 0x0c,
|
||||
0xad, 0x95, 0xc4, 0x6b, 0xd6, 0xeb, 0x08, 0xff, 0x06, 0x7e, 0x28, 0x7f, 0x03, 0x79, 0xd7, 0x1b,
|
||||
0x6a, 0xb7, 0xe5, 0x00, 0xb7, 0x79, 0x7c, 0xf3, 0xcd, 0xf7, 0x8d, 0x76, 0xe1, 0xc5, 0x2e, 0x4d,
|
||||
0x94, 0x5c, 0x5d, 0xc8, 0x97, 0x36, 0x10, 0xa5, 0xbe, 0x5c, 0x15, 0xa4, 0xf6, 0x69, 0x42, 0xab,
|
||||
0x5c, 0x49, 0x6d, 0x4b, 0x91, 0x09, 0x71, 0x72, 0x21, 0x23, 0x83, 0x8b, 0xea, 0x22, 0xfb, 0xe9,
|
||||
0xc3, 0xf0, 0x34, 0x49, 0x64, 0x99, 0x69, 0x9c, 0x82, 0x9f, 0xae, 0x43, 0x6f, 0xe1, 0x2d, 0xef,
|
||||
0x70, 0x3f, 0x5d, 0xe3, 0x7d, 0xe8, 0x6b, 0xb9, 0xa1, 0x2c, 0xf4, 0x4d, 0xc9, 0x26, 0x18, 0xc2,
|
||||
0x30, 0x51, 0x24, 0x34, 0xad, 0xc3, 0xde, 0xc2, 0x5b, 0xf6, 0xb8, 0x4b, 0xf1, 0x18, 0x06, 0xf4,
|
||||
0x23, 0x4f, 0x55, 0x15, 0x06, 0xa6, 0xd1, 0x64, 0xf8, 0x1c, 0xfa, 0x4a, 0x6e, 0xa9, 0x08, 0xfb,
|
||||
0x8b, 0xde, 0x72, 0x1c, 0xdf, 0x8b, 0x5a, 0x12, 0x22, 0x2e, 0xb7, 0xc4, 0x2d, 0x02, 0xdf, 0xc1,
|
||||
0x68, 0x47, 0x5a, 0xac, 0x85, 0x16, 0xe1, 0xc0, 0xa0, 0x9f, 0x76, 0xd0, 0x8d, 0xd8, 0xe8, 0xbc,
|
||||
0x81, 0x7d, 0xca, 0xb4, 0xaa, 0xf8, 0x61, 0x6a, 0xfe, 0x16, 0x26, 0xad, 0x16, 0xce, 0xa0, 0xb7,
|
||||
0xa1, 0xaa, 0xb1, 0x55, 0x87, 0xb5, 0xaf, 0xbd, 0xd8, 0x96, 0xe4, 0x7c, 0x99, 0xe4, 0x8d, 0xff,
|
||||
0xda, 0x63, 0x9f, 0x21, 0xa8, 0xd5, 0x20, 0x42, 0x90, 0x89, 0x1d, 0x35, 0x43, 0x26, 0xc6, 0x13,
|
||||
0x18, 0x29, 0x2a, 0x64, 0xa9, 0x12, 0x3b, 0x38, 0x8e, 0x1f, 0x74, 0x8d, 0x34, 0x6d, 0x7e, 0x00,
|
||||
0xb2, 0x18, 0x46, 0xae, 0x7a, 0x23, 0x29, 0x42, 0xa0, 0xab, 0xdc, 0x29, 0x31, 0x31, 0xfb, 0x00,
|
||||
0x77, 0xcf, 0x28, 0x23, 0x25, 0x34, 0x71, 0xfa, 0x5e, 0x52, 0xa1, 0xf1, 0x15, 0x0c, 0x85, 0xf5,
|
||||
0x6d, 0xa6, 0xc7, 0xf1, 0xf1, 0xcd, 0x57, 0xe1, 0x0e, 0xc6, 0x3e, 0xc2, 0xec, 0x0f, 0x49, 0x91,
|
||||
0xcb, 0xac, 0xa0, 0x7f, 0x60, 0x79, 0x06, 0x93, 0x2f, 0xa4, 0xd2, 0x6f, 0x95, 0x13, 0x72, 0x78,
|
||||
0x12, 0xde, 0x95, 0x27, 0xc1, 0xde, 0xc3, 0xd4, 0xc1, 0xfe, 0x67, 0x15, 0xa7, 0xbd, 0xdc, 0xd0,
|
||||
0xdf, 0x57, 0xcd, 0x60, 0xea, 0x60, 0x76, 0x55, 0xfc, 0xcb, 0x83, 0xe0, 0xb4, 0xd4, 0x97, 0x78,
|
||||
0x0e, 0x23, 0x67, 0x19, 0x1f, 0x77, 0xd6, 0x75, 0x0e, 0x3a, 0x7f, 0x72, 0x6b, 0xdf, 0xb2, 0xb2,
|
||||
0x23, 0x3c, 0x83, 0x81, 0x35, 0x85, 0x0f, 0x3b, 0xe0, 0xd6, 0x49, 0xe6, 0x8f, 0x6e, 0xe9, 0x5e,
|
||||
0x25, 0xb2, 0x92, 0xaf, 0x11, 0xb5, 0x0c, 0x5f, 0x23, 0x6a, 0xfb, 0x64, 0x47, 0x5f, 0x07, 0xe6,
|
||||
0x07, 0x9f, 0xfc, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x34, 0xce, 0x17, 0xf1, 0x03, 0x00, 0x00,
|
||||
}
|
119
auth/service/proto/auth.pb.micro.go
Normal file
119
auth/service/proto/auth.pb.micro.go
Normal file
@@ -0,0 +1,119 @@
|
||||
// Code generated by protoc-gen-micro. DO NOT EDIT.
|
||||
// source: micro/go-micro/auth/service/proto/auth.proto
|
||||
|
||||
package go_micro_auth
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/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 Auth service
|
||||
|
||||
type AuthService interface {
|
||||
Generate(ctx context.Context, in *GenerateRequest, opts ...client.CallOption) (*GenerateResponse, error)
|
||||
Verify(ctx context.Context, in *VerifyRequest, opts ...client.CallOption) (*VerifyResponse, error)
|
||||
Revoke(ctx context.Context, in *RevokeRequest, opts ...client.CallOption) (*RevokeResponse, error)
|
||||
}
|
||||
|
||||
type authService struct {
|
||||
c client.Client
|
||||
name string
|
||||
}
|
||||
|
||||
func NewAuthService(name string, c client.Client) AuthService {
|
||||
return &authService{
|
||||
c: c,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *authService) Generate(ctx context.Context, in *GenerateRequest, opts ...client.CallOption) (*GenerateResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Auth.Generate", in)
|
||||
out := new(GenerateResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *authService) Verify(ctx context.Context, in *VerifyRequest, opts ...client.CallOption) (*VerifyResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Auth.Verify", in)
|
||||
out := new(VerifyResponse)
|
||||
err := c.c.Call(ctx, req, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *authService) Revoke(ctx context.Context, in *RevokeRequest, opts ...client.CallOption) (*RevokeResponse, error) {
|
||||
req := c.c.NewRequest(c.name, "Auth.Revoke", in)
|
||||
out := new(RevokeResponse)
|
||||
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 {
|
||||
Generate(context.Context, *GenerateRequest, *GenerateResponse) error
|
||||
Verify(context.Context, *VerifyRequest, *VerifyResponse) error
|
||||
Revoke(context.Context, *RevokeRequest, *RevokeResponse) error
|
||||
}
|
||||
|
||||
func RegisterAuthHandler(s server.Server, hdlr AuthHandler, opts ...server.HandlerOption) error {
|
||||
type auth interface {
|
||||
Generate(ctx context.Context, in *GenerateRequest, out *GenerateResponse) error
|
||||
Verify(ctx context.Context, in *VerifyRequest, out *VerifyResponse) error
|
||||
Revoke(ctx context.Context, in *RevokeRequest, out *RevokeResponse) error
|
||||
}
|
||||
type Auth struct {
|
||||
auth
|
||||
}
|
||||
h := &authHandler{hdlr}
|
||||
return s.Handle(s.NewHandler(&Auth{h}, opts...))
|
||||
}
|
||||
|
||||
type authHandler struct {
|
||||
AuthHandler
|
||||
}
|
||||
|
||||
func (h *authHandler) Generate(ctx context.Context, in *GenerateRequest, out *GenerateResponse) error {
|
||||
return h.AuthHandler.Generate(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *authHandler) Verify(ctx context.Context, in *VerifyRequest, out *VerifyResponse) error {
|
||||
return h.AuthHandler.Verify(ctx, in, out)
|
||||
}
|
||||
|
||||
func (h *authHandler) Revoke(ctx context.Context, in *RevokeRequest, out *RevokeResponse) error {
|
||||
return h.AuthHandler.Revoke(ctx, in, out)
|
||||
}
|
50
auth/service/proto/auth.proto
Normal file
50
auth/service/proto/auth.proto
Normal file
@@ -0,0 +1,50 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package go.micro.auth;
|
||||
|
||||
service Auth {
|
||||
rpc Generate(GenerateRequest) returns (GenerateResponse) {};
|
||||
rpc Verify(VerifyRequest) returns (VerifyResponse) {};
|
||||
rpc Revoke(RevokeRequest) returns (RevokeResponse) {};
|
||||
}
|
||||
|
||||
message Account{
|
||||
string id = 1;
|
||||
string token = 2;
|
||||
int64 created = 3;
|
||||
int64 expiry = 4;
|
||||
repeated Role roles = 5;
|
||||
map<string, string> metadata = 6;
|
||||
}
|
||||
|
||||
message Role {
|
||||
string name = 1;
|
||||
Resource resource = 2;
|
||||
}
|
||||
|
||||
message Resource{
|
||||
string name = 1;
|
||||
string type = 2;
|
||||
}
|
||||
|
||||
message GenerateRequest {
|
||||
Account account = 1;
|
||||
}
|
||||
|
||||
message GenerateResponse {
|
||||
Account account = 1;
|
||||
}
|
||||
|
||||
message VerifyRequest {
|
||||
string token = 1;
|
||||
}
|
||||
|
||||
message VerifyResponse {
|
||||
Account account = 1;
|
||||
}
|
||||
|
||||
message RevokeRequest {
|
||||
string token = 1;
|
||||
}
|
||||
|
||||
message RevokeResponse {}
|
132
auth/service/service.go
Normal file
132
auth/service/service.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
pb "github.com/micro/go-micro/v2/auth/service/proto"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
)
|
||||
|
||||
// NewAuth returns a new instance of the Auth service
|
||||
func NewAuth(opts ...auth.Option) auth.Auth {
|
||||
svc := new(svc)
|
||||
svc.Init(opts...)
|
||||
return svc
|
||||
}
|
||||
|
||||
// svc is the service implementation of the Auth interface
|
||||
type svc struct {
|
||||
options auth.Options
|
||||
auth pb.AuthService
|
||||
}
|
||||
|
||||
func (s *svc) String() string {
|
||||
return "service"
|
||||
}
|
||||
|
||||
func (s *svc) Init(opts ...auth.Option) error {
|
||||
for _, o := range opts {
|
||||
o(&s.options)
|
||||
}
|
||||
|
||||
dc := client.DefaultClient
|
||||
s.auth = pb.NewAuthService("go.micro.auth", dc)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *svc) Options() auth.Options {
|
||||
return s.options
|
||||
}
|
||||
|
||||
// Generate a new auth account
|
||||
func (s *svc) Generate(id string, opts ...auth.GenerateOption) (*auth.Account, error) {
|
||||
// construct the request
|
||||
options := auth.NewGenerateOptions(opts...)
|
||||
sa := &auth.Account{
|
||||
Id: id,
|
||||
Roles: options.Roles,
|
||||
Metadata: options.Metadata,
|
||||
}
|
||||
req := &pb.GenerateRequest{Account: serializeAccount(sa)}
|
||||
|
||||
// execute the request
|
||||
resp, err := s.auth.Generate(context.Background(), req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// format the response
|
||||
return deserializeAccount(resp.Account), nil
|
||||
}
|
||||
|
||||
// Revoke an authorization account
|
||||
func (s *svc) Revoke(token string) error {
|
||||
// contruct the request
|
||||
req := &pb.RevokeRequest{Token: token}
|
||||
|
||||
// execute the request
|
||||
_, err := s.auth.Revoke(context.Background(), req)
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify an account token
|
||||
func (s *svc) Verify(token string) (*auth.Account, error) {
|
||||
resp, err := s.auth.Verify(context.Background(), &pb.VerifyRequest{Token: token})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return deserializeAccount(resp.Account), nil
|
||||
}
|
||||
|
||||
func serializeAccount(sa *auth.Account) *pb.Account {
|
||||
roles := make([]*pb.Role, len(sa.Roles))
|
||||
for i, r := range sa.Roles {
|
||||
roles[i] = &pb.Role{
|
||||
Name: r.Name,
|
||||
}
|
||||
|
||||
if r.Resource != nil {
|
||||
roles[i].Resource = &pb.Resource{
|
||||
Name: r.Resource.Name,
|
||||
Type: r.Resource.Type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &pb.Account{
|
||||
Id: sa.Id,
|
||||
Roles: roles,
|
||||
Metadata: sa.Metadata,
|
||||
}
|
||||
}
|
||||
|
||||
func deserializeAccount(a *pb.Account) *auth.Account {
|
||||
// format the response
|
||||
sa := &auth.Account{
|
||||
Id: a.Id,
|
||||
Token: a.Token,
|
||||
Created: time.Unix(a.Created, 0),
|
||||
Expiry: time.Unix(a.Expiry, 0),
|
||||
Metadata: a.Metadata,
|
||||
}
|
||||
|
||||
sa.Roles = make([]*auth.Role, len(a.Roles))
|
||||
for i, r := range a.Roles {
|
||||
sa.Roles[i] = &auth.Role{
|
||||
Name: r.Name,
|
||||
}
|
||||
|
||||
if r.Resource != nil {
|
||||
sa.Roles[i].Resource = &auth.Resource{
|
||||
Name: r.Resource.Name,
|
||||
Type: r.Resource.Type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sa
|
||||
}
|
130
auth/store/store.go
Normal file
130
auth/store/store.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/micro/go-micro/v2/auth"
|
||||
"github.com/micro/go-micro/v2/errors"
|
||||
"github.com/micro/go-micro/v2/store"
|
||||
)
|
||||
|
||||
type Auth struct {
|
||||
store store.Store
|
||||
opts auth.Options
|
||||
}
|
||||
|
||||
// NewAuth returns an instance of store auth
|
||||
func NewAuth(opts ...auth.Option) auth.Auth {
|
||||
var options auth.Options
|
||||
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
|
||||
return &Auth{
|
||||
store: store.DefaultStore,
|
||||
opts: options,
|
||||
}
|
||||
}
|
||||
|
||||
// Init the auth package
|
||||
func (a *Auth) Init(opts ...auth.Option) error {
|
||||
for _, o := range opts {
|
||||
o(&a.opts)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Options returns the options set
|
||||
func (a *Auth) Options() auth.Options {
|
||||
return a.opts
|
||||
}
|
||||
|
||||
// Generate a new auth Account
|
||||
func (a *Auth) Generate(id string, opts ...auth.GenerateOption) (*auth.Account, error) {
|
||||
// generate the token
|
||||
token, err := uuid.NewUUID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// parse the options
|
||||
options := auth.NewGenerateOptions(opts...)
|
||||
|
||||
// construct the account
|
||||
sa := auth.Account{
|
||||
Id: id,
|
||||
Token: token.String(),
|
||||
Created: time.Now(),
|
||||
Metadata: options.Metadata,
|
||||
Roles: options.Roles,
|
||||
}
|
||||
|
||||
// encode the data to bytes
|
||||
// TODO: replace with json
|
||||
buf := &bytes.Buffer{}
|
||||
e := gob.NewEncoder(buf)
|
||||
if err := e.Encode(sa); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// write to the store
|
||||
err = a.store.Write(&store.Record{
|
||||
Key: token.String(),
|
||||
Value: buf.Bytes(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// return the result
|
||||
return &sa, nil
|
||||
}
|
||||
|
||||
// Revoke an authorization Account
|
||||
func (a *Auth) Revoke(token string) error {
|
||||
records, err := a.store.Read(token, store.ReadSuffix())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(records) == 0 {
|
||||
return errors.BadRequest("go.micro.auth", "token not found")
|
||||
}
|
||||
|
||||
for _, r := range records {
|
||||
if err := a.store.Delete(r.Key); err != nil {
|
||||
return errors.InternalServerError("go.micro.auth", "error deleting from store")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Verify an account token
|
||||
func (a *Auth) Verify(token string) (*auth.Account, error) {
|
||||
// lookup the record by token
|
||||
records, err := a.store.Read(token, store.ReadSuffix())
|
||||
if err == store.ErrNotFound || len(records) == 0 {
|
||||
return nil, errors.Unauthorized("go.micro.auth", "invalid token")
|
||||
} else if err != nil {
|
||||
return nil, errors.InternalServerError("go.micro.auth", "error reading store")
|
||||
}
|
||||
|
||||
// decode the result
|
||||
// TODO: replace with json
|
||||
b := bytes.NewBuffer(records[0].Value)
|
||||
decoder := gob.NewDecoder(b)
|
||||
var sa auth.Account
|
||||
err = decoder.Decode(&sa)
|
||||
|
||||
// return the result
|
||||
return &sa, err
|
||||
}
|
||||
|
||||
// String returns the implementation
|
||||
func (a *Auth) String() string {
|
||||
return "store"
|
||||
}
|
@@ -10,10 +10,10 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/codec/json"
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/util/addr"
|
||||
"github.com/micro/go-micro/util/log"
|
||||
"github.com/micro/go-micro/v2/codec/json"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/util/addr"
|
||||
"github.com/nats-io/nats-server/v2/server"
|
||||
nats "github.com/nats-io/nats.go"
|
||||
)
|
||||
@@ -167,7 +167,7 @@ func (n *natsBroker) serve(exit chan bool) error {
|
||||
for _, node := range service.Nodes {
|
||||
u, err := url.Parse("nats://" + node.Address)
|
||||
if err != nil {
|
||||
log.Log(err)
|
||||
log.Info(err)
|
||||
continue
|
||||
}
|
||||
// append to the cluster routes
|
||||
@@ -240,6 +240,10 @@ func (n *natsBroker) serve(exit chan bool) error {
|
||||
// register the cluster address
|
||||
for {
|
||||
select {
|
||||
case err := <-n.closeCh:
|
||||
if err != nil {
|
||||
log.Info(err)
|
||||
}
|
||||
case <-exit:
|
||||
// deregister on exit
|
||||
n.opts.Registry.Deregister(®istry.Service{
|
||||
@@ -282,7 +286,6 @@ func (n *natsBroker) Connect() error {
|
||||
}
|
||||
|
||||
// set to connected
|
||||
n.connected = true
|
||||
}
|
||||
|
||||
status := nats.CLOSED
|
||||
@@ -295,6 +298,10 @@ func (n *natsBroker) Connect() error {
|
||||
return nil
|
||||
default: // DISCONNECTED or CLOSED or DRAINING
|
||||
opts := n.nopts
|
||||
opts.DrainTimeout = 1 * time.Second
|
||||
opts.AsyncErrorCB = n.onAsyncError
|
||||
opts.DisconnectedErrCB = n.onDisconnectedError
|
||||
opts.ClosedCB = n.onClose
|
||||
opts.Servers = n.servers
|
||||
opts.Secure = n.opts.Secure
|
||||
opts.TLSConfig = n.opts.TLSConfig
|
||||
@@ -309,6 +316,9 @@ func (n *natsBroker) Connect() error {
|
||||
return err
|
||||
}
|
||||
n.conn = c
|
||||
|
||||
n.connected = true
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -324,7 +334,6 @@ func (n *natsBroker) Disconnect() error {
|
||||
// drain the connection if specified
|
||||
if n.drain {
|
||||
n.conn.Drain()
|
||||
return <-n.closeCh
|
||||
}
|
||||
|
||||
// close the client connection
|
||||
@@ -332,10 +341,12 @@ func (n *natsBroker) Disconnect() error {
|
||||
|
||||
// shutdown the local server
|
||||
// and deregister
|
||||
select {
|
||||
case <-n.exit:
|
||||
default:
|
||||
close(n.exit)
|
||||
if n.server != nil {
|
||||
select {
|
||||
case <-n.exit:
|
||||
default:
|
||||
close(n.exit)
|
||||
}
|
||||
}
|
||||
|
||||
// set not connected
|
||||
@@ -434,6 +445,10 @@ func (n *natsBroker) onClose(conn *nats.Conn) {
|
||||
n.closeCh <- nil
|
||||
}
|
||||
|
||||
func (n *natsBroker) onDisconnectedError(conn *nats.Conn, err error) {
|
||||
n.closeCh <- err
|
||||
}
|
||||
|
||||
func (n *natsBroker) onAsyncError(conn *nats.Conn, sub *nats.Subscription, err error) {
|
||||
// There are kinds of different async error nats might callback, but we are interested
|
||||
// in ErrDrainTimeout only here.
|
||||
@@ -451,7 +466,8 @@ func NewBroker(opts ...Option) Broker {
|
||||
}
|
||||
|
||||
n := &natsBroker{
|
||||
opts: options,
|
||||
opts: options,
|
||||
closeCh: make(chan error),
|
||||
}
|
||||
n.setOption(opts...)
|
||||
|
||||
|
@@ -8,9 +8,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/micro/go-micro/broker"
|
||||
maddr "github.com/micro/go-micro/util/addr"
|
||||
mnet "github.com/micro/go-micro/util/net"
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
maddr "github.com/micro/go-micro/v2/util/addr"
|
||||
mnet "github.com/micro/go-micro/v2/util/net"
|
||||
)
|
||||
|
||||
type memoryBroker struct {
|
||||
|
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/micro/go-micro/broker"
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
)
|
||||
|
||||
func TestMemoryBroker(t *testing.T) {
|
||||
|
@@ -3,19 +3,9 @@ package nats
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/micro/go-micro/broker"
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
)
|
||||
|
||||
// setSubscribeOption returns a function to setup a context with given value
|
||||
func setSubscribeOption(k, v interface{}) broker.SubscribeOption {
|
||||
return func(o *broker.SubscribeOptions) {
|
||||
if o.Context == nil {
|
||||
o.Context = context.Background()
|
||||
}
|
||||
o.Context = context.WithValue(o.Context, k, v)
|
||||
}
|
||||
}
|
||||
|
||||
// setBrokerOption returns a function to setup a context with given value
|
||||
func setBrokerOption(k, v interface{}) broker.Option {
|
||||
return func(o *broker.Options) {
|
||||
@@ -25,13 +15,3 @@ func setBrokerOption(k, v interface{}) broker.Option {
|
||||
o.Context = context.WithValue(o.Context, k, v)
|
||||
}
|
||||
}
|
||||
|
||||
// setPublishOption returns a function to setup a context with given value
|
||||
func setPublishOption(k, v interface{}) broker.PublishOption {
|
||||
return func(o *broker.PublishOptions) {
|
||||
if o.Context == nil {
|
||||
o.Context = context.Background()
|
||||
}
|
||||
o.Context = context.WithValue(o.Context, k, v)
|
||||
}
|
||||
}
|
||||
|
@@ -11,11 +11,11 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/broker"
|
||||
"github.com/micro/go-micro/codec/json"
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/util/addr"
|
||||
"github.com/micro/go-micro/util/log"
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
"github.com/micro/go-micro/v2/codec/json"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/util/addr"
|
||||
"github.com/nats-io/nats-server/v2/server"
|
||||
nats "github.com/nats-io/nats.go"
|
||||
)
|
||||
@@ -164,7 +164,7 @@ func (n *natsBroker) serve(exit chan bool) error {
|
||||
for _, node := range service.Nodes {
|
||||
u, err := url.Parse("nats://" + node.Address)
|
||||
if err != nil {
|
||||
log.Log(err)
|
||||
log.Error(err)
|
||||
continue
|
||||
}
|
||||
// append to the cluster routes
|
||||
@@ -318,7 +318,7 @@ func (n *natsBroker) Disconnect() error {
|
||||
// drain the connection if specified
|
||||
if n.drain {
|
||||
n.conn.Drain()
|
||||
return <-n.closeCh
|
||||
n.closeCh <- nil
|
||||
}
|
||||
|
||||
// close the client connection
|
||||
@@ -440,6 +440,7 @@ func (n *natsBroker) setOption(opts ...broker.Option) {
|
||||
n.closeCh = make(chan error)
|
||||
n.nopts.ClosedCB = n.onClose
|
||||
n.nopts.AsyncErrorCB = n.onAsyncError
|
||||
n.nopts.DisconnectedErrCB = n.onDisconnectedError
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,6 +456,10 @@ func (n *natsBroker) onAsyncError(conn *nats.Conn, sub *nats.Subscription, err e
|
||||
}
|
||||
}
|
||||
|
||||
func (n *natsBroker) onDisconnectedError(conn *nats.Conn, err error) {
|
||||
n.closeCh <- err
|
||||
}
|
||||
|
||||
func NewBroker(opts ...broker.Option) broker.Broker {
|
||||
options := broker.Options{
|
||||
// Default codec
|
||||
|
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/micro/go-micro/broker"
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
nats "github.com/nats-io/nats.go"
|
||||
)
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package nats
|
||||
|
||||
import (
|
||||
"github.com/micro/go-micro/broker"
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
nats "github.com/nats-io/nats.go"
|
||||
)
|
||||
|
||||
|
@@ -4,8 +4,8 @@ import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
|
||||
"github.com/micro/go-micro/codec"
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/v2/codec"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
|
@@ -11,8 +11,8 @@ import (
|
||||
|
||||
import (
|
||||
context "context"
|
||||
client "github.com/micro/go-micro/client"
|
||||
server "github.com/micro/go-micro/server"
|
||||
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.
|
||||
|
@@ -5,10 +5,10 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/broker"
|
||||
pb "github.com/micro/go-micro/broker/service/proto"
|
||||
"github.com/micro/go-micro/client"
|
||||
"github.com/micro/go-micro/util/log"
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
pb "github.com/micro/go-micro/v2/broker/service/proto"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
)
|
||||
|
||||
type serviceBroker struct {
|
||||
|
@@ -1,9 +1,9 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/micro/go-micro/broker"
|
||||
pb "github.com/micro/go-micro/broker/service/proto"
|
||||
"github.com/micro/go-micro/util/log"
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
pb "github.com/micro/go-micro/v2/broker/service/proto"
|
||||
log "github.com/micro/go-micro/v2/logger"
|
||||
)
|
||||
|
||||
type serviceSub struct {
|
||||
|
@@ -2,16 +2,13 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/v2/util/backoff"
|
||||
)
|
||||
|
||||
type BackoffFunc func(ctx context.Context, req Request, attempts int) (time.Duration, error)
|
||||
|
||||
// exponential backoff
|
||||
func exponentialBackoff(ctx context.Context, req Request, attempts int) (time.Duration, error) {
|
||||
if attempts == 0 {
|
||||
return time.Duration(0), nil
|
||||
}
|
||||
return time.Duration(math.Pow(10, float64(attempts))) * time.Millisecond, nil
|
||||
return backoff.Do(attempts), nil
|
||||
}
|
||||
|
@@ -2,13 +2,19 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestBackoff(t *testing.T) {
|
||||
delta := time.Duration(0)
|
||||
results := []time.Duration{
|
||||
0 * time.Second,
|
||||
100 * time.Millisecond,
|
||||
600 * time.Millisecond,
|
||||
1900 * time.Millisecond,
|
||||
4300 * time.Millisecond,
|
||||
7900 * time.Millisecond,
|
||||
}
|
||||
|
||||
c := NewClient()
|
||||
|
||||
@@ -18,10 +24,8 @@ func TestBackoff(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if d < delta {
|
||||
t.Fatalf("Expected greater than %v, got %v", delta, d)
|
||||
if d != results[i] {
|
||||
t.Fatalf("Expected equal than %v, got %v", results[i], d)
|
||||
}
|
||||
|
||||
delta = time.Millisecond * time.Duration(math.Pow(10, float64(i+1)))
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/codec"
|
||||
"github.com/micro/go-micro/v2/codec"
|
||||
)
|
||||
|
||||
// Client is the interface used to make requests to services.
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@@ -9,8 +9,8 @@ import (
|
||||
"github.com/golang/protobuf/jsonpb"
|
||||
"github.com/golang/protobuf/proto"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/micro/go-micro/codec"
|
||||
"github.com/micro/go-micro/codec/bytes"
|
||||
"github.com/micro/go-micro/v2/codec"
|
||||
"github.com/micro/go-micro/v2/codec/bytes"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/encoding"
|
||||
)
|
||||
@@ -69,15 +69,21 @@ func (w wrapCodec) Unmarshal(data []byte, v interface{}) error {
|
||||
}
|
||||
|
||||
func (protoCodec) Marshal(v interface{}) ([]byte, error) {
|
||||
b, ok := v.(*bytes.Frame)
|
||||
if ok {
|
||||
return b.Data, nil
|
||||
switch m := v.(type) {
|
||||
case *bytes.Frame:
|
||||
return m.Data, nil
|
||||
case proto.Message:
|
||||
return proto.Marshal(m)
|
||||
}
|
||||
return proto.Marshal(v.(proto.Message))
|
||||
return nil, fmt.Errorf("failed to marshal: %v is not type of *bytes.Frame or proto.Message", v)
|
||||
}
|
||||
|
||||
func (protoCodec) Unmarshal(data []byte, v interface{}) error {
|
||||
return proto.Unmarshal(data, v.(proto.Message))
|
||||
m, ok := v.(proto.Message)
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to unmarshal: %v is not type of proto.Message", v)
|
||||
}
|
||||
return proto.Unmarshal(data, m)
|
||||
}
|
||||
|
||||
func (protoCodec) Name() string {
|
||||
@@ -149,7 +155,7 @@ func (g *grpcCodec) ReadHeader(m *codec.Message, mt codec.MessageType) error {
|
||||
m = new(codec.Message)
|
||||
}
|
||||
if m.Header == nil {
|
||||
m.Header = make(map[string]string)
|
||||
m.Header = make(map[string]string, len(md))
|
||||
}
|
||||
for k, v := range md {
|
||||
m.Header[k] = strings.Join(v, ",")
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"github.com/micro/go-micro/errors"
|
||||
"github.com/micro/go-micro/v2/errors"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
@@ -12,17 +12,21 @@ func microError(err error) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// micro error
|
||||
if v, ok := err.(*errors.Error); ok {
|
||||
return v
|
||||
if verr, ok := err.(*errors.Error); ok {
|
||||
return verr
|
||||
}
|
||||
|
||||
// grpc error
|
||||
if s, ok := status.FromError(err); ok {
|
||||
if e := errors.Parse(s.Message()); e.Code > 0 {
|
||||
return e // actually a micro error
|
||||
details := s.Details()
|
||||
if len(details) == 0 {
|
||||
if e := errors.Parse(s.Message()); e.Code > 0 {
|
||||
return e // actually a micro error
|
||||
}
|
||||
return errors.InternalServerError("go.micro.client", s.Message())
|
||||
}
|
||||
return errors.InternalServerError("go.micro.client", s.Message())
|
||||
// return first error from details
|
||||
return details[0].(error)
|
||||
}
|
||||
|
||||
// do nothing
|
||||
|
@@ -5,17 +5,20 @@ import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/broker"
|
||||
"github.com/micro/go-micro/client"
|
||||
"github.com/micro/go-micro/client/selector"
|
||||
raw "github.com/micro/go-micro/codec/bytes"
|
||||
"github.com/micro/go-micro/errors"
|
||||
"github.com/micro/go-micro/metadata"
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
raw "github.com/micro/go-micro/v2/codec/bytes"
|
||||
"github.com/micro/go-micro/v2/errors"
|
||||
"github.com/micro/go-micro/v2/metadata"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/util/config"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
@@ -23,10 +26,14 @@ import (
|
||||
gmetadata "google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
var (
|
||||
BearerScheme = "Bearer "
|
||||
)
|
||||
|
||||
type grpcClient struct {
|
||||
once sync.Once
|
||||
opts client.Options
|
||||
pool *pool
|
||||
once atomic.Value
|
||||
}
|
||||
|
||||
func init() {
|
||||
@@ -36,14 +43,36 @@ func init() {
|
||||
}
|
||||
|
||||
// secure returns the dial option for whether its a secure or insecure connection
|
||||
func (g *grpcClient) secure() grpc.DialOption {
|
||||
func (g *grpcClient) secure(addr string) grpc.DialOption {
|
||||
// first we check if theres'a tls config
|
||||
if g.opts.Context != nil {
|
||||
if v := g.opts.Context.Value(tlsAuth{}); v != nil {
|
||||
tls := v.(*tls.Config)
|
||||
creds := credentials.NewTLS(tls)
|
||||
// return tls config if it exists
|
||||
return grpc.WithTransportCredentials(creds)
|
||||
}
|
||||
}
|
||||
|
||||
// default config
|
||||
tlsConfig := &tls.Config{}
|
||||
defaultCreds := grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig))
|
||||
|
||||
// check if the address is prepended with https
|
||||
if strings.HasPrefix(addr, "https://") {
|
||||
return defaultCreds
|
||||
}
|
||||
|
||||
// if no port is specified or port is 443 default to tls
|
||||
_, port, err := net.SplitHostPort(addr)
|
||||
// assuming with no port its going to be secured
|
||||
if port == "443" {
|
||||
return defaultCreds
|
||||
} else if err != nil && strings.Contains(err.Error(), "missing port in address") {
|
||||
return defaultCreds
|
||||
}
|
||||
|
||||
// other fallback to insecure
|
||||
return grpc.WithInsecure()
|
||||
}
|
||||
|
||||
@@ -52,6 +81,10 @@ func (g *grpcClient) next(request client.Request, opts client.CallOptions) (sele
|
||||
|
||||
// get proxy
|
||||
if prx := os.Getenv("MICRO_PROXY"); len(prx) > 0 {
|
||||
// default name
|
||||
if prx == "service" {
|
||||
prx = "go.micro.proxy"
|
||||
}
|
||||
service = prx
|
||||
}
|
||||
|
||||
@@ -82,19 +115,28 @@ func (g *grpcClient) next(request client.Request, opts client.CallOptions) (sele
|
||||
}
|
||||
|
||||
func (g *grpcClient) call(ctx context.Context, node *registry.Node, req client.Request, rsp interface{}, opts client.CallOptions) error {
|
||||
var header map[string]string
|
||||
|
||||
address := node.Address
|
||||
|
||||
header := make(map[string]string)
|
||||
header = make(map[string]string)
|
||||
if md, ok := metadata.FromContext(ctx); ok {
|
||||
header = make(map[string]string, len(md))
|
||||
for k, v := range md {
|
||||
header[k] = v
|
||||
}
|
||||
} else {
|
||||
header = make(map[string]string)
|
||||
}
|
||||
|
||||
// set timeout in nanoseconds
|
||||
header["timeout"] = fmt.Sprintf("%d", opts.RequestTimeout)
|
||||
// set the content type for the request
|
||||
header["x-content-type"] = req.ContentType()
|
||||
// set the authorization token if one is saved locally
|
||||
if token, err := config.Get("token"); err == nil && len(token) > 0 {
|
||||
header["authorization"] = BearerScheme + token
|
||||
}
|
||||
|
||||
md := gmetadata.New(header)
|
||||
ctx = gmetadata.NewOutgoingContext(ctx, md)
|
||||
@@ -112,7 +154,7 @@ func (g *grpcClient) call(ctx context.Context, node *registry.Node, req client.R
|
||||
grpcDialOptions := []grpc.DialOption{
|
||||
grpc.WithDefaultCallOptions(grpc.ForceCodec(cf)),
|
||||
grpc.WithTimeout(opts.DialTimeout),
|
||||
g.secure(),
|
||||
g.secure(address),
|
||||
grpc.WithDefaultCallOptions(
|
||||
grpc.MaxCallRecvMsgSize(maxRecvMsgSize),
|
||||
grpc.MaxCallSendMsgSize(maxSendMsgSize),
|
||||
@@ -147,20 +189,24 @@ func (g *grpcClient) call(ctx context.Context, node *registry.Node, req client.R
|
||||
case err := <-ch:
|
||||
grr = err
|
||||
case <-ctx.Done():
|
||||
grr = ctx.Err()
|
||||
grr = errors.Timeout("go.micro.client", "%v", ctx.Err())
|
||||
}
|
||||
|
||||
return grr
|
||||
}
|
||||
|
||||
func (g *grpcClient) stream(ctx context.Context, node *registry.Node, req client.Request, opts client.CallOptions) (client.Stream, error) {
|
||||
var header map[string]string
|
||||
|
||||
address := node.Address
|
||||
|
||||
header := make(map[string]string)
|
||||
if md, ok := metadata.FromContext(ctx); ok {
|
||||
header = make(map[string]string, len(md))
|
||||
for k, v := range md {
|
||||
header[k] = v
|
||||
}
|
||||
} else {
|
||||
header = make(map[string]string)
|
||||
}
|
||||
|
||||
// set timeout in nanoseconds
|
||||
@@ -189,7 +235,8 @@ func (g *grpcClient) stream(ctx context.Context, node *registry.Node, req client
|
||||
|
||||
grpcDialOptions := []grpc.DialOption{
|
||||
grpc.WithDefaultCallOptions(grpc.ForceCodec(wc)),
|
||||
g.secure(),
|
||||
grpc.WithTimeout(opts.DialTimeout),
|
||||
g.secure(address),
|
||||
}
|
||||
|
||||
if opts := g.getGrpcDialOptions(); opts != nil {
|
||||
@@ -217,6 +264,12 @@ func (g *grpcClient) stream(ctx context.Context, node *registry.Node, req client
|
||||
|
||||
st, err := cc.NewStream(newCtx, desc, methodToGRPC(req.Service(), req.Endpoint()), grpcCallOptions...)
|
||||
if err != nil {
|
||||
// we need to cleanup as we dialled and created a context
|
||||
// cancel the context
|
||||
cancel()
|
||||
// close the connection
|
||||
cc.Close()
|
||||
// now return the error
|
||||
return nil, errors.InternalServerError("go.micro.client", fmt.Sprintf("Error creating stream: %v", err))
|
||||
}
|
||||
|
||||
@@ -339,6 +392,11 @@ func (g *grpcClient) NewRequest(service, method string, req interface{}, reqOpts
|
||||
}
|
||||
|
||||
func (g *grpcClient) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
|
||||
if req == nil {
|
||||
return errors.InternalServerError("go.micro.client", "req is nil")
|
||||
} else if rsp == nil {
|
||||
return errors.InternalServerError("go.micro.client", "rsp is nil")
|
||||
}
|
||||
// make a copy of call opts
|
||||
callOpts := g.opts.CallOptions
|
||||
for _, opt := range opts {
|
||||
@@ -559,17 +617,15 @@ func (g *grpcClient) Publish(ctx context.Context, p client.Message, opts ...clie
|
||||
body = b
|
||||
}
|
||||
|
||||
g.once.Do(func() {
|
||||
g.opts.Broker.Connect()
|
||||
})
|
||||
if !g.once.Load().(bool) {
|
||||
if err = g.opts.Broker.Connect(); err != nil {
|
||||
return errors.InternalServerError("go.micro.client", err.Error())
|
||||
}
|
||||
g.once.Store(true)
|
||||
}
|
||||
|
||||
topic := p.Topic()
|
||||
|
||||
// get proxy topic
|
||||
if prx := os.Getenv("MICRO_PROXY"); len(prx) > 0 {
|
||||
options.Exchange = prx
|
||||
}
|
||||
|
||||
// get the exchange
|
||||
if len(options.Exchange) > 0 {
|
||||
topic = options.Exchange
|
||||
@@ -635,9 +691,9 @@ func newClient(opts ...client.Option) client.Client {
|
||||
}
|
||||
|
||||
rc := &grpcClient{
|
||||
once: sync.Once{},
|
||||
opts: options,
|
||||
}
|
||||
rc.once.Store(false)
|
||||
|
||||
rc.pool = newPool(options.PoolSize, options.PoolTTL, rc.poolMaxIdle(), rc.poolMaxStreams())
|
||||
|
||||
|
@@ -5,10 +5,11 @@ import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/micro/go-micro/client"
|
||||
"github.com/micro/go-micro/client/selector"
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/registry/memory"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
"github.com/micro/go-micro/v2/errors"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/registry/memory"
|
||||
pgrpc "google.golang.org/grpc"
|
||||
pb "google.golang.org/grpc/examples/helloworld/helloworld"
|
||||
)
|
||||
@@ -18,6 +19,9 @@ type greeterServer struct{}
|
||||
|
||||
// SayHello implements helloworld.GreeterServer
|
||||
func (g *greeterServer) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
|
||||
if in.Name == "Error" {
|
||||
return nil, &errors.Error{Id: "1", Code: 99, Detail: "detail"}
|
||||
}
|
||||
return &pb.HelloReply{Message: "Hello " + in.Name}, nil
|
||||
}
|
||||
|
||||
@@ -84,4 +88,25 @@ func TestGRPCClient(t *testing.T) {
|
||||
t.Fatalf("Got unexpected response %v", rsp.Message)
|
||||
}
|
||||
}
|
||||
|
||||
req := c.NewRequest("helloworld", "/helloworld.Greeter/SayHello", &pb.HelloRequest{
|
||||
Name: "Error",
|
||||
})
|
||||
|
||||
rsp := pb.HelloReply{}
|
||||
|
||||
err = c.Call(context.TODO(), req, &rsp)
|
||||
if err == nil {
|
||||
t.Fatal("nil error received")
|
||||
}
|
||||
|
||||
verr, ok := err.(*errors.Error)
|
||||
if !ok {
|
||||
t.Fatalf("invalid error received %#+v\n", err)
|
||||
}
|
||||
|
||||
if verr.Code != 99 && verr.Id != "1" && verr.Detail != "detail" {
|
||||
t.Fatalf("invalid error received %#+v\n", verr)
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"github.com/micro/go-micro/client"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
)
|
||||
|
||||
type grpcEvent struct {
|
||||
|
@@ -5,7 +5,7 @@ import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
|
||||
"github.com/micro/go-micro/client"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/encoding"
|
||||
)
|
||||
|
@@ -4,8 +4,8 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/micro/go-micro/client"
|
||||
"github.com/micro/go-micro/codec"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/codec"
|
||||
)
|
||||
|
||||
type grpcRequest struct {
|
||||
|
@@ -3,8 +3,8 @@ package grpc
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/micro/go-micro/codec"
|
||||
"github.com/micro/go-micro/codec/bytes"
|
||||
"github.com/micro/go-micro/v2/codec"
|
||||
"github.com/micro/go-micro/v2/codec/bytes"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/encoding"
|
||||
)
|
||||
@@ -27,7 +27,7 @@ func (r *response) Header() map[string]string {
|
||||
if err != nil {
|
||||
return map[string]string{}
|
||||
}
|
||||
hdr := make(map[string]string)
|
||||
hdr := make(map[string]string, len(md))
|
||||
for k, v := range md {
|
||||
hdr[k] = strings.Join(v, ",")
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ import (
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/micro/go-micro/client"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
package mucp
|
||||
|
||||
import (
|
||||
"github.com/micro/go-micro/client"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
)
|
||||
|
||||
// NewClient returns a new micro client interface
|
||||
|
@@ -4,11 +4,11 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/broker"
|
||||
"github.com/micro/go-micro/client/selector"
|
||||
"github.com/micro/go-micro/codec"
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/transport"
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
"github.com/micro/go-micro/v2/codec"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/transport"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
@@ -291,6 +291,12 @@ func WithDialTimeout(d time.Duration) CallOption {
|
||||
}
|
||||
}
|
||||
|
||||
func WithMessageContentType(ct string) MessageOption {
|
||||
return func(o *MessageOptions) {
|
||||
o.ContentType = ct
|
||||
}
|
||||
}
|
||||
|
||||
// Request Options
|
||||
|
||||
func WithContentType(ct string) RequestOption {
|
||||
|
@@ -4,7 +4,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/transport"
|
||||
"github.com/micro/go-micro/v2/transport"
|
||||
)
|
||||
|
||||
func TestCallOptions(t *testing.T) {
|
||||
|
@@ -3,7 +3,7 @@ package client
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/micro/go-micro/errors"
|
||||
"github.com/micro/go-micro/v2/errors"
|
||||
)
|
||||
|
||||
// note that returning either false or a non-nil error will result in the call not being retried
|
||||
|
@@ -4,25 +4,24 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/micro/go-micro/broker"
|
||||
"github.com/micro/go-micro/client/selector"
|
||||
"github.com/micro/go-micro/codec"
|
||||
raw "github.com/micro/go-micro/codec/bytes"
|
||||
"github.com/micro/go-micro/errors"
|
||||
"github.com/micro/go-micro/metadata"
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/transport"
|
||||
"github.com/micro/go-micro/util/buf"
|
||||
"github.com/micro/go-micro/util/pool"
|
||||
"github.com/micro/go-micro/v2/broker"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
"github.com/micro/go-micro/v2/codec"
|
||||
raw "github.com/micro/go-micro/v2/codec/bytes"
|
||||
"github.com/micro/go-micro/v2/errors"
|
||||
"github.com/micro/go-micro/v2/metadata"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/transport"
|
||||
"github.com/micro/go-micro/v2/util/buf"
|
||||
"github.com/micro/go-micro/v2/util/pool"
|
||||
)
|
||||
|
||||
type rpcClient struct {
|
||||
once sync.Once
|
||||
once atomic.Value
|
||||
opts Options
|
||||
pool pool.Pool
|
||||
seq uint64
|
||||
@@ -38,11 +37,11 @@ func newRpcClient(opt ...Option) Client {
|
||||
)
|
||||
|
||||
rc := &rpcClient{
|
||||
once: sync.Once{},
|
||||
opts: opts,
|
||||
pool: p,
|
||||
seq: 0,
|
||||
}
|
||||
rc.once.Store(false)
|
||||
|
||||
c := Client(rc)
|
||||
|
||||
@@ -74,6 +73,11 @@ func (r *rpcClient) call(ctx context.Context, node *registry.Node, req Request,
|
||||
md, ok := metadata.FromContext(ctx)
|
||||
if ok {
|
||||
for k, v := range md {
|
||||
// don't copy Micro-Topic header, that used for pub/sub
|
||||
// this fix case then client uses the same context that received in subscriber
|
||||
if k == "Micro-Topic" {
|
||||
continue
|
||||
}
|
||||
msg.Header[k] = v
|
||||
}
|
||||
}
|
||||
@@ -337,6 +341,10 @@ func (r *rpcClient) next(request Request, opts CallOptions) (selector.Next, erro
|
||||
|
||||
// get proxy
|
||||
if prx := os.Getenv("MICRO_PROXY"); len(prx) > 0 {
|
||||
// default name
|
||||
if prx == "service" {
|
||||
prx = "go.micro.proxy"
|
||||
}
|
||||
service = prx
|
||||
}
|
||||
|
||||
@@ -601,11 +609,6 @@ func (r *rpcClient) Publish(ctx context.Context, msg Message, opts ...PublishOpt
|
||||
// set the topic
|
||||
topic := msg.Topic()
|
||||
|
||||
// get proxy
|
||||
if prx := os.Getenv("MICRO_PROXY"); len(prx) > 0 {
|
||||
options.Exchange = prx
|
||||
}
|
||||
|
||||
// get the exchange
|
||||
if len(options.Exchange) > 0 {
|
||||
topic = options.Exchange
|
||||
@@ -641,9 +644,12 @@ func (r *rpcClient) Publish(ctx context.Context, msg Message, opts ...PublishOpt
|
||||
body = b.Bytes()
|
||||
}
|
||||
|
||||
r.once.Do(func() {
|
||||
r.opts.Broker.Connect()
|
||||
})
|
||||
if !r.once.Load().(bool) {
|
||||
if err = r.opts.Broker.Connect(); err != nil {
|
||||
return errors.InternalServerError("go.micro.client", err.Error())
|
||||
}
|
||||
r.once.Store(true)
|
||||
}
|
||||
|
||||
return r.opts.Broker.Publish(topic, &broker.Message{
|
||||
Header: md,
|
||||
|
@@ -5,10 +5,10 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/micro/go-micro/client/selector"
|
||||
"github.com/micro/go-micro/errors"
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/registry/memory"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
"github.com/micro/go-micro/v2/errors"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/registry/memory"
|
||||
)
|
||||
|
||||
func newTestRegistry() registry.Registry {
|
||||
|
@@ -4,16 +4,16 @@ import (
|
||||
"bytes"
|
||||
errs "errors"
|
||||
|
||||
"github.com/micro/go-micro/codec"
|
||||
raw "github.com/micro/go-micro/codec/bytes"
|
||||
"github.com/micro/go-micro/codec/grpc"
|
||||
"github.com/micro/go-micro/codec/json"
|
||||
"github.com/micro/go-micro/codec/jsonrpc"
|
||||
"github.com/micro/go-micro/codec/proto"
|
||||
"github.com/micro/go-micro/codec/protorpc"
|
||||
"github.com/micro/go-micro/errors"
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/transport"
|
||||
"github.com/micro/go-micro/v2/codec"
|
||||
raw "github.com/micro/go-micro/v2/codec/bytes"
|
||||
"github.com/micro/go-micro/v2/codec/grpc"
|
||||
"github.com/micro/go-micro/v2/codec/json"
|
||||
"github.com/micro/go-micro/v2/codec/jsonrpc"
|
||||
"github.com/micro/go-micro/v2/codec/proto"
|
||||
"github.com/micro/go-micro/v2/codec/protorpc"
|
||||
"github.com/micro/go-micro/v2/errors"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/transport"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"github.com/micro/go-micro/codec"
|
||||
"github.com/micro/go-micro/v2/codec"
|
||||
)
|
||||
|
||||
type rpcRequest struct {
|
||||
|
@@ -1,8 +1,8 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"github.com/micro/go-micro/codec"
|
||||
"github.com/micro/go-micro/transport"
|
||||
"github.com/micro/go-micro/v2/codec"
|
||||
"github.com/micro/go-micro/v2/transport"
|
||||
)
|
||||
|
||||
type rpcResponse struct {
|
||||
|
@@ -5,7 +5,7 @@ import (
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/micro/go-micro/codec"
|
||||
"github.com/micro/go-micro/v2/codec"
|
||||
)
|
||||
|
||||
// Implements the streamer interface
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package selector
|
||||
|
||||
import (
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@@ -3,8 +3,8 @@ package selector
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/registry/cache"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/registry/cache"
|
||||
)
|
||||
|
||||
type registrySelector struct {
|
||||
|
@@ -3,7 +3,7 @@ package selector
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/micro/go-micro/registry/memory"
|
||||
"github.com/micro/go-micro/v2/registry/memory"
|
||||
)
|
||||
|
||||
func TestRegistrySelector(t *testing.T) {
|
||||
|
@@ -6,8 +6,8 @@ import (
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"github.com/micro/go-micro/client/selector"
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
)
|
||||
|
||||
type dnsSelector struct {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package selector
|
||||
|
||||
import (
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
)
|
||||
|
||||
// FilterEndpoint is an endpoint based Select Filter which will
|
||||
|
@@ -3,7 +3,7 @@ package selector
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
)
|
||||
|
||||
func TestFilterEndpoint(t *testing.T) {
|
||||
|
@@ -3,7 +3,7 @@ package selector
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
|
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/micro/go-micro/client/selector"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
)
|
||||
|
||||
// Set the registry cache ttl
|
||||
|
@@ -2,7 +2,7 @@
|
||||
package registry
|
||||
|
||||
import (
|
||||
"github.com/micro/go-micro/client/selector"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
)
|
||||
|
||||
// NewSelector returns a new registry selector
|
||||
|
@@ -7,11 +7,11 @@ import (
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/micro/go-micro/client"
|
||||
"github.com/micro/go-micro/client/selector"
|
||||
"github.com/micro/go-micro/registry"
|
||||
"github.com/micro/go-micro/router"
|
||||
pb "github.com/micro/go-micro/router/service/proto"
|
||||
"github.com/micro/go-micro/v2/client"
|
||||
"github.com/micro/go-micro/v2/client/selector"
|
||||
"github.com/micro/go-micro/v2/registry"
|
||||
"github.com/micro/go-micro/v2/router"
|
||||
pb "github.com/micro/go-micro/v2/router/service/proto"
|
||||
)
|
||||
|
||||
type routerSelector struct {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user