Compare commits

..

1170 Commits

Author SHA1 Message Date
dependabot[bot] 31135d4696 Bump github.com/docker/docker from 20.10.7+incompatible to 20.10.24+incompatible (#2625)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-26 02:22:47 +02:00
Coder 1478a8e46d fix(config/source/cli): mergo.Map error, src and dst must be of same … (#2628) 2023-04-26 02:21:08 +02:00
Mohamed MHAMDI ad8fca255b fix(config): fix file source watcher stop behavior when Stop is called (#2630)
Co-authored-by: Mohamed MHAMDI <mmhamdi@hubside.com>
2023-04-26 02:19:52 +02:00
Lukasz Raczylo a7522e7d6c fix: struct field alignment (#2632) 2023-04-26 02:16:34 +02:00
Asim Aslam 0f9b2f00c9 Update README.md 2023-04-12 11:09:56 +01:00
Asim Aslam 7fe95e8732 Update README.md 2023-04-12 11:09:40 +01:00
Asim Aslam d44ed328d1 Add Handle option (#2627) 2023-04-11 10:29:03 +01:00
Thomas Chandelle d392e72021 fix(api/handler): avoid zombie goroutine when connection unexpectedly closes (#2624) 2023-04-05 22:50:24 +02:00
dependabot[bot] 683e2729b4 Bump github.com/opencontainers/runc from 1.1.4 to 1.1.5 (#2623)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-30 20:19:21 +02:00
asim 6f8930926f gofmt 2023-03-22 16:42:54 +00:00
Asim Aslam 2117672933 Update FUNDING.yml 2023-03-21 20:51:42 +00:00
Asim Aslam d7e692b5d1 Update README.md 2023-03-21 15:19:07 +00:00
asim d949258b2f update the logo 2023-03-20 16:48:44 +00:00
fuyou d376656528 fix(sec): upgrade github.com/containerd/containerd to 1.6.18 (#2617)
* update github.com/containerd/containerd v1.4.3 to 1.6.18

* fix(sec): upgrade containerd

* fix(sec): go mod tidy

---------

Co-authored-by: Davincible <david.brouwer.99@gmail.com>
2023-03-07 17:28:22 +01:00
dependabot[bot] 415b3e3a2f Bump golang.org/x/net from 0.0.0-20210510120150-4163338589ed to 0.7.0 (#2615)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.0.0-20210510120150-4163338589ed to 0.7.0.
- [Release notes](https://github.com/golang/net/releases)
- [Commits](https://github.com/golang/net/commits/v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-07 17:11:10 +01:00
Hellis e337eb2c3d fix(api): add WithRegistry option for api (#2618) 2023-03-07 17:05:25 +01:00
dependabot[bot] 521e6b644c Bump golang.org/x/crypto from 0.0.0-20210513164829-c07d793c2f9a to 0.1.0 (#2619)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.0.0-20210513164829-c07d793c2f9a to 0.1.0.
- [Release notes](https://github.com/golang/crypto/releases)
- [Commits](https://github.com/golang/crypto/commits/v0.1.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-07 17:04:20 +01:00
Stanislav ad0b4f103d feat(errors): append errors use variadic arguments (#2606) 2023-01-03 12:58:03 +01:00
Davincible 68a6425ad8 fix(service): profile stop error scope 2022-11-16 05:07:41 +01:00
leoujz 0a91ba7b5d api gateway handing http request adds Content-Type application/x-www-form-urlencoded, and extract endpoints from path if no endpoint matched (#2592)
Co-authored-by: l <l@x>
2022-11-09 04:28:39 +01:00
645775992 a17eaf64da update gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b to 3.0.0 (#2589) 2022-11-04 12:06:13 +01:00
645775992 6df085fd6d update github.com/opencontainers/runc v0.1.1 to 1.1.2 (#2590) 2022-11-04 12:05:41 +01:00
David Brouwer 697ea1b21e Update README.md 2022-11-02 21:45:35 +01:00
JellyTony b442dbb56b fix: fix configuration version data competition (#2586)
Co-authored-by: JeffreyBool <zhanggaoyuan@mediatrack.cn>
2022-10-26 12:12:44 +02:00
Sagan Yaroslav b988a78bae fix: store table initialization (#2584) 2022-10-20 14:59:08 +02:00
David Brouwer a3980c2308 feat: add test framework & refactor RPC server (#2579)
Co-authored-by: Rene Jochum <rene@jochum.dev>
2022-10-20 13:00:50 +02:00
keepstep c25dee7c8a fix(registry/cache): do not watch when ttl=0 eg: some custom registry no s… (#2580)
Co-authored-by: keep <keep@pa.com>
2022-10-08 15:19:48 +02:00
Rene Jochum 24dfcef49a fix(transport/memory): Improve the memory transport, 4x speed (#2581) 2022-10-07 23:54:09 +02:00
Rene Jochum 065f9714e9 fix: easy lint fixes to api/ (#2567) 2022-10-01 10:50:11 +02:00
Rene Jochum 010b1d9f11 fix: linting issues (#2566) 2022-09-30 20:32:55 +02:00
David Brouwer 85c0b0b8eb fix: some linting issues (#2563) 2022-09-30 16:27:07 +02:00
David Brouwer 47e6a8d725 feat(CI): add linting and pretty test output (#2562) 2022-09-30 02:08:42 +02:00
Mohamed MHAMDI 1db36357d5 feat(logger): add logger option to all micro components (override DefaultLogger) closes #2556 (#2559)
Run tests / Test repo (push) Waiting to run
* feat(logger): add logger option to all components

* fix: refactor api/rpc.go

* fix: refactor api/stream.go

* fix: api/options.go comment

* fix(logger): do not use logger.Helper internally

* fix(logger): fix comments

* fix(logger): use level.Enabled method

* fix: rename mlogger to log

* fix: run go fmt

* fix: log level

* fix: factories

Co-authored-by: Mohamed MHAMDI <mmhamdi@hubside.com>
Co-authored-by: Davincible <david.brouwer.99@gmail.com>
2022-09-29 16:44:53 +02:00
David Brouwer 57a0ef5a0f docs: update README shields (#2558)
* docs: add badges to README.md

* docs: new discord badge

* docs: update discord badge

* docs: update discord badge

* docs: remove shield
2022-09-24 03:40:48 +02:00
Mohamed MHAMDI 39e00f11a8 feat(config): add withFs option to file source (#2557)
Co-authored-by: Mohamed MHAMDI <mmhamdi@hubside.com>
2022-09-24 02:46:18 +02:00
David Bereza 34b6434791 fix: prevent returning empty strings for list (#2553) 2022-09-06 20:03:23 +01:00
Asim Aslam a702a1b097 Update README.md 2022-08-17 10:02:52 +01:00
asim d32c8bd0eb move logo
Run tests / Test repo (push) Waiting to run
2022-08-17 09:50:32 +01:00
刘志铭 d7d8123bc7 Fix a problem with the Register Memory component (#2545) 2022-08-13 11:23:42 +01:00
David Bereza f40cfdda82 feat(sync): Add additional context option to sync (#2544) 2022-08-11 13:09:25 +08:00
Arvin 51250bf248 fix: Fix a logic judgment bug. (#2540)
Signed-off-by: Arvin <1458070668@qq.com>
2022-08-02 17:54:51 +01:00
Arvin 63a9b94820 support use of listen options (#2536)
* feat: support use of listen options

* style: Adjust the import order of packages.
2022-07-30 10:56:14 +01:00
Asim Aslam adcc1761d0 Update README.md 2022-07-24 06:39:24 +01:00
Asim Aslam cc53b5e7d7 Update README.md 2022-07-23 11:25:07 +01:00
asim 4d63d61c20 remove function
Run tests / Test repo (push) Waiting to run
2022-07-22 20:12:24 +01:00
asim 678c227061 remove deprecated function 2022-07-22 20:11:27 +01:00
asim ec847fa60c remove generate file 2022-07-22 20:10:06 +01:00
asim 616060876f remove file 2022-07-22 20:08:37 +01:00
asim 641be04fc0 remove plugins dir 2022-07-22 20:07:34 +01:00
Asim Aslam 28f36e8fd6 strip debug handler (#2532)
* strip debug handler

* fix tests
2022-07-22 20:03:27 +01:00
asim a8224e1c67 Merge branch 'master' of ssh://github.com/asim/go-micro 2022-07-22 10:22:58 +01:00
asim 38293f479a strip wrappers for trace/stats 2022-07-22 10:22:50 +01:00
Ak-Army 48eae3b968 Fix http transport panic (#2531)
* [fix] etcd config source prefix issue (#2389)

* http transport data race issue (#2436)

* [fix] #2431 http transport data race issue

* [feature] Ability to close connection while receiving.
Ability to send messages while receiving.
Icreased r channel limit to 100 to more fluently communication.
Do not dropp sent request if r channel is full.

* [fix] Read buff before reset it, when the connection is closed

Co-authored-by: Johnson C <chengqiaosheng@gmail.com>
Co-authored-by: Hunyadvári Péter <peter.hunyadvari@vcc.live>
2022-07-22 08:40:58 +01:00
Asim Aslam e28f5b97f6 Update README.md 2022-07-20 10:34:27 +01:00
Asim Aslam 140f90b354 Update README.md 2022-07-20 10:12:05 +01:00
Asim Aslam 467c8a34e3 Update README.md 2022-07-18 11:40:43 +01:00
Ak-Army 582e3f9310 Http transport stream (#2529)
* [fix] etcd config source prefix issue (#2389)

* http transport data race issue (#2436)

* [fix] #2431 http transport data race issue

* [feature] Ability to close connection while receiving.
Ability to send messages while receiving.
Icreased r channel limit to 100 to more fluently communication.
Do not dropp sent request if r channel is full.

Co-authored-by: Johnson C <chengqiaosheng@gmail.com>
Co-authored-by: Hunyadvári Péter <peter.hunyadvari@vcc.live>
2022-07-15 11:04:41 +01:00
Asim Aslam 98375c7ae5 api honours naming convention of other interfaces 2022-07-11 15:49:30 +01:00
Asim Aslam 7e903d80b6 Update README.md 2022-07-11 15:41:03 +01:00
Asim Aslam 6cf2b02f0f move cmd to util (#2527)
* move cmd to util

* go fmt
2022-07-11 14:37:34 +01:00
Asim Aslam b36949f2c1 Update README.md 2022-07-11 13:08:54 +01:00
Asim Aslam 995abaaea6 go mod tidy 2022-07-11 09:51:48 +01:00
Asim Aslam 97d59fbf78 remove generator and move to github.com/go-micro 2022-07-11 09:11:59 +01:00
Asim Aslam ff1312438c Update README.md 2022-07-07 12:49:56 +01:00
Asim Aslam edaa353826 strip body from gateway 2022-07-04 10:15:14 +01:00
Asim Aslam 48d6650f28 rename api to gateway 2022-07-02 14:42:12 +01:00
Asim Aslam 3381a9f3db Remove body from endpoint 2022-07-02 14:38:58 +01:00
Asim Aslam 63d1f9de4a minor changes 2022-07-02 14:25:21 +01:00
Asim Aslam e313863a2a make router configurable in api 2022-07-02 14:15:02 +01:00
Asim Aslam 73dc3723c7 Update api.go 2022-07-02 13:50:45 +01:00
Asim Aslam 667ee9b85e rename field to Versions 2022-07-02 12:35:57 +01:00
Asim Aslam b6b866c0b2 api package (#2522)
* api gateway

* add comment
2022-07-02 12:11:59 +01:00
Johnson C 28298a30e4 feat: remove plugins and related docs (#2521)
* feat: redis implementation of cache

* Revert "feat: redis implementation of cache"

This reverts commit 4b3f25c1fc494d934613992d8a762024fafad7b6.

* feat: remove plugins
2022-07-02 10:25:57 +01:00
Johnson C b884a68347 feat: update out of date docs (#2520)
Run tests / Test repo (push) Waiting to run
* feat: redis implementation of cache

* Revert "feat: redis implementation of cache"

This reverts commit 4b3f25c1fc494d934613992d8a762024fafad7b6.

* feat: update out of date docs
2022-07-02 08:44:32 +01:00
Asim Aslam bfcdfc3c7f remove m3o
Run tests / Test repo (push) Waiting to run
2022-07-01 11:37:13 +01:00
Asim Aslam 392610022a Update README.md 2022-07-01 08:38:57 +01:00
Asim Aslam 34a51c9f29 Update README.md 2022-07-01 08:34:20 +01:00
Asim Aslam a5fb3fab66 Update README.md 2022-07-01 08:33:53 +01:00
JellyTony 96576a612a feat(web): add start and stop functions to the web (#2519) 2022-07-01 08:06:27 +01:00
Thomas Chandelle 87c96bc4d0 Correctly check error on redis command XTRIM (#2518)
Also:
 - add comment about version requirement
 - move minID to var for code readability
2022-06-30 18:24:27 +08:00
JellyTony 65a2e4ed02 fix(registry): fix watch services only first time (#2517) 2022-06-29 08:49:22 +01:00
Abdul Hadi 9960cd1d36 typo siza #2429 (#2515) 2022-06-24 19:18:47 +01:00
David Brouwer 107bd74187 fix: allow event subscribers to use pointers (#2514)
When a subscriber would use a pointer as event type, panics would occur.
2022-06-22 09:01:13 +08:00
Johnson C 7a6a2b6373 feat: redis implementation of cache (#2513)
* feat: redis implementation of cache

* Revert "feat: redis implementation of cache"

This reverts commit 4b3f25c1fc494d934613992d8a762024fafad7b6.

* feat: redis implementation of cache
2022-06-21 20:05:00 +01:00
Asim Aslam cf51ddeb26 Update README.md 2022-05-30 08:50:02 +01:00
Asim Aslam 13b76331ec Update README.md
Run tests / Test repo (push) Waiting to run
2022-05-11 09:55:41 +01:00
Asim Aslam de0b456b46 Update README.md 2022-05-10 06:59:08 +01:00
yulian 072547201c remove unused variable in loop (#2495) 2022-05-03 11:06:13 +08:00
bosima 8293988499 fix: consume and publish blocked after rabbitmq reconnecting (#2492)
* Support direct generation of grpc method when package and service names of proto files are different.

* fix req.Interface() return nil.

* Get rid of dependence on 'Micro-Topic'

* Revert "Get rid of dependence on 'Micro-Topic'"

This reverts commit 3ff69443364d39f5fda3a32fc2249826e2d207dd.

* Revert "fix req.Interface() return nil."

This reverts commit 90a1b34195e07772fa6f2074e1cf22237ac2a87f.

* Revert "Revert "fix req.Interface() return nil.""

This reverts commit e64737b7da8d1767c4456881f6730f1c196cea60.

* Revert "Revert "Get rid of dependence on 'Micro-Topic'""

This reverts commit 141bb0a557c81cb6d1c651b085b3e65483d5e681.

* fix: consume and publish blocked after reconnecting

Co-authored-by: maxinglun <maxinglun@zhijiaxing.net>
2022-04-28 17:55:06 +08:00
Asim Aslam 367771923c Update README.md 2022-04-19 15:47:45 +01:00
Asim Aslam 4ca75f3ab3 Update README.md 2022-04-19 15:47:31 +01:00
Asim Aslam 4a7c16419e Update README.md 2022-04-19 15:31:23 +01:00
Asim Aslam 1d396bdd64 Update README.md 2022-04-19 15:31:11 +01:00
Sergey Galkin ca807e36c5 option to disable file watcher (#2485)
Co-authored-by: Sergey Galkin <v.sergey.galkin@reddit.com>
2022-04-18 19:30:14 +01:00
Asim Aslam cce02927e7 Update README.md 2022-04-18 19:20:45 +01:00
Wang 034ba9a0de typo fix; (#2480) 2022-04-15 09:55:30 +08:00
bosima 1919048c8f Support direct generation of grpc method (#2474)
* Support direct generation of grpc method when package and service names of proto files are different.
* fix req.Interface() return nil.
2022-04-10 22:12:39 +08:00
Asim Aslam 62c2981baf remove cli 2022-04-07 11:46:07 +01:00
Asim Aslam efa2c4f2d2 remove dashboard 2022-04-07 11:45:58 +01:00
Asim Aslam 27b98c450e Remove examples 2022-04-07 11:45:39 +01:00
Asim Aslam e8604f065c remove services 2022-04-07 11:45:22 +01:00
Asim Aslam aaca7c27da Update README.md 2022-04-07 11:44:47 +01:00
Asim Aslam 664ee31b1a Update README.md 2022-04-07 08:20:57 +01:00
Wang 6dedee5d8c Add header suppor for Kafka broker plugin; (#2470) 2022-04-04 19:54:19 +01:00
Wang d1806e2883 Fix codec/bytes (#2466)
* Update marshaler.go

Byes codec always return error "invalid message" now.

* Update go.mod

Update package name

* Update go.mod
2022-04-02 18:11:12 +01:00
Morya 1f086a3002 fix https://github.com/asim/go-micro/issues/2344 (#2462)
fix https://github.com/asim/go-micro/issues/2344
2022-04-01 07:10:51 +01:00
Muhammad Iqbal Alaydrus 73eda3346d Add Wait option support for sync/etcd plugins (#2459)
* Add Wait support for sync/etcd plugins

* Use ErrLockTimeout if context deadline exceeded
2022-03-25 10:28:19 +08:00
Chris Moran c6d352c832 #2453 Fix with associated test update (#2454) 2022-03-17 10:22:05 +08:00
baerwang 356448017f style:arrays pre-allocation (#2449) 2022-03-14 14:03:14 +08:00
dependabot[bot] d6a74c1a8e Bump github.com/nats-io/nats-server/v2 in /plugins/events/natsjs (#2447)
Bumps [github.com/nats-io/nats-server/v2](https://github.com/nats-io/nats-server) from 2.6.2 to 2.7.4.
- [Release notes](https://github.com/nats-io/nats-server/releases)
- [Changelog](https://github.com/nats-io/nats-server/blob/main/.goreleaser.yml)
- [Commits](https://github.com/nats-io/nats-server/compare/v2.6.2...v2.7.4)

---
updated-dependencies:
- dependency-name: github.com/nats-io/nats-server/v2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-14 12:02:12 +08:00
Willy Kloucek e5a35d38f9 fix natsjs syntax error, remove TODOs and enable tests (#2446) 2022-03-11 16:03:35 +08:00
Willy Kloucek a2f6fac852 add NATS JetStream events plugin (#2433)
* add NATS JetStream plugin

* add notes about de-duplication and inprogress call

* fix typo
2022-03-04 14:53:15 +00:00
Ak-Army dca3a3b553 [fix] http transport deadlock (#2441)
Co-authored-by: Hunyadvári Péter <peter.hunyadvari@vcc.live>
2022-02-24 09:32:09 +00:00
AlkaidChen 4154ed6a80 add tls option for sync etcd plugin (#2440) 2022-02-24 17:07:14 +08:00
Chris Moran 69b4b5d1c6 Support for -micro_out=module=<module_prefix> for protoc-gen-micro (#2435) 2022-02-23 13:14:50 +08:00
Asim Aslam d47c2d984b add new services 2022-02-16 08:43:36 +00:00
Asim Aslam 91cfd18373 Update README.md 2022-02-16 08:35:22 +00:00
Asim Aslam 9e0be6c85d add service updates (#2418)
Run tests / Test repo (push) Waiting to run
2022-01-18 15:27:36 +00:00
Asim Aslam 23f1de80c5 Update README.md 2022-01-17 13:35:01 +00:00
Asim Aslam 6bc97c16ee Update README.md 2022-01-17 13:34:30 +00:00
Asim Aslam a612e09a34 Add files via upload 2022-01-15 20:26:27 +00:00
Asim Aslam 1e2d197c7d default the content type to json (#2412) 2022-01-11 13:36:20 +00:00
Asim Aslam 3a999a0db6 Add files via upload 2022-01-11 12:07:54 +00:00
Asim Aslam b8c2eb2b28 Update README.md 2022-01-11 08:35:55 +00:00
Asim Aslam 6f15174a2f Update README.md 2022-01-11 08:35:16 +00:00
Asim Aslam 748fb39cac Add files via upload 2022-01-11 08:34:58 +00:00
simon 5f2251cfad Add Kafka asynchronous send support (#2409)
* Add Kafka asynchronous send support

* Add Kafka asynchronous send support

* Upgrade sarama to 1.30.1

* Example
2022-01-09 14:12:10 +00:00
Amir Khazaie ef7528ebdb use read lock and unlock instead of write ones (#2410)
Co-authored-by: Amir Khazaie <a.khazaie@digikala.com>
2022-01-09 10:20:08 +00:00
Asim Aslam 696a0ba714 Merge branch 'master' of ssh://github.com/asim/go-micro 2022-01-03 11:21:29 +00:00
Asim Aslam 267da35259 move the api client 2022-01-03 11:21:20 +00:00
Asim Aslam d152870bdb Update client_test.go 2021-12-31 12:39:12 +00:00
Asim Aslam da41ab146e switch services client 2021-12-31 10:11:49 +00:00
Asim Aslam 757d0fe343 fix client 2021-12-30 09:47:40 +00:00
Asim Aslam c8d94c44f0 remove the client 2021-12-30 09:42:08 +00:00
Asim Aslam 5fa6e89f4f fix go mod 2021-12-30 09:35:21 +00:00
Asim Aslam 85f1c44000 Delete go.sum 2021-12-30 08:58:45 +00:00
Asim Aslam 3ba69f11ff Delete go.mod 2021-12-30 08:58:34 +00:00
Asim Aslam af5e70a1d6 add service interfaces 2021-12-30 08:44:34 +00:00
Johnson C 5fe884e59f [FEATURE] add changelog (#2400)
change logs for release history
2021-12-29 11:01:40 +08:00
isfk 415016c6e4 nats config plugin (#2397) 2021-12-28 11:27:36 +08:00
Asim Aslam e0de23c546 Update and rename m3o.go to services.go 2021-12-24 11:43:20 +00:00
Asim Aslam 7af0eb4b7a Update services/ (#2392) 2021-12-21 13:18:29 +00:00
isfk 8e52761edb fix context value nil (#2391) 2021-12-20 16:31:48 +08:00
Johnson C 37de747d19 [fix] nats deregister issue (#2384)
Run tests / Test repo (push) Waiting to run
2021-12-10 19:32:21 +08:00
Johnson C a40f6e8fae [fix] fixing f.IsExported undefined issue (#2382)
IsExported needs go1.17, replace with PkgPath
2021-12-07 17:30:48 +08:00
Johnson C b00c8368b9 [feat] dashboard update (#2381)
* [feature] dashboard update
2021-12-07 10:42:31 +08:00
Ak-Army 97f169c424 fix http_transport Recv and Close race condition on buff (#2374)
fix rpc_stream panic override with the "Unlock of unlocked RWMutex" panic

Co-authored-by: Hunyadvári Péter <peter.hunyadvari@vcc.live>
2021-12-05 11:56:17 +00:00
Ak-Army 81244a41f1 Extend client mock with ability to test publish, and a few useful method like SetResponse and SetSubscriber (#2375)
Co-authored-by: Hunyadvári Péter <peter.hunyadvari@vcc.live>
2021-12-05 11:55:54 +00:00
JeffreyBool 229b369702 [fix] update protoc-gen-micro install doc 2021-12-04 12:52:02 +08:00
Johnson C c0e0b2b225 [FEATURE] dashboard support publish messages (#2373)
* [feature] dashboard

* [feat] support publish message
2021-12-02 13:15:38 +08:00
Johnson C 1e4dd94b71 [fix] zookeeper registry delete event (#2372)
* [fix] #2358 zookeeper delete event
2021-12-01 16:26:31 +08:00
zhaoyang b25d744f5c feat: delete redundant lines (#2364) 2021-11-24 17:41:54 +00:00
zhaoyang 685f9979a1 feat: modify the dependencies urls (#2363) 2021-11-24 16:43:05 +00:00
Asim Aslam 6fc5e45626 Update README.md 2021-11-24 07:32:51 +00:00
Asim Aslam 2c6515152a Update load.go 2021-11-24 07:32:20 +00:00
Johnson C 70d2bd8a6b [feature] dashboard (#2361) 2021-11-24 11:27:23 +08:00
Johnson C 90b3e4af0b [fix] ignore unexported field (#2354)
ignore unexported field when register endpoints
2021-11-18 17:07:00 +08:00
Niek den Breeje 4f1a571704 Fix Micro CLI's proto comments (#2353) 2021-11-18 06:10:43 +01:00
陈杨文 799b8d6a65 upgrade to go 1.17 (#2346)
Run tests / Test repo (push) Waiting to run
2021-11-11 14:03:34 +00:00
Asim Aslam 8e312801a1 Update README.md 2021-11-08 09:03:37 +00:00
Asim Aslam 335c4e54a1 Merge branch 'master' of ssh://github.com/asim/go-micro 2021-11-08 09:01:56 +00:00
Asim Aslam e6d17257b0 add nats and redis events plugins 2021-11-08 08:59:14 +00:00
Asim Aslam 0c2041e439 add events package (#2341)
* add events package

* update go version
2021-11-08 08:52:39 +00:00
Johnson C c5be9f560c fix(#2333): etcd grpc marshal issue (#2334)
make protocodec compatible with legacy proto message type
2021-11-03 10:58:05 +08:00
Asim Aslam 62b985f49c Update README.md 2021-11-01 21:44:52 +00:00
Asim Aslam 2b9a6f9aeb flatten cli (#2332)
Run tests / Test repo (push) Waiting to run
2021-11-01 14:34:09 +00:00
Asim Aslam 3c70d23a1d m3o client changed 2021-11-01 11:00:21 +00:00
Asim Aslam adaa98e6cf use vanity url for cli command 2021-11-01 09:00:14 +00:00
无相 ed90a65783 fix broker nsq plugin nil pointer error (#2329)
Co-authored-by: longhaoteng <longhaoteng@kingsoft.com>
2021-11-01 08:47:22 +00:00
无相 268278c53e fix config json slice parsing (#2330)
Co-authored-by: longhaoteng <longhaoteng@kingsoft.com>
2021-11-01 08:47:00 +00:00
Benjamin 5d5aee1f08 replace ioutil with io and os (#2327)
set the go version to 1.16 in pr.yml and tests.yml, so as to be consistent with the version in go.mod.
2021-10-30 19:24:40 +01:00
Johnson C ed690ed838 fixing #2308 (#2326)
IPV6 too many colons in address
net.SplitHostPort need ipv6 address in [host]:port format
2021-10-28 17:03:48 +08:00
Niek den Breeje e155029a4b Fix Micro CLI by removing replace line in go.mod 2021-10-27 17:40:26 +02:00
Asim Aslam 880d751df4 Update README.md 2021-10-27 16:34:55 +01:00
Niek den Breeje a3202b00ee Rename gomu to micro (#2325)
* Rename Gomu to Micro

* docs: Remove license reference in CLI's README
2021-10-27 16:31:29 +01:00
Asim Aslam efcda9a48c Update README.md 2021-10-26 20:17:07 +01:00
Asim Aslam 2c73c7fcf3 strip protoc-gen-micro go mod 2021-10-26 19:46:25 +01:00
Johnson C d2a51d05c4 [feature] stream CloseSend (#2323)
* support stream CloseSend

* move CloseSend into Closer
2021-10-26 15:07:08 +01:00
Johnson C af3cfa0a4c remove unnecessary dependencies between plugins
remove unnecessary dependencies between plugins
upgrade go-micro.dev/v4 to v4.2.1
2021-10-23 16:20:42 +08:00
Johnson C f96b48dad9 1. use default memory registry in grpc plugins (#2317)
2. try fixing grpc plugin failed to get issue
use v4.0.0-v4.0.0-00010101000000-000000000000 instead of specific version
3. kafka panic on disconnect
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x18 pc=0x1266c50]

goroutine 31 [running]:
github.com/asim/go-micro/plugins/broker/kafka/v3.(*kBroker).Disconnect(0xc0002400c0)
        C:/Workshop/Go/pkg/mod/github.com/asim/go-micro/plugins/broker/kafka/v3@v3.7.0/kafka.go:130 +0xd0
github.com/asim/go-micro/plugins/server/grpc/v3.(*grpcServer).Start.func2()
        C:/Workshop/Go/pkg/mod/github.com/asim/go-micro/plugins/server/grpc/v3@v3.0.0-20210712061837-0532fd9de8ae/grpc.go:998 +0xc8d
created by github.com/asim/go-micro/plugins/server/grpc/v3.(*grpcServer).Start
        C:/Workshop/Go/pkg/mod/github.com/asim/go-micro/plugins/server/grpc/v3@v3.0.0-20210712061837-0532fd9de8ae/grpc.go:917 +0xcaf
exit status 2
2021-10-22 22:30:28 +08:00
Niek den Breeje 9edc569e68 Add update rule to Makefile (#2315)
I realized that when writing `require go-micro.dev/v4 v4.1.0` in the
`go.mod` file, `go mod tidy` will install that exact version of
`go-micro.dev/v4`. As of right now, v4.1.0 is an outdated version, and
preferably we shouldn't be updating gomu's Go Modules template everytime
a new release is tagged, but still want gomu users to generate projects
using the latest Go Micro version.

In an attempt to solve this problem, I'm opting to add a new Makefile
rule for new projects generated by gomu, `update` that runs `go get -u`.
This aggressively updates any dependencies your Go Modules project may
have.  `go mod tidy` is then able to prune the `go.mod` and `go.sum`
files by removing the unnecessary checksums and transitive dependencies
(e.g. `// indirect`), that were added to by go get -u due to newer
semver available.

Put one and one together and you get two. In addition to adding an
`update` rule to the Makefile generated for new projects by gomu, I'm
also updating the proto and client comments printed when new projects
have been generated to promote the `update` rule.

References:

- https://stackoverflow.com/questions/67201708/go-update-all-modules
2021-10-19 21:12:42 +02:00
Johnson C 29fefbad4e Plugins (#2311)
* release plugins

* add window plugins release bat script

Co-authored-by: Johnson C <johnson.cheng@scenestek.com>
2021-10-16 05:56:51 +01:00
Asim Aslam 9f4770e7fd fix generation (#2312)
Run tests / Test repo (push) Waiting to run
2021-10-15 14:03:40 +01:00
Asim Aslam e7dbda689e fix gomu
Run tests / Test repo (push) Waiting to run
2021-10-14 08:09:21 +01:00
Asim Aslam 00f461141a fix examples go mod
Run tests / Test repo (push) Waiting to run
2021-10-13 13:37:24 +01:00
Asim Aslam 8cad88edae update go sums 2021-10-13 13:35:17 +01:00
Asim Aslam 62801c3d68 update 2021-10-13 13:31:23 +01:00
Asim Aslam 7136c61dbd rename to go-micro.dev 2021-10-13 09:52:05 +01:00
Asim Aslam a87f9a808c move to go-micro.dev 2021-10-13 09:44:24 +01:00
Asim Aslam ca594b922c Merge branch 'master' of ssh://github.com/asim/go-micro 2021-10-13 09:42:31 +01:00
Asim Aslam aa4a87ed9a move to v4 in protoc-gen-micro 2021-10-13 09:42:21 +01:00
justcy 690facdb5c update model template (#2307) 2021-10-13 08:07:48 +01:00
Asim Aslam f63e46a7d1 use 4.1.0 2021-10-12 13:22:08 +01:00
Asim Aslam 1cd7cfaa6c go-micro.dev/v4 (#2305)
Run tests / Test repo (push) Waiting to run
2021-10-12 12:55:53 +01:00
jxlwqq d9a6faeb7a Add latest version (#2303)
Run tests / Test repo (push) Waiting to run
2021-10-11 15:15:42 +01:00
Asim Aslam 4cb6168780 Update README.md 2021-10-11 09:21:06 +01:00
Asim Aslam b8d7f87d17 remove file 2021-10-11 09:19:20 +01:00
Asim Aslam b2e17a89e5 rename file 2021-10-11 09:19:01 +01:00
Asim Aslam 4ae2528cbe add m3o services (#2301)
* add m3o services

* update readme
2021-10-11 09:18:28 +01:00
Asim Aslam 043a82bce2 Update README.md 2021-10-11 08:38:31 +01:00
Asim Aslam 99e0b182b7 Update README.md 2021-10-11 08:38:07 +01:00
Asim Aslam ab1b10f13d Update README.md 2021-10-11 08:37:38 +01:00
jxlwqq 86eabf4a4c Use go install (#2300)
go get: installing executables with 'go get' in module mode is deprecated.
        To adjust and download dependencies of the current module, use 'go get -d'.
        To install using requirements of the current module, use 'go install'.
        To install ignoring the current module, use 'go install' with a version,
        like 'go install example.com/cmd@latest'.
        For more information, see https://golang.org/doc/go-get-install-deprecation
        or run 'go help get' or 'go help install'.
2021-10-11 06:32:13 +01:00
Qalifah a99a1e9356 add MultiError type (#2297) 2021-10-06 17:55:14 +01:00
Asim Aslam 2ef523a7eb Delete index.html 2021-10-02 13:13:22 +01:00
Asim Aslam a1da40d9aa Delete CNAME 2021-10-01 20:23:38 +01:00
Defoo Li a315fc2dda Fix missing content type (#2289) 2021-09-30 12:15:09 +01:00
Johnson C 6dc25053ea Errors (#2290)
* add errors.As

convert target err to *Error, return false if err don't match *Error

* update errors.As to (*Error, bool)

* fixing FromError panic issue when err is nil
2021-09-30 07:45:10 +01:00
Qiu Yu 4612baa7f8 zap plugin: allow injecting zap logger options (#2287)
Though some of the Zap logger option can be customized through
plugins/logger/zap.Options, this change allows go.uber.org/zap.Option be
be injected directly for deeper customization.
2021-09-29 07:12:16 +01:00
Johnson C 44ecd6a457 Hystrix filter (#2286)
* support hystrix filter

* filter function should return true of false
2021-09-28 11:23:04 +01:00
Asim Aslam 8c39b1e120 Update index.html 2021-09-24 09:10:04 +01:00
Asim Aslam 12eff1cc60 go fmt 2021-09-24 09:08:39 +01:00
Asim Aslam 9deb715ebb Update go.mod 2021-09-24 09:08:16 +01:00
Arsen 3b60db0dcd logger helper: add "inject" method, to make a pair with "extract" (#2283) 2021-09-23 16:48:08 +01:00
Asim Aslam af22cbb108 Update README.md 2021-09-22 14:48:20 +01:00
Asim Aslam 9d7131a512 Update README.md 2021-09-22 14:43:37 +01:00
Asim Aslam bca9ab165d Update README.md 2021-09-22 14:42:17 +01:00
Asim Aslam d111f96993 Update README.md 2021-09-22 14:41:29 +01:00
Asim Aslam 2f223c276c Update README.md 2021-09-22 14:32:06 +01:00
Asim Aslam 33acb4a956 update readme 2021-09-22 14:31:21 +01:00
Asim Aslam b515785637 add services dir 2021-09-22 14:30:40 +01:00
Asim Aslam 3dcdcdad32 Update README.md 2021-09-22 13:37:07 +01:00
Arsen 916ed6b8ee logger: caller's skip correction (#2280) 2021-09-22 09:01:03 +01:00
gregkv b8fbe87e1f Use context to log "panic recovered" errors in grpc-server plugin (#2278) 2021-09-20 10:50:13 +01:00
Asim Aslam cb3db7dd83 Update options.go 2021-09-19 17:22:28 +01:00
simon 066ce5045b Command Option add NewConfig,NewProfile func (#2276)
* Add grpc,memory,quic transport automatically discover

* Add grpc,memory,quic transport automatically discover

* Add jwt auth automatically discover

* Add jwt auth automatically discover

* Add config command option automatically discover

* Add AuthCall wrapper func

* Add NewConfig func

* Add NewProfile func
2021-09-19 17:21:55 +01:00
Asim Aslam a65932ff82 Create CNAME 2021-09-19 15:10:47 +01:00
Asim Aslam 5496086916 Create index.html 2021-09-19 14:44:03 +01:00
Kurisu_Amatist efd4ef0e62 fix(cache): only watch calling service in registry (#2273) 2021-09-19 10:40:21 +01:00
gregkv 00d819a199 Remove fields map from Helper, add Extract method and fix for defaultLogger.Fields (#2274) 2021-09-19 10:40:09 +01:00
helloword ad532522ea Config CORS (#2270)
* Added cors.config for CORS

* Added cors.config for CORS

* Added cors.config for CORS

Co-authored-by: 于海洋 <yhy@iothinking.com>
2021-09-17 10:17:12 +01:00
Christoffer Åström 4c7d2e28eb test(api): fix randomly failing rpc test (#2268) 2021-09-13 21:56:36 +01:00
Branden Horiuchi d78d35078c Consul sync plugin (#2267)
* adding consul sync provider

* adding logging options

Co-authored-by: Branden Horiuchi <Branden.Horiuchi@blackline.com>
2021-09-13 19:08:05 +01:00
Johnson C 22409c8ff3 support hystrix filter (#2265) 2021-09-13 09:23:26 +01:00
binbin.zhang 6c3a5c161f upgrade nacos sdk version (#2264)
Co-authored-by: binbin <binbin@didiglobal.com>
2021-09-12 22:16:46 +01:00
Niek den Breeje fa27250605 Add generate kubernetes command (#2261) 2021-09-10 18:56:51 +01:00
Niek den Breeje ac21bb5b19 Document Gomu's generator package (#2262) 2021-09-10 18:48:09 +01:00
Niek den Breeje 5b8d22a463 Add Kubernetes flag to new command (#2263)
To remain consistent with the Gomu's generate command, we add a
Kubernetes flag to Gomu's new command as well.
2021-09-10 18:47:55 +01:00
Niek den Breeje 56d5143557 Document Gomu's generate command (#2260) 2021-09-10 14:30:46 +01:00
Niek den Breeje 5772697752 Make generator package a first class citizen (#2259)
There's really no point in having the `generator` be embedded in a
`file` package so we remove the `file` package and make the `generator`
package a first class citizen instead.
2021-09-10 13:31:52 +01:00
Niek den Breeje e23006b1a5 Generate Gomu files after the fact (#2258)
* Move file generation to new package

* Use text/template instead of html/template

* Make config variables more consistent

* Combine generate files and print comments there

* Add gomu generate command

* Refactor project templating to file library

* Determine client earlier
2021-09-10 13:20:57 +01:00
Niek den Breeje 01b7b4409b Fix generating Dockerfile with Gomu (#2254)
Somehow I didn't test this and managed to forget to properly close a
template control structure. This change fixes that.
2021-09-08 14:43:52 +01:00
Niek den Breeje 0dd6afe128 Optimize Dockerfile generated by Gomu (#2253)
This change prevents having to rebuild the entire Docker image when your
source code changes.
2021-09-08 12:50:30 +01:00
Niek den Breeje a36f52c6d2 Fix Gomu's call response (#2251)
Gomu expects a `map[string]string` type response back, but this isn't
always the case. When Gomu calls a service endpoint that responds with,
let's say, a key where its value is a map or a list, Gomu would be
unable to decode that response. By expecting a `map[string]interface{}`
type response, Gomu is able to decode those responses as well.
2021-09-08 08:30:53 +01:00
simon 440aa4a1ce Add AuthCall wrapper func (#2250)
* Add grpc,memory,quic transport automatically discover

* Add grpc,memory,quic transport automatically discover

* Add jwt auth automatically discover

* Add jwt auth automatically discover

* Add config command option automatically discover

* Add AuthCall wrapper func
2021-09-07 07:13:56 +01:00
Niek den Breeje f77c91b7ae Simplify gomu cmd registering (#2249)
* Use internal runtime package for gomu run

This change refactors the `gomu run` command to use Go Micro's internal
runtime package in order to run services. Not only does this clean up
duplicate functionality between Go Micro and Gomu, but also adds the
feature to Gomu to run remote projects. For example, the following
command pulls in a remote project and runs it locally.

```bash
gomu run github.com/auditemarlow/helloworld
```

The `gomu run` command remains backwards compatible. By invoking `gomu
run` in a Go Micro project directory, Gomu will simply run that project.

* Simplify Gomu's command registering

By leveraging Go's `init()` function, we can simplify registering
commands just a tad.
2021-09-06 14:12:27 +01:00
Niek den Breeje a58b8883f8 Use internal runtime package for gomu run (#2248)
This change refactors the `gomu run` command to use Go Micro's internal
runtime package in order to run services. Not only does this clean up
duplicate functionality between Go Micro and Gomu, but also adds the
feature to Gomu to run remote projects. For example, the following
command pulls in a remote project and runs it locally.

```bash
gomu run github.com/auditemarlow/helloworld
```

The `gomu run` command remains backwards compatible. By invoking `gomu
run` in a Go Micro project directory, Gomu will simply run that project.
2021-09-06 14:01:29 +01:00
simon 270d910b73 Add config command option automatically discover (#2246)
* Add grpc,memory,quic transport automatically discover

* Add grpc,memory,quic transport automatically discover

* Add jwt auth automatically discover

* Add jwt auth automatically discover

* Add config command option automatically discover
2021-09-04 07:17:21 +01:00
Niek den Breeje 77bf39f2cd Fix client gRPC plugin (#2245)
The helloworld examples found in the `google.golang.org/grpc/examples`
package were imported multiple times as different versions, resulting in
package conflicts. By running `go mod tidy`, these conflicts are
resolved and the gRPC client plugin can now be imported again.
2021-09-03 14:16:56 +01:00
Niek den Breeje c45073a308 Fix Skaffold pipelines for client projects (#2244)
* Update greeter references to helloworld

* Add new client command

With this change, Gomu users will be able to generate template projects
for clients to services. Additionally vendor support has been built in
so Gomu users can now generate projects using fully qualified package
names, for example:

```bash
gomu new service github.com/auditemarlow/helloworld
```

This will create a new service project `helloworld` with its module name
already set to `github.com/auditemarlow/helloworld`. Likewise, Gomu
users can then generate client projects in the same manner:

```bash
gomu new client github.com/auditemarlow/helloworld
```

This will create a `helloworld-client` project that uses the protobufs
found in the `github.com/auditemarlow/helloworld` service. This removes
at least some strain in configuring these module dependencies yourself;
you can just scaffold them outright from the start.

Although the default client project is highly opinionated, it works
straight out of the box and has Skaffold in mind. Gomu users should be
able to get going in a matter of seconds.

* Update README

* Fix Skaffold pipeline for generated client projects
2021-09-03 13:26:34 +01:00
Niek den Breeje 86de031adc [WIP] Add new client cmd (#2243)
* Update greeter references to helloworld

* Add new client command

With this change, Gomu users will be able to generate template projects
for clients to services. Additionally vendor support has been built in
so Gomu users can now generate projects using fully qualified package
names, for example:

```bash
gomu new service github.com/auditemarlow/helloworld
```

This will create a new service project `helloworld` with its module name
already set to `github.com/auditemarlow/helloworld`. Likewise, Gomu
users can then generate client projects in the same manner:

```bash
gomu new client github.com/auditemarlow/helloworld
```

This will create a `helloworld-client` project that uses the protobufs
found in the `github.com/auditemarlow/helloworld` service. This removes
at least some strain in configuring these module dependencies yourself;
you can just scaffold them outright from the start.

Although the default client project is highly opinionated, it works
straight out of the box and has Skaffold in mind. Gomu users should be
able to get going in a matter of seconds.

* Update README
2021-09-03 12:33:10 +01:00
simon 80dbe51077 Add jwt auth automatically discover (#2242)
* Add grpc,memory,quic transport automatically discover

* Add grpc,memory,quic transport automatically discover

* Add jwt auth automatically discover

* Add jwt auth automatically discover
2021-09-03 07:49:49 +01:00
Johnson C f444dadd50 fixing #2235 win10 install failed issue (#2239) 2021-09-03 07:49:39 +01:00
Christoffer Åström e080791787 chore(gomu): tweak makefile template (#2238) 2021-09-02 18:24:28 +01:00
simon a159598f36 Add grpc,memory,quic transport automatically discover (#2237)
* Add grpc,memory,quic transport automatically discover

* Add grpc,memory,quic transport automatically discover
2021-09-02 18:10:24 +01:00
Niek den Breeje 993e2f55bd Add Kubernetes resources (#2236)
* Refact new command implementation

Everytime I want to add or modify files in the new command, I will have
to do so in 2 places. This change will consolidate functionality so
there's only a single place to modify.

* Move Kubernetes resources to its own file

* Add Kubernetes resources
2021-09-02 13:35:00 +01:00
Niek den Breeje ed9053ed94 Add cache example (#2232) 2021-09-01 10:08:43 +01:00
Niek den Breeje 05a299b76c Add simple in-memory cache (#2231)
* Add simple in-memory cache

* Support configuring cache expiration duration

* Support preinitializing cache with items

* Register cache
2021-08-31 15:31:16 +01:00
Asim Aslam dd0a7746ff update the gomu gomod 2021-08-31 15:19:45 +01:00
Asim Aslam 088ccb5001 Update README.md 2021-08-31 09:27:36 +01:00
Niek den Breeje 4363678e48 Exit when help flag is provided on service run (#2225) 2021-08-31 09:13:35 +01:00
Niek den Breeje 9a77c06b44 Move from micro/cli/v2 to urfave/cli/v2 (#2224)
* Use urfave/cli/v2 instead of micro/cli/v2

Wherever possible we may want to eliminate the use of github.com/micro
imports.

* Fix broken cli test
2021-08-31 09:05:08 +01:00
Niek den Breeje 78bea87690 Add gomu CLI tool (#2223) 2021-08-30 15:48:57 +01:00
Johnson C 49eccbc85a fixing proto3 optional unsupported error (#2213)
add supported features
2021-08-24 08:14:33 +01:00
Asim Aslam 7f1ebaa572 Update README.md 2021-08-23 16:45:04 +01:00
Qiu Yu c7195aae98 Grpc server injection (#2208)
Run tests / Test repo (push) Waiting to run
* plugin: update grpc server readme

* plugin: refactor gprc server test

This is a no-op change to enable test logic reuse for different
combinations.

* plugin: grpc server test Init after New

* plugin: allow grpc.Server to be injected
2021-08-12 18:26:26 +01:00
Arsen ffb0a2f896 grpc client: fix grpc code to micro http status conversion for the fallback case with empty Details (#2206) 2021-08-12 12:15:49 +01:00
Qiu Yu b977a51253 Examples: fix grpc config (#2207)
This change fixes grpc config example code which is currently broken.

Several pieces in the change:
- use yaml encoder to read config files
- rename *.yml to *.yaml to fix format (file suffix) for encoder lookup
- replace util/log package with logger as the former one is deprecated
2021-08-12 06:27:04 +01:00
dependabot[bot] 046d0785c9 Bump github.com/gin-gonic/gin from 1.6.3 to 1.7.0 in /examples (#2205)
Bumps [github.com/gin-gonic/gin](https://github.com/gin-gonic/gin) from 1.6.3 to 1.7.0.
- [Release notes](https://github.com/gin-gonic/gin/releases)
- [Changelog](https://github.com/gin-gonic/gin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gin-gonic/gin/compare/v1.6.3...v1.7.0)

---
updated-dependencies:
- dependency-name: github.com/gin-gonic/gin
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-11 13:57:15 +01:00
Qiu Yu 828d3f2b74 loader: avoid overwriting values if error happens (#2204) 2021-08-11 13:33:58 +01:00
Qiu Yu a46dc0b856 Add yaml config example (#2203)
* examples: add yaml config

* examples: update go mod for yaml plugin
2021-08-11 13:31:29 +01:00
Johnson C 3e0411a3f6 fixing mem.pprof issue: (#2198)
parsing profile: concatenated profiles detected
fixing web service not start profile issue
fixing no default profile options issue
2021-08-04 09:39:01 +01:00
bacndcmc c3107e6843 fix code proto return invalid message (#2196)
Co-authored-by: ben <norton0395@gmail.com>
2021-07-26 06:25:21 +01:00
Asim Aslam e1bc7e3028 Update README.md 2021-07-21 09:06:34 +01:00
Asim Aslam 992418236e Update README.md 2021-07-21 09:05:38 +01:00
Asim Aslam 27a792790b Update README.md 2021-07-21 09:05:20 +01:00
Asim Aslam bd9821111e remove tidy file 2021-07-19 17:57:33 +01:00
Asim Aslam dbba07e7ed Delete tidy.md 2021-07-19 17:55:08 +01:00
xshytikx 753022d2ae fix: imported and not used (log, os) (#2195)
github.com/asim/go-micro/plugins/registry/consul/v3@v3.0.0-20210716165540-546225f1d8db/watcher.go:5:2: imported and not used: "log"
github.com/asim/go-micro/plugins/registry/consul/v3@v3.0.0-20210716165540-546225f1d8db/watcher.go:5:2: imported and not used: "log"
2021-07-18 07:18:11 +01:00
JeffreyBool 546225f1d8 Not Recommended Function Correction (#2194)
* Update http.go

Exit before deregister is executed

* Create http.go

Exit before deregister is executed

* Solve the problem that the resources have not been fully released due to early exit

* Optimize some code

* Optimize some code

* Optimize some code

* fix service default logger

* Not Recommended Function Correction
2021-07-16 17:55:40 +01:00
JeffreyBool 0532fd9de8 fix logger v3 (#2193)
* Update http.go

Exit before deregister is executed

* Create http.go

Exit before deregister is executed

* Solve the problem that the resources have not been fully released due to early exit

* Optimize some code

* Optimize some code

* Optimize some code

* fix service default logger

* Repair mq asynchronous send, mq write failure without error output

* Repair mq asynchronous send, mq write failure without error output

* fix logger v3
2021-07-12 07:18:37 +01:00
lanrion 3fbf2c304f Optimize prometheus wrapper,removed mutex,initialize MetricVec at init() (#2192)
Co-authored-by: dylan.deng <dylan.deng@yijinin.com>
2021-07-09 12:52:08 +01:00
JeffreyBool 6cdf28270f Repair mq asynchronous send, mq write failure without error output (#2191)
* Update http.go

Exit before deregister is executed

* Create http.go

Exit before deregister is executed

* Solve the problem that the resources have not been fully released due to early exit

* Optimize some code

* Optimize some code

* Optimize some code

* fix service default logger

* Repair mq asynchronous send, mq write failure without error output

* Repair mq asynchronous send, mq write failure without error output
2021-07-09 06:19:09 +01:00
Johnson C 7f1de77e8c try fixing staticcheck warning (#2190)
Run tests / Test repo (push) Waiting to run
https://github.com/golang/protobuf/issues/1077
package github.com/golang/protobuf/proto is deprecated: Use the "google.golang.org/protobuf/proto" package instead.  (SA1019)
2021-07-06 12:51:28 +01:00
Asim Aslam 1c482e8922 add web package 2021-07-06 11:12:19 +01:00
wangYue 70ed9bf154 fix missing error (#2189)
Co-authored-by: wangyue <wangyue@actiontech.com>
2021-06-30 10:13:05 +01:00
Jerry 93ba8cd0df continue fix pre version go get bug that unknown v3.5.1 (#2188)
* 1.fix plugins go get bug.
2.update all mode.
3.add tidy tools

* continue fix pre version go get bug that unknown v3.5.1
2021-06-30 09:24:00 +01:00
Jerry c13bb07171 1.fix plugins go get bug. (#2187)
2.update all mode.
3.add tidy tools
2021-06-30 07:21:03 +01:00
Jerry 4929a7c16e update etcd version (#2186)
Remove missing gRPC example from README.md (#2112)

Delete docker.yml

Delete Dockerfile

update plugins version & remove replace (#2118)

* update memory registry plugins version & remove replace

* update plugins version & remove replace

Co-authored-by: 申法宽 <shenfakuan@163.com>

update client/grpc plugins version & remove replace (#2119)

* update memory registry plugins version & remove replace

* update plugins version & remove replace

* update plugins/client/grpc/v3 version

Co-authored-by: 申法宽 <shenfakuan@163.com>

update etcd version (#2120)

update mod version

update

update pulgin registry mod version (#2121)

* update etcd version

* update mod version

* update

fix store delete

support for tls on http plugin (#2126)

improve code quality (#2128)

* Fix inefficient string comparison

* Fix unnecessary calls to Printf

* Canonicalize header key

* Replace `t.Sub(time.Now())` with `time.Until`

* Remove unnecessary blank (_) identifier

* Remove unnecessary use of slice

* Remove unnecessary comparison with bool

Update README.md

Update README.md

remove network package

update quic go mod

remove indirects

update etcd mod version

Update registry plugins mod version (#2130)

* update etcd version

* update mod version

* update

* update etcd mod version

Update README.md

Update README.md

Update README.md

fixing etcd stack in getToken (#2145)

when provide username and password, etcd will try to get auth token from server
if server is unavailble, etcd client will stack in
when dial timeout is set, it will return err instead of stack in

Update README.md

add http demo; http client can call http server; http client can call rpc server (#2149)

Add etcd to default registries when plugin is loaded (#2150)

Co-authored-by: Andrew Jones <andrew@gotoblink.com>

Update README.md

make rpcClient compatible with 32bit arm systems (#2156)

On ARM, 386, and 32-bit MIPS, it is the caller's responsibility to
arrange for 64-bit alignment of 64-bit words accessed
atomically. Only the first word in an allocated struct can
be relied upon to be 64-bit aligned.

optimize the process of switching grpc error to micro error (#2158)

Fix util/log/log.Infof format didn't work (#2160)

Co-authored-by: Cui Gang <cuigang@yunpbx.com>

fixing string field contains invalid UTF-8 issue (#2164)

fix k8s api memory leak (#2166)

fix http No release Broker (#2167)

* Update http.go

Exit before deregister is executed

* Create http.go

Exit before deregister is executed

fix: "Solve the problem that the resources have not been fully released due to early exit" (#2168)

* Update http.go

Exit before deregister is executed

* Create http.go

Exit before deregister is executed

* Solve the problem that the resources have not been fully released due to early exit

* Optimize some code

* Optimize some code

fix service default logger (#2171)

* Update http.go

Exit before deregister is executed

* Create http.go

Exit before deregister is executed

* Solve the problem that the resources have not been fully released due to early exit

* Optimize some code

* Optimize some code

* Optimize some code

* fix service default logger

Update README.md

get k8s pod (#2173)

Update README.md

fix:field (#2176)

* get k8s pod

* fix: filed

* field

Update README.md

add rmq message properties (#2177)

Co-authored-by: dtitov <dtitov@might24.ru>

Update README.md

grpc server add RegisterCheck (#2178)

fix 404 bug (#2179)

fix undefined: err (#2181)

Add registry and config/source plugins based on nacos/v2 (#2182)

* Add registry plugins implement by nacos/v2

* Add config/source plugins implement by nacos/v2

support hystrix fallback (#2183)

Windows event log plugin (#2180)

* add rmq message properties

* eventlog start

* start eventlog

* windows event logger

* readme

* readme

Co-authored-by: dtitov <dtitov@might24.ru>

support etcd auth with env args (#2184)

* support etcd auth with env args
set default registry address with env arg instead of 127.0.0.1

* fixing MICRO_REGISTRY_ADDRESS may empty issue

update mod version
2021-06-29 13:40:54 +01:00
Johnson C 212df8e6c3 support etcd auth with env args (#2184)
* support etcd auth with env args
set default registry address with env arg instead of 127.0.0.1

* fixing MICRO_REGISTRY_ADDRESS may empty issue
2021-06-23 07:45:01 +01:00
Dmitry Titov 8dc9bf49a1 Windows event log plugin (#2180)
* add rmq message properties

* eventlog start

* start eventlog

* windows event logger

* readme

* readme

Co-authored-by: dtitov <dtitov@might24.ru>
2021-06-20 09:28:30 +01:00
qm012 4daa499912 support hystrix fallback (#2183) 2021-06-20 09:28:15 +01:00
Yusan Kurban 939f346d83 Add registry and config/source plugins based on nacos/v2 (#2182)
* Add registry plugins implement by nacos/v2

* Add config/source plugins implement by nacos/v2
2021-06-18 14:23:03 +01:00
qm012 08216ccf31 fix undefined: err (#2181) 2021-06-17 11:11:38 +01:00
qm012 4deeaff8ad fix 404 bug (#2179) 2021-06-16 07:56:41 +01:00
dudu b892efa25f grpc server add RegisterCheck (#2178) 2021-06-11 09:57:44 +01:00
Asim Aslam 4af9e245fb Update README.md 2021-06-09 10:31:10 +01:00
Dmitry Titov 52bb3845f6 add rmq message properties (#2177)
Co-authored-by: dtitov <dtitov@might24.ru>
2021-06-08 10:34:47 +01:00
Asim Aslam a1e9b88495 Update README.md 2021-06-04 10:17:30 +01:00
biubiubiu-ljd ed44e9acc3 fix:field (#2176)
* get k8s pod

* fix: filed

* field
2021-06-03 07:01:26 +01:00
Asim Aslam 86d8d8f07e Update README.md 2021-06-02 14:02:58 +01:00
biubiubiu-ljd 62112b015f get k8s pod (#2173) 2021-06-02 13:54:02 +01:00
Asim Aslam ca2014bf8e Update README.md 2021-06-01 06:23:33 +01:00
JeffreyBool acc3f5479f fix service default logger (#2171)
* Update http.go

Exit before deregister is executed

* Create http.go

Exit before deregister is executed

* Solve the problem that the resources have not been fully released due to early exit

* Optimize some code

* Optimize some code

* Optimize some code

* fix service default logger
2021-05-23 08:38:20 +01:00
JeffreyBool f48911d2c3 fix: "Solve the problem that the resources have not been fully released due to early exit" (#2168)
* Update http.go

Exit before deregister is executed

* Create http.go

Exit before deregister is executed

* Solve the problem that the resources have not been fully released due to early exit

* Optimize some code

* Optimize some code
2021-05-17 08:16:52 +01:00
JeffreyBool 4c1f81dadb fix http No release Broker (#2167)
* Update http.go

Exit before deregister is executed

* Create http.go

Exit before deregister is executed
2021-05-13 13:07:25 +01:00
Tt yo 32cb1b435b fix k8s api memory leak (#2166) 2021-05-11 08:58:19 +01:00
Johnson C 8c9c7a5927 fixing string field contains invalid UTF-8 issue (#2164) 2021-05-10 11:25:31 +01:00
Cui Gang 9e9157d878 Fix util/log/log.Infof format didn't work (#2160)
Co-authored-by: Cui Gang <cuigang@yunpbx.com>
2021-05-06 06:43:05 +01:00
Scout Wang 1b5d372b5b optimize the process of switching grpc error to micro error (#2158) 2021-04-29 13:03:40 +01:00
Tobias Wellnitz b11a2f17e9 make rpcClient compatible with 32bit arm systems (#2156)
On ARM, 386, and 32-bit MIPS, it is the caller's responsibility to
arrange for 64-bit alignment of 64-bit words accessed
atomically. Only the first word in an allocated struct can
be relied upon to be 64-bit aligned.
2021-04-25 06:54:00 +01:00
Asim Aslam a91d1f7a3d Update README.md
Run tests / Test repo (push) Waiting to run
2021-04-16 17:34:42 +01:00
Andrew 0d57213d3f Add etcd to default registries when plugin is loaded (#2150)
Co-authored-by: Andrew Jones <andrew@gotoblink.com>
2021-04-08 18:31:39 +01:00
orange-jacky 6ae252b892 add http demo; http client can call http server; http client can call rpc server (#2149) 2021-04-08 18:31:15 +01:00
Asim Aslam e7a7e3a050 Update README.md 2021-04-03 08:39:40 +01:00
Johnson C bed53b605f fixing etcd stack in getToken (#2145)
when provide username and password, etcd will try to get auth token from server
if server is unavailble, etcd client will stack in
when dial timeout is set, it will return err instead of stack in
2021-04-01 09:55:21 +01:00
Asim Aslam 9b41d1bf08 Update README.md 2021-03-29 11:33:59 +01:00
Asim Aslam 0a41e6d80f Update README.md 2021-03-17 09:37:20 +00:00
Asim Aslam b636a4bfe3 Update README.md 2021-03-17 07:52:35 +00:00
Jerry df90f2ca63 Update registry plugins mod version (#2130)
* update etcd version

* update mod version

* update

* update etcd mod version
2021-02-27 06:48:44 +00:00
Asim Aslam 0bf3719a9a remove indirects 2021-02-26 08:34:03 +00:00
Asim Aslam bfa9e7c88c update quic go mod 2021-02-26 08:14:11 +00:00
Asim Aslam 57003414be remove network package 2021-02-26 08:13:12 +00:00
Asim Aslam a54f40baa7 Update README.md 2021-02-25 10:32:47 +00:00
Asim Aslam 56c779f9df Update README.md 2021-02-25 10:31:55 +00:00
Shubhendra Singh Chauhan 26b859c4f9 improve code quality (#2128)
* Fix inefficient string comparison

* Fix unnecessary calls to Printf

* Canonicalize header key

* Replace `t.Sub(time.Now())` with `time.Until`

* Remove unnecessary blank (_) identifier

* Remove unnecessary use of slice

* Remove unnecessary comparison with bool
2021-02-25 08:30:35 +00:00
Alex Unger 0f0ace1a44 support for tls on http plugin (#2126) 2021-02-17 18:20:06 +00:00
Asim Aslam f9f5e7422d fix store delete 2021-02-10 07:14:49 +00:00
Jerry 2653e7a977 update pulgin registry mod version (#2121)
* update etcd version

* update mod version

* update
2021-02-08 08:56:39 +00:00
Jerry 55b477ba07 update etcd version (#2120) 2021-02-07 12:15:06 +00:00
isfk 6f666d63c8 update client/grpc plugins version & remove replace (#2119)
* update memory registry plugins version & remove replace

* update plugins version & remove replace

* update plugins/client/grpc/v3 version

Co-authored-by: 申法宽 <shenfakuan@163.com>
2021-02-05 09:50:42 +00:00
isfk e8167a8b79 update plugins version & remove replace (#2118)
* update memory registry plugins version & remove replace

* update plugins version & remove replace

Co-authored-by: 申法宽 <shenfakuan@163.com>
2021-02-05 09:09:25 +00:00
Asim Aslam 0702501552 Delete Dockerfile 2021-02-02 14:58:31 +00:00
Asim Aslam 89fe31310e Delete docker.yml 2021-02-02 14:58:19 +00:00
Josemy Duarte ca3dfc4580 Remove missing gRPC example from README.md (#2112) 2021-01-30 18:13:56 +00:00
francescocarzaniga bba3107ae1 Remove hpcloud/tail in favour of nxadm/tail (#2109)
Docker / build (push) Waiting to run
Run tests / Test repo (push) Waiting to run
2021-01-25 07:51:17 +00:00
Asim Aslam 60010e82e2 update protoc-gen-micro
Docker / build (push) Waiting to run
Run tests / Test repo (push) Waiting to run
2021-01-20 21:36:17 +00:00
Asim Aslam ad94eeb635 Update README.md
Docker / build (push) Waiting to run
Run tests / Test repo (push) Waiting to run
2021-01-20 21:30:26 +00:00
Asim Aslam 88be70a6af Update README.md 2021-01-20 21:30:10 +00:00
Asim Aslam 226833c4ab Update README.md 2021-01-20 21:29:36 +00:00
Asim Aslam 8e3b7a57d9 examples at v3 2021-01-20 21:28:48 +00:00
Asim Aslam dc8236ec05 update v3 plugins (#2105) 2021-01-20 21:01:10 +00:00
Asim Aslam d94936f6c9 v3 (#2104)
* v3

* revert plugins

* fixup some issues
2021-01-20 13:54:31 +00:00
Goober bf4ab679e1 Fix zk watchDir (#2102)
Signed-off-by: Goober <chenhao86899@gmail.com>
2021-01-05 17:32:17 +00:00
Asim Aslam 20b5755788 move encoders out to plugins 2020-12-30 08:46:31 +00:00
Asim Aslam f64ffdbab1 remove indirects in go mod 2020-12-30 08:26:26 +00:00
Asim Aslam eb1e22bd10 strip grpc 2020-12-30 08:21:30 +00:00
Asim Aslam 18fb7a5d62 move certmagic 2020-12-29 20:12:10 +00:00
Asim Aslam ee8b369a19 add initialisers 2020-12-29 16:50:18 +00:00
Asim Aslam f4f6feafb3 remove etcd store 2020-12-29 16:32:06 +00:00
Asim Aslam 9ddfe696a4 go fmt 2020-12-29 16:29:58 +00:00
Asim Aslam 762fff8a51 Merge branch 'master' of ssh://github.com/asim/go-micro 2020-12-29 16:28:21 +00:00
Asim Aslam 36bcd8317b remove micro deps 2020-12-29 16:28:12 +00:00
Asim Aslam 10005db702 Rename default.go to noop.go 2020-12-29 16:24:31 +00:00
Asim Aslam 1b610403ba go mod tidy 2020-12-29 15:50:14 +00:00
Asim Aslam 2fde8a76eb Merge branch 'master' of ssh://github.com/asim/go-micro 2020-12-29 15:49:33 +00:00
Asim Aslam a7c31a0d2b refactor all the things 2020-12-29 15:49:26 +00:00
Asim Aslam 35d72660c8 Update README.md 2020-12-26 15:42:10 +00:00
Asim Aslam d197438e16 Merge branch 'master' of ssh://github.com/asim/go-micro 2020-12-26 15:32:54 +00:00
Asim Aslam 7fc0b7ef72 add all the plugins 2020-12-26 15:32:45 +00:00
Asim Aslam f44b832bac Update README.md 2020-12-26 15:23:06 +00:00
Asim Aslam 5fe144bda8 Update README.md 2020-12-26 15:22:41 +00:00
Asim Aslam df2dab0169 Update README.md 2020-12-26 15:22:14 +00:00
Asim Aslam 7ab46b0850 rename imports 2020-12-26 15:21:29 +00:00
Asim Aslam c3fe6eb3ac update readme 2020-12-26 15:18:11 +00:00
Asim Aslam a34c70de0e Add examples 2020-12-26 15:17:20 +00:00
Asim Aslam 273bab5dd7 update readme 2020-12-26 15:15:39 +00:00
Asim Aslam f8fc9d0304 Add protoc-gen-micro 2020-12-26 15:13:09 +00:00
Hao b5431de2e8 Use singleflight to prevent registry cache breakdown (#2098) 2020-12-21 14:34:59 +00:00
Asim Aslam dc0cac9ba4 Update README.md 2020-12-18 18:45:14 +00:00
Asim Aslam 8628dc0fc4 Update FUNDING.yml 2020-12-13 08:18:02 +00:00
Asim Aslam b57f56fb0b Merge branch 'master' of ssh://github.com/asim/go-micro 2020-12-12 20:51:40 +00:00
Asim Aslam 690169f6e5 remove k8s logs 2020-12-12 20:51:32 +00:00
Asim Aslam a543157f50 Delete debug.go 2020-12-12 20:50:53 +00:00
Asim Aslam 15a62ae0b9 move debug handler 2020-12-12 20:50:36 +00:00
Asim Aslam 28afbf164f Merge branch 'master' of ssh://github.com/asim/go-micro 2020-12-12 20:44:45 +00:00
Asim Aslam 4ce77373c0 remove auth cruft 2020-12-12 20:44:32 +00:00
Asim Aslam 8de1ede0f0 Update network.go 2020-12-12 20:35:43 +00:00
Asim Aslam 8054478cc3 remove util/scope 2020-12-12 20:28:09 +00:00
Asim Aslam 167fcd0d78 fix wrapper test 2020-12-12 20:25:29 +00:00
Asim Aslam 206bf8cd0a remove web 2020-12-12 20:15:59 +00:00
Asim Aslam df687fe5d4 move selector 2020-12-12 20:14:50 +00:00
Asim Aslam de4f3ee4a2 separate rules and auth 2020-12-12 20:08:39 +00:00
Asim Aslam 202338bd2d update all the things to go 1.15 2020-12-12 19:51:18 +00:00
Asim Aslam e2034b2438 Merge branch 'master' of ssh://github.com/asim/go-micro 2020-12-12 19:39:14 +00:00
Asim Aslam 0ec2399a2c fix command 2020-12-12 19:39:04 +00:00
Asim Aslam df5f158cef Delete .golangci.yml 2020-12-12 19:09:48 +00:00
Asim Aslam 19ac4fbcaf move rules 2020-12-12 19:08:36 +00:00
Asim Aslam d07de3751e remove auth provider 2020-12-12 19:06:43 +00:00
Asim Aslam 4977aca09c move router 2020-12-12 19:04:19 +00:00
Asim Aslam 43ff2a540d move proxy 2020-12-12 19:02:04 +00:00
Asim Aslam 35c59042bf refactor network 2020-12-12 18:59:40 +00:00
Asim Aslam f8f84b42ac Merge branch 'master' of ssh://github.com/asim/go-micro 2020-12-11 21:42:43 +00:00
Asim Aslam 1dc9b40b90 move network/tunnel 2020-12-11 21:42:31 +00:00
Asim Aslam 345845ec16 Delete CNAME 2020-12-11 11:22:37 +00:00
Asim Aslam dbe8c93e20 remove service implementations (#2094) 2020-12-11 11:12:44 +00:00
Asim Aslam 4d481b0363 Update README.md 2020-12-09 21:52:18 +00:00
Asim Aslam 88d954cf97 Update README.md 2020-12-09 18:35:07 +00:00
Asim Aslam 71883f1b04 Update tests.yml 2020-12-09 18:19:37 +00:00
Asim Aslam bfc212f7ed remove service package 2020-12-09 18:11:10 +00:00
Asim Aslam 43f80b1b0d Delete build-micro.sh 2020-12-09 18:09:02 +00:00
Asim Aslam f83d64d092 Delete build-all-examples.sh 2020-12-09 18:08:55 +00:00
Asim Aslam e67b9f0cc1 Delete micro-main.yml 2020-12-09 18:08:39 +00:00
Asim Aslam 134c5f0e41 Delete micro-examples.yml 2020-12-09 18:08:26 +00:00
Asim Aslam e761aa1940 move cmd 2020-12-09 18:07:01 +00:00
Asim Aslam 8c8380dcd4 delete agent package 2020-12-09 18:03:00 +00:00
Asim Aslam dd5eca2561 Update README.md 2020-12-09 17:05:05 +00:00
Dominic Wong 94bd1025a6 push tags to docker hub (#1766)
Docker / build (push) Waiting to run
Run tests / Test repo (push) Waiting to run
2020-07-03 11:30:59 +01:00
Dominic Wong 7be4a67673 MDNS registry fix for users on VPNs (#1759)
* filter out unsolicited responses
* send to local ip in case
* allow ip func to be passed in. add option for sending to 0.0.0.0
2020-07-03 11:30:59 +01:00
Di Wu 3e6ac73cfe Fix invalid usage for sync.WaitGroup (#1752)
* Custom private blocks

* Fix invalid usage for sync.WaitGroup

Co-authored-by: Asim Aslam <asim@aslam.me>
2020-07-03 11:30:59 +01:00
Colin Hoglund aef6878ee0 config: use configured reader by default (#1717) 2020-07-03 11:30:59 +01:00
sunfuze 81aa8e0231 Fix config watch (#1670)
* add dirty overrite test case

* need version to figure out if config need update or not

* using nanosecond as version for two goroutine can run in same second

* config should check snapshot version when update

* set checksum of ChangeSet

Co-authored-by: Asim Aslam <asim@aslam.me>
2020-07-03 11:30:59 +01:00
Di Wu c28f625cd4 Custom private blocks (#1705)
Co-authored-by: Asim Aslam <asim@aslam.me>
2020-07-03 11:30:59 +01:00
Dmitry Kozlov 5b161b88f7 Split long discord output message into the chunks by 2000 characters (#1704)
Signed-off-by: Dmitry Kozlov <dmitry.f.kozlov@gmail.com>
2020-07-03 11:30:59 +01:00
ben-toogood cca8826a1f registry/mdns: fix nil host bug (#1703) 2020-07-03 11:30:59 +01:00
Dominic Wong 0327f30e3c Fix regex detection. Fixes #1663 (#1696)
Docker / build (push) Waiting to run
Run tests / Test repo (push) Waiting to run
2020-06-12 10:42:52 +01:00
Dominic Wong 0ce132eb8f Fix race condition when updating process being waited on (#1694) 2020-06-12 10:42:52 +01:00
Janos Dobronszki 00b76e0a64 Initialize selector before we make an auth.Generate call (#1693) 2020-06-12 10:42:52 +01:00
Dominic Wong aec27be9b4 Fix race when opening DB for first time (#1691) 2020-06-12 10:42:52 +01:00
Dominic Wong 86dfcb819b Ignore "no such process" error (#1686)
* Cleanup how status is updated for service. Ignore "no such process" error as it could be that the pid died

* add nice error log to record process error exit
2020-06-12 10:42:52 +01:00
Janos Dobronszki d613804b0a Sigterm instead of Sigkill (#1687)
Co-authored-by: Dominic Wong <domwongemail@googlemail.com>
Co-authored-by: Asim Aslam <asim@aslam.me>
2020-06-12 10:42:52 +01:00
Vasiliy Tolstov 92e9d05432 api/handler/rpc: dont log error on normal websocket error code (#1688)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-06-12 10:42:52 +01:00
ben-toogood 8dfd93e915 util/wrapper: Add Static Client wrapper (#1685)
* util/wrapper: Add Static Client wrapper

* util/wrapper/static: pass address to stream too

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* add static client wrapper tests

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* server: fix error message spaces between words

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* server/{rpc,grpc}: replace log.Error with log.Errorf

* server/grpc: fix log typo

* server/rpc: fix log typo

Co-authored-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-06-12 10:42:52 +01:00
Dominic Wong e5136332e3 Add build and test of micro to pre-release testing (#1684)
* fix up example test build

* build and test micro when cutting a new release
2020-06-12 10:42:52 +01:00
Dominic Wong f10fd4b479 Build all micro/examples for release-X.X.X branches (#1683)
* Build all the examples on push to any release branch
2020-06-12 10:42:52 +01:00
ben-toogood 74368026a5 Fix incorrect namespace variable name (merge conflict) (#1677) 2020-06-12 10:42:52 +01:00
ben-toogood fde1aa9d6a Move auth account creation to config/cmd (#1676) 2020-06-12 10:42:52 +01:00
ben-toogood f45cdba9ba Apply wrappers to gRPC streams (#1675)
* Add wrappers to grpc streams

* Fix typo
2020-06-12 10:42:52 +01:00
Asim Aslam b270860b79 Update README.md (#1695) 2020-06-10 10:22:53 +01:00
Asim Aslam e7ba930236 Update FUNDING.yml (#1692) 2020-06-08 18:12:19 +01:00
Dominic Wong aa679f7a73 Create PULL_REQUEST_TEMPLATE.md 2020-06-03 10:32:28 +01:00
Asim Aslam 7b379bf1f1 WIP: Add metadata to store record (#1604)
* Add metadata to store record

* Add metadata to cockroach store

* add metadata to store service implementation

* fix breaking cache test

* Test/fix cockroach metadata usage

* fix store memory metadata bug
2020-06-03 09:45:08 +01:00
Dominic Wong e4e56b0f3f Merge pull request #1671 from sadwxqezc/fix-jwt
Fix jwt revoke
2020-06-02 09:27:14 +01:00
huanghuan.27@bytedance.com 219d29f664 fix jwt revoke 2020-06-02 10:26:33 +08:00
Asim Aslam 8fb138af06 Update README.md 2020-05-31 11:56:55 +01:00
Asim Aslam a39e6515da Update README.md
Docker / build (push) Waiting to run
Run tests / Test repo (push) Waiting to run
2020-05-31 11:35:09 +01:00
Asim Aslam 2c7fd286de Update README.md 2020-05-31 11:34:49 +01:00
Asim Aslam 8aa2712b4d Delete README.zh-cn.md 2020-05-31 11:33:31 +01:00
Asim Aslam b5c2121cef Update README.md 2020-05-31 11:31:41 +01:00
Asim Aslam ca9b877646 Update README.md 2020-05-31 11:28:32 +01:00
Asim Aslam ff49b4fc71 Update README.md 2020-05-31 11:27:54 +01:00
Asim Aslam 222431b57a Update README.md 2020-05-31 11:26:46 +01:00
Asim Aslam ddb51529a7 Update README.md 2020-05-31 11:26:18 +01:00
Asim Aslam 7c048f331a Update README.md 2020-05-31 11:21:55 +01:00
Asim Aslam 8475183bbb Update README.md 2020-05-31 11:19:26 +01:00
Asim Aslam 10f35db3ed Update README.md 2020-05-31 11:16:20 +01:00
Asim Aslam b68af8ab63 run go fmt 2020-05-30 11:00:43 +01:00
Asim Aslam 266602a3d6 Update README.md 2020-05-30 10:59:59 +01:00
mlboy 15d5142d9b fix: misspell (#1667) 2020-05-29 17:49:22 +01:00
Máximo Cuadros 0d88650511 go modules cleanup and remove wrong self import to v1 (#1658)
* Runtime local git, simply go-git code
* go modules cleanup and remove wrong self import to v1
* pin mergo v0.3.8 to avoid panics

Signed-off-by: Máximo Cuadros <mcuadros@gmail.com>
Co-authored-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-05-29 14:32:11 +03:00
Dominic Wong 8660370dc9 Merge pull request #1657 from xpunch/master
logger caller not trim in windows
2020-05-29 10:35:03 +01:00
Dominic Wong 73339dde85 Merge branch 'master' into master 2020-05-29 10:27:20 +01:00
Dominic Wong 3f354f3c30 Merge pull request #1661 from micro/bugfix/sock_pool_threads
fix locking of socket pool
2020-05-28 08:31:47 +01:00
potato c08eb5f892 Merge branch 'master' into master 2020-05-28 10:19:53 +08:00
Dominic Wong 27e41c4ad5 fix locking of socket pool 2020-05-27 20:18:26 +01:00
Dominic Wong 1da8a640da Merge pull request #1660 from micro/bugfix/mdns_nil_host
Check ipv4 or ipv6 address is valid before assigning
2020-05-27 15:53:27 +01:00
Dominic Wong e7ad031eb8 Check ipv4 or ipv6 address is valid before assigning 2020-05-27 15:47:12 +01:00
ben-toogood 192f548c83 Merge pull request #1659 from micro/config-srv-not-found
Handle config service not found errors
2020-05-27 12:24:33 +01:00
Ben Toogood d85b4197b4 Return nil changeset and not blank 2020-05-27 12:20:31 +01:00
Ben Toogood bb5f2e5525 Handle config service not found errors 2020-05-27 12:12:34 +01:00
ben-toogood f00b696282 Merge pull request #1654 from micro/auth-scopes
Auth Improvements
2020-05-27 10:52:07 +01:00
Ben Toogood e2d662608c Fix tests 2020-05-27 09:14:16 +01:00
Ben Toogood 9e9773c9c7 Only use namespace for cache key 2020-05-27 09:07:59 +01:00
potato 2f8e2487f7 Merge branch 'master' into master 2020-05-27 09:32:27 +08:00
Ben Toogood d6c1fbf841 Fix web service auth name 2020-05-26 17:43:45 +01:00
Ben Toogood c3b404bab0 Fix server calling across namespace 2020-05-26 17:35:06 +01:00
Ben Toogood cd283654eb Cache Rules 2020-05-26 15:53:28 +01:00
Ben Toogood 5712cc9c62 Merge master 2020-05-26 15:52:21 +01:00
ben-toogood be5a10a4d4 Merge pull request #1656 from micro/client-cache
Client Cache
2020-05-26 15:38:30 +01:00
Ben Toogood b53a2c67f1 Merge branch 'master' of https://github.com/micro/go-micro into auth-scopes 2020-05-26 15:37:31 +01:00
johnson cc79692d68 make caller filepath package/file style
this code is from zap
https://github.com/uber-go/zap/blob/9a9fa7d4b5f07a9b634983678a65b5525f81e58b/zapcore/entry.go#L101
2020-05-26 14:33:56 +08:00
potato 796a598b37 Merge pull request #7 from micro/master
go micro v2
2020-05-26 14:18:25 +08:00
Ben Toogood 73b4423682 Merge branch 'master' of https://github.com/micro/go-micro into client-cache 2020-05-24 20:36:22 +01:00
Ben Toogood 198e942889 Remove redundant test 2020-05-24 20:32:22 +01:00
Ben Toogood 95703e4565 Fixes and improved test coverage 2020-05-24 20:26:37 +01:00
Ben Toogood 2729569f66 Add Debug.Cache method 2020-05-24 18:45:57 +01:00
Ben Toogood 67146ecdc2 Client Cache tests 2020-05-24 18:05:23 +01:00
Asim Aslam bd049a51e6 Update README.md 2020-05-23 16:47:23 +01:00
Asim Aslam ffd89599a0 Update README.md 2020-05-23 16:46:50 +01:00
Ben Toogood 496293afa1 Use hash/fnv, add tests, fix request bug 2020-05-23 11:34:44 +01:00
Ben Toogood 7d7f4046e8 Client Cache 2020-05-22 16:52:24 +01:00
Ben Toogood c800070477 Check for error before loading rules 2020-05-22 14:03:12 +01:00
Ben Toogood 877fe5fb0a Update web wildcard to enable /foo/bar/baz/* to verify /foo/bar/baz 2020-05-22 14:02:02 +01:00
Ben Toogood dad011cab4 Fix noop issuer bug 2020-05-22 12:40:34 +01:00
Ben Toogood f939200b34 Improve service auth log 2020-05-22 12:24:37 +01:00
Ben Toogood 9c072a372c Add auth scope constants 2020-05-22 11:37:12 +01:00
Ben Toogood fbb91c6cb7 Auth wrapper tests 2020-05-22 10:44:18 +01:00
Ben Toogood b2cf501952 Auth Rules tests & bug fixes 2020-05-22 09:31:15 +01:00
Ben Toogood 1fce0f02b6 Verify Namespace 2020-05-21 18:11:35 +01:00
Ben Toogood 12061bd006 Add account issuers 2020-05-21 16:41:55 +01:00
Ben Toogood 856c73b341 Remove roles (replaced with scope) 2020-05-21 14:56:17 +01:00
Ben Toogood 4de19805ba Remove redundant test 2020-05-21 12:33:58 +01:00
Ben Toogood c09b871a6b Merge branch 'master' of https://github.com/micro/go-micro into auth-scopes 2020-05-21 12:32:52 +01:00
Ben Toogood e876cb917d auth/service support for micro clients (rules from mutltiple namespaces 2020-05-21 12:25:47 +01:00
Ben Toogood 8f5ef012ff Update Rules.Delete proto 2020-05-21 12:07:22 +01:00
Ben Toogood 287992cef3 Fix service => service namespace bug 2020-05-21 11:35:07 +01:00
Ben Toogood 344ce061ce Verify Options 2020-05-20 16:49:52 +01:00
Ben Toogood 5d14970a55 Fix nil account bug 2020-05-20 16:11:34 +01:00
Janos Dobronszki 0615fe825f Auth invalid token fix (#1650) 2020-05-20 16:18:05 +02:00
Asim Aslam 6a661fd08c check if the db conn is nil before doing anything (#1652) 2020-05-20 14:03:38 +01:00
Ben Toogood f6d9416a9e Add Rule to Auth interface 2020-05-20 11:59:01 +01:00
Asim Aslam a29676b86a Registration Retry / Interval (#1651)
* Change the default ttl to 90 seconds

* add retries to registration

* Add retry to web register
2020-05-20 11:49:09 +01:00
Ben Toogood dc10f88c12 Replace auth account.Namespace with account.Scopes 2020-05-19 18:17:17 +01:00
ben-toogood e61edf6280 Merge pull request #1645 from micro/runtime-multitenancy
Runtime multi-tenancy
2020-05-19 17:06:11 +01:00
ben-toogood 3410a0949b Merge branch 'master' into runtime-multitenancy 2020-05-19 17:00:51 +01:00
Jake Sanders 9216a47724 fix client race (#1647) 2020-05-19 14:44:46 +01:00
ben-toogood cf37d64819 Merge branch 'master' into runtime-multitenancy 2020-05-19 13:24:35 +01:00
Patrik Lindahl f0c0f3d4c4 Fixes for #1560 (#1644)
close #1560

This fixes one of the reported data races and also allows for
having a different name on the micro.Service and web.Service.
This makes it possible to discover the two service variants separately.

Co-authored-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-05-19 14:11:26 +03:00
Ben Toogood c4e3f8c336 Merge branch 'master' of https://github.com/micro/go-micro into runtime-multitenancy 2020-05-19 11:02:40 +01:00
Ben Toogood 8875719619 Default Runtime multi-tenancy 2020-05-19 11:01:06 +01:00
Ben Toogood c19b349e96 Update runtime.Event struct 2020-05-19 10:14:07 +01:00
Ben Toogood 14155c7e02 Add runtime ErrNotFound 2020-05-19 09:28:00 +01:00
Maarten Bezemer 3d36398818 Fix client RPC stream close mutex (#1643)
Docker / build (push) Waiting to run
Run tests / Test repo (push) Waiting to run
2020-05-18 17:22:33 +01:00
Asim Aslam 56a7897c91 update readme 2020-05-17 12:39:20 +01:00
ben-toogood 5efb386224 Merge pull request #1640 from micro/auth/public-rule
Auth: setup a public rule
2020-05-15 10:28:52 +01:00
Ben Toogood 4d2de923cd Auth: setup a public rule 2020-05-15 10:24:30 +01:00
ben-toogood f64b1468a5 Merge pull request #1639 from micro/registy-not-found
Registry service: return not found error
2020-05-14 19:43:19 +01:00
ben-toogood 56f281002b Merge branch 'master' into registy-not-found 2020-05-14 19:39:43 +01:00
Ben Toogood 0d7250352f Registry service: return not found error 2020-05-14 19:38:56 +01:00
ben-toogood ef43f01da4 Merge pull request #1638 from micro/registry-addrs-fix
Fix registry address option unused
2020-05-14 18:07:14 +01:00
ben-toogood c9e5ae6a2b Merge branch 'master' into registry-addrs-fix 2020-05-14 18:03:46 +01:00
Ben Toogood 8a802d8f7a Fix registry address option unused 2020-05-14 18:00:13 +01:00
ben-toogood 331ab3715c Merge pull request #1636 from micro/auth-util
Refactor auth setup to util/auth
2020-05-14 16:15:47 +01:00
Ben Toogood 6b451a2197 Refactor auth setup to util/auth 2020-05-14 16:10:14 +01:00
ben-toogood b4c0224746 Merge pull request #1635 from micro/auth-fixes
Auth: Move token generation logic out the client wrappers
2020-05-14 14:00:55 +01:00
Ben Toogood 500d793fc4 Merge branch 'auth-fixes' of https://github.com/micro/go-micro into auth-fixes 2020-05-14 13:57:00 +01:00
Ben Toogood 16af265e8b Seperate JWT refresh / access tokens 2020-05-14 13:56:51 +01:00
ben-toogood b222cf8e13 Merge branch 'master' into auth-fixes 2020-05-14 13:47:26 +01:00
Ben Toogood f549e20fa2 tidy go mdo 2020-05-14 13:33:11 +01:00
Ben Toogood 83e9c1fad2 Remove unnecessary change 2020-05-14 13:32:42 +01:00
Ben Toogood c220686c29 Fix token bug 2020-05-14 13:30:21 +01:00
Ben Toogood 1b18730d54 Custom micro client 2020-05-14 11:25:19 +01:00
Ben Toogood 5764519f5b Refactor auth to load token outside wrappers 2020-05-14 11:06:22 +01:00
ben-toogood 957001f8ad Merge pull request #1634 from micro/disable-clients
Disable Clients
2020-05-13 18:54:34 +01:00
Ben Toogood 0955671e45 Merge branch 'disable-clients' of https://github.com/micro/go-micro into disable-clients 2020-05-13 18:49:47 +01:00
Ben Toogood 57b060bac5 Disable Addresses 2020-05-13 18:49:36 +01:00
ben-toogood 3136e1409e Merge branch 'master' into disable-clients 2020-05-13 18:48:24 +01:00
Ben Toogood ca791d7e8d Disable Clients 2020-05-13 18:47:53 +01:00
Dominic Wong 05858b746c kill all processes correctly for micro kill command (#1633) 2020-05-13 18:36:45 +01:00
ben-toogood 09d1450d7d Merge pull request #1632 from micro/fix-auth-bug
Auth: Fix recursive bug
2020-05-13 18:18:39 +01:00
Ben Toogood 1ca1fd411a Auth: Fix recursive bug 2020-05-13 18:17:04 +01:00
ben-toogood a2d4d62f1c Merge pull request #1631 from micro/auth-address
Auth: Set address
2020-05-13 18:02:10 +01:00
Ben Toogood 8ab20f501c Fix merge conflicts 2020-05-13 17:58:03 +01:00
Ben Toogood 366fb228e5 Auth: Set address 2020-05-13 17:54:47 +01:00
Asim Aslam bba8c254d7 fix auth initialisation (#1630) 2020-05-13 17:35:57 +01:00
ben-toogood ebd53794af Merge pull request #1629 from micro/auth/rules-fix
Auth: Load rules if not present
2020-05-13 17:27:53 +01:00
Ben Toogood 2299244332 Auth: Load rules if not present 2020-05-13 17:07:46 +01:00
ben-toogood cf61d98635 Merge pull request #1628 from micro/registry
Misc Muti-Tenancy / Auth Fixes
2020-05-13 16:53:39 +01:00
ben-toogood 15d1967aaf Merge branch 'master' into registry 2020-05-13 16:50:12 +01:00
Ben Toogood 410fec8ee4 Fix auth bug 2020-05-13 16:49:17 +01:00
Ben Toogood c831b6c03a Fix 2020-05-13 16:35:57 +01:00
Asim Aslam 290595f88e Strip down router code (#1627) 2020-05-13 16:13:36 +01:00
ben-toogood ba64518ebd Merge pull request #1626 from PieterVoorwinden/master
Check if auth is nil to prevent nilpointer
2020-05-13 15:18:58 +01:00
Pieter Voorwinden b14d63b4a1 Check if auth is nil to prevent nilpointer 2020-05-13 16:13:23 +02:00
x1nchen af2db0a0d9 fix: update dependency certmagic (#1625)
module github.com/mholt/certmagic has been renamed github.com/caddyserver/certmagic,
so upgrade on this module will fail.

fix: micro/micro#835

caddyserver/certmagic@v0.10.6 is Maximum upgradeable version with go version 1.13

Higher version use *tls.ClientHelloInfo.SupportsCertificate which only supported in go 1.14
2020-05-13 15:00:13 +01:00
ben-toogood fb255a7e5a Merge pull request #1622 from micro/registry-multi-tenancy
Registry mutli-tenancy
2020-05-13 13:54:39 +01:00
Ben Toogood 47c1cb433e Store account credentials 2020-05-13 13:48:25 +01:00
Ben Toogood 3fac7d79ab Remove service type role 2020-05-13 13:42:56 +01:00
Ben Toogood 25c937fd0e Naming changes 2020-05-13 13:38:13 +01:00
Ben Toogood e5c1fbc591 Merge branch 'master' of https://github.com/micro/go-micro into registry-multi-tenancy 2020-05-13 13:35:47 +01:00
Ben Toogood d781c9ae2d Remove namespace specific logic 2020-05-13 13:35:34 +01:00
Ben Toogood 54951740bf Authenticate on service start 2020-05-13 13:13:11 +01:00
Janos Dobronszki 0fb4734e67 Upload local source code to micro server (#1613) 2020-05-13 12:07:53 +02:00
Ben Toogood 346e034d0a Add mutli-tenancy support to the registry 2020-05-13 10:40:08 +01:00
Asim Aslam 116cc1e9ee Stop parsing proxy address (#1619) 2020-05-12 17:38:22 +01:00
ben-toogood 762a5bc9e8 Merge pull request #1618 from micro/auth-namespace-flag
Auth Namespace Flag
2020-05-12 16:45:42 +01:00
Ben Toogood d39b723511 Auth Namespace Flag 2020-05-12 16:41:29 +01:00
ben-toogood 5494e935f4 Merge pull request #1617 from micro/k8s/secret-type
K8s: Add Secret Type to yaml template
2020-05-12 14:21:30 +01:00
Ben Toogood e0863bb7eb K8s: Add Secret Type to yaml template 2020-05-12 14:10:39 +01:00
ben-toogood 89f86167ad Merge pull request #1616 from micro/k8s/secret-template-fix
Fix k8s secret template (yaml)
2020-05-12 11:45:12 +01:00
ben-toogood dfec1ad6b1 Merge branch 'master' into k8s/secret-template-fix 2020-05-12 11:41:41 +01:00
Ben Toogood 66d3e4a595 Fix k8s secret template (yaml) 2020-05-12 11:40:54 +01:00
Asim Aslam 19a03babc4 Update server.go 2020-05-12 11:32:01 +01:00
ben-toogood ee24b4f083 Merge pull request #1615 from micro/disable-auth-client
Disable auth service client
2020-05-11 20:38:49 +01:00
Ben Toogood 937ecc8d2f Disable auth service client 2020-05-11 20:38:05 +01:00
ben-toogood 6078adb8bc Merge pull request #1614 from micro/runtime-clients
Runtime Options: Replace client.DefaultClient
2020-05-11 20:05:00 +01:00
ben-toogood 39f18b0b70 Merge branch 'master' into runtime-clients 2020-05-11 18:03:11 +01:00
Ben Toogood efb64b7dbb Pass client to more of the runtime 2020-05-11 17:57:39 +01:00
Ben Toogood f892b41299 Add runtime to service.Options() 2020-05-11 17:09:28 +01:00
Janos Dobronszki 1eb63635b5 Adding file upload and download capabilities (#1610) 2020-05-11 14:08:27 +02:00
ben-toogood 688228377b Merge pull request #1612 from micro/auth-options
Auth: pass options in service RPC
2020-05-11 11:53:38 +01:00
Ben Toogood 506006f0fa Auth Options 2020-05-11 11:47:59 +01:00
ben-toogood 22de001a80 Merge pull request #1611 from micro/auth-has-role
Auth account.HasRole
2020-05-11 11:40:20 +01:00
ben-toogood d90cc8bf2f Merge branch 'master' into auth-has-role 2020-05-11 11:36:06 +01:00
Ben Toogood 5a8f19589b Auth account.HasRole 2020-05-11 11:34:22 +01:00
gggwvg d61df6363b web: fix advertise address (#1608)
* web: fix advertise address
* web: fix test

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
Co-authored-by: Asim Aslam <asim@aslam.me>
Co-authored-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-05-08 12:31:03 +03:00
ben-toogood f062013a7b Merge pull request #1607 from micro/k8s-debug
Log k8s Requests
2020-05-07 11:41:43 +01:00
Ben Toogood fea93a5b7a Log k8s Requests 2020-05-07 11:35:56 +01:00
fztcjjl 30dc29e17f fix ring buffer (#1606) 2020-05-07 10:45:48 +01:00
ben-toogood 5387f73b5d Handle cockroach createDB error (#1603) 2020-05-06 10:58:14 +01:00
Vasiliy Tolstov 90dd1f63c8 api/handler/rpc: fix encoding of inner message (#1601)
* api/handler/rpc: fix encoding of inner message

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-05-04 15:50:53 +03:00
Asim Aslam 38cdb9cc2f Set table name in store
Docker / build (push) Waiting to run
Run tests / Test repo (push) Waiting to run
2020-05-01 18:24:35 +01:00
Asim Aslam b3915b6020 Add store to options (#1600) 2020-05-01 18:05:09 +01:00
Asim Aslam 08a2de1ef5 Account for missing options database/table in cockroach store 2020-05-01 15:31:55 +01:00
Asim Aslam 7a2dea6cc2 Set database/table from init first 2020-05-01 15:22:44 +01:00
Asim Aslam 2a14feed93 force codec on call not on dial (#1599) 2020-05-01 14:59:50 +01:00
Asim Aslam e8105d22ad cruft 2020-05-01 00:25:17 +01:00
Asim Aslam c76a5e608d sql fixes 2020-04-30 23:53:54 +01:00
Asim Aslam 359b8bc503 Add opts to service proto (#1517)
* Add opts to service proto

* Support database/table opts
2020-04-30 22:51:25 +01:00
Janos Dobronszki fccab8ad27 Runtime name should be base folder outside repos (#1598) 2020-04-30 18:20:51 +02:00
Socket 46d09ec2bc unsubscribe can async (#1596)
Co-authored-by: huangshaojie <huangshaojie@corp.netease.com>
Co-authored-by: Asim Aslam <asim@aslam.me>
2020-04-30 10:42:13 +01:00
Asim Aslam 7792dbc34d Update FUNDING.yml 2020-04-29 18:45:55 +01:00
ben-toogood 1d29f126f9 Merge pull request #1595 from micro/auth-client-wrapper
Auth Client Wrapper
2020-04-29 15:43:30 +01:00
Ben Toogood bcddb98867 Fix Tests 2020-04-29 15:37:02 +01:00
Ben Toogood f48dec1fb0 Use Server ID in account name 2020-04-29 15:27:18 +01:00
Ben Toogood ef9f65c78b Improve Comments 2020-04-29 15:15:38 +01:00
Ben Toogood 99f8be5b3d Auth Client Wrapper 2020-04-29 15:11:06 +01:00
ben-toogood 9d2fdb84be Merge pull request #1592 from micro/jwt-auth
JWT auth implementation
2020-04-29 14:10:05 +01:00
ben-toogood 8b004feb9a Merge branch 'master' into jwt-auth 2020-04-29 13:33:47 +01:00
Ben Toogood 70736e24c0 Set RefreshToken 2020-04-29 13:33:22 +01:00
Vasiliy Tolstov d44adafca5 api/router: avoid unneeded loops and fix path match (#1594)
* api/router: avoid unneeded loops and fix path match

* if match found in google api path syntax, not try pcre loop
* if path is not ending via $ sign, append it to pcre to avoid matching other strings like
  /api/account/register can be matched to /api/account
* api: add tests and validations

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-29 15:23:10 +03:00
ben-toogood e57b20c1f8 Merge branch 'master' into jwt-auth 2020-04-29 13:22:09 +01:00
Ben Toogood 94971aee77 Complete JWT implementation 2020-04-29 13:21:51 +01:00
Ben Toogood 0ed66d0664 Fix Typo 2020-04-29 09:38:39 +01:00
Ben Toogood 7e27c97c6c Remove Comment 2020-04-29 09:22:15 +01:00
Ben Toogood 669364985e JWT auth implementation 2020-04-29 09:21:17 +01:00
Asim Aslam c7440274dd touch 2020-04-28 19:35:13 +01:00
Asim Aslam 8ccbf53dfc secret cookie unused 2020-04-28 18:12:07 +01:00
Asim Aslam f908110fb6 swap out context access for account (#1589) 2020-04-28 17:35:18 +01:00
Vasiliy Tolstov 9bb1904a38 broker: add publish context (#1590)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-28 19:29:00 +03:00
Vasiliy Tolstov 06220ab8c8 client: add context publish option (#1588)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-28 19:03:37 +03:00
Janos Dobronszki da66561d1e Fixing too large offsets for default runtime logs (#1587) 2020-04-28 13:42:15 +01:00
Dmitry Kozlov 52861310b0 fix HTTP 401 Unauthorized, {"message": "401: Unauthorized", "code": 0} (#1586)
fix file=bot.go:426 level=error service=bot error starting bot HTTP 401 Unauthorized, {"message": "401: Unauthorized", "code": 0}
see https://github.com/bwmarrin/discordgo#usage
2020-04-28 13:06:01 +01:00
Vasiliy Tolstov 414b2ec5f8 web: fix deadlock (#1585)
* web: fix deadlock

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* add web tests

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-28 12:23:52 +01:00
Janos Dobronszki b875868a39 Don't ignore errors from checkout source code (#1584)
Don't check out code for builtin services.
2020-04-28 10:51:39 +02:00
Janos Dobronszki 8148e0a0f8 Micro log fixes (#1570) 2020-04-28 09:49:39 +02:00
ben-toogood 25c82245b1 Merge pull request #1582 from micro/k8s-srv-accounts
Runtime: Add Kubernetes ServiceAccounts & Remove imagePullSecrets
2020-04-27 15:24:16 +01:00
ben-toogood 95a7e21f5f Merge branch 'master' into k8s-srv-accounts 2020-04-27 15:08:24 +01:00
Asim Aslam 83ab47333f rename Codec to Secrets (#1581) 2020-04-27 14:57:57 +01:00
Ben Toogood 8d7d6ef358 Add k8s secrets 2020-04-27 14:37:28 +01:00
Ben Toogood 494e0b5060 Runtime: Add Kubernetes ServiceAccounts & Remove imagePullSecrets 2020-04-27 14:13:51 +01:00
Janos Dobronszki 434997e676 Display only logging file name as opposed to path in logs (#1580) 2020-04-27 09:55:50 +01:00
Janos Dobronszki ec44b67e9f Fixing log file path in logs (#1578) 2020-04-27 09:36:09 +01:00
Vasiliy Tolstov e0c9234c0e web: use default logger (#1577)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-27 00:03:05 +03:00
Vasiliy Tolstov 980b772801 fix races in web and logger (#1576)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-26 17:41:36 +03:00
Vasiliy Tolstov a22da39e1c logger: add caller info to default implementation (#1575)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-26 17:11:53 +03:00
徐旭 7253635cd3 delete invalid copy (#1573)
* prealloc

* delete invalid copy
2020-04-26 12:44:59 +01:00
Asim Aslam 0a030f3d8a strip unused list endpoint 2020-04-24 18:05:38 +01:00
Asim Aslam edee3b6765 Add proxy env test (#1569) 2020-04-24 11:26:46 +01:00
Asim Aslam d62ae23a9c Strip label 2020-04-23 20:20:48 +01:00
Asim Aslam c68226e9b0 only do namespace check if not default 2020-04-23 19:19:13 +01:00
ben-toogood 041d68b1ce Merge pull request #1566 from micro/image-pull-secret-fix
Fix Runtime Namespace List
2020-04-23 18:16:38 +01:00
ben-toogood 85a8f36565 Merge branch 'master' into image-pull-secret-fix 2020-04-23 18:15:04 +01:00
Ben Toogood f34d58cfbd Remove Debug 2020-04-23 18:14:06 +01:00
Asim Aslam e0a651bfc3 set namespace on create 2020-04-23 18:10:13 +01:00
Ben Toogood cd35f503a0 Remove hardcoded labels 2020-04-23 18:08:02 +01:00
Ben Toogood 8b3d223fc0 Remove hardcoded labels: 2020-04-23 18:05:58 +01:00
Ben Toogood bb25bd94c8 Log k8s requests 2020-04-23 17:56:00 +01:00
ben-toogood 986e3d3c35 Merge pull request #1565 from micro/image-pull-secret-fix
Runtime: Fix ImagePullSecret
2020-04-23 17:53:09 +01:00
Ben Toogood 616db3442a Debugging 2020-04-23 17:44:40 +01:00
Ben Toogood 5fe3c0bfe5 Merge branch 'image-pull-secret-fix' of https://github.com/micro/go-micro into image-pull-secret-fix 2020-04-23 17:37:33 +01:00
Ben Toogood 8849b85a7f Merge branch 'master' of https://github.com/micro/go-micro into image-pull-secret-fix 2020-04-23 17:37:15 +01:00
ben-toogood 893bbafa03 Merge branch 'master' into image-pull-secret-fix 2020-04-23 17:28:06 +01:00
Ben Toogood 4c05623a3c Image pull secret fix 2020-04-23 17:26:59 +01:00
Asim Aslam ec929b3d2f log error and ensure we pass through namespace 2020-04-23 17:14:30 +01:00
Asim Aslam 2299559397 Check for namespace (#1564) 2020-04-23 16:22:41 +01:00
ben-toogood 6be53536d3 Merge pull request #1562 from micro/git-secrets
Runtime - Image Pull Secrets
2020-04-23 15:45:32 +01:00
ben-toogood 99d4b2b31a Merge branch 'master' into git-secrets 2020-04-23 15:39:37 +01:00
Janos Dobronszki ff8ad7d4ca Default runtime now checks out code on demand (#1563)
* Default runtime now checks out code on demand

* Go mod tidy
2020-04-23 16:30:43 +02:00
ben-toogood b692c045b5 Merge branch 'master' into git-secrets 2020-04-23 15:01:47 +01:00
Ben Toogood b5f53595ca Pass image_pull_secrets in runtime service 2020-04-23 14:22:23 +01:00
Ben Toogood 88176dca53 Remove debugging 2020-04-23 14:13:07 +01:00
Ben Toogood 020476614c Tweak CreateImagePullSecret 2020-04-23 14:06:33 +01:00
Ben Toogood 0f42346976 Additonal Debugging 2020-04-23 14:03:04 +01:00
ben-toogood 692b27578c Runtime Namespace (#1547)
* Add context option to runtime; Add dynamic namespace to kubectl client

* Add namespace runtime arg

* Fixes & Debugging

* Pass options in k8s runtime

* Set namespace on k8s resources

* Additional Logging

* More debugging

* Remove Debugging

* Ensure namespace exists

* Add debugging

* Refactor namespaceExists check

* Fix

* Fix

* Fix

* Fix

* Change the way we check for namespace

* Fix

* Tidying Up

* Fix Test

* Fix merge bugs

* Serialize k8s namespaces

* Add namespace to watch

* Serialize namespace when creating k8s namespace

Co-authored-by: Ben Toogood <ben@micro.mu>
Co-authored-by: Asim Aslam <asim@aslam.me>
2020-04-23 13:53:42 +01:00
Micro 316b81f790 Debugging 2020-04-23 13:11:00 +01:00
Micro 5e3262a62c Passs img pull secrets using name key 2020-04-23 12:52:59 +01:00
Micro 053fa0e457 Fix template syntax 2020-04-23 12:38:00 +01:00
Micro 501a6bf3ea Add imagePullSecrets to PodSpec 2020-04-23 12:27:36 +01:00
Asim Aslam 7345ce9192 change logging for service startup 2020-04-23 11:24:39 +01:00
Vasiliy Tolstov 6fa27373ed bundle qson lib in util (#1561)
* copy qson from https://github.com/joncalhoun/qson
  as author not want to maintain repo
* latest code contains our fix to proper decode strings
  with escaped & symbol
* replace package in api/handler/rpc

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-23 11:08:09 +03:00
徐旭 e55c23164a fix prealloc in trace (#1558) 2020-04-22 16:10:59 +03:00
Asim Aslam e25ab9f4ca Fix typo for proxy 2020-04-22 10:44:34 +01:00
Vasiliy Tolstov bea092f082 server: set registered only after configuring subscribers (#1557)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-21 23:01:59 +03:00
Asim Aslam d7ecb58f6c Add network proxying (#1556)
* Add network proxying

* go fmt
2020-04-21 15:54:40 +01:00
Jake Sanders 05d2b34e10 Add util/pki for creating and signing certificates (#1555) 2020-04-21 15:03:33 +01:00
ben-toogood 211fd9b9a3 Merge pull request #1554 from micro/oauth-login-hint
Add oauth login hint param
2020-04-21 13:40:47 +01:00
Ben Toogood 19f0836e70 Add oauth login hint param 2020-04-21 13:37:26 +01:00
Janos Dobronszki 075d7d4fef Renaming ShutdownSignals -> Shutdown (#1553) 2020-04-21 14:14:20 +02:00
Janos Dobronszki e5c215556e Add SIGKILL to shutdown signals (#1552)
* Add SIGKILL to shutdown signals

* go mod tidy

* Add missing file
2020-04-21 14:00:12 +02:00
Janos Dobronszki 7c31edd5f8 Enabling default runtime to run multiple versions (#1545)
* Enabling default runtime to run multiple versions

* Trigger build

* Fix

* Sprintf
2020-04-20 15:54:29 +02:00
Asim Aslam c4acf3c2cb Static serving disabled 2020-04-19 20:30:38 +01:00
Asim Aslam 53db26a614 Use go.micro.mu 2020-04-19 17:03:25 +01:00
Asim Aslam dde8f18b52 Update readme 2020-04-19 00:46:33 +01:00
Asim Aslam 6071b74fb5 Update readme 2020-04-19 00:45:29 +01:00
Asim Aslam ab041012b2 Update readme 2020-04-19 00:44:52 +01:00
Asim Aslam 226d6ad22b log whats happening in http handler 2020-04-19 00:41:03 +01:00
Asim Aslam a08ff90976 fix this bs logging issue 2020-04-18 23:36:00 +01:00
Asim Aslam ae8404d760 Log listening port 2020-04-18 23:32:20 +01:00
Vasiliy Tolstov f00fd7a49e api/router: support pcre and google.api pattern matching (#1549)
* api/router: support pcre and google.api pattern matching

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-19 00:31:34 +03:00
Asim Aslam ecbc42755c set network nodes in http resolver 2020-04-18 21:00:00 +01:00
Asim Aslam 16db76bee2 remove list endpoint from runtime and stop checking type in update 2020-04-17 17:54:34 +01:00
Asim Aslam dca5305e8a replaced build with updated timestamp in runtime 2020-04-17 16:29:05 +01:00
Asim Aslam c0b0f63757 Update docker workflow to push releases 2020-04-17 10:50:44 +01:00
Janos Dobronszki ac5822f1ee Fix local runtime updates (#1543) 2020-04-16 17:50:24 +02:00
ben-toogood ae56becbbd Merge pull request #1542 from micro/stream-auth
Set authorization header on grpc stream
2020-04-16 15:06:19 +01:00
ben-toogood 5bb18e685e Merge branch 'master' into stream-auth 2020-04-16 15:03:12 +01:00
Ben Toogood 2dfaab439c Set authorization header on grpc stream 2020-04-16 15:01:16 +01:00
Vasiliy Tolstov 62cedf64da api/router/registry: extract path based parameters from url to req (#1530)
Run tests / Test repo (push) Waiting to run
* api/router/registry: extract path based parameters from url to req
* api/handler/rpc: fix empty body request parsing
* bundle grpc-gateway util funcs

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-15 17:50:51 +03:00
ben-toogood 9961ebb46e Merge pull request #1538 from micro/rule-priority
Add priority to auth.CreateRequest and auth.DeleteRequest
2020-04-15 11:54:01 +01:00
Ben Toogood fe31a71557 Fix formatting 2020-04-15 11:50:52 +01:00
Ben Toogood c9a6b07c52 Add priority to auth.CreateRequest and auth.DeleteRequest 2020-04-15 11:49:24 +01:00
ben-toogood f1e6eff303 Merge pull request #1537 from micro/rule-priority
Add Priority to auth rules
2020-04-15 11:42:53 +01:00
Ben Toogood 2de03e5fd7 Tidy go mod 2020-04-15 11:39:53 +01:00
Ben Toogood 234c192faf Update protoc-gen-micro 2020-04-15 11:39:12 +01:00
Ben Toogood ea29920afb Add Priority to auth rules 2020-04-15 11:31:19 +01:00
Vasiliy Tolstov 4d177a782e vendor proto files from google (#1536)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-15 13:22:32 +03:00
Vasiliy Tolstov b700d425a4 api/handler/rpc: improvements and fixes (#1535)
* api/handler/rpc: fix empty body case
* api/handler/rpc: copy all request headers to metadata

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-15 01:37:15 +03:00
Asim Aslam 9a5b8ff50d use api 2020-04-14 22:14:55 +01:00
Asim Aslam c787fd0483 fix missing pointer 2020-04-14 17:13:38 +01:00
Asim Aslam 1134ea5ff3 make proto.Message compatible with raw json 2020-04-14 16:59:24 +01:00
ben-toogood fd16cd298f Merge pull request #1532 from micro/registry-namespace
Registry Namespace
2020-04-14 16:14:18 +01:00
ben-toogood 67e7aa223a Merge branch 'master' into registry-namespace 2020-04-14 16:03:29 +01:00
Asim Aslam 9d0381306d add a proto message without serialisation 2020-04-14 15:54:25 +01:00
ben-toogood f8837bfcbd Merge branch 'master' into registry-namespace 2020-04-14 15:37:44 +01:00
Vasiliy Tolstov 268651df18 regenerate all proto based files (#1531)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-14 16:25:09 +03:00
Ben Toogood e17825474f Add context options to the runtime 2020-04-14 12:32:59 +01:00
Ben Toogood 0c75a0306b Merge master into registry-namespace 2020-04-14 09:15:13 +01:00
Ben Toogood d61d30ef66 Inject Namespace into Context 2020-04-14 09:14:07 +01:00
Asim Aslam 71d4253927 Merge branch 'master' of ssh://github.com/micro/go-micro 2020-04-13 23:05:47 +01:00
Asim Aslam e515005083 Remove only allowing certain methods 2020-04-13 23:05:39 +01:00
Asim Aslam 4bdc18d64a Update README.md 2020-04-13 22:15:21 +01:00
Asim Aslam f840a5003e Remove runtime List 2020-04-12 23:46:06 +01:00
Asim Aslam 5ef1698632 remove readme 2020-04-12 23:43:55 +01:00
Asim Aslam 1bb6967a38 reorder 2020-04-12 23:41:21 +01:00
Asim Aslam a056bdce7c fix metadata parsing 2020-04-12 14:40:37 +01:00
Asim Aslam b08c636b44 fixup handler tests 2020-04-12 14:29:38 +01:00
Asim Aslam d03a02f2e4 fix import 2020-04-12 11:25:12 +01:00
Asim Aslam 08ca61c121 add metadata set 2020-04-12 11:17:23 +01:00
Asim Aslam 962588b649 Strip MetadataKey global var 2020-04-12 11:16:08 +01:00
Asim Aslam cf67d460b7 strip down mdns watcher 2020-04-12 11:01:09 +01:00
Asim Aslam 4e539361fa strip file 2020-04-12 10:58:12 +01:00
Vasiliy Tolstov 3ce2ab88f5 broker/nats: remove embed nats server reference (#1527)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-11 22:37:29 +03:00
Vasiliy Tolstov 0a2363b49b api minor improvements (#1526)
* api/handler/rpc: unblock all http methods and set Host meta
* api/router/static: add debug log

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-11 22:21:55 +03:00
Asim Aslam ec80ceb8c2 Update readme 2020-04-11 18:23:37 +01:00
Asim Aslam ea2bb0275c Strip external use of mdns 2020-04-11 13:02:53 +01:00
Asim Aslam 51d4f737b8 fixup store cache# 2020-04-11 12:10:19 +01:00
Asim Aslam 3f81f685df Move sync 2020-04-11 12:00:34 +01:00
Asim Aslam bb1ccf09e8 prefix store dir 2020-04-11 11:23:41 +01:00
Asim Aslam c878237567 fix log file creation 2020-04-11 11:22:02 +01:00
Asim Aslam ac8b6f944e Prefix logs dir micro/logs for runtime 2020-04-11 11:15:01 +01:00
Asim Aslam 0f2006ac50 fix compilation issues 2020-04-11 11:02:06 +01:00
Asim Aslam c697eed1be Update comments 2020-04-11 10:48:32 +01:00
Asim Aslam b887d91f94 remove readme 2020-04-11 10:38:13 +01:00
Asim Aslam 39470c1b11 Completely replace sync implementation 2020-04-11 10:37:54 +01:00
Asim Aslam 6d553cb6fe add whitespace 2020-04-11 09:34:04 +01:00
Asim Aslam c612d86480 Move sync store 2020-04-11 09:33:10 +01:00
Asim Aslam 3f3d2f5027 fixup broker http address 2020-04-11 01:51:26 +01:00
Vasiliy Tolstov bc71640fd9 broker: swap default broker from eats to http (#1524)
* broker: swap default broker from eats to http

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-11 03:46:54 +03:00
Asim Aslam b979db6d9d remove sync event 2020-04-10 23:29:15 +01:00
Asim Aslam 57b758db7e push 2020-04-10 22:09:06 +01:00
Asim Aslam b5f546b137 go mod tidy 2020-04-10 19:55:45 +01:00
Asim Aslam d4b2c948dd Remove cloudflare store 2020-04-10 19:50:57 +01:00
Asim Aslam b9a5e9d610 fixup sync map 2020-04-10 17:47:13 +01:00
Asim Aslam 57853b2849 remove etcd store 2020-04-10 17:43:02 +01:00
Asim Aslam e5268dd0a6 move reg util to own package (#1523)
* move reg util to own package

* fix test

* fix broken static router
2020-04-10 17:41:10 +01:00
Asim Aslam 4fd12430d0 cleanup mdns files 2020-04-10 17:19:26 +01:00
Asim Aslam d134b469be rename file 2020-04-10 17:17:24 +01:00
Asim Aslam 9a685b2df5 delete k8s registry (#1522) 2020-04-10 17:15:20 +01:00
Jake Sanders 6a666c9c7d Add json tags to store.Record (#1518) 2020-04-09 19:38:43 +01:00
Asim Aslam 53549b6b30 Add options for Database/Table (#1516)
* Add options for Database/Table

* fix opts
2020-04-09 17:56:13 +01:00
Jake Sanders 0a27a08184 Add Databases and Tables endpoints to store RPC proto (#1515)
* Add Databases and Tables to store RPC

* add Database to TablesRequest
2020-04-09 16:37:32 +01:00
Janos Dobronszki 77f0abb0ba Enabling micro run for subfolders (#1510)
* Enabling micro run for subfolders

* Use source instead of os.Args[2]

* Works now

* PR comments

* WorkDir -> Dir
2020-04-09 15:44:39 +01:00
Asim Aslam 29cccd0b4a minor tweak add log line to proxy and basic auth provider by default (#1513) 2020-04-09 14:10:17 +01:00
ben-toogood bf65dc71c7 Merge pull request #1505 from micro/resover-refactor
Extract Micro Resolver (Namespace)
2020-04-09 13:14:49 +01:00
Asim Aslam 5bc8ee39f7 Merge branch 'master' into resover-refactor 2020-04-09 13:07:05 +01:00
Vasiliy Tolstov 8c1b477279 store/cockroach: fixup test (#1512)
* store/cockroach: fixup test

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-09 14:58:50 +03:00
Ben Toogood f9cfbe96c0 Merge master into resover-refactor 2020-04-09 12:42:34 +01:00
Jake Sanders 2e379ca7d0 Don't break the build! 2020-04-09 12:18:02 +01:00
Jake Sanders 2659215d5e cockroachDB doesn't support this syntax (#1509) 2020-04-09 12:11:24 +01:00
Vasiliy Tolstov 1063b954de dont display t.Log/t.Logf as errors in github actions (#1508)
* fix tests and github action annotations

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-09 14:05:46 +03:00
Ben Toogood 4ff959ef50 Dynamic Namespace 2020-04-09 11:03:33 +01:00
Janos Dobronszki bc1c8223e6 Remove ugly unneeded log in runtime local (#1507) 2020-04-09 11:50:12 +02:00
Ben Toogood 27eb7db1c2 Add default resolver to api router 2020-04-09 10:34:21 +01:00
Ben Toogood 3ede494945 Change import name 2020-04-09 10:32:08 +01:00
Ben Toogood f102aba4c1 Fix HTTP tests 2020-04-09 10:28:38 +01:00
Asim Aslam f2dd091ec0 strip log 2020-04-09 10:28:16 +01:00
Asim Aslam c1ad6d6c7c set service name in web 2020-04-09 09:41:50 +01:00
Jake Sanders 1e7cd8c484 Make the constraint explicit rather than inferred (#1506) 2020-04-08 23:52:35 +01:00
Asim Aslam bf8ebf8ad2 add namespace 2020-04-08 23:27:32 +01:00
Asim Aslam 1768958af7 fix typo 2020-04-08 22:50:56 +01:00
Asim Aslam bf41d8d28e fix store table env var 2020-04-08 19:44:49 +01:00
Asim Aslam 45700eaabe set database/table in header 2020-04-08 19:25:57 +01:00
Asim Aslam 48dd30c4c2 fix http test 2020-04-08 19:20:43 +01:00
Ben Toogood 8ff86ae08b Extract micro resolver 2020-04-08 16:21:53 +01:00
Asim Aslam b2079669f7 Strip namespace from router 2020-04-08 15:39:01 +01:00
Asim Aslam 2c1d1afd71 Strip namespace from registry router 2020-04-08 15:38:02 +01:00
Asim Aslam 9a73828782 Remove unused handlers 2020-04-08 15:34:11 +01:00
ben-toogood c5d085cff8 Merge pull request #1496 from micro/namespace
Configurable Namespace & Public Suffix Domain Resolution
2020-04-08 13:48:50 +01:00
ben-toogood 9f4286fc4e Merge branch 'master' into namespace 2020-04-08 13:44:46 +01:00
Jake Sanders 77f5cc5023 Fix nil dereference in cloudflare store (#1504) 2020-04-08 13:00:30 +01:00
Vasiliy Tolstov 8400aba81c broker/memory: small memory improvements (#1501)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-08 14:56:54 +03:00
Jake Sanders cc027d900e Close statements, add default table if the store was not initialised through service.Init() (#1502) 2020-04-08 12:08:08 +01:00
Edward bc0dc2e509 fix :no syscall.Kill on windows #1474 (#1474) 2020-04-08 10:50:44 +01:00
Vasiliy Tolstov 1fbc056dd4 minimize allocations (#1472)
* server: minimize allocations on re-register

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* server: stop old instance before Init()

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* client/grpc: fix allocations in protobuf marshal

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* codec/json: fix allocations in protobuf marshal

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* remove stop from init

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* codec/grpc: expose MaxMessageSize

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* codec: use buffer pool

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* metadata: minimize reallocations

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* util/wrapper: use metadata helper

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* registry/cache: move logs to debug level

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* server: move logs to debug level

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* server: cache service only when Advertise is ip addr

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* server: use metadata.Copy

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-08 10:50:19 +01:00
Asim Aslam 98fc3dfbad use single data bucket 2020-04-08 09:57:51 +01:00
Asim Aslam 4b0e27413e add Store Close method (#1500)
* add Store Close method

* Update sync store build failure
2020-04-08 09:51:10 +01:00
ben-toogood 6b524e2c55 Merge branch 'master' into namespace 2020-04-08 09:12:28 +01:00
Asim Aslam 4cac7dcc48 fix file tests 2020-04-07 19:45:27 +01:00
Ben Toogood e907d24e3b API Wrappers 2020-04-07 19:29:26 +01:00
Asim Aslam 39c352f210 Remove the test that takes 30 seconds sleeping 2020-04-07 18:22:40 +01:00
Ben Toogood 67cd59d7bc Rename namespace from Resolver.Endpoint 2020-04-07 16:27:59 +01:00
Ben Toogood 3735b0e529 Remove global namespace option 2020-04-07 16:27:01 +01:00
Ben Toogood 4362a885eb Refactor Namespace Resolver 2020-04-07 16:24:51 +01:00
Janos Dobronszki 038b936ce9 Setting up file store in constructor and not in init which is o… (#1499) 2020-04-07 16:43:43 +02:00
Vasiliy Tolstov 6aaad7d63f api/router/static: allow to specify body dst (#1486)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-07 15:38:27 +01:00
Janos Dobronszki aaee01b1a7 Use file store by default (as opposed to memory store) (#1498)
* Use file store by default (as opposed to memory store)

* Default table for file store
2020-04-07 15:19:45 +02:00
Jake Sanders 71538adfdc Explicitly set the table name during service init (#1497) 2020-04-07 13:00:05 +01:00
Janos Dobronszki 2ea5b33955 Disk backed local store (#1491) 2020-04-07 13:53:22 +02:00
Ben Toogood 3df87510a1 Add namespace 2020-04-07 12:46:44 +01:00
Ben Toogood 9d598836c3 Fix Tests 2020-04-07 11:37:04 +01:00
Ben Toogood 05ac3ff274 Tweak 2020-04-07 11:24:13 +01:00
Ben Toogood 76f6f80318 Default to Hostname 2020-04-07 11:23:21 +01:00
Ben Toogood cb96949551 Merge branch 'master' of https://github.com/micro/go-micro into namespace 2020-04-07 10:58:54 +01:00
ben-toogood 87cc4f273b Merge pull request #1495 from micro/log-level
Change cross namespace request err level
2020-04-07 10:58:22 +01:00
Ben Toogood f0980e9b30 Change cross namespace request err level 2020-04-07 10:54:27 +01:00
Ben Toogood 977934f8fd ServiceNamespace => ServicePrefix in api server 2020-04-07 10:39:27 +01:00
Ben Toogood 9e116731b1 ServiceNamespace => ServicePrefix in api server 2020-04-07 10:38:27 +01:00
Ben Toogood 316424f0f7 Fix comments typo 2020-04-07 10:35:57 +01:00
Ben Toogood bd23dc1f18 Improve micro.mu check 2020-04-07 10:34:26 +01:00
Ben Toogood 501fc5c059 Refactor to use publicsuffix 2020-04-07 10:28:39 +01:00
Ben Toogood 11e1e9120a Remove debugging 2020-04-07 10:10:37 +01:00
Ben Toogood a81d86ed08 Merge Asim's Fixes 2020-04-07 10:08:06 +01:00
Ben Toogood 7206d5f964 Add Namespace to CombinedAuthHandler 2020-04-07 09:40:40 +01:00
Asim Aslam b5f5027549 Move store scope to util 2020-04-07 02:23:16 +01:00
Asim Aslam e8a86585da contains missing host port 2020-04-07 00:54:27 +01:00
Asim Aslam 5374896ed0 clone request 2020-04-07 00:29:35 +01:00
Asim Aslam b6348ba59a Fix cruft 2020-04-07 00:25:11 +01:00
Asim Aslam ca11c4a672 Few nitpicks 2020-04-07 00:19:49 +01:00
Lars Lehtonen 900b2d24f9 config/secrets/box: fix dropped test error (#1494) 2020-04-06 23:09:42 +01:00
Jake Sanders 3324d140c0 Rename store Namespace / Prefix options to Database and Table (#1492)
* Rename Namespace to DB, Rename Prefix to table, Remove Suffix Option

* Rename options

* Rename options

* Add store_table option

* Table per service, not Database per service
2020-04-06 16:45:55 +01:00
ben-toogood 3a378eb7d6 Merge pull request #1493 from micro/auth-encode-endpoint
Encode Endpoint in API auth wrapper
2020-04-06 16:21:14 +01:00
Ben Toogood 574bf5ac69 Set value in context, not metadata 2020-04-06 16:10:08 +01:00
Ben Toogood 774c0d30a7 Encode Endpoint in API auth wrapper 2020-04-06 16:01:42 +01:00
ben-toogood 0f570d98e1 Merge pull request #1475 from micro/auth-resolver
Auth integrate resolver to support micro web & api
2020-04-06 14:57:41 +01:00
ben-toogood 7f07e1a642 Merge branch 'master' into auth-resolver 2020-04-06 14:43:22 +01:00
ben-toogood 9b546a7242 Change auth namespace log level (#1490)
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-04-06 13:51:28 +01:00
Asim Aslam c4442a7533 Don't set the registry in new options for web services (#1489) 2020-04-06 13:40:40 +01:00
ben-toogood bea7c3f7e7 Merge pull request #1488 from micro/disable-warn-log
Change namespace error log level
2020-04-06 12:55:47 +01:00
ben-toogood cca9773269 Merge branch 'master' into disable-warn-log 2020-04-06 12:51:47 +01:00
Ben Toogood 600b20fb81 Change namespace error log level 2020-04-06 12:50:04 +01:00
Edward 31a1ea6fae fix: use registry from opts not use default directly:(#1436) (#1468)
web: use passed user registry, or default
2020-04-05 13:15:38 +03:00
Vasiliy Tolstov bc7579f1d8 api/handler/rpc: fix panic on invalid error conversation (#1483)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-04 00:55:15 +03:00
Vasiliy Tolstov 38aed6f0f6 api/handler/rpc: not log error on client disconnect (#1482)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-04 00:37:18 +03:00
ben-toogood 7f8b35e295 Merge pull request #1480 from micro/host-fix
Add Debugging
2020-04-03 15:07:22 +01:00
ben-toogood b09dd9a689 Merge branch 'master' into host-fix 2020-04-03 15:03:49 +01:00
Ben Toogood a82ce4d1ae Add Debug 2020-04-03 15:03:18 +01:00
ben-toogood 34234fc486 Merge pull request #1479 from micro/host-fix
Auth host fix
2020-04-03 14:43:35 +01:00
Ben Toogood 4a850ff8a0 Auth host fix 2020-04-03 14:40:24 +01:00
ben-toogood 350dd41732 Merge branch 'master' into auth-resolver 2020-04-03 14:19:03 +01:00
ben-toogood d8cca31738 Merge pull request #1478 from micro/auth-hosts-fix
Fix auth hosts bug
2020-04-03 14:13:51 +01:00
Ben Toogood b864b3e350 Fix auth hosts bug 2020-04-03 14:09:25 +01:00
ben-toogood 41b746e435 Merge pull request #1477 from micro/fix
Hotfix
2020-04-03 13:37:50 +01:00
Ben Toogood 906263291b Hotfix 2020-04-03 13:37:02 +01:00
ben-toogood 46f0bda31e Merge pull request #1476 from micro/namespace-fix
Namespace Fix
2020-04-03 13:30:30 +01:00
Ben Toogood d0e47206cc Fix 2020-04-03 13:29:48 +01:00
ben-toogood ed6fe67880 Merge pull request #1471 from micro/namespace
Detect & Propagate Namespace
2020-04-03 13:07:26 +01:00
Ben Toogood 1374a9e528 Fix namespace bug in auth wrapper 2020-04-03 13:03:27 +01:00
Ben Toogood a9c0e043d2 Fix nil grpc server auth bug 2020-04-03 12:50:50 +01:00
Ben Toogood 49a568e9c0 Set default server auth 2020-04-03 12:33:19 +01:00
Ben Toogood dea2d7ab9f Fix go-micro auth wrapper init 2020-04-03 12:27:01 +01:00
Ben Toogood ebb1a42d48 Merge branch 'namespace' of https://github.com/micro/go-micro into namespace 2020-04-03 12:14:26 +01:00
Ben Toogood 1096c8fb39 Fix failing test 2020-04-03 10:16:19 +01:00
Ben Toogood 91b9c3f92e Add defaults 2020-04-03 10:08:39 +01:00
Ben Toogood 183c8bfb81 Apply fix for apis 2020-04-03 09:45:39 +01:00
Ben Toogood 49a1130281 Merge branch 'auth-resolver' of https://github.com/micro/go-micro into auth-resolver 2020-04-03 09:34:57 +01:00
Ben Toogood 760233b858 Reverse Change 2020-04-03 09:34:52 +01:00
ben-toogood ede076e899 Merge branch 'master' into auth-resolver 2020-04-03 09:33:13 +01:00
Ben Toogood fdcb013f24 Fix web registry compatability bugs 2020-04-03 09:18:30 +01:00
Ben Toogood ce23ab36cb Improve Err Handling 2020-04-02 18:41:06 +01:00
ben-toogood 61f0619e97 Merge branch 'master' into namespace 2020-04-02 18:05:21 +01:00
Ben Toogood cfde3ec3d9 Remove resolver logic 2020-04-02 18:03:57 +01:00
Ben Toogood 4a4c666528 Remove resolver logic 2020-04-02 18:03:21 +01:00
Ben Toogood 8b35c264eb Pass resolver to api auth handler 2020-04-02 17:44:48 +01:00
Ben Toogood 4999f6dfd4 Namespace requests coming via api & web 2020-04-02 17:01:06 +01:00
Asim Aslam 31c4452fc7 delete monitor (#1470) 2020-04-02 14:05:17 +01:00
Janos Dobronszki 2cafa289b6 Stop LogStream if there is an error in k8s pod log streaming (#1469)
* Stop LogStream if there is an error in k8s pod log streaming

* Locking stream Stops

* PR comment
2020-04-02 12:16:35 +01:00
Vasiliy Tolstov 0241197c6a api/handler/rpc: binary streaming support (#1466)
* api/handler/rpc: binary streaming support

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* fixup

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* fix

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* fix sec webscoekt protol

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-02 10:13:04 +01:00
Asim Aslam 0a15ae9b9d Move String method (#1467) 2020-04-01 23:27:15 +01:00
Janos Dobronszki d2b6d35220 log.Errorf when pod streaming fails (#1463)
* log.Errorf when pod streaming fails

* Error method added for loggers

Co-authored-by: Asim Aslam <asim@aslam.me>
2020-04-01 23:03:26 +01:00
Asim Aslam e1bc0f6288 replace strings for store prefix (#1465)
Co-authored-by: ben-toogood <bentoogood@gmail.com>
2020-04-01 20:19:21 +01:00
ben-toogood cd3d704aa5 Merge pull request #1459 from micro/auth-interface-update
Auth Interface Iteration
2020-04-01 17:56:38 +01:00
Ben Toogood 9de69529ce Fix token tests 2020-04-01 17:29:17 +01:00
ben-toogood 623f0c0c90 Merge branch 'master' into auth-interface-update 2020-04-01 17:24:01 +01:00
Ben Toogood c766679687 Fix typo 2020-04-01 17:22:01 +01:00
Ben Toogood df8c0bb5e1 Auth Generate, make secret optional 2020-04-01 17:20:02 +01:00
Ben Toogood d577c32563 Add back auth.PrivateKey 2020-04-01 17:17:40 +01:00
Ben Toogood 365dfe9df5 Code => State 2020-04-01 17:11:46 +01:00
Ben Toogood ae15793fc3 Support oauth codes 2020-04-01 15:36:22 +01:00
Janos Dobronszki 15fcd5ecef Remove Go micro 1.18 dependency (#1462) 2020-04-01 16:14:08 +02:00
Ben Toogood 1750fd8d10 Merge branch 'auth-interface-update' of https://github.com/micro/go-micro into auth-interface-update 2020-04-01 14:42:37 +01:00
Ben Toogood 525ab094c8 Remove LoginOptions 2020-04-01 14:42:11 +01:00
Janos Dobronszki bb51b8203e Runtime logs (#1447)
* Runtime logs

* Slightly broken

* Pushing for diff

* Log trailing works locally

* LogsOptions

* Comments and streamcount support for local logs

* Adding kubernetes logs

* Fixing k8s logs

* K8s fixes

* StreamCount is now nuked

* PR comments

* PR comments again

* Fix typo
2020-04-01 15:40:15 +02:00
ben-toogood 75a75c56ad Merge branch 'master' into auth-interface-update 2020-04-01 14:37:06 +01:00
Ben Toogood 26cb6bf5b9 Remove Legacy JWT fields 2020-04-01 14:27:56 +01:00
Ben Toogood 9cbbd71855 Remove default login 2020-04-01 14:26:24 +01:00
Ben Toogood f7655b71ea Merge branch 'auth-interface-update' of https://github.com/micro/go-micro into auth-interface-update 2020-04-01 14:25:07 +01:00
Ben Toogood 8e4d9e1702 Further Refactoring 2020-04-01 14:25:00 +01:00
Asim Aslam 20c95d94cd api completeness (#1460) 2020-04-01 12:07:50 +01:00
ben-toogood 0a7d8afe67 Merge branch 'master' into auth-interface-update 2020-04-01 09:42:45 +01:00
Vasiliy Tolstov 7b7a859a03 api: use http request Clone (#1458)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-01 01:50:37 +03:00
Vasiliy Tolstov 8a8742f867 api/handler/rpc: dont change types of url fields (#1457)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-01 01:26:58 +03:00
Asim Aslam 68b0238a5d add stream timeout option which defaults to 0 (#1456)
* add stream timeout option which defaults to 0

* fix option
2020-03-31 23:22:11 +01:00
Vasiliy Tolstov 1490aff38e api/handler/rpc: correctly parse nested url vars (#1455)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-04-01 00:23:17 +03:00
Vasiliy Tolstov 3a22efbd7d metadata: change method name (#1454)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-31 23:39:18 +03:00
Vasiliy Tolstov 5e65a46be3 metadata: allow to remove key from metadata (#1453)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-31 22:55:33 +03:00
Vasiliy Tolstov 18061723bb fix api metadata extract from context (#1452)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-31 22:36:51 +03:00
Vasiliy Tolstov d6bef84de0 api/handler/rpc: fix metadata cleanup (#1451)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-31 21:59:35 +03:00
Ben Toogood 82bc3cbf8d Update interface to add provider and make secret optional 2020-03-31 19:01:43 +01:00
Ben Toogood cffb0a1eae Remove ContextWithToken 2020-03-31 18:34:31 +01:00
Ben Toogood 134bc1c68a Implement new interface 2020-03-31 18:17:01 +01:00
Asim Aslam 6c6c5359b1 Add options to config (#1450) 2020-03-31 17:13:21 +01:00
Ben Toogood 8dbb5153f4 Tweak Auth Interface 2020-03-31 17:01:51 +01:00
ben-toogood 2674790694 Service => Service Auth (#1448)
* Service => Service Auth

* WithServicePrivileges => ServicePrivileges

* Fixes for CLI login

* ServicePrivileges => ServiceToken

* Fallback to service token

Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-31 16:18:04 +01:00
ben-toogood 9fb1d476a2 Merge branch 'master' into auth-srv-srv 2020-03-31 16:15:17 +01:00
Ben Toogood 36386354d7 Fallback to service token 2020-03-31 13:51:32 +01:00
Ben Toogood bd70820b6b ServicePrivileges => ServiceToken 2020-03-31 13:48:28 +01:00
Ben Toogood 956029ae3d Fixes for CLI login 2020-03-31 13:30:14 +01:00
Ben Toogood e0c7f48d20 WithServicePrivileges => ServicePrivileges 2020-03-31 12:57:38 +01:00
Ben Toogood d659e435c6 Service => Service Auth 2020-03-31 12:44:34 +01:00
Jake Sanders 3d274ab6a2 Add namespace support to Kubernetes client (#1446)
* Add namespace support to Kubernetes client

* Fix LastUpdateTime Condition
2020-03-31 12:03:32 +01:00
Asim Aslam 1222d076f2 There can be only one! (#1445)
Run tests / Test repo (push) Waiting to run
* There can be only one

* fix proto?
2020-03-31 10:18:50 +01:00
ben-toogood 76ade7efd9 Auth - Swap Refresh to Token and change secrets to be strings, not tokens (#1444)
* Refresh => Token

* Secret is no longer a token

Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-31 10:06:13 +01:00
Vasiliy Tolstov c706ebe3fb auth proto: provide help to protoc-gen-go (#1442)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-31 00:35:11 +03:00
Vasiliy Tolstov 9e6db79860 regenerate all proto (#1440)
* regenerate all proto

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* regenerate from proto

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* regenerate from proto

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-30 21:58:32 +01:00
Vasiliy Tolstov 756b346672 auth/service: move all proto files to single dir (#1439)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-30 18:23:00 +03:00
ben-toogood 4db2f5e79d Add Namespace to Auth (#1438)
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-30 09:51:37 +01:00
Vasiliy Tolstov 3d7d5ce6b4 api: add static router and improve path parser in rpc handler (#1437)
* api: add static router and improve path parser in rpc handler

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* expose metadata context key to be able to get unmodified map keys

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* server/grpc: fix jsonpb codec for protobuf msg

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* api/handler/rpc: write 204 status code when rsp is nil

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* api/handler/rpc: add check for nil response for non javascript

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-30 09:04:59 +01:00
Socket 8282e781e4 grpc pool should check state (#1435)
Co-authored-by: huangshaojie <huangshaojie@corp.netease.com>
2020-03-28 08:48:25 +00:00
Vasiliy Tolstov e4acc63d5f add mdns registry debug (#1434)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-27 22:33:49 +03:00
Asim Aslam 45ee5e9ad1 Move error for api validation to trace level (#1432)
* remove error on endpoint validation

* trace level
2020-03-27 14:01:47 +00:00
Asim Aslam b60fde0e64 Pass through source and metadata in Update and Delete calls to runtime (#1431) 2020-03-27 11:37:12 +00:00
Lars Lehtonen 011a783a9e store/cockroach: fix dropped test errors (#1419)
Co-authored-by: Asim Aslam <asim@aslam.me>
2020-03-27 10:15:37 +00:00
ben-toogood 6723d17b22 Default auth, return account secret on Inspect (#1430)
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-27 09:54:29 +00:00
ben-toogood 47c7181d41 Default Auth: Add blank secret to account to prevent nil errors (#1429)
* Remove debug auth logs

* Default auth, return account secret on Inspect

Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-27 09:46:17 +00:00
Vasiliy Tolstov b38da6ced0 api/handler/rpc: process all methods and merge url params to json body (#1427)
* api/handler/rpc: process all methods and merge url params to json body

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* add merge json test

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-27 07:59:31 +00:00
ben-toogood 1a53307a78 Remove debug auth logs (#1426)
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-26 19:00:24 +00:00
Asim Aslam e204f3e2e8 Add metadata Get method (#1425) 2020-03-26 18:50:00 +00:00
ben-toogood 329bd09f93 Fix Auth Init bug (#1424)
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-26 18:09:51 +00:00
ben-toogood 4648fd0d09 Auth debugging (#1423)
* More auth debugging

* More auth debugging

* Increase auth debugging

Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-26 17:55:35 +00:00
ben-toogood c905df3be6 Log auth verify requests (#1422)
* More auth debugging

* More auth debugging

Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-26 17:35:28 +00:00
Asim Aslam 62f9a054a4 100mb (#1421) 2020-03-26 16:57:31 +00:00
ben-toogood 00e7804f96 Auth - Add debugging to loading rules (#1420)
* Fix auth multi-rule edgecase

* Add logging to auth rules

Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-26 16:30:31 +00:00
ben-toogood 42b6bf5bbf Fix auth multi-rule edgecase (#1418)
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-26 15:52:48 +00:00
ben-toogood 844c456839 Refactor Auth Service Protos, Add Access Rules (#1411)
* Refactor auth/service into two protos

* Accounts Proto

* Store Prefixes

* Misc

* Tweak Protos

Co-authored-by: Ben Toogood <ben@micro.mu>
Co-authored-by: Asim Aslam <asim@aslam.me>
2020-03-26 13:12:43 +00:00
Asim Aslam 7182ca1fd0 fix server logging (#1417) 2020-03-26 13:08:06 +00:00
Vasiliy Tolstov 02839cfba5 api/handler: use http.MaxBytesReader and buffer pool (#1415)
* api/handler: use http.MaxBytesReader

protect api handlers from OOM cases

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-26 14:29:28 +03:00
Asim Aslam 776a7d6cd6 Update filter comment for proxy (#1416) 2020-03-26 08:05:00 +00:00
Vasiliy Tolstov beaa434610 logger: fix reading env var (#1414)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-25 22:00:43 +00:00
Asim Aslam 6efc5556e5 use requested service (#1413) 2020-03-25 20:59:37 +00:00
Asim Aslam 8d0826a031 Add check for k8s condition (#1412) 2020-03-25 19:32:41 +00:00
ben-toogood 378d03eb66 Tidying up auth (#1410)
* Don't clear auth rules if request fails

* Add jitter to auth service loading rules

* Remove unused error from ContextWithToken result

Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-25 18:34:13 +00:00
ben-toogood 56af826230 Update auth to pass seconds and not nanoseconds (#1409)
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-25 17:03:45 +00:00
ben-toogood 511ebd8ec2 Fix Token Expiry Bug (#1408)
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-25 14:40:37 +00:00
ben-toogood 1057ef6acb Add ContextWithToken (#1407)
* Add ContextWithToken

* Tidying up BearerScheme

Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-25 11:20:53 +00:00
ben-toogood 35e2a68a98 Fix auth bug restricting access to unauthorised endpoints (#1405)
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-25 10:31:33 +00:00
ben-toogood 0e56382107 Fix service level auth, add improved error descriptions to aid with debugging (#1403)
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-25 09:35:29 +00:00
Jake Sanders dff98355be Missing ; in SQL query 2020-03-24 23:49:09 +00:00
Vasiliy Tolstov 8100d26430 api/router/registry: use logger (#1402)
* api/router/registry: use logger

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* api/server/acme: use logger

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-24 20:45:11 +00:00
Jake Sanders 397a8638f4 Cockroach Store bugfix (#1401) 2020-03-24 17:16:38 +00:00
Jake Sanders eb4d2ae6aa Remove useless variable from cockroach store (#1400) 2020-03-24 15:37:30 +00:00
Jake Sanders 914340585c Trim space from env variables (#1399) 2020-03-24 14:51:43 +00:00
ben-toogood 84b4eb5404 Fix missing loop (#1398)
* WithRoles variadic args

* Load Rules

* Timer => Ticker

* Add missing for loop in auth service

Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-24 14:16:57 +00:00
ben-toogood fd664f4392 Auth load rules (#1397)
* WithRoles variadic args

* Load Rules

* Timer => Ticker

Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-24 13:48:37 +00:00
ben-toogood 86272a3064 WithRoles variadic args (#1395)
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-24 10:18:34 +00:00
ben-toogood c1978265ab Auth Wildcard Endpoints (#1394)
* Auth Wildcard Endpoints

* Fix joinkey bug, improve tests

* Change joinKey

Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-24 09:39:33 +00:00
ben-toogood e0e77f3983 Updated auth interface (#1384)
* Updated  auth interface

* Add Rule

* Remove Rule

* Return token from Renew

* Renew => Refresh

* Implement Tokens & Default Auth Implementation

* Change default auth to noop

* Change default auth to noop

* Move token.Token to auth.Token

* Remove Token from Account

* Auth service implementation

* Decode JWT locally

* Cookie for secret

* Move string to bottom of interface definition

* Depricate auth_exclude

* Update auth wrappers

* Update go.sum

Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-23 16:19:30 +00:00
Vasiliy Tolstov 9826ddbd64 api/handler/rpc: log errors (#1390)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-23 10:31:35 +03:00
0987363 87617be227 Add client header to rpcRequest header; issue #957 (#1378)
Co-authored-by: Asim Aslam <asim@aslam.me>
2020-03-21 23:25:23 +00:00
Vasiliy Tolstov d559587807 client/grpc: remove json-iterator usage (#1387)
* minimize external deps and binary size
* if user wants json-iterator codec it must be used in server and
  client code. so best to use it via go-plugins

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-21 09:40:58 +00:00
Janos Dobronszki 9501512219 Auth util func RequestToContext (#1386) 2020-03-20 15:23:12 +00:00
Asim Aslam d2f153d795 Add type of service (#1385) 2020-03-20 12:48:12 +00:00
Asim Aslam e49be1da42 fix local runtime (#1383) 2020-03-19 22:38:37 +00:00
Jake Sanders 4c6f68d537 Implement store read cache (#1366)
* Implement store read cache

* Added cache tests and fixed a bug in memory store
2020-03-19 18:19:07 +00:00
Vasiliy Tolstov cbb958def5 config: fix panic on multiple Close() (#1374)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-19 12:54:59 +03:00
Asim Aslam 40ff6ddfcf sigh, further status changes (#1371) 2020-03-18 22:47:03 +00:00
Asim Aslam 5ad7c36bd4 Fix labels for k8s (#1370) 2020-03-18 22:13:21 +00:00
Asim Aslam 99c3fe2bb8 fix status parsing (#1368) 2020-03-18 21:50:52 +00:00
Asim Aslam 1bd340701b add k8s service ip to metadata (#1367)
* add k8s service ip to metadata

* go fmt

* use same port as container
2020-03-18 18:27:29 +00:00
Jake Sanders c91bf7e9e7 [WIP] Store Sync (#1365)
* Initial cache implementation

* Write queue implementation

* Accidentally started writing the storage sync service
2020-03-18 16:39:36 +00:00
Vasiliy Tolstov 41f8a8cb00 errors: add FromError func (#1362)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-18 03:10:38 +03:00
ben-toogood cd04111e3d Pass redirect_to param on auth (#1361)
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-17 20:04:16 +00:00
ben-toogood 00cd2448a4 Fix bug where auth token is not set from cookie when excluded endpoint (#1360)
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-17 19:24:10 +00:00
ben-toogood 8a41d369f2 Auth JWT ID Fix (#1359)
* Auth JWT ID Fix

* Remove unused ID in jwt claims

Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-17 16:59:57 +00:00
Jake Sanders 638c219736 Cockroach store feature completion (#1358)
* Start fixing cockroach store

* Add prefix, suffix, limit, offset for cockroachdb store
2020-03-17 16:15:23 +00:00
ben-toogood b3c631dd38 Support Wildcard Auth Excludes (#1357)
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-17 16:03:49 +00:00
Vasiliy Tolstov ab73127063 grpc client/server fixes (#1355)
Run tests / Test repo (push) Waiting to run
* grpc client/server fixes

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-17 14:27:20 +03:00
Asim Aslam 03031a694d use pod phase/status (#1356) 2020-03-16 23:47:34 +00:00
li.peng 5712aafba9 fix: context cancel (#1350)
Co-authored-by: Asim Aslam <asim@aslam.me>
2020-03-16 10:45:33 +00:00
Vasiliy Tolstov ac333d9d47 client/grpc: unwrap error after call (#1352)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-16 13:33:38 +03:00
ben-toogood 247707f583 Return store.ErrNotFound if not found when calling over rpc (#1353)
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-16 10:30:56 +00:00
ben-toogood d91c14eb30 grpc client error fix (#1351)
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-16 12:53:15 +03:00
Asim Aslam ca8684a886 fix k8s issues (#1349) 2020-03-15 15:09:18 +00:00
Asim Aslam 0449138f61 fix panic (#1348) 2020-03-14 21:18:41 +00:00
Vasiliy Tolstov 609f4826b3 server: remove duplicate code (#1346)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-13 22:15:09 +00:00
Vasiliy Tolstov 60993e6275 config/source/service: base64 fix (#1345)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-13 21:44:55 +00:00
Asim Aslam e803fb0855 Runtime hacks (#1344)
* Add Args/Image to runtime

* remove the hacks
2020-03-13 18:39:59 +00:00
Vasiliy Tolstov 3543b275e0 fix log level helper (#1342)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-13 17:36:42 +03:00
Vasiliy Tolstov fbde872e7f Revert "server/grpc: fix ordering of register and check for registered (#1338)" (#1341)
This reverts commit 62a644ddd8.
2020-03-13 09:30:44 +00:00
Asim Aslam 078dd4eb9b fix etcd (#1340)
* fix etcd

* update go mod
2020-03-13 08:55:23 +00:00
Vasiliy Tolstov 62a644ddd8 server/grpc: fix ordering of register and check for registered (#1338)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-12 22:04:11 +00:00
Asim Aslam d8cfa7a295 add config to cmd (#1337)
* add config to cmd

* fix build
2020-03-12 18:47:40 +00:00
ben-toogood 47f1203e97 Add Config to service options (#1336)
Co-authored-by: Ben Toogood <ben@micro.mu>
Co-authored-by: Asim Aslam <asim@aslam.me>
2020-03-12 18:13:03 +00:00
Jake Sanders 1b4e881d74 Rewrite the store interface (#1335)
* WIP store rewrite

* Fix memory store tests

* Store hard expiry times rather than duration!

* Clarify memory test

* Add limit to store interface

* Implement suffix option

* Don't return nils from noop store

* Fix syncmap

* Start fixing store service

* wip service and cache

* Use _ for special characters in cockroachdb namespace

* Improve cockroach namespace comment

* Use service name as default store namespace

* Fixes

* Implement Store Scope

* Start fixing etcd

* implement read and write with expiry and prefix

* Fix etcd tests

* Fix cockroach store

* Fix cloudflare interface

* Fix certmagic / cloudflare store

* comment lint

* cache isn't implemented yet

* Only prepare DB staements once

Co-authored-by: Ben Toogood <ben@micro.mu>
Co-authored-by: ben-toogood <bentoogood@gmail.com>
2020-03-12 13:41:30 +00:00
ben-toogood 20ce61da5a Oauth google fixes (#1330)
* Fix Auth Headers

* Tweak Oauth to work for Google

Co-authored-by: Ben Toogood <ben@micro.mu>
Co-authored-by: Asim Aslam <asim@aslam.me>
2020-03-12 13:11:35 +00:00
chengguoqiang eef4825be4 Update etcd.go (#1334)
add leaseId to the trace log
2020-03-12 10:09:38 +00:00
Asim Aslam be9c6141f5 delete options (#1333) 2020-03-12 09:05:09 +00:00
Asim Aslam 1ca4619506 return store.ErrNotFound (#1332) 2020-03-11 23:09:42 +00:00
Asim Aslam f55493993c set namespace rather than key (#1331) 2020-03-11 22:31:24 +00:00
Vasiliy Tolstov 7b385bf163 minimize allocations in logger and tunnel code (#1323)
* logs alloc

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* fix allocs

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* fix allocs

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* tunnel allocs

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* try to fix tunnel

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* cache cipher for send

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* more logger

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* more logger

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* more logger

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* more logger

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* more logger

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* more logger

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* more logger

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-11 17:55:39 +00:00
Jake Sanders 4125ae8d53 Add secrets interface to config/secrets (#1325)
* Interface for secrets

* Add secretbox secrets implementation

* Start working on box

* typo

* Add asymmetric encryption implementation

* go mod tidy

* Fix review comments

Co-authored-by: Asim Aslam <asim@aslam.me>
2020-03-10 22:52:06 +00:00
ben-toogood 48b2a5c37c Fix Auth Headers (#1324)
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-10 16:47:01 +00:00
Asim Aslam ed83c27f0e add websocket streaming to api rpc handler (#1326) 2020-03-10 15:21:43 +00:00
Vasiliy Tolstov 241614ff68 add helper function to determine logger level (#1321)
* add helper function to determine logger level

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-09 23:43:05 +03:00
mlboy 1a4f608ed1 add: auth add generate options Expiry for set token expires (#1319)
Co-authored-by: mlboy <ml3@meitu.com>
Co-authored-by: Asim Aslam <asim@aslam.me>
2020-03-09 17:16:31 +00:00
Vasiliy Tolstov 43b0dbb123 tunnel: reduce allocation and improve performance (#1320)
* tunnel: reduce allocation and improve performance

BenchmarkSha256Old-16 100000 156748 ns/op 11835 B/op 168 allocs/op
BenchmarkSha256Old-16 100000 156229 ns/op 11819 B/op 168 allocs/op

BenchmarkSha256New-16 100000 154751 ns/op 11107 B/op 161 allocs/op
BenchmarkSha256New-16 100000 154263 ns/op 11110 B/op 161 allocs/op

simple change lowers allocations and brings performance

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* fix

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* tunnel: reuse buf in Decrypt

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* fix unneeded conversations

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* base32 string is smaller than hex string

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-09 17:10:08 +00:00
ben-toogood b344171c80 URL Encode Provider.Endpoint() (#1317)
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-09 10:21:49 +00:00
ben-toogood e3ce45495a os.Exit on log.Fatal (#1316)
* os.Exit on log.Fatal

* Fix TestOptions

Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-09 09:23:42 +00:00
Vasiliy Tolstov f01664a551 Merge pull request #1313 from micro/upstream
fix ipv6 address usage in mdns registry and util/addr
2020-03-07 23:50:03 +03:00
Vasiliy Tolstov 8ecbdc1cd6 registry/mdns: add logging for invalid endpoint
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-07 23:19:48 +03:00
Vasiliy Tolstov 55c19afb0b registry/mdns: fix ipv6 addr in mdns registry
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-07 23:17:00 +03:00
Vasiliy Tolstov 077063c212 util/addr: check ip addrs before return
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-07 23:13:56 +03:00
ben-toogood 9a7a65f05e Auth Provider (#1309)
* auth provider mock interface

* Auth Provider Options

* Implement API Server Auth Package

* Add weh utils

* Add Login URL

* Auth Provider Options

* Add auth provider scope and setting token in cookie

* Remove auth_login_url flag

Co-authored-by: Asim Aslam <asim@aslam.me>
Co-authored-by: Ben Toogood <ben@micro.mu>
2020-03-07 11:06:57 +00:00
Vasiliy Tolstov 8ee5607254 [WIP]: broker ErrorHandler option (#1296)
* broker ErrorHandler option

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* rewrite Event interface, add error

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* implement new interface

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* change ErrorHandler func to broker.Handler

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* fix

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-06 21:25:16 +00:00
Vasiliy Tolstov 11be2c68b9 util/stream: fix imports (#1310)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-06 21:17:57 +00:00
Vasiliy Tolstov a864f812f1 web: fix ipv6 address issue (#1308)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-06 18:44:56 +03:00
Asim Aslam ae60bea8d8 add stream fix (#1305) 2020-03-06 14:40:47 +00:00
Jake Sanders a851b9db7a Comment typo in gRPC subscriber (#1304) 2020-03-05 14:55:46 +00:00
Vasiliy Tolstov d807dac2a7 server/grpc: avoid panic in case of nil Header (#1303)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-05 17:45:31 +03:00
Vasiliy Tolstov ce2ba71002 server: subscribe to topic with own name if router not nil (#1295)
* server: subscribe to topic with own name if router not nil

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-05 10:29:50 +03:00
Asim Aslam 67c26c71b6 add jitter (#1298) 2020-03-04 15:37:17 +00:00
ben-toogood 9386f36a13 Exit on log.Fatal (#1297) 2020-03-04 13:46:01 +00:00
ben-toogood 6d803d9e45 Implement api/server/cors (#1294) 2020-03-04 11:40:53 +00:00
ben-toogood 6a9001bdb1 Set auth account in context (#1293) 2020-03-04 09:54:52 +00:00
Jake Sanders 3f0c28a815 Expiration is actually a unix timestamp (#1290)
* Expiration is actually a unix timestamp

* int -> int64
2020-03-03 18:15:50 +00:00
Asim Aslam 49ffc60afb Use Foo.Call on /foo (#1286)
Co-authored-by: Jake Sanders <i@am.so-aweso.me>
2020-03-03 16:47:15 +00:00
Jake Sanders beb5e80e87 Fix nil pointer dereference (#1289) 2020-03-03 13:54:56 +00:00
Jake Sanders eebd69c995 Change from renekroon/ttlcache to patrickmn/go-cache (#1288) 2020-03-03 13:35:49 +00:00
Jake Sanders bc71989e2c int64 -> time.Duration (#1287) 2020-03-03 13:15:26 +00:00
Vasiliy Tolstov 89ba602e17 logger fixes and improvements (#1285)
* fix helper fields
* add metadata output for default logger

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-03 11:07:37 +03:00
Jake Sanders f6102bde70 Add a cache to workers KV storage implementation (#1284)
* cloudflare-cache

* go mod tidy
2020-03-02 18:14:25 +00:00
Pieter Voorwinden 7cad77bfc0 Initialize header to prevent assignment to entry in nil map error (#1282)
Co-authored-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-02 19:17:26 +03:00
ben-toogood 1f2e067f71 k8s runtime - get status from pods (#1283) 2020-03-02 15:49:10 +00:00
Vasiliy Tolstov b555269b1b copy fields in helper (#1281)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-02 14:18:36 +00:00
ben-toogood 9200c70202 Replace validation error with regex for cockroach namespace (#1270)
Co-authored-by: Asim Aslam <asim@aslam.me>
2020-03-01 22:09:06 +00:00
Sumanth Chinthagunta d8377e09c9 feat(dockerfile): adding dumb-init to base image (#1278) 2020-02-29 21:55:15 +00:00
Vasiliy Tolstov 0754229878 broker/memory: add codec support (#1276)
allow easy testing of other services with memory broker
and also allows to more deeply simulate real brokers

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-29 23:00:29 +03:00
Vasiliy Tolstov 6b8930a960 add new helper method to logger (#1273)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-29 00:39:41 +00:00
Vasiliy Tolstov d0a978bd50 redesign logger (#1272)
* redesign logger

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-29 03:31:59 +03:00
ben-toogood afe6861e2f Update the k8s deployment to use metadata labels & custom source (#1271)
Run tests / Test repo (push) Waiting to run
2020-02-28 15:07:55 +00:00
ben-toogood 962567ef42 Implement config singleton (#1268)
* Implement config singleton

* Pass token in grpc request headers

* Refactor BearerScheme

* Fix typo
2020-02-28 12:58:27 +00:00
Asim Aslam e21ed3a183 gen account on base32 decode failure (#1269) 2020-02-27 16:11:05 +00:00
Vasiliy Tolstov 64a5ce9607 various fixes (#1267)
* logger: remove Panic log level

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* server/grpc: add missing Unlock in Subscribe error

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* server: minor code change

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* server/grpc: extend test suite with pub/sub testing

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* server/grpc: fix invalid check and allow subscriber error to be returned

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* server/grpc: add pubsub tests

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* client/grpc: check for nil req/rsp

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-26 18:34:40 +00:00
Asim Aslam d651b16acd generate pseudo accounts (#1264)
* generate pseudo accounts

* when you think you're being clever

* return garbage pseudo account when no token
2020-02-26 13:42:32 +00:00
Eric 1034837f69 Adjusting the BeforeStart () position (#1263)
Co-authored-by: Asim Aslam <asim@aslam.me>
2020-02-26 11:44:10 +03:00
Lars Lehtonen 80f2bfd5d0 config: remove unused sep variable (#1262) 2020-02-26 08:25:33 +00:00
Asim Aslam 6aaaf54275 add MICRO_AUTH_TOKEN, parse token in wrapper, preload config and othe… (#1261)
* add MICRO_AUTH_TOKEN, parse token in wrapper, preload config and other things

* fix wrapper panic
2020-02-25 22:15:44 +00:00
Di Wu 603d37b135 Set option and cli args to the service profile (#1259) 2020-02-25 16:42:42 +00:00
Eric 53c3bff819 add Panic & Panicf to logger (#1258)
* add Panic & Panicf to logger
2020-02-25 17:44:29 +03:00
ben-toogood dcf859098b Fix k8s commands for github (#1257) 2020-02-25 11:39:03 +00:00
Vasiliy Tolstov b4a743898e fix router panic (#1254)
Run tests / Test repo (push) Waiting to run
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-24 23:15:59 +00:00
ben-toogood f1e7ea3020 Handle non IsNotExist errors in config (#1251)
Co-authored-by: Asim Aslam <asim@aslam.me>
2020-02-24 18:07:11 +00:00
ben-toogood 5e8d5834eb Dynamic Runtime source for k8s with github packages (#1252)
* Dynamic Runtime source for k8s

* Still check for source

* Replace / with - for k8s service names

* Simplify sourceForName function
2020-02-24 17:47:47 +00:00
ben-toogood ffdf986aac Refactor auth: add token and store implementations (#1230)
* Refactor auth: add token and memory implementations

* Fix typo

* Remove memory auth (implemented already by the store implementation), revert default to noop

* Add grpc header

* Global Config

* config/global => util/config

* Rename package to remove confict

* Tweak

* Improve Error Handling
2020-02-24 15:07:27 +00:00
Jake Sanders 56f8115ea8 Rename PR job (#1250) 2020-02-24 14:16:51 +00:00
Vasiliy Tolstov 5b0175c2e5 allocations improvements and tunnel fixes (#1248)
* reduce allocations in tunnel code

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* another allocation fix

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* allocate maps with len if it known

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* allocate key for send once

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-24 14:15:20 +00:00
Jake Sanders 01d88601c0 Split PR and merge tests (#1249) 2020-02-24 14:11:17 +00:00
Lars Lehtonen d467236f8f broker/nats: remove unused setPublishOption() (#1234)
broker/nats: remove unused setSubscribeOption()
2020-02-24 13:49:27 +00:00
Vasiliy Tolstov 24d574ae71 server/grpc: add MaxConn option to limit max inflight requests (#1247)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-24 13:48:56 +00:00
Vasiliy Tolstov cf0b39eaac logger fixes (#1244)
* logger: fix race conditions

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* restore util/log for compatibility

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-24 13:07:40 +00:00
Vasiliy Tolstov 1f767ba18c update go modules (#1240)
Run tests / Test repo (push) Waiting to run
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-23 20:47:44 +00:00
Asim Aslam 915c424213 Add docker build (#1239) 2020-02-23 15:57:21 +00:00
Vasiliy Tolstov 117f56ebf7 prune util/log and user logger (#1237)
* prune util/log and user logger

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* plaintext logger

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* add newline

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-23 13:45:20 +00:00
Gao.QiLin ceed8942fc Update README.md change godoc => go.dev (#1236)
* Update README.md add go dev

* Update README.zh-cn.md add go dev
2020-02-22 08:56:42 +00:00
Vasiliy Tolstov d1e25e7ead add metadata set method (#1232)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-21 23:04:47 +03:00
Jake Sanders 7e24c0c1cf Also run tests on PR (#1233) 2020-02-21 17:57:07 +00:00
Jake Sanders ca251ba111 Switch from Travis CI to GitHub Actions (#1231)
* Create Github Action to run tests on push

* -v

* Update tests.yml

* TODO: Fix tests

* Fix colours

* Delete .travis.yml

* Update tests.yml

* builds -> build
2020-02-21 17:43:50 +00:00
Asim Aslam 116855572b Add log level helper funtions (#1229) 2020-02-21 08:43:23 +00:00
Asim Aslam ee977acfef strip SetGlobalLevel (#1228) 2020-02-21 08:28:21 +00:00
Sumanth Chinthagunta 3fa7c26946 logger with helper methods (#1216)
* support unix daemon socket

* refactor(logger): logger fields changed to map[string]interface{}

* improvement(logger): adding string to Level Parser

* improvement(logger): rename ParseLevel to GetLevel

* refactor(logger): adding basic logger

adding micro default logger, and refactor logger interface

* refactor(logger): moved basic logger to top level package

* refactor(logger): adding default logger
2020-02-21 07:57:59 +00:00
Lars Lehtonen 88457b812e tunnel: Prune Unused Functions (#1224)
* tunnel: remove unused link.setLoopback()

* tunnel: remove unused link.accept()

* tunnel: remove unused link.connect()
2020-02-20 17:05:49 +00:00
Asim Aslam 78df154a4d move log level setting to option (#1222) 2020-02-20 08:26:12 +00:00
Lars Lehtonen c7eed618c2 server/grpc: Prune Unused Code (#1220)
* server/grpc: remove unused grpcServer.newCodec()

* server/grpc: remove unused defaultRPCCodecs
2020-02-19 20:58:22 +00:00
ben-toogood 36bcd3bd82 Improve JWT Package Errors (#1206)
Co-authored-by: Asim Aslam <asim@aslam.me>
2020-02-19 09:51:43 +01:00
Asim Aslam f4118dc357 secure the grpc client (#1215)
* secure the grpc client

* make compile

* Add system cert pool

* Revert manually adding ca certs

* Tweak comment

Co-authored-by: ben-toogood <bentoogood@gmail.com>
2020-02-19 08:44:35 +00:00
Vasiliy Tolstov 58598d0fe0 fixes for safe conversation and avoid panics (#1213)
* fixes for safe convertation

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* fix client publish panic

If broker connect returns error we dont check it status and use
it later to publish message, mostly this is unexpected because
broker connection failed and we cant use it.
Also proposed solution have benefit - we flag connection status
only when we have succeseful broker connection

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* api/handler/broker: fix possible broker publish panic

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-18 23:05:38 +00:00
Vasiliy Tolstov 6248f05f74 add missing option to client.NewMessage (#1212)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-18 14:18:59 +03:00
ben-toogood aa9a0a8d23 Fix Micro Proxy nil Transport Bug (#1208) 2020-02-17 12:28:48 +03:00
ben-toogood 1e40c86dfe Ignore gRPC Proxy (#1205) 2020-02-17 08:14:45 +00:00
Asim Aslam 9696efde02 reorder auth interface (#1204) 2020-02-16 19:36:45 +00:00
Asim Aslam b3fc8be24e normalise proxy name (#1203) 2020-02-15 21:57:30 +00:00
Sumanth Chinthagunta fc5339a368 [W.I.P] refactor(logger): logger fields changed to map[string]interface{} (#1198)
* support unix daemon socket

* refactor(logger): logger fields changed to map[string]interface{}

* improvement(logger): adding string to Level Parser

* improvement(logger): rename ParseLevel to GetLevel
2020-02-15 18:19:28 +00:00
Asim Aslam 964b7dee3f add tls config to server (#1202)
* add tls config

* add TLSConfig to acme provider
2020-02-15 15:10:26 +00:00
Asim Aslam 158949d0d0 accept Listen option in grpc server (#1201) 2020-02-15 14:09:24 +00:00
Asim Aslam eed8a0bf50 delete proxy cached route before updating (#1200) 2020-02-15 12:05:22 +00:00
Asim Aslam c691d116ab when the stream errors cleanup the connection (#1199) 2020-02-15 11:35:08 +00:00
Eric cbe8b7dd09 Removed redundant spaces (#1196) 2020-02-14 10:32:02 +03:00
Asim Aslam 203486fd31 check for etcd watcher canceled value 2020-02-13 22:34:56 +00:00
Asim Aslam d9b3b17582 set dial timeout in stream 2020-02-13 18:51:32 +00:00
ben-toogood e080ecb43a Auth Improvements (#1195)
* Exclude Stats & Trace from Auth

* Update Excluded Endpoints Format

* Tweak Implementation
2020-02-13 14:07:14 +00:00
ben-toogood ea70711dd3 Exclude Stats & Trace from Auth (#1192) 2020-02-13 12:02:29 +00:00
Vasiliy Tolstov 6dc942bc19 client/grpc: fix panic on invalid message (#1191)
* client/grpc: fix panic on invalid message
* travis: disable lint and race for now

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-13 14:57:21 +03:00
Janos Dobronszki d76baf59de Trace type is now being recorded (#1188) 2020-02-12 10:57:17 +00:00
Vasiliy Tolstov 79ad1e6fe3 various fixes for broker and messaging in server (#1187)
* provide broker disconnect messages in server

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* broker/eats: another fix

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-11 18:41:23 +00:00
Vasiliy Tolstov 2764de9a1a broker/eats: broker disconnect fix (#1186)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-11 15:46:50 +00:00
Asim Aslam d1d6eada98 parse url encoded form in rpc handler (#1183)
* parse url encoded form in rpc handler

* Remove comment
2020-02-11 11:27:16 +00:00
ben-toogood 4a03183481 Return a 401 error on invalid auth tokens (#1184) 2020-02-11 11:22:22 +00:00
Asim Aslam 8ea84ac3eb Fix router panic for nil watcher 2020-02-10 15:38:41 +00:00
ben-toogood 4401c12e6c Auth Wrapper (#1174)
* Auth Wrapper

* Tweak cmd flag

* auth_excludes => auth_exclude

* Make Auth.Excludes variadic

* Use metadata.Get (passes through http and http2 it will go through various case formats)

* fix auth wrapper auth.Auth interface initialisation

Co-authored-by: Asim Aslam <asim@aslam.me>
2020-02-10 08:26:28 +00:00
Vasiliy Tolstov c706afcf04 logger helper to pass down it via context (#1180)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-09 21:26:46 +00:00
Lars Lehtonen ca1d0b94c3 config/cmd: remove 8 unused variables (#1175) 2020-02-08 11:19:10 +00:00
Vasiliy Tolstov 67acd9288b config/source/cli: fix tests (#1179)
* config/source/cli: fix tests
* skip mdns test in travis

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-08 02:45:32 +03:00
Vasiliy Tolstov 0bf6c9fc08 config/source/cli: fix default flag value loading (#1178)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-08 02:14:34 +03:00
Vasiliy Tolstov 99807a680c strip Micro-Topic header from incoming context in client.Call (#1177)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-07 22:09:52 +00:00
Vasiliy Tolstov f0f7f860d6 add some docs (#1176)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-07 21:48:24 +00:00
Asim Aslam ef537270ad Don't store traces for Debug endpoints 2020-02-07 20:58:03 +00:00
Asim Aslam c7f075d157 rename file 2020-02-07 14:00:27 +00:00
Asim Aslam 812ea78604 Fix runtime deadlock 2020-02-07 14:00:09 +00:00
Asim Aslam 0755084a59 fix deadlock 2020-02-07 13:55:55 +00:00
ben-toogood fe7f5a4134 Runtime Retries Limit (#1163)
* Implement Runtime Retries

* Remove Debug

* Action Feedback

* Refactor Retries

* Fix WithRetires Typo
2020-02-07 12:02:41 +00:00
ben-toogood 19c454ec4b Fix Local Runtime Default Command (#1173)
* Auth API Proto

* Fix local runtime bug

* Add Platform Proto

* Restructuring
2020-02-07 11:39:26 +00:00
Asim Aslam 0e9b4c26a4 import with braces 2020-02-06 21:39:08 +00:00
Asim Aslam d40b13a045 mux to mtx 2020-02-06 21:37:17 +00:00
Asim Aslam 4079b22c1e reorder logger methods 2020-02-06 21:36:33 +00:00
Shu xian fdfb2bc4c1 [WIP] logger first (#1161)
* logger first

* log->logger

* update comment

* add context in Options

* add Fields

* remove logfi

* add field encode

* add common Field Types

* update logger field
2020-02-06 21:35:46 +00:00
Asim Aslam dbeb7cfe9c remove errors import 2020-02-06 18:45:12 +00:00
Asim Aslam 512df2628f trim source url if its set to github.com/ 2020-02-06 18:34:16 +00:00
Janos Dobronszki 92571db693 Tracing: traces now correctly form a tree (#1170)
* First cut of trace

* Dial it back yo

* Defensive programming
2020-02-06 17:22:16 +00:00
ben-toogood 16552620e0 Runtime Custom Source (Part 2) (#1169) 2020-02-06 16:16:01 +00:00
Ben Toogood 5414195dc3 Add Args 2020-02-06 12:31:54 +00:00
Ben Toogood 0591760932 Arg => Args 2020-02-06 12:17:16 +00:00
Ben Toogood 48b9f3f5e9 Fix 2020-02-06 11:28:34 +00:00
Ben Toogood e46278a766 Test 2020-02-06 11:24:56 +00:00
Ben Toogood 2925b1615c Fix 2020-02-06 11:15:30 +00:00
Ben Toogood fc4191c647 Fix 2020-02-06 11:12:40 +00:00
Ben Toogood 111126c780 Debugging 2020-02-06 11:00:14 +00:00
Ben Toogood 54371bba6a Debugging 2020-02-06 10:55:41 +00:00
Ben Toogood c28737e88e Debugging 2020-02-06 10:54:11 +00:00
Ben Toogood c7d922fac2 Debugging 2020-02-06 10:49:01 +00:00
Ben Toogood f8e696bd30 Debugging 2020-02-06 10:44:12 +00:00
Ben Toogood 6aef28dad2 Runtime set service source 2020-02-06 10:33:23 +00:00
Vasiliy Tolstov 7105e4099c pass micro errors from grpc server to grpc client (#1167)
* pass micro errors from grpc server to grpc client

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>

* wrap micro errors.Error to grpc status

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-06 10:18:33 +00:00
Ben Toogood f0762bbb6b Improve Logging 2020-02-06 10:16:32 +00:00
Ben Toogood 243c6a4246 Debug 2020-02-06 10:08:56 +00:00
Ben Toogood 9983aea928 Tidying Up 2020-02-06 09:29:27 +00:00
Ben Toogood aa58a9749b Action Asim's Feedback 2020-02-06 09:17:10 +00:00
ben-toogood d8110b70a3 Runtime custom docker img (#1168)
* Add DeploymentOptions to K8s Client

* WithBaseImage for  Runtime

* Revert Change

* Fix sequencing
2020-02-06 08:52:25 +00:00
Vasiliy Tolstov a44dc90d45 fix ctx.Done issue #720 (#1166)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-05 21:13:14 +00:00
Shu xian 12181bd441 fix LevelInfo > LevelWarn (#1162) 2020-02-05 18:16:57 +00:00
Ben Toogood 8d44f7226f Merge branch 'master' of https://github.com/micro/go-micro 2020-02-05 13:59:51 +00:00
ben-toogood bf747a86f4 Runtime (#1160)
* Add String to Runtime interface

* Setup Dynamic Runtime Configuration
2020-02-05 13:59:35 +00:00
Lars Lehtonen 4333f00a43 runtime/kubernetes: remove unused constants (#1159) 2020-02-04 21:02:05 +00:00
Vasiliy Tolstov 7ab3a31ac4 update micro/cli, tidy mod (#1156)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-03 23:29:44 +00:00
Ben Toogood a1d5d6831f Add String to Runtime interface 2020-02-03 15:56:16 +00:00
ben-toogood 1b9cabd654 Update Micro Auth Protocol Buffer to use V2 (#1155) 2020-02-03 08:26:57 +00:00
ben-toogood d621548120 Auth (#1147)
Implement the Auth interface, with JWT and service implementations.

* Update Auth Interface

* Define Auth Service Implementation

* Support Service Auth

* Add Auth Service Proto

* Remove erronious files

* Implement Auth Service Package

* Update Auth Interface

* Update Auth Interface. Add Validate, remove Add/Remove roles

* Make Revoke interface more explicit

* Refactor serializing and deserializing service accounts

* Fix srv name & update interface to be more explicit

* Require jwt public key for auth

* Rename Variables (Resource.ID => Resource.Name & ServiceAccount => Account)

* Implement JWT Auth Package

* Remove parent, add ID

* Update auth imports to v2. Add String() to auth interface
2020-02-03 08:16:02 +00:00
tpam28 449bcb46fe New backoff (#1153)
* new backoff function

* use backoff from util/backoff

* remove reset atemts

* change comment

* fmt
2020-02-02 20:32:55 +00:00
Asim Aslam 079102ea59 Merge branch 'master' of ssh://github.com/micro/go-micro 2020-02-02 19:50:09 +00:00
Asim Aslam a9d371e727 fatal on command error 2020-02-02 19:49:59 +00:00
Asim Aslam 27efbc8779 Merge pull request #1150 from unistack-org/grpc_race
fix map race condition in grpc server
2020-02-01 00:10:46 +00:00
Vasiliy Tolstov efb59d9709 fix map race condition in grpc server
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-02-01 02:52:53 +03:00
Asim Aslam 003f00b483 Merge branch 'master' of ssh://github.com/micro/go-micro 2020-01-30 23:24:54 +00:00
Asim Aslam 0be22c98c6 add tracing 2020-01-30 23:24:46 +00:00
Asim Aslam bafedf1aad Merge pull request #1149 from alrs/remove-unused-kubernetes-variable
runtime/kubernetes: remove unused name variable
2020-01-30 17:30:43 +00:00
Lars Lehtonen 98d55545fd runtime/kubernetes: remove unused name variable 2020-01-30 09:25:50 -08:00
Asim Aslam 5f6271b044 Merge pull request #1148 from tpam28/master
fix test and description
2020-01-30 17:09:41 +00:00
Evgeniy 87753ad289 format results in TestBacloff 2020-01-30 20:08:03 +03:00
Evgeniy ffb9da0230 fix test and description 2020-01-30 19:43:03 +03:00
Asim Aslam 50ac642666 Merge pull request #1146 from tpam28/master
exponentialBackoff was changed from power function to exponential
2020-01-30 14:35:17 +00:00
Evgeniy f6fcfcb8fc exponentialBackoff was changed from power function to exponential function 2020-01-30 17:25:07 +03:00
625 changed files with 27032 additions and 43104 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
# These are supported funding model platforms
issuehunt: micro/development
github: [asim, davincinble, jochumdev, xpunch]
+8 -7
View File
@@ -2,23 +2,24 @@
name: Bug report
about: For reporting bugs in go-micro
title: "[BUG]"
labels: ''
assignees: ''
labels: ""
assignees: ""
---
**Describe the bug**
## Describe the bug
1. What are you trying to do?
2. What did you expect to happen?
3. What happens instead?
**How to reproduce the bug:**
## How to reproduce the bug
If possible, please include a minimal code snippet here.
**Environment:**
## Environment
Go Version: please paste `go version` output here
```
```go
please paste `go env` output here
```
@@ -2,9 +2,8 @@
name: Feature request / Enhancement
about: If you have a need not served by go-micro
title: "[FEATURE]"
labels: ''
assignees: ''
labels: ""
assignees: ""
---
**Is your feature request related to a problem? Please describe.**
+4 -5
View File
@@ -1,13 +1,12 @@
---
name: Question
about: Ask a question about go-micro
title: ''
labels: ''
assignees: ''
title: ""
labels: ""
assignees: ""
---
Before asking, please check if your question has already been answered:
Before asking, please check if your question has already been answered:
1. Check the documentation - https://micro.mu/docs/
2. Check the examples and plugins - https://github.com/micro/examples & https://github.com/micro/go-plugins
+11
View File
@@ -0,0 +1,11 @@
# Pull Request template
Please, go through these steps before clicking submit on this PR.
1. Make sure this PR targets the `develop` branch. We follow the git-flow branching model.
2. Give a descriptive title to your PR.
3. Provide a description of your changes.
4. Make sure you have some relevant tests.
5. Put `closes #XXXX` in your comment to auto-close the issue that your PR fixes (if applicable).
## PLEASE REMOVE THIS TEMPLATE BEFORE SUBMITTING
+65
View File
@@ -0,0 +1,65 @@
name: Run Tests
on:
push:
branches:
- "**"
pull_request:
types:
- opened
- reopened
branches:
- "**"
jobs:
golangci:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.19
check-latest: true
cache: true
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
unittests:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19
check-latest: true
cache: true
- name: Get dependencies
run: |
go install github.com/kyoh86/richgo@latest
go get -v -t -d ./...
- name: Run tests
id: tests
run: richgo test -v -race -cover -bench=. ./...
env:
IN_TRAVIS_CI: yes
RICHGO_FORCE_COLOR: 1
summary:
name: Summary Report
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19
check-latest: true
cache: true
- name: Get dependencies
run: |
go install github.com/mfridman/tparse@latest
go get -v -t -d ./...
- name: Run tests
id: tests
run: go test -v -race -cover -json -bench=. ./... | tparse -notests -format=markdown >> $GITHUB_STEP_SUMMARY
env:
IN_TRAVIS_CI: yes
+5
View File
@@ -1,6 +1,7 @@
# Develop tools
/.vscode/
/.idea/
/.trunk
# Binaries for programs and plugins
*.exe
@@ -34,3 +35,7 @@ _cgo_export.*
*~
*.swp
*.swo
# go work files
go.work
go.work.sum
+251
View File
@@ -0,0 +1,251 @@
# This file contains all available configuration options
# with their default values.
# options for analysis running
run:
# go: '1.18'
# default concurrency is a available CPU number
# concurrency: 4
# timeout for analysis, e.g. 30s, 5m, default is 1m
deadline: 10m
# exit code when at least one issue was found, default is 1
issues-exit-code: 1
# include test files or not, default is true
tests: true
# which files to skip: they will be analyzed, but issues from them
# won't be reported. Default value is empty list, but there is
# no need to include all autogenerated files, we confidently recognize
# autogenerated files. If it's not please let us know.
skip-files:
[]
# - .*\\.pb\\.go$
allow-parallel-runners: true
# list of build tags, all linters use it. Default is empty list.
build-tags: []
# output configuration options
output:
# Format: colored-line-number|line-number|json|tab|checkstyle|code-climate|junit-xml|github-actions
#
# Multiple can be specified by separating them by comma, output can be provided
# for each of them by separating format name and path by colon symbol.
# Output path can be either `stdout`, `stderr` or path to the file to write to.
# Example: "checkstyle:report.json,colored-line-number"
#
# Default: colored-line-number
format: colored-line-number
# Print lines of code with issue.
# Default: true
print-issued-lines: true
# Print linter name in the end of issue text.
# Default: true
print-linter-name: true
# Make issues output unique by line.
# Default: true
uniq-by-line: true
# Add a prefix to the output file references.
# Default is no prefix.
path-prefix: ""
# Sort results by: filepath, line and column.
sort-results: true
# all available settings of specific linters
linters-settings:
wsl:
allow-cuddle-with-calls: ["Lock", "RLock", "defer"]
funlen:
lines: 80
statements: 60
varnamelen:
# The longest distance, in source lines, that is being considered a "small scope".
# Variables used in at most this many lines will be ignored.
# Default: 5
max-distance: 26
ignore-names:
- err
- id
- ch
- wg
- mu
ignore-decls:
- c echo.Context
- t testing.T
- f *foo.Bar
- e error
- i int
- const C
- T any
- m map[string]int
errcheck:
# report about not checking of errors in type assetions: `a := b.(MyStruct)`;
# default is false: such cases aren't reported by default.
check-type-assertions: true
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
# default is false: such cases aren't reported by default.
check-blank: true
govet:
# report about shadowed variables
check-shadowing: false
gofmt:
# simplify code: gofmt with `-s` option, true by default
simplify: true
gocyclo:
# minimal code complexity to report, 30 by default (but we recommend 10-20)
min-complexity: 15
maligned:
# print struct with more effective memory layout or not, false by default
suggest-new: true
dupl:
# tokens count to trigger issue, 150 by default
threshold: 100
goconst:
# minimal length of string constant, 3 by default
min-len: 3
# minimal occurrences count to trigger, 3 by default
min-occurrences: 3
depguard:
list-type: blacklist
# Packages listed here will reported as error if imported
packages:
- github.com/golang/protobuf/proto
misspell:
# Correct spellings using locale preferences for US or UK.
# Default is to use a neutral variety of English.
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
locale: US
lll:
# max line length, lines longer will be reported. Default is 120.
# '\t' is counted as 1 character by default, and can be changed with the tab-width option
line-length: 120
# tab width in spaces. Default to 1.
tab-width: 1
unused:
# treat code as a program (not a library) and report unused exported identifiers; default is false.
# XXX: if you enable this setting, unused will report a lot of false-positives in text editors:
# if it's called for subdir of a project it can't find funcs usages. All text editor integrations
# with golangci-lint call it on a directory with the changed file.
check-exported: false
unparam:
# call graph construction algorithm (cha, rta). In general, use cha for libraries,
# and rta for programs with main packages. Default is cha.
algo: cha
# Inspect exported functions, default is false. Set to true if no external program/library imports your code.
# XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:
# if it's called for subdir of a project it can't find external interfaces. All text editor integrations
# with golangci-lint call it on a directory with the changed file.
check-exported: false
nakedret:
# make an issue if func has more lines of code than this setting and it has naked returns; default is 30
max-func-lines: 60
nolintlint:
allow-unused: false
allow-leading-space: false
allow-no-explanation: []
require-explanation: false
require-specific: true
prealloc:
# XXX: we don't recommend using this linter before doing performance profiling.
# For most programs usage of prealloc will be a premature optimization.
# Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.
# True by default.
simple: true
range-loops: true # Report preallocation suggestions on range loops, true by default
for-loops: false # Report preallocation suggestions on for loops, false by default
cyclop:
# the maximal code complexity to report
max-complexity: 20
gomoddirectives:
replace-local: true
retract-allow-no-explanation: false
exclude-forbidden: true
linters:
enable-all: true
disable-all: false
fast: false
disable:
- golint
- varcheck
- ifshort
- structcheck
- deadcode
# - nosnakecase
- interfacer
- maligned
- scopelint
- exhaustivestruct
- testpackage
- promlinter
- nonamedreturns
- makezero
- gofumpt
- nlreturn
- thelper
# Can be considered to be enabled
- gochecknoinits
- gochecknoglobals # RIP
- dogsled
- wrapcheck
- paralleltest
- ireturn
- gomnd
- goerr113
- exhaustruct
- containedctx
- godox
- forcetypeassert
- gci
- lll
issues:
# List of regexps of issue texts to exclude, empty list by default.
# But independently from this option we use default exclude patterns,
# it can be disabled by `exclude-use-default: false`. To list all
# excluded by default patterns execute `golangci-lint run --help`
# exclude:
# - package comment should be of the form "Package services ..." # revive
# - ^ST1000 # ST1000: at least one file in a package should have a package comment (stylecheck)
# exclude-rules:
# - path: internal/app/machined/pkg/system/services
# linters:
# - dupl
exclude-rules:
- path: _test\.go
linters:
- gocyclo
- dupl
- gosec
- funlen
- varnamelen
- wsl
# Independently from option `exclude` we use default exclude patterns,
# it can be disabled by this option. To list all
# excluded by default patterns execute `golangci-lint run --help`.
# Default value for this option is true.
exclude-use-default: false
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
max-issues-per-linter: 0
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
max-same-issues: 0
# Show only new issues: if there are unstaged changes or untracked files,
# only those changes are analyzed, else only changes in HEAD~ are analyzed.
# It's a super-useful option for integration of golangci-lint into existing
# large codebase. It's not practical to fix all existing issues at the moment
# of integration: much better don't allow issues in new code.
# Default is false.
new: false
-26
View File
@@ -1,26 +0,0 @@
run:
deadline: 10m
linters:
disable-all: false
enable-all: false
enable:
- megacheck
- staticcheck
- deadcode
- varcheck
- gosimple
- unused
- prealloc
- scopelint
- gocritic
- goimports
- unconvert
- govet
- nakedret
- structcheck
- gosec
disable:
- maligned
- interfacer
- typecheck
- dupl
+29
View File
@@ -0,0 +1,29 @@
labelType: long
coverThreshold: 70
buildStyle:
bold: true
foreground: yellow
startStyle:
foreground: lightBlack
passStyle:
foreground: green
failStyle:
bold: true
foreground: "#821515"
skipStyle:
foreground: lightBlack
passPackageStyle:
foreground: green
hide: false
failPackageStyle:
bold: true
foreground: "#821515"
coveredStyle:
foreground: green
uncoveredStyle:
bold: true
foreground: yellow
fileStyle:
foreground: cyan
lineStyle:
foreground: magenta
-17
View File
@@ -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
+7
View File
@@ -0,0 +1,7 @@
*out
*logs
*actions
*notifications
plugins
user_trunk.yaml
user.yaml
+10
View File
@@ -0,0 +1,10 @@
# Autoformatter friendly markdownlint config (all formatting rules disabled)
default: true
blank_lines: false
bullet: false
html: false
indentation: false
line_length: false
spaces: false
url: false
whitespace: false
+28
View File
@@ -0,0 +1,28 @@
version: 0.1
actions:
enabled:
- trunk-announce
- trunk-cache-prune
- trunk-check-pre-push
- trunk-fmt-pre-commit
- trunk-upgrade-available
runtimes:
enabled:
- go@1.18.3
- node@16.14.2
lint:
enabled:
- actionlint@1.6.20
- git-diff-check
- gitleaks@8.13.0
- gofmt@1.16.7
- golangci-lint@1.49.0
- markdownlint@0.32.2
- prettier@2.7.1
cli:
version: 0.18.1-beta
plugins:
sources:
- id: trunk
ref: v0.0.4
uri: https://github.com/trunk-io/plugins
+774
View File
@@ -0,0 +1,774 @@
# 4.7.0 (2022/05/19)
### Features
- remove unused variable in loop (#2495)
- option to disable file watcher (#2485)
- Support direct generation of grpc method (#2474)
- remove cli
- remove dashboard
- Remove examples
- Add header suppor for Kafka broker plugin; (#2470)
- Fix codec/bytes (#2466)
- Add Wait option support for sync/etcd plugins (#2459)
- #2453 Fix with associated test update (#2454)
- style:arrays pre-allocation (#2449)
- Bump github.com/nats-io/nats-server/v2 in /plugins/events/natsjs (#2447)
- add NATS JetStream events plugin (#2433)
- add tls option for sync etcd plugin (#2440)
- add new services
### Bug Fixes
- fix: consume and publish blocked after rabbitmq reconnecting (#2492)
- typo fix; (#2480)
- fix https://github.com/asim/go-micro/issues/2344 (#2462)
- fix natsjs syntax error, remove TODOs and enable tests (#2446)
- http transport deadlock (#2441)
- Support for `-micro_out=module=<module_prefix>` for protoc-gen-micro (#2435)
# 4.6.0 (2022/02/08)
### Features
- add service updates (#2418)
- Add files via upload
- default the content type to json (#2412)
- Add Kafka asynchronous send support (#2409)
- use read lock and unlock instead of write ones (#2410)
- move the api client
- Update client_test.go
- switch services client
- remove the client
- add service interfaces
- [FEATURE] add changelog (#2400)
- nats config plugin (#2397)
- Update and rename m3o.go to services.go
- Update services/ (#2392)
### Bug Fixes
- fix client
- fix context value nil (#2391)
# 4.5.0 (2021/12/19)
### Bug Fixes
- nats deregister issue (#2384)
- fixing f.IsExported undefined issue (#2382)
- fix http_transport Recv and Close race condition on buff (#2374)
- update protoc-gen-micro install doc
- zookeeper registry delete event (#2372)
- delete redundant lines (#2364)
- modify the dependencies urls (#2363)
- ignore unexported field (#2354)
- Fix Micro CLI's proto comments (#2353)
### Features
- Extend client mock with ability to test publish, and a few useful method like SetResponse and SetSubscriber (#2375)
- go micro dashboard (#2361)
# 4.4.0 (2021/11/11)
### Bug Fixes
- fix(#2333): etcd grpc marshal issue (#2334)
### Features
- upgrade to go 1.17 (#2346)
- add nats and redis events plugins
- add events package (#2341)
# 4.3.0 (2021/11/01)
### Bug Fixes
- flatten cli (#2332)
- m3o client changed
- use vanity url for cli command
- fix broker nsq plugin nil pointer error (#2329)
- fix config json slice parsing (#2330)
- replace ioutil with io and os (#2327)
- fixing #2308 (#2326)
- Fix Micro CLI by removing replace line in go.mod
- remove unnecessary dependencies between plugins
- 1. use default memory registry in grpc plugins (#2317)
- Add update rule to Makefile (#2315)
- Plugins (#2311)
### Features
- Rename gomu to micro (#2325)
- stream CloseSend (#2323)
- strip protoc-gen-micro go mod
### BREAKING CHANGES
- go install go-micro.dev/v4/cmd/micro@v4
- go install go-micro.dev/v4/cmd/protoc-gen-micro@v4
- upgrade go micro to support stream.CloseSend
# 4.2.1 (2021/10/14)
### Bug Fixes
- fix gomu.
# 4.2.0 (2021/10/13)
### Bug Fixes
- fix examples go mod.
- update go sums.
- move to go-micro.dev.
- upgrade protoc-gen-micro to v4.
# 4.1.0 (2021/10/12)
- v4.1.0.
# 4.0.0 (2021/10/12)
### Features
- Vanity URL go-micro.dev([#2271](https://github.com/asim/go-micro/issues/2271)).
### BREAKING CHANGES
- upgrade github.com/asim/go-micro/v3 to go-micro.dev/v4.
# 3.7.0 (2021/10/11)
- Add latest version (#2303).
# 3.6.0 (2021/08/23)
- Minor fixes https://github.com/asim/go-micro/compare/v3.5.2...c7195aae9817db4eaf5483990fcb8706f86d3002.
# 3.5.2 (2021/07/06)
- Tag it and bag it.
# 3.5.1 (2021/04/20)
- Minor bug fixes.
# 3.5.0 (2021/01/29)
- kill the bugs.
# 3.0.1 (2021/01/20)
- Tag with protoc changes.
# 3.0.0 (2021/01/20)
- V3.
### BREAKING CHANGES
- upgrade github.com/micro/go-micro/v2 to github.com/asim/go-micro/v3.
- change default transport from gRPC to mucp, using grpc server/client plugins.
# 3.0.0-beta.3 (2020/09/29)
- Secret implementation of config. Supporting config merge (#2027)
- remove transport options
- read service package (#2026)
- env config implementation (#2024)
- runtime: remove builder package (moved to micro) (#2023)
- Fix branch names support for k8s runtime (#2020)
- fix config bug (#2021)
- runtime: minor fixes for local runtime (#2019)
- remove memcache and update gomod
- Add errors to config methods (#2015)
- store/file: fix segmentation violation bug (#2013)
- Config interface change (#2010)
- proxy/grpc: fix client streaming bug (EOF not sent to the server) (#2011)
- client/grpc: fix stream closed bug (#2009)
- store/file: don't keep connection to boltdb open (#2006)
- runtime/builder with golang implementation (#2003)
- store: implement s3 blob store (#2005)
- store: add blob interface with file implementation (#2004)
- auth: remove micro specific code (#1999)
- Fix running subfolders (#1998)
- api: fix request body re-sequencing bug (#1996)
- add Name to auth.Account as a user friendly alias (#1992)
- Fixing top level run outside repo (#1993)
- runtime: normalised service statuses (#1994)
- Add 'Namespace' header to allowed CORS headers (#1990)
- Remove all the external plugins except grpc (#1988)
- util/kubernetes: fix TCPSocketAction bug (#1987)
- Fixing the metric tagging issue here (#1986).
# 3.0.0-beta.2 (2020/09/05)
- Cut a v3 beta 2.
# 3.0.0-beta (2020/08/12)
- write nil when expiry is zero.
# 3.0.0-alpha (2020/07/27)
- v3 refactor (#1868).
# 2.9.1 (2020/07/03)
- push tags to docker hub (#1766).
# 2.9.0 (2020/06/12)
- Fix regex detection. Fixes #1663 (#1696).
# 2.9.0-rc5 (2020/06/11)
- Merge branch 'master' into release-2.9.0.
# 2.9.0-rc4 (2020/06/11)
- Merge branch 'master' into release-2.9.0.
# 2.9.0-rc1 (2020/06/11)
- Merge branch 'master' into release-2.9.0.
# 2.8.0 (2020/05/31)
- Rewrite Auth interface to use Rules
- Add Cache interface into the Client for request caching
- Fix atomic sequence updates in Client
- Update go mod deps
- Fix ipv6 parsing in mdns registry
- Add namespacing to the default runtime
- Replace go-git with v5
- Increase register ttl to 90 seconds.
# 2.7.0 (2020/05/18)
- Fix the rpc handler json rpc body parsing
- Use caddyserver/certmagic instead of mholt
- Add HasRole to Account
- Add jwt refresh token generation
- Fix rpc stream close locking race
- Add auth namespace env var
- Strip the router penalty code
- Add file upload util
- Fix killing processes in runtime
- Pass namespace to runtime commands
- Generate account on start
- Check errors in cockroachdb.
# 2.6.0 (2020/05/04)
- Fix discord bot authentication header
- Improve api rpc regexp matching
- Change auth account access via context
- Create a jwt implementation of auth
- Fix grpc content-type encoding bug
- Consolidate proxy/network env var logic
- Change secrets interface naming
- Log file path in the logger
- Change location of network resolver
- Add Store to service options
- Fix default runtime log parsing
- Add namespace checks to k8s runtime
- Add proper git checkout in local runtime
- Add database/table options for store
- Add pki implementation
- Import qson.
# 2.5.0 (2020/04/15)
- api/router/registry: extract path based parameters from url to req (#1530).
# 2.4.0 (2020/03/31)
- There can be only one! (#1445).
# 2.3.0 (2020/03/17)
- grpc client/server fixes (#1355).
# 2.2.0 (2020/02/28)
- Rename Auth Validate to Verify
- Replaces noop auth with base32 generated tokens
- Change Excludes to Exclude
- Add token option to auth
- Add profile option and flags for debug
- Add config loading for auth token
- Move before start to before listening.
# 2.1.2 (2020/02/24)
- fix router panic (#1254).
# 2.1.1 (2020/02/23)
- update go modules (#1240).
# 2.1.0 (2020/02/13)
- Exclude Stats & Trace from Auth (#1192).
# 2.0.0 (2020/01/30)
- v2 release.
# 1.18.0 (2019/12/08)
- Add golang ci linter
- Add race detection to travis
- Please the linter
- Do some perf optimisations on slice alloc
- Move http broker to use single entry in registry
- Strip the grpc metadata filtering
- Strip the old codec usage
- Disable retries in client when MICRO_PROXY is enabled
- Strip old X-Micro headers
- Add debug/log streaming implementations
- Add first debug/log interface
- Huge network/tunnel refactor to fix bugs
- Fix proxy slice allocation bug
- Splay out some of the network events
- Default to AdvertiseLocal for router
- Add runtime filtering with Type
- Remove SIGKILL processing.
# 1.17.1 (2019/11/27)
- fix rpc server go routine leak
- add a psuedo socket pool
- update debug buffer to return entries.
# 1.17.0 (2019/11/27)
- Add github related issue templates
- Add Dockerfile for predownloaded go-micro source
- Regenerate all the protos to move to \*.pb.micro.go
- Fix api handler to parse text/plain as default content type
- Fix event handler to allow GET requests
- Change http broker ids to go.micro.http.broker-uuid
- Require protocol field in metadata to query services via client
- Process raw frames in call to Publish
- Complete proxy support for processing messages
- Proxy support for publishing of messages
- Fix grpc connection leak by always closing the connection
- Add a debug ring buffer
- Add broker to tunnel and network
- Force network dns resolver to use cloudflare 1.0.0.1
- Add option to specify whether server should handle signalling
- Change mdns request timeout to 10ms rather than 100ms
- Add router AdvertiseNone and AdvertiseLocal strategies
- Rename runtime packager to builder
- Add full support for a kubernetes runtime.
# 1.16.0 (2019/11/09)
- Pre-make slices for perf optimisation
- Add runtime flag and k8s runtime
- Add debug/profile for pprof profiling
- Reduce go routines in mdns registry and registry cache
- Optimise the router flap detection.
# 1.15.1 (2019/11/03)
- Router recovery penalty should be below 500.
# 1.15.0 (2019/11/03)
- go fmt -s
- web generate service on registration
- downgrade some network messages to trace
- fix tunnel panic on deleting link
- add postgres store
- change grpc recover logging
- add runtime service
- add kubernetes runtime
- add runtime notifier
- proxy add header based routing for Micro-{Gateway, Router, Network}
- network hash address based on service + node id
- metadata add mergecontext function.
# 1.14.0 (2019/10/25)
- Remove consul registry
- Change store Sync endpoint to List
- Remove cloudflare-go usage in store
- Add non-backwards compatible link changes.
# 1.13.2 (2019/10/22)
- Fix proxy selection to use round robin strategy.
# 1.13.1 (2019/10/19)
- Fix divide by zero bug in broker.
# 1.13.0 (2019/10/18)
- Fix network recursive read lock bug
- Add certmagic random pull time
- Strip http broker topic: prefix.
# 1.12.0 (2019/10/17)
- Add ACME Provider interface
- Implement certmagic ACME Provider
- Add certmagic Store implementation
- Add broker service implementation
- Add ability to set grpc dial and call options
- Add etcd registry and other plugins
- Add Network.Connect rpc endpoint
- Resolve network node dns names
- Support Network.Routes querying
- Fix caching registry bugs
- Move gossip registry to go-plugins
- Add router advertise strategy
- Add Cloudflare store implementation
- Add store service implementation.
# 1.11.3 (2019/10/12)
- Fix the quic-go checksum mismatch by updating to 0.12.1.
# 1.11.2 (2019/10/12)
- Fix cache error check.
# 1.11.1 (2019/10/07)
- Fix cache registry deadlocking bug.
# 1.11.0 (2019/10/01)
- This is likely the last release of v1.
# 1.10.0 (2019/09/11)
- Add grpc client code application/grpc content-type
- Move client to use stream dialer
- Add network implementation
- Add dynamic plugin loading
- Add multilink usage in proxy
- Add registry implementation
- Scope mdns to .micro domain
- Support grpc server processing by default
- Add tunnel broker.
# 1.9.1 (2019/08/19)
- Fix waitgroup race condition.
# 1.9.0 (2019/08/19)
- Fix grpc codec for broker publishing
- Use the connection pool for streaming
- Send EOS from client when closing stream
- Add stream header to mucp protocol
- Add stream multiplexing in the server
- Fix watcher bug in file config source
- Fix monitoring watcher to only look at mucp services
- Only check router status on lookup failure
- Fix proxy streaming and client request processing
- Fix host:port processing for messaging systems
- Add start method to the router
- Fix router race condition for default values
- Add loopback detection to the tunnel
- Add connection retry logic to tunnel
- Make log levels accessible for the logger
- Add proxy muxer for internal calls.
# 1.8.3 (2019/08/12)
- Fix nats draining
- More verbose selector errors to return service name
- Move handler debug package
- Add a monitoring package
- Fix consul address parsing
- Fix server extraction code
- Add tunnel implementation
- Add util log level
- Add util io package to wrap transport socket.
# 1.8.2 (2019/08/06)
- Point release for micro
- Adds travis caching
- Removes unused network code
- Adds tunnel interface
- Consul agent check
- Router handler interface
- Non host:port fixes.
# 1.8.1 (2019/07/31)
- Use mdns 0.2.0 release tag.
# 1.8.0 (2019/07/29)
- Move the selector into client
- Change broker.Publication to broker.Event
- Move cmd into config
- Enable default json processing in api
- Remove port from registry
- Memory broker/transport race fixes
- GRPC codec fix
- Client pool interface
- Router interface/service implementations
- Config decoding fixes
- Memory store expiration fix
- Network link/tunnel/resolver packages
- Proxy router caching
- Registry util functions.
# 1.7.0 (2019/06/21)
- Update go mod
- Move mock data out of memory registry
- wrap the grpc codecs to support framing
- change grpc resolution to use service.method
- support full proxying via grpc
- add text codec
- move data/store
- add network interface
- add router package and implementation
- move options to config/options
- send gossip updates on register/deregister
- fix node add/del bug
- add handler wrapper back into core router.
# 1.6.0 (2019/06/07)
- Massive go.mod dependency cleanup _ Moved etcd, memcache, redis sync things to go-plugins _ uuid to google uuid \* blew away go.mod
- Add better proxy interface and features
- Add new options interface.
# 1.5.0 (2019/06/05)
- Fix go mod issues.
# 1.4.0 (2019/06/04)
- Final consolidation of all libraries.
# 1.3.1 (2019/06/03)
- Fix broken pipe bug. Don't send message when client closed connection..
# 1.3.0 (2019/05/31)
- The great rewrite.
# 1.2.0 (2019/05/22)
- Update go mod
- Fix mock client
- Fix retries logic
- Fix consul api change
- Use consul client for watcher
- Fix gossip data races
- Add registry check function.
# 1.1.0 (2019/03/28)
- Update go mod
- Fix endpoint extractor generation.
# 1.0.0 (2019/03/05)
- 1.0.0 release.
# 0.27.1 (2019/03/05)
- Fix nil consul client.
# 0.27.0 (2019/02/23)
- Remove buff check in http transport
- Change default version to latest
- Add exchange routing
- Update go modules.
# 0.26.1 (2019/02/13)
- Fix gossip registry
- Update go modules for rcache.
# 0.26.0 (2019/02/13)
- Update go modules
- Add gossip registry rejoin
- Move selector to rcache.
# 0.25.0 (2019/02/04)
- Add server request body.
# 0.24.1 (2019/02/01)
- Various bug fixes
- Backwards compatible with 0.14 and older
- Fix mdns and gossip race conditions
- Use official h2c server
- Enable support for MICRO_PROXY.
# 0.24.0 (2019/01/30)
- Add go mod.
# 0.23.0 (2019/01/29)
- Move headers from X-Micro to Micro
- Remove Register/Deregister methods from server
- Move register_interval to be internal
- Add subscriber context option.
# 0.22.1 (2019/01/22)
- Fix broken error handling
- now returns error from ServeRequest router.
# 0.22.0 (2019/01/18)
- Address backwards compatibility.
# 0.21.0 (2019/01/17)
- Make MDNS the default registry
- Move mocks to be memory implementations
- Add metadata.Copy function.
# 0.20.0 (2019/01/14)
- BREAKING CHANGES.
# 0.17.0 (2019/01/03)
- Offline inbox for http broker
- JSON/Proto/GRPC codecs
- HTTP proxy from environment.
# 0.16.0 (2018/12/29)
- Fix cache/gossip data race
- Rename cache selector to registry.
# 0.15.1 (2018/12/18)
- Selector cache lookup optimization.
# 0.15.0 (2018/12/13)
- Public NewSubscribeOptions
- http2 broker support
- Timeout error function
- Consul Query Options
- Gossip registry
- RPC Codec renaming.
# 0.14.1 (2018/11/22)
- bug fix socket headers.
# 0.14.0 (2018/11/21)
- use google uuid
- add http handler option.
# 0.13.0 (2018/11/15)
- add local/remote ip methods
- various linting things
- get checks on 0 ttl
- accept loop.
# 0.12.0 (2018/10/09)
- reorder server flag
- atomic increment sequence
- new error method.
# 0.11.0 (2018/08/24)
- Support Consul Connect registration
- Add/Use Init for initialisation from cmd.
# 0.10.0 (2018/07/26)
- Fix broker locking
- Add RetryOnError as default retry policy
- Fix mock client reflection
- Support dialtimeout only above 0
- Add verbose client errors
- Allow client retries to be 0.
# 0.9.0 (2018/06/09)
- Reset server address on shutdown
- Set default pool size to 1
- Support reinitialising connection pool
- Set retries to 1 by default
- Return error for subscribers.
# 0.8.0 (2018/04/20)
- Rework of interfaces.
# 0.7.0 (2018/04/10)
- Move misc to util package
- Add register ttl and interval flags
- Fix protoc-gen-micro example.
# 0.6.0 (2018/04/05)
- Add consul TCP check
- Atomic increment rpc stream sequence.
# 0.5.0 (2018/03/04)
- Support consul services without version
- Switch to stdlib context.
# 0.4.0 (2018/02/19)
- Add WatchOption which allows filtering by service
- Add Options method to registry
- Add Conflict error
- Only watch selected services in cache.
# 0.3.0 (2018/01/02)
- https support for consul
- subscriber deadlock fix
- selector top level option.
# 0.2.0 (2017/10/29)
- Performance improvements.
# 0.1.4 (2017/09/04)
- sort handler/subscriber endpoints
- pass options to new subscriber.
# 0.1.3 (2017/08/15)
- Bug fix nil consul http client.
# 0.1.2 (2017/07/20)
- respond when codec errors out.
# 0.1.1 (2017/06/12)
- Fix potential panic/waitgroup bug.
# 0.1.0 (2017/06/12)
- Initial release.
-1
View File
@@ -1 +0,0 @@
go-micro.dev
-13
View File
@@ -1,13 +0,0 @@
FROM golang:1.13-alpine
RUN mkdir /user && \
echo 'nobody:x:65534:65534:nobody:/:' > /user/passwd && \
echo 'nobody:x:65534:' > /user/group
ENV GO111MODULE=on
RUN apk --no-cache add make git gcc libtool musl-dev ca-certificates && \
rm -rf /var/cache/apk/* /tmp/*
WORKDIR /
COPY ./go.mod ./go.sum ./
RUN go mod download && rm go.mod go.sum
+118 -30
View File
@@ -1,48 +1,136 @@
# Go Micro [![License](https://img.shields.io/:license-apache-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![GoDoc](https://godoc.org/github.com/micro/go-micro?status.svg)](https://godoc.org/github.com/micro/go-micro) [![Travis CI](https://api.travis-ci.org/micro/go-micro.svg?branch=master)](https://travis-ci.org/micro/go-micro) [![Go Report Card](https://goreportcard.com/badge/micro/go-micro)](https://goreportcard.com/report/github.com/micro/go-micro)
# Go Micro [![License](https://img.shields.io/:license-apache-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Go.Dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/go-micro.dev/v4?tab=doc) [![Go Report Card](https://goreportcard.com/badge/github.com/go-micro/go-micro)](https://goreportcard.com/report/github.com/go-micro/go-micro) [![Discord](https://dcbadge.vercel.app/api/server/qV3HvnEJfB?style=flat-square&theme=default-inverted)](https://discord.gg/qV3HvnEJfB)
Go Micro is a framework for microservice development.
Go Micro is a framework for distributed systems development.
Note: V5 is in development. Leave feedback in this [form](https://forms.gle/41gEWAcSgnf88GKt7)
## Overview
Go Micro provides the core requirements for distributed systems development including RPC and Event driven communication.
The **micro** philosophy is sane defaults with a pluggable architecture. We provide defaults to get you started quickly
but everything can be easily swapped out.
<img src="https://micro.mu/docs/images/go-micro.svg" />
Plugins are available at [github.com/micro/go-plugins](https://github.com/micro/go-plugins).
Follow us on [Twitter](https://twitter.com/microhq) or join the [Community](https://micro.mu/slack).
Go Micro provides the core requirements for distributed systems development including RPC and Event driven communication.
The Go Micro philosophy is sane defaults with a pluggable architecture. We provide defaults to get you started quickly
but everything can be easily swapped out.
## Features
Go Micro abstracts away the details of distributed systems. Here are the main features.
- **Service Discovery** - Automatic service registration and name resolution. Service discovery is at the core of micro service
development. When service A needs to speak to service B it needs the location of that service. The default discovery mechanism is
multicast DNS (mdns), a zeroconf system.
- **Authentication** - Auth is built in as a first class citizen. Authentication and authorization enable secure
zero trust networking by providing every service an identity and certificates. This additionally includes rule
based access control.
- **Load Balancing** - Client side load balancing built on service discovery. Once we have the addresses of any number of instances
of a service we now need a way to decide which node to route to. We use random hashed load balancing to provide even distribution
across the services and retry a different node if there's a problem.
- **Dynamic Config** - Load and hot reload dynamic config from anywhere. The config interface provides a way to load application
level config from any source such as env vars, file, etcd. You can merge the sources and even define fallbacks.
- **Message Encoding** - Dynamic message encoding based on content-type. The client and server will use codecs along with content-type
to seamlessly encode and decode Go types for you. Any variety of messages could be encoded and sent from different clients. The client
and server handle this by default. This includes protobuf and json by default.
- **Data Storage** - A simple data store interface to read, write and delete records. It includes support for memory, file and
CockroachDB by default. State and persistence becomes a core requirement beyond prototyping and Micro looks to build that into the framework.
- **Request/Response** - RPC based request/response with support for bidirectional streaming. We provide an abstraction for synchronous
communication. A request made to a service will be automatically resolved, load balanced, dialled and streamed. The default
transport is [gRPC](https://grpc.io/).
- **Service Discovery** - Automatic service registration and name resolution. Service discovery is at the core of micro service
development. When service A needs to speak to service B it needs the location of that service. The default discovery mechanism is
multicast DNS (mdns), a zeroconf system.
- **Async Messaging** - PubSub is built in as a first class citizen for asynchronous communication and event driven architectures.
Event notifications are a core pattern in micro service development. The default messaging system is an embedded [NATS](https://nats.io/)
server.
- **Load Balancing** - Client side load balancing built on service discovery. Once we have the addresses of any number of instances
of a service we now need a way to decide which node to route to. We use random hashed load balancing to provide even distribution
across the services and retry a different node if there's a problem.
- **Pluggable Interfaces** - Go Micro makes use of Go interfaces for each distributed system abstraction. Because of this these interfaces
are pluggable and allows Go Micro to be runtime agnostic. You can plugin any underlying technology. Find plugins in
[github.com/micro/go-plugins](https://github.com/micro/go-plugins).
- **Message Encoding** - Dynamic message encoding based on content-type. The client and server will use codecs along with content-type
to seamlessly encode and decode Go types for you. Any variety of messages could be encoded and sent from different clients. The client
and server handle this by default. This includes protobuf and json by default.
- **RPC Client/Server** - RPC based request/response with support for bidirectional streaming. We provide an abstraction for synchronous
communication. A request made to a service will be automatically resolved, load balanced, dialled and streamed.
- **Async Messaging** - PubSub is built in as a first class citizen for asynchronous communication and event driven architectures.
Event notifications are a core pattern in micro service development. The default messaging system is a HTTP event message broker.
- **Event Streaming** - PubSub is great for async notifications but for more advanced use cases event streaming is preferred. Offering
persistent storage, consuming from offsets and acking. Go Micro includes support for NATS Jetstream and Redis streams.
- **Synchronization** - Distributed systems are often built in an eventually consistent manner. Support for distributed locking and
leadership are built in as a Sync interface. When using an eventually consistent database or scheduling use the Sync interface.
- **Pluggable Interfaces** - Go Micro makes use of Go interfaces for each distributed system abstraction. Because of this these interfaces
are pluggable and allows Go Micro to be runtime agnostic. You can plugin any underlying technology.
## Getting Started
See the [docs](https://micro.mu/docs/framework.html) for detailed information on the architecture, installation and use of go-micro.
To make use of Go Micro import it
```golang
import "go-micro.dev/v4
```
Define a handler (protobuf is optionally supported - see [example](https://github.com/go-micro/examples/blob/main/helloworld/main.go))
```golang
type Request struct {
Name string `json:"name"`
}
type Response struct {
Message string `json:"message"`
}
type Helloworld struct{}
func (h *Helloworld) Greeting(ctx context.Context, req *Request, rsp *Response) error {
rsp.Message = "Hello " + req.Name
return nil
}
```
Create, initialise and run the service
```golang
// create a new service
service := micro.NewService(
micro.Name("helloworld"),
micro.Handle(new(Helloworld)),
)
// initialise flags
service.Init()
// start the service
service.Run()
```
Optionally set fixed address
```golang
service := micro.NewService(
// set address
micro.Handle(":8080"),
)
```
Call it via curl
```
curl -XPOST \
-H 'Content-Type: application/json' \
-H 'Micro-Endpoint: Helloworld.Greeting' \
-d '{"name": "alice"}' \
http://localhost:8080
```
See the [examples](https://github.com/go-micro/examples) for detailed information on usage.
## Toolkit
See [github.com/go-micro](https://github.com/go-micro) for tooling.
- [API](https://github.com/go-micro/api)
- [CLI](https://github.com/go-micro/cli)
- [Demo](https://github.com/go-micro/demo)
- [Plugins](https://github.com/go-micro/plugins)
- [Examples](https://github.com/go-micro/examples)
- [Dashboard](https://github.com/go-micro/dashboard)
- [Generator](https://github.com/go-micro/generator)
## Changelog
See [CHANGELOG.md](https://github.com/micro/go-micro/tree/master/CHANGELOG.md) for release history.
## License
Go Micro is Apache 2.0 licensed.
-36
View File
@@ -1,36 +0,0 @@
# Go Micro [![License](https://img.shields.io/:license-apache-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![GoDoc](https://godoc.org/github.com/micro/go-micro?status.svg)](https://godoc.org/github.com/micro/go-micro) [![Travis CI](https://api.travis-ci.org/micro/go-micro.svg?branch=master)](https://travis-ci.org/micro/go-micro) [![Go Report Card](https://goreportcard.com/badge/micro/go-micro)](https://goreportcard.com/report/github.com/micro/go-micro)
Go Micro是基于Golang的微服务开发框架。
## 概览
Go Micro提供分布式系统开发的核心库,包含RPC与事件驱动的通信机制。
**micro**的设计哲学是可插拔的架构理念,她提供可快速构建系统的组件,并且可以根据自身的需求剥离默认实现并自行定制。
<img src="https://micro.mu/docs/images/go-micro.svg" />
所有插件可在仓库[github.com/micro/go-plugins](https://github.com/micro/go-plugins)中找到。
可以订阅我们的[Twitter](https://twitter.com/microhq)或者加入[Slack](http://slack.micro.mu/)论坛。
## 特性
Go Micro把分布式系统的各种细节抽象出来。下面是它的主要特性。
- **服务发现(Service Discovery** - 自动服务注册与名称解析。服务发现是微服务开发中的核心。当服务A要与服务B协作时,它得知道B在哪里。默认的服务发现系统是Consul,而multicast DNS (mdns,组播)机制作为本地解决方案,或者零依赖的P2P网络中的SWIM协议(gossip)。
- **负载均衡(Load Balancing)** - 在服务发现之上构建了负载均衡机制。当我们得到一个服务的任意多个的实例节点时,我们要一个机制去决定要路由到哪一个节点。我们使用随机处理过的哈希负载均衡机制来保证对服务请求颁发的均匀分布,并且在发生问题时进行重试。
- **消息编码(Message Encoding** - 支持基于内容类型(content-type)动态编码消息。客户端和服务端会一起使用content-type的格式来对Go进行无缝编/解码。各种各样的消息被编码会发送到不同的客户端,客户端服服务端默认会处理这些消息。content-type默认包含proto-rpc和json-rpc。
- **Request/Response** - RPC通信基于支持双向流的请求/响应方式,我们提供有抽象的同步通信机制。请求发送到服务时,会自动解析、负载均衡、拨号、转成字节流。默认的传输协议是http/1.1,而tls下使用http2协议。
- **异步消息(Async Messaging** - 发布订阅(PubSub)头等功能内置在异步通信与事件驱动架构中。事件通知在微服务开发中处于核心位置。默认的消息传送使用点到点http/1.1,激活tls时则使用http2。
- **可插拔接口(Pluggable Interfaces** - Go Micro为每个分布式系统抽象出接口。因此,Go Micro的接口都是可插拔的,允许其在运行时不可知的情况下仍可支持。所以只要实现接口,可以在内部使用任何的技术。更多插件请参考:[github.com/micro/go-plugins](https://github.com/micro/go-plugins)。
## 快速上手
更多关于架构、安装的资料可以查看[文档](https://micro.mu/docs/cn/)。
-1
View File
@@ -1 +0,0 @@
theme: jekyll-theme-architect
-2
View File
@@ -1,2 +0,0 @@
// Package agent provides an interface for building robots
package agent
-54
View File
@@ -1,54 +0,0 @@
// Package command is an interface for defining bot commands
package command
var (
// Commmands keyed by golang/regexp patterns
// regexp.Match(key, input) is used to match
Commands = map[string]Command{}
)
// Command is the interface for specific named
// commands executed via plugins or the bot.
type Command interface {
// Executes the command with args passed in
Exec(args ...string) ([]byte, error)
// Usage of the command
Usage() string
// Description of the command
Description() string
// Name of the command
String() string
}
type cmd struct {
name string
usage string
description string
exec func(args ...string) ([]byte, error)
}
func (c *cmd) Description() string {
return c.description
}
func (c *cmd) Exec(args ...string) ([]byte, error) {
return c.exec(args...)
}
func (c *cmd) Usage() string {
return c.usage
}
func (c *cmd) String() string {
return c.name
}
// NewCommand helps quickly create a new command
func NewCommand(name, usage, description string, exec func(args ...string) ([]byte, error)) Command {
return &cmd{
name: name,
usage: usage,
description: description,
exec: exec,
}
}
-65
View File
@@ -1,65 +0,0 @@
package command
import (
"testing"
)
func TestCommand(t *testing.T) {
c := &cmd{
name: "test",
usage: "test usage",
description: "test description",
exec: func(args ...string) ([]byte, error) {
return []byte("test"), nil
},
}
if c.String() != c.name {
t.Fatalf("expected name %s got %s", c.name, c.String())
}
if c.Usage() != c.usage {
t.Fatalf("expected usage %s got %s", c.usage, c.Usage())
}
if c.Description() != c.description {
t.Fatalf("expected description %s got %s", c.description, c.Description())
}
if r, err := c.Exec(); err != nil {
t.Fatal(err)
} else if string(r) != "test" {
t.Fatalf("expected exec result test got %s", string(r))
}
}
func TestNewCommand(t *testing.T) {
c := &cmd{
name: "test",
usage: "test usage",
description: "test description",
exec: func(args ...string) ([]byte, error) {
return []byte("test"), nil
},
}
nc := NewCommand(c.name, c.usage, c.description, c.exec)
if nc.String() != c.name {
t.Fatalf("expected name %s got %s", c.name, nc.String())
}
if nc.Usage() != c.usage {
t.Fatalf("expected usage %s got %s", c.usage, nc.Usage())
}
if nc.Description() != c.description {
t.Fatalf("expected description %s got %s", c.description, nc.Description())
}
if r, err := nc.Exec(); err != nil {
t.Fatal(err)
} else if string(r) != "test" {
t.Fatalf("expected exec result test got %s", string(r))
}
}
-22
View File
@@ -1,22 +0,0 @@
# Discord input for micro-bot
[Discord](https://discordapp.com) support for micro bot based on [discordgo](github.com/bwmarrin/discordgo).
This was originally written by Aleksandr Tihomirov (@zet4) and can be found at https://github.com/zet4/micro-misc/.
## Options
### discord_token
You have to supply an application token via `--discord_token`.
Head over to Discord's [developer introduction](https://discordapp.com/developers/docs/intro)
to learn how to create applications and how the API works.
### discord_prefix
Set a command prefix with `--discord_prefix`. The default prefix is `Micro `.
You can mention the bot or use the prefix to run a command.
### discord_whitelist
Pass a list of comma-separated user IDs with `--discord_whitelist`. Only allow
these users to use the bot.
-94
View File
@@ -1,94 +0,0 @@
package discord
import (
"errors"
"strings"
"sync"
"github.com/bwmarrin/discordgo"
"github.com/micro/go-micro/v2/agent/input"
"github.com/micro/go-micro/v2/util/log"
)
type discordConn struct {
master *discordInput
exit chan struct{}
recv chan *discordgo.Message
sync.Mutex
}
func newConn(master *discordInput) *discordConn {
conn := &discordConn{
master: master,
exit: make(chan struct{}),
recv: make(chan *discordgo.Message),
}
conn.master.session.AddHandler(func(s *discordgo.Session, m *discordgo.MessageCreate) {
if m.Author.ID == master.botID {
return
}
whitelisted := false
for _, ID := range conn.master.whitelist {
if m.Author.ID == ID {
whitelisted = true
break
}
}
if len(master.whitelist) > 0 && !whitelisted {
return
}
var valid bool
m.Message.Content, valid = conn.master.prefixfn(m.Message.Content)
if !valid {
return
}
conn.recv <- m.Message
})
return conn
}
func (dc *discordConn) Recv(event *input.Event) error {
for {
select {
case <-dc.exit:
return errors.New("connection closed")
case msg := <-dc.recv:
event.From = msg.ChannelID + ":" + msg.Author.ID
event.To = dc.master.botID
event.Type = input.TextEvent
event.Data = []byte(msg.Content)
return nil
}
}
}
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)
}
return nil
}
func (dc *discordConn) Close() error {
if err := dc.master.session.Close(); err != nil {
return err
}
select {
case <-dc.exit:
return nil
default:
close(dc.exit)
}
return nil
}
-153
View File
@@ -1,153 +0,0 @@
package discord
import (
"fmt"
"sync"
"errors"
"strings"
"github.com/bwmarrin/discordgo"
"github.com/micro/cli/v2"
"github.com/micro/go-micro/v2/agent/input"
)
func init() {
input.Inputs["discord"] = newInput()
}
func newInput() *discordInput {
return &discordInput{}
}
type discordInput struct {
token string
whitelist []string
prefix string
prefixfn func(string) (string, bool)
botID string
session *discordgo.Session
sync.Mutex
running bool
exit chan struct{}
}
func (d *discordInput) Flags() []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Name: "discord_token",
EnvVars: []string{"MICRO_DISCORD_TOKEN"},
Usage: "Discord token (prefix with Bot if it's for bot account)",
},
&cli.StringFlag{
Name: "discord_whitelist",
EnvVars: []string{"MICRO_DISCORD_WHITELIST"},
Usage: "Discord Whitelist (seperated by ,)",
},
&cli.StringFlag{
Name: "discord_prefix",
Usage: "Discord Prefix",
EnvVars: []string{"MICRO_DISCORD_PREFIX"},
Value: "Micro ",
},
}
}
func (d *discordInput) Init(ctx *cli.Context) error {
token := ctx.String("discord_token")
whitelist := ctx.String("discord_whitelist")
prefix := ctx.String("discord_prefix")
if len(token) == 0 {
return errors.New("require token")
}
d.token = token
d.prefix = prefix
if len(whitelist) > 0 {
d.whitelist = strings.Split(whitelist, ",")
}
return nil
}
func (d *discordInput) Start() error {
if len(d.token) == 0 {
return errors.New("missing discord configuration")
}
d.Lock()
defer d.Unlock()
if d.running {
return nil
}
var err error
d.session, err = discordgo.New(d.token)
if err != nil {
return err
}
u, err := d.session.User("@me")
if err != nil {
return err
}
d.botID = u.ID
d.prefixfn = CheckPrefixFactory(fmt.Sprintf("<@%s> ", d.botID), fmt.Sprintf("<@!%s> ", d.botID), d.prefix)
d.exit = make(chan struct{})
d.running = true
return nil
}
func (d *discordInput) Stream() (input.Conn, error) {
d.Lock()
defer d.Unlock()
if !d.running {
return nil, errors.New("not running")
}
//Fire-n-forget close just in case...
d.session.Close()
conn := newConn(d)
if err := d.session.Open(); err != nil {
return nil, err
}
return conn, nil
}
func (d *discordInput) Stop() error {
d.Lock()
defer d.Unlock()
if !d.running {
return nil
}
close(d.exit)
d.running = false
return nil
}
func (d *discordInput) String() string {
return "discord"
}
// CheckPrefixFactory Creates a prefix checking function and stuff.
func CheckPrefixFactory(prefixes ...string) func(string) (string, bool) {
return func(content string) (string, bool) {
for _, prefix := range prefixes {
if strings.HasPrefix(content, prefix) {
return strings.TrimPrefix(content, prefix), true
}
}
return "", false
}
}
-55
View File
@@ -1,55 +0,0 @@
// Package input is an interface for bot inputs
package input
import (
"github.com/micro/cli/v2"
)
type EventType string
const (
TextEvent EventType = "text"
)
var (
// Inputs keyed by name
// Example slack or hipchat
Inputs = map[string]Input{}
)
// Event is the unit sent and received
type Event struct {
Type EventType
From string
To string
Data []byte
Meta map[string]interface{}
}
// Input is an interface for sources which
// provide a way to communicate with the bot.
// Slack, HipChat, XMPP, etc.
type Input interface {
// Provide cli flags
Flags() []cli.Flag
// Initialise input using cli context
Init(*cli.Context) error
// Stream events from the input
Stream() (Conn, error)
// Start the input
Start() error
// Stop the input
Stop() error
// name of the input
String() string
}
// Conn interface provides a way to
// send and receive events. Send and
// Recv both block until succeeding
// or failing.
type Conn interface {
Close() error
Recv(*Event) error
Send(*Event) error
}
-160
View File
@@ -1,160 +0,0 @@
package slack
import (
"errors"
"fmt"
"strings"
"sync"
"time"
"github.com/micro/go-micro/v2/agent/input"
"github.com/nlopes/slack"
)
// Satisfies the input.Conn interface
type slackConn struct {
auth *slack.AuthTestResponse
rtm *slack.RTM
exit chan bool
sync.Mutex
names map[string]string
}
func (s *slackConn) run() {
// func retrieves user names and maps to IDs
setNames := func() {
names := make(map[string]string)
users, err := s.rtm.Client.GetUsers()
if err != nil {
return
}
for _, user := range users {
names[user.ID] = user.Name
}
s.Lock()
s.names = names
s.Unlock()
}
setNames()
t := time.NewTicker(time.Minute)
defer t.Stop()
for {
select {
case <-s.exit:
return
case <-t.C:
setNames()
}
}
}
func (s *slackConn) getName(id string) string {
s.Lock()
name := s.names[id]
s.Unlock()
return name
}
func (s *slackConn) Close() error {
select {
case <-s.exit:
return nil
default:
close(s.exit)
}
return nil
}
func (s *slackConn) Recv(event *input.Event) error {
if event == nil {
return errors.New("event cannot be nil")
}
for {
select {
case <-s.exit:
return errors.New("connection closed")
case e := <-s.rtm.IncomingEvents:
switch ev := e.Data.(type) {
case *slack.MessageEvent:
// only accept type message
if ev.Type != "message" {
continue
}
// only accept DMs or messages to me
switch {
case strings.HasPrefix(ev.Channel, "D"):
case strings.HasPrefix(ev.Text, s.auth.User):
case strings.HasPrefix(ev.Text, fmt.Sprintf("<@%s>", s.auth.UserID)):
default:
continue
}
// Strip username from text
switch {
case strings.HasPrefix(ev.Text, s.auth.User):
args := strings.Split(ev.Text, " ")[1:]
ev.Text = strings.Join(args, " ")
event.To = s.auth.User
case strings.HasPrefix(ev.Text, fmt.Sprintf("<@%s>", s.auth.UserID)):
args := strings.Split(ev.Text, " ")[1:]
ev.Text = strings.Join(args, " ")
event.To = s.auth.UserID
}
if event.Meta == nil {
event.Meta = make(map[string]interface{})
}
// fill in the blanks
event.From = ev.Channel + ":" + ev.User
event.Type = input.TextEvent
event.Data = []byte(ev.Text)
event.Meta["reply"] = ev
return nil
case *slack.InvalidAuthEvent:
return errors.New("invalid credentials")
}
}
}
}
func (s *slackConn) Send(event *input.Event) error {
var channel, message, name string
if len(event.To) == 0 {
return errors.New("require Event.To")
}
parts := strings.Split(event.To, ":")
if len(parts) == 2 {
channel = parts[0]
name = s.getName(parts[1])
// try using reply meta
} else if ev, ok := event.Meta["reply"]; ok {
channel = ev.(*slack.MessageEvent).Channel
name = s.getName(ev.(*slack.MessageEvent).User)
}
// don't know where to send the message
if len(channel) == 0 {
return errors.New("could not determine who message is to")
}
if len(name) == 0 || strings.HasPrefix(channel, "D") {
message = string(event.Data)
} else {
message = fmt.Sprintf("@%s: %s", name, string(event.Data))
}
s.rtm.SendMessage(s.rtm.NewOutgoingMessage(message, channel))
return nil
}
-147
View File
@@ -1,147 +0,0 @@
package slack
import (
"errors"
"sync"
"github.com/micro/cli/v2"
"github.com/micro/go-micro/v2/agent/input"
"github.com/nlopes/slack"
)
type slackInput struct {
debug bool
token string
sync.Mutex
running bool
exit chan bool
api *slack.Client
}
func init() {
input.Inputs["slack"] = NewInput()
}
func (p *slackInput) Flags() []cli.Flag {
return []cli.Flag{
&cli.BoolFlag{
Name: "slack_debug",
Usage: "Slack debug output",
EnvVars: []string{"MICRO_SLACK_DEBUG"},
},
&cli.StringFlag{
Name: "slack_token",
Usage: "Slack token",
EnvVars: []string{"MICRO_SLACK_TOKEN"},
},
}
}
func (p *slackInput) Init(ctx *cli.Context) error {
debug := ctx.Bool("slack_debug")
token := ctx.String("slack_token")
if len(token) == 0 {
return errors.New("missing slack token")
}
p.debug = debug
p.token = token
return nil
}
func (p *slackInput) Stream() (input.Conn, error) {
p.Lock()
defer p.Unlock()
if !p.running {
return nil, errors.New("not running")
}
// test auth
auth, err := p.api.AuthTest()
if err != nil {
return nil, err
}
rtm := p.api.NewRTM()
exit := make(chan bool)
go rtm.ManageConnection()
go func() {
select {
case <-p.exit:
select {
case <-exit:
return
default:
close(exit)
}
case <-exit:
}
rtm.Disconnect()
}()
conn := &slackConn{
auth: auth,
rtm: rtm,
exit: exit,
names: make(map[string]string),
}
go conn.run()
return conn, nil
}
func (p *slackInput) Start() error {
if len(p.token) == 0 {
return errors.New("missing slack token")
}
p.Lock()
defer p.Unlock()
if p.running {
return nil
}
api := slack.New(p.token, slack.OptionDebug(p.debug))
// test auth
_, err := api.AuthTest()
if err != nil {
return err
}
p.api = api
p.exit = make(chan bool)
p.running = true
return nil
}
func (p *slackInput) Stop() error {
p.Lock()
defer p.Unlock()
if !p.running {
return nil
}
close(p.exit)
p.running = false
return nil
}
func (p *slackInput) String() string {
return "slack"
}
func NewInput() input.Input {
return &slackInput{}
}
-18
View File
@@ -1,18 +0,0 @@
# Telegram Messenger input for micro bot
[Telegram](https://telegram.org) support for micro bot based on [telegram-bot-api](https://github.com/go-telegram-bot-api/telegram-bot-api).
## Options
### --telegram_token (required)
Sets bot's token for interacting with API.
Head over to Telegram's [API documentation](https://core.telegram.org/bots/api)
to learn how to create bots and how the API works.
### --telegram_debug
Sets the debug flag to make the bot's output verbose.
### --telegram_whitelist
Sets a list of comma-separated nicknames (without @ symbol in the beginning) for interacting with bot. Only these users can use the bot.
-113
View File
@@ -1,113 +0,0 @@
package telegram
import (
"errors"
"strings"
"sync"
"github.com/forestgiant/sliceutil"
"github.com/micro/go-micro/v2/agent/input"
"github.com/micro/go-micro/v2/util/log"
tgbotapi "gopkg.in/telegram-bot-api.v4"
)
type telegramConn struct {
input *telegramInput
recv <-chan tgbotapi.Update
exit chan bool
syncCond *sync.Cond
mutex sync.Mutex
}
func newConn(input *telegramInput) (*telegramConn, error) {
conn := &telegramConn{
input: input,
}
conn.syncCond = sync.NewCond(&conn.mutex)
go conn.run()
return conn, nil
}
func (tc *telegramConn) run() {
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
updates, err := tc.input.api.GetUpdatesChan(u)
if err != nil {
return
}
tc.recv = updates
tc.syncCond.Signal()
select {
case <-tc.exit:
return
}
}
func (tc *telegramConn) Close() error {
return nil
}
func (tc *telegramConn) Recv(event *input.Event) error {
if event == nil {
return errors.New("event cannot be nil")
}
for {
if tc.recv == nil {
tc.mutex.Lock()
tc.syncCond.Wait()
}
update := <-tc.recv
if update.Message == nil || (len(tc.input.whitelist) > 0 && !sliceutil.Contains(tc.input.whitelist, update.Message.From.UserName)) {
continue
}
if event.Meta == nil {
event.Meta = make(map[string]interface{})
}
event.Type = input.TextEvent
event.From = update.Message.From.UserName
event.To = tc.input.api.Self.UserName
event.Data = []byte(update.Message.Text)
event.Meta["chatId"] = update.Message.Chat.ID
event.Meta["chatType"] = update.Message.Chat.Type
event.Meta["messageId"] = update.Message.MessageID
return nil
}
}
func (tc *telegramConn) Send(event *input.Event) error {
messageText := strings.TrimSpace(string(event.Data))
chatId := event.Meta["chatId"].(int64)
chatType := ChatType(event.Meta["chatType"].(string))
msgConfig := tgbotapi.NewMessage(chatId, messageText)
msgConfig.ParseMode = tgbotapi.ModeHTML
if sliceutil.Contains([]ChatType{Group, Supergroup}, chatType) {
msgConfig.ReplyToMessageID = event.Meta["messageId"].(int)
}
_, err := tc.input.api.Send(msgConfig)
if err != nil {
// probably it could be because of nested HTML tags -- telegram doesn't allow nested tags
log.Log("[telegram][Send] error:", err)
msgConfig.Text = "This bot couldn't send the response (Internal error)"
tc.input.api.Send(msgConfig)
}
return nil
}
-101
View File
@@ -1,101 +0,0 @@
package telegram
import (
"errors"
"strings"
"sync"
"github.com/micro/cli/v2"
"github.com/micro/go-micro/v2/agent/input"
tgbotapi "gopkg.in/telegram-bot-api.v4"
)
type telegramInput struct {
sync.Mutex
debug bool
token string
whitelist []string
api *tgbotapi.BotAPI
}
type ChatType string
const (
Private ChatType = "private"
Group ChatType = "group"
Supergroup ChatType = "supergroup"
)
func init() {
input.Inputs["telegram"] = &telegramInput{}
}
func (ti *telegramInput) Flags() []cli.Flag {
return []cli.Flag{
&cli.BoolFlag{
Name: "telegram_debug",
EnvVars: []string{"MICRO_TELEGRAM_DEBUG"},
Usage: "Telegram debug output",
},
&cli.StringFlag{
Name: "telegram_token",
EnvVars: []string{"MICRO_TELEGRAM_TOKEN"},
Usage: "Telegram token",
},
&cli.StringFlag{
Name: "telegram_whitelist",
EnvVars: []string{"MICRO_TELEGRAM_WHITELIST"},
Usage: "Telegram bot's users (comma-separated values)",
},
}
}
func (ti *telegramInput) Init(ctx *cli.Context) error {
ti.debug = ctx.Bool("telegram_debug")
ti.token = ctx.String("telegram_token")
whitelist := ctx.String("telegram_whitelist")
if whitelist != "" {
ti.whitelist = strings.Split(whitelist, ",")
}
if len(ti.token) == 0 {
return errors.New("missing telegram token")
}
return nil
}
func (ti *telegramInput) Stream() (input.Conn, error) {
ti.Lock()
defer ti.Unlock()
return newConn(ti)
}
func (ti *telegramInput) Start() error {
ti.Lock()
defer ti.Unlock()
api, err := tgbotapi.NewBotAPI(ti.token)
if err != nil {
return err
}
ti.api = api
api.Debug = ti.debug
return nil
}
func (ti *telegramInput) Stop() error {
return nil
}
func (p *telegramInput) String() string {
return "telegram"
}
-216
View File
@@ -1,216 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: github.com/micro/go-micro/v2/agent/proto/bot.proto
package go_micro_bot
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 HelpRequest struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *HelpRequest) Reset() { *m = HelpRequest{} }
func (m *HelpRequest) String() string { return proto.CompactTextString(m) }
func (*HelpRequest) ProtoMessage() {}
func (*HelpRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_018e8d5b14a89d12, []int{0}
}
func (m *HelpRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_HelpRequest.Unmarshal(m, b)
}
func (m *HelpRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_HelpRequest.Marshal(b, m, deterministic)
}
func (m *HelpRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_HelpRequest.Merge(m, src)
}
func (m *HelpRequest) XXX_Size() int {
return xxx_messageInfo_HelpRequest.Size(m)
}
func (m *HelpRequest) XXX_DiscardUnknown() {
xxx_messageInfo_HelpRequest.DiscardUnknown(m)
}
var xxx_messageInfo_HelpRequest proto.InternalMessageInfo
type HelpResponse struct {
Usage string `protobuf:"bytes,1,opt,name=usage,proto3" json:"usage,omitempty"`
Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *HelpResponse) Reset() { *m = HelpResponse{} }
func (m *HelpResponse) String() string { return proto.CompactTextString(m) }
func (*HelpResponse) ProtoMessage() {}
func (*HelpResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_018e8d5b14a89d12, []int{1}
}
func (m *HelpResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_HelpResponse.Unmarshal(m, b)
}
func (m *HelpResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_HelpResponse.Marshal(b, m, deterministic)
}
func (m *HelpResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_HelpResponse.Merge(m, src)
}
func (m *HelpResponse) XXX_Size() int {
return xxx_messageInfo_HelpResponse.Size(m)
}
func (m *HelpResponse) XXX_DiscardUnknown() {
xxx_messageInfo_HelpResponse.DiscardUnknown(m)
}
var xxx_messageInfo_HelpResponse proto.InternalMessageInfo
func (m *HelpResponse) GetUsage() string {
if m != nil {
return m.Usage
}
return ""
}
func (m *HelpResponse) GetDescription() string {
if m != nil {
return m.Description
}
return ""
}
type ExecRequest struct {
Args []string `protobuf:"bytes,1,rep,name=args,proto3" json:"args,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ExecRequest) Reset() { *m = ExecRequest{} }
func (m *ExecRequest) String() string { return proto.CompactTextString(m) }
func (*ExecRequest) ProtoMessage() {}
func (*ExecRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_018e8d5b14a89d12, []int{2}
}
func (m *ExecRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ExecRequest.Unmarshal(m, b)
}
func (m *ExecRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ExecRequest.Marshal(b, m, deterministic)
}
func (m *ExecRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_ExecRequest.Merge(m, src)
}
func (m *ExecRequest) XXX_Size() int {
return xxx_messageInfo_ExecRequest.Size(m)
}
func (m *ExecRequest) XXX_DiscardUnknown() {
xxx_messageInfo_ExecRequest.DiscardUnknown(m)
}
var xxx_messageInfo_ExecRequest proto.InternalMessageInfo
func (m *ExecRequest) GetArgs() []string {
if m != nil {
return m.Args
}
return nil
}
type ExecResponse struct {
Result []byte `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"`
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ExecResponse) Reset() { *m = ExecResponse{} }
func (m *ExecResponse) String() string { return proto.CompactTextString(m) }
func (*ExecResponse) ProtoMessage() {}
func (*ExecResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_018e8d5b14a89d12, []int{3}
}
func (m *ExecResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ExecResponse.Unmarshal(m, b)
}
func (m *ExecResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ExecResponse.Marshal(b, m, deterministic)
}
func (m *ExecResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_ExecResponse.Merge(m, src)
}
func (m *ExecResponse) XXX_Size() int {
return xxx_messageInfo_ExecResponse.Size(m)
}
func (m *ExecResponse) XXX_DiscardUnknown() {
xxx_messageInfo_ExecResponse.DiscardUnknown(m)
}
var xxx_messageInfo_ExecResponse proto.InternalMessageInfo
func (m *ExecResponse) GetResult() []byte {
if m != nil {
return m.Result
}
return nil
}
func (m *ExecResponse) GetError() string {
if m != nil {
return m.Error
}
return ""
}
func init() {
proto.RegisterType((*HelpRequest)(nil), "go.micro.bot.HelpRequest")
proto.RegisterType((*HelpResponse)(nil), "go.micro.bot.HelpResponse")
proto.RegisterType((*ExecRequest)(nil), "go.micro.bot.ExecRequest")
proto.RegisterType((*ExecResponse)(nil), "go.micro.bot.ExecResponse")
}
func init() {
proto.RegisterFile("github.com/micro/go-micro/v2/agent/proto/bot.proto", fileDescriptor_018e8d5b14a89d12)
}
var fileDescriptor_018e8d5b14a89d12 = []byte{
// 246 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x50, 0x4d, 0x4b, 0xc4, 0x30,
0x10, 0xdd, 0xea, 0xba, 0xb2, 0xd3, 0x7a, 0x09, 0x22, 0x75, 0x4f, 0x35, 0xa7, 0xbd, 0x98, 0x80,
0x5e, 0x05, 0x0f, 0xa2, 0x78, 0xee, 0x3f, 0x68, 0xbb, 0x43, 0x2c, 0x6c, 0x3b, 0x35, 0x99, 0x82,
0xff, 0xc1, 0x3f, 0x2d, 0x4d, 0x72, 0x08, 0xc5, 0xdb, 0x7b, 0x79, 0xe1, 0x7d, 0x0c, 0x68, 0xd3,
0xf3, 0xd7, 0xdc, 0xaa, 0x8e, 0x06, 0x3d, 0xf4, 0x9d, 0x25, 0x6d, 0xe8, 0x31, 0x80, 0xc6, 0xe0,
0xc8, 0x7a, 0xb2, 0xc4, 0xa4, 0x5b, 0x62, 0xe5, 0x91, 0x28, 0x0c, 0x29, 0xaf, 0xab, 0x96, 0x58,
0xde, 0x40, 0xfe, 0x89, 0xe7, 0xa9, 0xc6, 0xef, 0x19, 0x1d, 0xcb, 0x0f, 0x28, 0x02, 0x75, 0x13,
0x8d, 0x0e, 0xc5, 0x2d, 0x5c, 0xcd, 0xae, 0x31, 0x58, 0x66, 0x55, 0x76, 0xdc, 0xd7, 0x81, 0x88,
0x0a, 0xf2, 0x13, 0xba, 0xce, 0xf6, 0x13, 0xf7, 0x34, 0x96, 0x17, 0x5e, 0x4b, 0x9f, 0xe4, 0x03,
0xe4, 0xef, 0x3f, 0xd8, 0x45, 0x5b, 0x21, 0x60, 0xdb, 0x58, 0xe3, 0xca, 0xac, 0xba, 0x3c, 0xee,
0x6b, 0x8f, 0xe5, 0x0b, 0x14, 0xe1, 0x4b, 0x8c, 0xba, 0x83, 0x9d, 0x45, 0x37, 0x9f, 0xd9, 0x67,
0x15, 0x75, 0x64, 0x4b, 0x05, 0xb4, 0x96, 0x6c, 0x8c, 0x09, 0xe4, 0xe9, 0x37, 0x83, 0xeb, 0x37,
0x1a, 0x86, 0x66, 0x3c, 0x89, 0x57, 0xd8, 0x2e, 0xa5, 0xc5, 0xbd, 0x4a, 0xa7, 0xa9, 0x64, 0xd7,
0xe1, 0xf0, 0x9f, 0x14, 0x82, 0xe5, 0x66, 0x31, 0x58, 0xaa, 0xac, 0x0d, 0x92, 0x05, 0x6b, 0x83,
0xb4, 0xb9, 0xdc, 0xb4, 0x3b, 0x7f, 0xda, 0xe7, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0xbd,
0x39, 0x29, 0x8d, 0x01, 0x00, 0x00,
}
-108
View File
@@ -1,108 +0,0 @@
// Code generated by protoc-gen-micro. DO NOT EDIT.
// source: github.com/micro/go-micro/v2/agent/proto/bot.proto
package go_micro_bot
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 Command service
type CommandService interface {
Help(ctx context.Context, in *HelpRequest, opts ...client.CallOption) (*HelpResponse, error)
Exec(ctx context.Context, in *ExecRequest, opts ...client.CallOption) (*ExecResponse, error)
}
type commandService struct {
c client.Client
name string
}
func NewCommandService(name string, c client.Client) CommandService {
if c == nil {
c = client.NewClient()
}
if len(name) == 0 {
name = "go.micro.bot"
}
return &commandService{
c: c,
name: name,
}
}
func (c *commandService) Help(ctx context.Context, in *HelpRequest, opts ...client.CallOption) (*HelpResponse, error) {
req := c.c.NewRequest(c.name, "Command.Help", in)
out := new(HelpResponse)
err := c.c.Call(ctx, req, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *commandService) Exec(ctx context.Context, in *ExecRequest, opts ...client.CallOption) (*ExecResponse, error) {
req := c.c.NewRequest(c.name, "Command.Exec", in)
out := new(ExecResponse)
err := c.c.Call(ctx, req, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for Command service
type CommandHandler interface {
Help(context.Context, *HelpRequest, *HelpResponse) error
Exec(context.Context, *ExecRequest, *ExecResponse) error
}
func RegisterCommandHandler(s server.Server, hdlr CommandHandler, opts ...server.HandlerOption) error {
type command interface {
Help(ctx context.Context, in *HelpRequest, out *HelpResponse) error
Exec(ctx context.Context, in *ExecRequest, out *ExecResponse) error
}
type Command struct {
command
}
h := &commandHandler{hdlr}
return s.Handle(s.NewHandler(&Command{h}, opts...))
}
type commandHandler struct {
CommandHandler
}
func (h *commandHandler) Help(ctx context.Context, in *HelpRequest, out *HelpResponse) error {
return h.CommandHandler.Help(ctx, in, out)
}
func (h *commandHandler) Exec(ctx context.Context, in *ExecRequest, out *ExecResponse) error {
return h.CommandHandler.Exec(ctx, in, out)
}
-25
View File
@@ -1,25 +0,0 @@
syntax = "proto3";
package go.micro.bot;
service Command {
rpc Help(HelpRequest) returns (HelpResponse) {};
rpc Exec(ExecRequest) returns (ExecResponse) {};
}
message HelpRequest {
}
message HelpResponse {
string usage = 1;
string description = 2;
}
message ExecRequest {
repeated string args = 1;
}
message ExecResponse {
bytes result = 1;
string error = 2;
}
+66 -37
View File
@@ -1,15 +1,49 @@
// Package api is for building api gateways
package api
import (
"context"
"errors"
"regexp"
"strings"
"github.com/micro/go-micro/v2/registry"
"github.com/micro/go-micro/v2/server"
"go-micro.dev/v4/api/router"
"go-micro.dev/v4/client"
"go-micro.dev/v4/registry"
"go-micro.dev/v4/server"
)
// Endpoint is a mapping between an RPC method and HTTP endpoint
// API interface provides a way to
// create composable API gateways.
type Api interface {
// Initialize options
Init(...Option) error
// Get the options
Options() Options
// Register an endpoint
Register(*Endpoint) error
// Deregister an endpoint
Deregister(*Endpoint) error
// Run the api
Run(context.Context) error
// Implemenation of api e.g http
String() string
}
// Options are API options.
type Options struct {
// Router for resolving routes
Router router.Router
// Client to use for RPC
Client client.Client
// Address of the server
Address string
}
// Option type are API option args.
type Option func(*Options) error
// Endpoint is a mapping between an RPC method and HTTP endpoint.
type Endpoint struct {
// RPC Method e.g. Greeter.Hello
Name string
@@ -23,16 +57,18 @@ type Endpoint struct {
Method []string
// HTTP Path e.g /greeter. Expect POSIX regex
Path []string
// Stream flag
Stream bool
}
// Service represents an API service
// Service represents an API service.
type Service struct {
// Name of service
Name string
// The endpoint for this service
Endpoint *Endpoint
// Versions of this service
Services []*registry.Service
Versions []*registry.Service
}
func strip(s string) string {
@@ -51,21 +87,22 @@ func slice(s string) []string {
return sl
}
// Encode encodes an endpoint to endpoint metadata
// Encode encodes an endpoint to endpoint metadata.
func Encode(e *Endpoint) map[string]string {
if e == nil {
return nil
}
// endpoint map
ep := make(map[string]string)
em := make(map[string]string)
// set vals only if they exist
set := func(k, v string) {
if len(v) == 0 {
return
}
ep[k] = v
em[k] = v
}
set("endpoint", e.Name)
@@ -75,10 +112,10 @@ func Encode(e *Endpoint) map[string]string {
set("path", strings.Join(e.Path, ","))
set("host", strings.Join(e.Host, ","))
return ep
return em
}
// Decode decodes endpoint metadata into an endpoint
// Decode decodes endpoint metadata into an endpoint.
func Decode(e map[string]string) *Endpoint {
if e == nil {
return nil
@@ -94,7 +131,7 @@ func Decode(e map[string]string) *Endpoint {
}
}
// Validate validates an endpoint to guarantee it won't blow up when being served
// Validate validates an endpoint to guarantee it won't blow up when being served.
func Validate(e *Endpoint) error {
if e == nil {
return errors.New("endpoint is nil")
@@ -105,9 +142,18 @@ func Validate(e *Endpoint) error {
}
for _, p := range e.Path {
_, err := regexp.CompilePOSIX(p)
if err != nil {
return err
ps := p[0]
pe := p[len(p)-1]
if ps == '^' && pe == '$' {
_, err := regexp.CompilePOSIX(p)
if err != nil {
return err
}
} else if ps == '^' && pe != '$' {
return errors.New("invalid path")
} else if ps != '^' && pe == '$' {
return errors.New("invalid path")
}
}
@@ -118,33 +164,11 @@ func Validate(e *Endpoint) error {
return nil
}
/*
Design ideas
// Gateway is an api gateway interface
type Gateway interface {
// Register a http handler
Handle(pattern string, http.Handler)
// Register a route
RegisterRoute(r Route)
// Init initialises the command line.
// It also parses further options.
Init(...Option) error
// Run the gateway
Run() error
}
// NewGateway returns a new api gateway
func NewGateway() Gateway {
return newGateway()
}
*/
// WithEndpoint returns a server.HandlerOption with endpoint metadata set
//
// Usage:
//
// proto.RegisterHandler(service.Server(), new(Handler), api.WithEndpoint(
// proto.RegisterHandler(service.Server(), new(Handler), api.WithEndpoint(
// &api.Endpoint{
// Name: "Greeter.Hello",
// Path: []string{"/greeter"},
@@ -153,3 +177,8 @@ func NewGateway() Gateway {
func WithEndpoint(e *Endpoint) server.HandlerOption {
return server.EndpointMetadata(e.Name, Encode(e))
}
// NewApi returns a new api gateway.
func NewApi(opts ...Option) Api {
return newApi(opts...)
}
+38
View File
@@ -111,3 +111,41 @@ func TestEncoding(t *testing.T) {
}
}
}
func TestValidate(t *testing.T) {
epPcre := &Endpoint{
Name: "Foo.Bar",
Description: "A test endpoint",
Handler: "meta",
Host: []string{"foo.com"},
Method: []string{"GET"},
Path: []string{"^/test/?$"},
}
if err := Validate(epPcre); err != nil {
t.Fatal(err)
}
epGpath := &Endpoint{
Name: "Foo.Bar",
Description: "A test endpoint",
Handler: "meta",
Host: []string{"foo.com"},
Method: []string{"GET"},
Path: []string{"/test/{id}"},
}
if err := Validate(epGpath); err != nil {
t.Fatal(err)
}
epPcreInvalid := &Endpoint{
Name: "Foo.Bar",
Description: "A test endpoint",
Handler: "meta",
Host: []string{"foo.com"},
Method: []string{"GET"},
Path: []string{"/test/?$"},
}
if err := Validate(epPcreInvalid); err == nil {
t.Fatalf("invalid pcre %v", epPcreInvalid.Path[0])
}
}
+233
View File
@@ -0,0 +1,233 @@
// Package client provides an api client
package client
import (
"bytes"
"encoding/json"
"errors"
"io/ioutil"
"net/http"
"net/url"
"strings"
"time"
"github.com/gorilla/websocket"
"go-micro.dev/v4/logger"
)
const (
// local address for api.
localAddress = "http://localhost:8080"
)
// Options of the Client.
type Options struct {
// Token for authentication
Token string
// Address of the micro platform.
// By default it connects to live. Change it or use the local flag
// to connect to your local installation.
Address string
// Helper flag to help users connect to the default local address
Local bool
// set a timeout
Timeout time.Duration
}
// Request is the request of the generic `api-client` call.
type Request struct {
// eg. "go.micro.srv.greeter"
Service string `json:"service"`
// eg. "Say.Hello"
Endpoint string `json:"endpoint"`
// json and then base64 encoded body
Body string `json:"body"`
}
// Response is the response of the generic `api-client` call.
type Response struct {
// json and base64 encoded response body
Body string `json:"body"`
ID string `json:"id"`
Detail string `json:"detail"`
Status string `json:"status"`
// error fields. Error json example
// {"id":"go.micro.client","code":500,"detail":"malformed method name: \"\"","status":"Internal Server Error"}
Code int `json:"code"`
}
// Client enables generic calls to micro.
type Client struct {
options Options
}
// Stream is a websockets stream.
type Stream struct {
conn *websocket.Conn
service, endpoint string
}
// NewClient returns a generic micro client that connects to live by default.
func NewClient(options *Options) *Client {
ret := new(Client)
ret.options = Options{
Address: localAddress,
}
// no options provided
if options == nil {
return ret
}
if options.Token != "" {
ret.options.Token = options.Token
}
if options.Local {
ret.options.Address = localAddress
ret.options.Local = true
}
if options.Timeout > 0 {
ret.options.Timeout = options.Timeout
}
return ret
}
// SetToken sets the api auth token.
func (client *Client) SetToken(t string) {
client.options.Token = t
}
// SetTimeout sets the http client's timeout.
func (client *Client) SetTimeout(d time.Duration) {
client.options.Timeout = d
}
// Call enables you to access any endpoint of any service on Micro.
func (client *Client) Call(service, endpoint string, request, response interface{}) error {
// example curl: curl -XPOST -d '{"service": "go.micro.srv.greeter", "endpoint": "Say.Hello"}'
// -H 'Content-Type: application/json' http://localhost:8080/client {"body":"eyJtc2ciOiJIZWxsbyAifQ=="}
uri, err := url.Parse(client.options.Address)
if err != nil {
return err
}
// set the url to go through the v1 api
uri.Path = "/" + service + "/" + endpoint
b, err := marshalRequest(endpoint, request)
if err != nil {
return err
}
req, err := http.NewRequest("POST", uri.String(), bytes.NewBuffer(b))
if err != nil {
return err
}
// set the token if it exists
if len(client.options.Token) > 0 {
req.Header.Set("Authorization", "Bearer "+client.options.Token)
}
req.Header.Set("Content-Type", "application/json")
// if user didn't specify Timeout the default is 0 i.e no timeout
httpClient := &http.Client{
Timeout: client.options.Timeout,
}
resp, err := httpClient.Do(req)
if err != nil {
return err
}
defer func() {
if err = resp.Body.Close(); err != nil {
logger.DefaultLogger.Log(logger.ErrorLevel, err)
}
}()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
if resp.StatusCode <= 200 || resp.StatusCode > 300 {
return errors.New(string(body))
}
return unmarshalResponse(body, response)
}
// Stream enables the ability to stream via websockets.
func (client *Client) Stream(service, endpoint string, request interface{}) (*Stream, error) {
bytes, err := marshalRequest(endpoint, request)
if err != nil {
return nil, err
}
uri, err := url.Parse(client.options.Address)
if err != nil {
return nil, err
}
// set the url to go through the v1 api
uri.Path = "/" + service + "/" + endpoint
// replace http with websocket
uri.Scheme = strings.Replace(uri.Scheme, "http", "ws", 1)
// create the headers
header := make(http.Header)
// set the token if it exists
if len(client.options.Token) > 0 {
header.Set("Authorization", "Bearer "+client.options.Token)
}
header.Set("Content-Type", "application/json")
// dial the connection, connection not closed as conn is returned
conn, _, err := websocket.DefaultDialer.Dial(uri.String(), header)
if err != nil {
return nil, err
}
// send the first request
if err := conn.WriteMessage(websocket.TextMessage, bytes); err != nil {
return nil, err
}
return &Stream{conn, service, endpoint}, nil
}
// Recv will receive a message from a stream and unmarshal it.
func (s *Stream) Recv(v interface{}) error {
// read response
_, message, err := s.conn.ReadMessage()
if err != nil {
return err
}
return unmarshalResponse(message, v)
}
// Send will send a message into the stream.
func (s *Stream) Send(v interface{}) error {
b, err := marshalRequest(s.endpoint, v)
if err != nil {
return err
}
return s.conn.WriteMessage(websocket.TextMessage, b)
}
func marshalRequest(_ string, v interface{}) ([]byte, error) {
return json.Marshal(v)
}
func unmarshalResponse(body []byte, v interface{}) error {
return json.Unmarshal(body, &v)
}
+24
View File
@@ -0,0 +1,24 @@
package client
import (
"os"
"testing"
)
func TestBasicCall(t *testing.T) {
if v := os.Getenv("IN_TRAVIS_CI"); v == "yes" {
return
}
response := map[string]interface{}{}
if err := NewClient(&Options{
Token: os.Getenv("TOKEN"),
}).Call("groups", "list", map[string]interface{}{
"memberId": "random",
}, &response); err != nil {
t.Fatal(err)
}
if len(response) > 0 {
t.Fatal(len(response))
}
}
+87
View File
@@ -0,0 +1,87 @@
package api
import (
"context"
"go-micro.dev/v4/api/handler"
"go-micro.dev/v4/api/handler/rpc"
"go-micro.dev/v4/api/router/registry"
"go-micro.dev/v4/api/server"
"go-micro.dev/v4/api/server/http"
)
type api struct {
options Options
server server.Server
}
func newApi(opts ...Option) Api {
options := NewOptions(opts...)
rtr := options.Router
if rtr == nil {
// TODO: make configurable
rtr = registry.NewRouter()
}
// TODO: make configurable
hdlr := rpc.NewHandler(
handler.WithRouter(rtr),
)
// TODO: make configurable
// create a new server
srv := http.NewServer(options.Address)
// TODO: allow multiple handlers
// define the handler
srv.Handle("/", hdlr)
return &api{
options: options,
server: srv,
}
}
func (a *api) Init(opts ...Option) error {
for _, o := range opts {
o(&a.options)
}
return nil
}
// Get the options.
func (a *api) Options() Options {
return a.options
}
// Register a http handler.
func (a *api) Register(*Endpoint) error {
return nil
}
// Register a route.
func (a *api) Deregister(*Endpoint) error {
return nil
}
func (a *api) Run(ctx context.Context) error {
if err := a.server.Start(); err != nil {
return err
}
// wait to finish
<-ctx.Done()
if err := a.server.Stop(); err != nil {
return err
}
return nil
}
func (a *api) String() string {
return "http"
}
+38 -29
View File
@@ -4,80 +4,94 @@ package api
import (
"net/http"
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"
"go-micro.dev/v4/api/handler"
api "go-micro.dev/v4/api/proto"
"go-micro.dev/v4/api/router"
"go-micro.dev/v4/client"
"go-micro.dev/v4/errors"
"go-micro.dev/v4/selector"
"go-micro.dev/v4/util/ctx"
)
type apiHandler struct {
opts handler.Options
s *goapi.Service
}
const (
// Handler is the name of the Handler.
Handler = "api"
)
// API handler is the default handler which takes api.Request and returns api.Response
// API handler is the default handler which takes api.Request and returns api.Response.
func (a *apiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
bsize := handler.DefaultMaxRecvSize
if a.opts.MaxRecvSize > 0 {
bsize = a.opts.MaxRecvSize
}
r.Body = http.MaxBytesReader(w, r.Body, bsize)
request, err := requestToProto(r)
if err != nil {
er := errors.InternalServerError("go.micro.api", err.Error())
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(500)
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(er.Error()))
return
}
var service *goapi.Service
var service *router.Route
if a.s != nil {
// we were given the service
service = a.s
} else if a.opts.Router != nil {
if a.opts.Router != nil {
// try get service from router
s, err := a.opts.Router.Route(r)
if err != nil {
er := errors.InternalServerError("go.micro.api", err.Error())
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(500)
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(er.Error()))
return
}
service = s
} else {
// we have no way of routing the request
er := errors.InternalServerError("go.micro.api", "no route found")
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(500)
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(er.Error()))
return
}
// create request and response
c := a.opts.Service.Client()
req := c.NewRequest(service.Name, service.Endpoint.Name, request)
c := a.opts.Client
req := c.NewRequest(service.Service, service.Endpoint.Name, request)
rsp := &api.Response{}
// create the context from headers
cx := ctx.FromRequest(r)
// create strategy
so := selector.WithStrategy(strategy(service.Services))
// create strategy:
so := selector.WithStrategy(strategy(service.Versions))
if err := c.Call(cx, req, rsp, client.WithSelectOption(so)); err != nil {
w.Header().Set("Content-Type", "application/json")
ce := errors.Parse(err.Error())
switch ce.Code {
case 0:
w.WriteHeader(500)
w.WriteHeader(http.StatusInternalServerError)
default:
w.WriteHeader(int(ce.Code))
}
w.Write([]byte(ce.Error()))
return
} else if rsp.StatusCode == 0 {
rsp.StatusCode = http.StatusOK
@@ -94,6 +108,7 @@ func (a *apiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
w.WriteHeader(int(rsp.StatusCode))
w.Write([]byte(rsp.Body))
}
@@ -101,17 +116,11 @@ func (a *apiHandler) String() string {
return "api"
}
// NewHandler returns an api.Handler.
func NewHandler(opts ...handler.Option) handler.Handler {
options := handler.NewOptions(opts...)
return &apiHandler{
opts: options,
}
}
func WithService(s *goapi.Service, opts ...handler.Option) handler.Handler {
options := handler.NewOptions(opts...)
return &apiHandler{
opts: options,
s: s,
}
}
+23 -10
View File
@@ -2,20 +2,25 @@ package api
import (
"fmt"
"io/ioutil"
"mime"
"net"
"net/http"
"strings"
api "github.com/micro/go-micro/v2/api/proto"
"github.com/micro/go-micro/v2/client/selector"
"github.com/micro/go-micro/v2/registry"
"github.com/oxtoacart/bpool"
api "go-micro.dev/v4/api/proto"
"go-micro.dev/v4/registry"
"go-micro.dev/v4/selector"
)
var (
// need to calculate later to specify useful defaults.
bufferPool = bpool.NewSizedBufferPool(1024, 8)
)
func requestToProto(r *http.Request) (*api.Request, error) {
if err := r.ParseForm(); err != nil {
return nil, fmt.Errorf("Error parsing form: %v", err)
return nil, fmt.Errorf("Error parsing form: %w", err)
}
req := &api.Request{
@@ -29,19 +34,24 @@ func requestToProto(r *http.Request) (*api.Request, error) {
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
if err != nil {
ct = "text/plain; charset=UTF-8" //default CT is text/plain
ct = "text/plain; charset=UTF-8" // default CT is text/plain
r.Header.Set("Content-Type", ct)
}
//set the body:
// set the body:
if r.Body != nil {
switch ct {
case "application/x-www-form-urlencoded":
// expect form vals in Post data
default:
buf := bufferPool.Get()
defer bufferPool.Put(buf)
data, _ := ioutil.ReadAll(r.Body)
req.Body = string(data)
if _, err = buf.ReadFrom(r.Body); err != nil {
return nil, err
}
req.Body = buf.String()
}
}
@@ -73,6 +83,7 @@ func requestToProto(r *http.Request) (*api.Request, error) {
}
req.Get[key] = header
}
header.Values = vals
}
@@ -85,6 +96,7 @@ func requestToProto(r *http.Request) (*api.Request, error) {
}
req.Post[key] = header
}
header.Values = vals
}
@@ -96,13 +108,14 @@ func requestToProto(r *http.Request) (*api.Request, error) {
}
req.Header[key] = header
}
header.Values = vals
}
return req, nil
}
// strategy is a hack for selection
// strategy is a hack for selection.
func strategy(services []*registry.Service) selector.Strategy {
return func(_ []*registry.Service) selector.Next {
// ignore input to this function, use services above
-268
View File
@@ -1,268 +0,0 @@
// Package broker provides a go-micro/broker handler
package broker
import (
"encoding/json"
"io/ioutil"
"net/http"
"net/url"
"strings"
"sync"
"time"
"github.com/gorilla/websocket"
"github.com/micro/go-micro/v2/api/handler"
"github.com/micro/go-micro/v2/broker"
"github.com/micro/go-micro/v2/util/log"
)
const (
Handler = "broker"
pingTime = (readDeadline * 9) / 10
readLimit = 16384
readDeadline = 60 * time.Second
writeDeadline = 10 * time.Second
)
type brokerHandler struct {
opts handler.Options
u websocket.Upgrader
}
type conn struct {
b broker.Broker
cType string
topic string
queue string
exit chan bool
sync.Mutex
ws *websocket.Conn
}
var (
once sync.Once
contentType = "text/plain"
)
func checkOrigin(r *http.Request) bool {
origin := r.Header["Origin"]
if len(origin) == 0 {
return true
}
u, err := url.Parse(origin[0])
if err != nil {
return false
}
return u.Host == r.Host
}
func (c *conn) close() {
select {
case <-c.exit:
return
default:
close(c.exit)
}
}
func (c *conn) readLoop() {
defer func() {
c.close()
c.ws.Close()
}()
// set read limit/deadline
c.ws.SetReadLimit(readLimit)
c.ws.SetReadDeadline(time.Now().Add(readDeadline))
// set close handler
ch := c.ws.CloseHandler()
c.ws.SetCloseHandler(func(code int, text string) error {
err := ch(code, text)
c.close()
return err
})
// set pong handler
c.ws.SetPongHandler(func(string) error {
c.ws.SetReadDeadline(time.Now().Add(readDeadline))
return nil
})
for {
_, message, err := c.ws.ReadMessage()
if err != nil {
return
}
c.b.Publish(c.topic, &broker.Message{
Header: map[string]string{"Content-Type": c.cType},
Body: message,
})
}
}
func (c *conn) write(mType int, data []byte) error {
c.Lock()
c.ws.SetWriteDeadline(time.Now().Add(writeDeadline))
err := c.ws.WriteMessage(mType, data)
c.Unlock()
return err
}
func (c *conn) writeLoop() {
ticker := time.NewTicker(pingTime)
var opts []broker.SubscribeOption
if len(c.queue) > 0 {
opts = append(opts, broker.Queue(c.queue))
}
subscriber, err := c.b.Subscribe(c.topic, func(p broker.Event) error {
b, err := json.Marshal(p.Message())
if err != nil {
return nil
}
return c.write(websocket.TextMessage, b)
}, opts...)
defer func() {
subscriber.Unsubscribe()
ticker.Stop()
c.ws.Close()
}()
if err != nil {
log.Log(err.Error())
return
}
for {
select {
case <-ticker.C:
if err := c.write(websocket.PingMessage, []byte{}); err != nil {
return
}
case <-c.exit:
return
}
}
}
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()
})
// Parse
r.ParseForm()
topic := r.Form.Get("topic")
// Can't do anything without a topic
if len(topic) == 0 {
http.Error(w, "Topic not specified", 400)
return
}
// Post assumed to be Publish
if r.Method == "POST" {
// Create a broker message
msg := &broker.Message{
Header: make(map[string]string),
}
// Set header
for k, v := range r.Header {
msg.Header[k] = strings.Join(v, ", ")
}
// Read body
b, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
// Set body
msg.Body = b
// Publish
br.Publish(topic, msg)
return
}
// now back to our regularly scheduled programming
if r.Method != "GET" {
http.Error(w, "Method not allowed", 405)
return
}
queue := r.Form.Get("queue")
ws, err := b.u.Upgrade(w, r, nil)
if err != nil {
log.Log(err.Error())
return
}
cType := r.Header.Get("Content-Type")
if len(cType) == 0 {
cType = contentType
}
c := &conn{
b: br,
cType: cType,
topic: topic,
queue: queue,
exit: make(chan bool),
ws: ws,
}
go c.writeLoop()
c.readLoop()
}
func (b *brokerHandler) String() string {
return "broker"
}
func NewHandler(opts ...handler.Option) handler.Handler {
return &brokerHandler{
u: websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
ReadBufferSize: 1024,
WriteBufferSize: 1024,
},
opts: handler.NewOptions(opts...),
}
}
func WithCors(cors map[string]bool, opts ...handler.Option) handler.Handler {
return &brokerHandler{
u: websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
if origin := r.Header.Get("Origin"); cors[origin] {
return true
} else if len(origin) > 0 && cors["*"] {
return true
} else if checkOrigin(r) {
return true
}
return false
},
ReadBufferSize: 1024,
WriteBufferSize: 1024,
},
opts: handler.NewOptions(opts...),
}
}
-94
View File
@@ -1,94 +0,0 @@
// Package cloudevents provides a cloudevents handler publishing the event using the go-micro/client
package cloudevents
import (
"net/http"
"path"
"regexp"
"strings"
"github.com/micro/go-micro/v2/api/handler"
"github.com/micro/go-micro/v2/util/ctx"
)
type event struct {
options handler.Options
}
var (
Handler = "cloudevents"
versionRe = regexp.MustCompilePOSIX("^v[0-9]+$")
)
func eventName(parts []string) string {
return strings.Join(parts, ".")
}
func evRoute(ns, p string) (string, string) {
p = path.Clean(p)
p = strings.TrimPrefix(p, "/")
if len(p) == 0 {
return ns, "event"
}
parts := strings.Split(p, "/")
// no path
if len(parts) == 0 {
// topic: namespace
// action: event
return strings.Trim(ns, "."), "event"
}
// Treat /v[0-9]+ as versioning
// /v1/foo/bar => topic: v1.foo action: bar
if len(parts) >= 2 && versionRe.Match([]byte(parts[0])) {
topic := ns + "." + strings.Join(parts[:2], ".")
action := eventName(parts[1:])
return topic, action
}
// /foo => topic: ns.foo action: foo
// /foo/bar => topic: ns.foo action: bar
topic := ns + "." + strings.Join(parts[:1], ".")
action := eventName(parts[1:])
return topic, action
}
func (e *event) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// request to topic:event
// create event
// publish to topic
topic, _ := evRoute(e.options.Namespace, r.URL.Path)
// create event
ev, err := FromRequest(r)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
// get client
c := e.options.Service.Client()
// create publication
p := c.NewMessage(topic, ev)
// publish event
if err := c.Publish(ctx.FromRequest(r), p); err != nil {
http.Error(w, err.Error(), 500)
return
}
}
func (e *event) String() string {
return "cloudevents"
}
func NewHandler(opts ...handler.Option) handler.Handler {
return &event{
options: handler.NewOptions(opts...),
}
}
-282
View File
@@ -1,282 +0,0 @@
/*
* From: https://github.com/serverless/event-gateway/blob/master/event/event.go
* Modified: Strip to handler requirements
*
* Copyright 2017 Serverless, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package cloudevents
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"mime"
"net/http"
"strings"
"time"
"unicode"
"github.com/google/uuid"
validator "gopkg.in/go-playground/validator.v9"
)
const (
// TransformationVersion is indicative of the revision of how Event Gateway transforms a request into CloudEvents format.
TransformationVersion = "0.1"
// CloudEventsVersion currently supported by Event Gateway
CloudEventsVersion = "0.1"
)
// Event is a default event structure. All data that passes through the Event Gateway
// is formatted to a format defined CloudEvents v0.1 spec.
type Event struct {
EventType string `json:"eventType" validate:"required"`
EventTypeVersion string `json:"eventTypeVersion,omitempty"`
CloudEventsVersion string `json:"cloudEventsVersion" validate:"required"`
Source string `json:"source" validate:"uri,required"`
EventID string `json:"eventID" validate:"required"`
EventTime *time.Time `json:"eventTime,omitempty"`
SchemaURL string `json:"schemaURL,omitempty"`
Extensions map[string]interface{} `json:"extensions,omitempty"`
ContentType string `json:"contentType,omitempty"`
Data interface{} `json:"data"`
}
// New return new instance of Event.
func New(eventType string, mimeType string, payload interface{}) *Event {
now := time.Now()
event := &Event{
EventType: eventType,
CloudEventsVersion: CloudEventsVersion,
Source: "https://micro.mu",
EventID: uuid.New().String(),
EventTime: &now,
ContentType: mimeType,
Data: payload,
Extensions: map[string]interface{}{
"eventgateway": map[string]interface{}{
"transformed": "true",
"transformation-version": TransformationVersion,
},
},
}
event.Data = normalizePayload(event.Data, event.ContentType)
return event
}
// FromRequest takes an HTTP request and returns an Event along with path. Most of the implementation
// is based on https://github.com/cloudevents/spec/blob/master/http-transport-binding.md.
// This function also supports legacy mode where event type is sent in Event header.
func FromRequest(r *http.Request) (*Event, error) {
contentType := r.Header.Get("Content-Type")
mimeType, _, err := mime.ParseMediaType(contentType)
if err != nil {
if err.Error() != "mime: no media type" {
return nil, err
}
mimeType = "application/octet-stream"
}
// Read request body
body := []byte{}
if r.Body != nil {
body, err = ioutil.ReadAll(r.Body)
if err != nil {
return nil, err
}
}
var event *Event
if mimeType == mimeCloudEventsJSON { // CloudEvents Structured Content Mode
return parseAsCloudEvent(mimeType, body)
} else if isCloudEventsBinaryContentMode(r.Header) { // CloudEvents Binary Content Mode
return parseAsCloudEventBinary(r.Header, body)
} else if isLegacyMode(r.Header) {
if mimeType == mimeJSON { // CloudEvent in Legacy Mode
event, err = parseAsCloudEvent(mimeType, body)
if err != nil {
return New(string(r.Header.Get("event")), mimeType, body), nil
}
return event, err
}
return New(string(r.Header.Get("event")), mimeType, body), nil
}
return New("http.request", mimeJSON, newHTTPRequestData(r, body)), nil
}
// Validate Event struct
func (e *Event) Validate() error {
validate := validator.New()
err := validate.Struct(e)
if err != nil {
return fmt.Errorf("CloudEvent not valid: %v", err)
}
return nil
}
func isLegacyMode(headers http.Header) bool {
if headers.Get("Event") != "" {
return true
}
return false
}
func isCloudEventsBinaryContentMode(headers http.Header) bool {
if headers.Get("CE-EventType") != "" &&
headers.Get("CE-CloudEventsVersion") != "" &&
headers.Get("CE-Source") != "" &&
headers.Get("CE-EventID") != "" {
return true
}
return false
}
func parseAsCloudEventBinary(headers http.Header, payload interface{}) (*Event, error) {
event := &Event{
EventType: headers.Get("CE-EventType"),
EventTypeVersion: headers.Get("CE-EventTypeVersion"),
CloudEventsVersion: headers.Get("CE-CloudEventsVersion"),
Source: headers.Get("CE-Source"),
EventID: headers.Get("CE-EventID"),
ContentType: headers.Get("Content-Type"),
Data: payload,
}
err := event.Validate()
if err != nil {
return nil, err
}
if headers.Get("CE-EventTime") != "" {
val, err := time.Parse(time.RFC3339, headers.Get("CE-EventTime"))
if err != nil {
return nil, err
}
event.EventTime = &val
}
if val := headers.Get("CE-SchemaURL"); len(val) > 0 {
event.SchemaURL = val
}
event.Extensions = map[string]interface{}{}
for key, val := range flatten(headers) {
if strings.HasPrefix(key, "Ce-X-") {
key = strings.TrimLeft(key, "Ce-X-")
// Make first character lowercase
runes := []rune(key)
runes[0] = unicode.ToLower(runes[0])
event.Extensions[string(runes)] = val
}
}
event.Data = normalizePayload(event.Data, event.ContentType)
return event, nil
}
func flatten(h http.Header) map[string]string {
headers := map[string]string{}
for key, header := range h {
headers[key] = header[0]
if len(header) > 1 {
headers[key] = strings.Join(header, ", ")
}
}
return headers
}
func parseAsCloudEvent(mime string, payload interface{}) (*Event, error) {
body, ok := payload.([]byte)
if ok {
event := &Event{}
err := json.Unmarshal(body, event)
if err != nil {
return nil, err
}
err = event.Validate()
if err != nil {
return nil, err
}
event.Data = normalizePayload(event.Data, event.ContentType)
return event, nil
}
return nil, errors.New("couldn't cast to []byte")
}
const (
mimeJSON = "application/json"
mimeFormMultipart = "multipart/form-data"
mimeFormURLEncoded = "application/x-www-form-urlencoded"
mimeCloudEventsJSON = "application/cloudevents+json"
)
// normalizePayload takes anything, checks if it's []byte array and depending on provided mime
// type converts it to either string or map[string]interface to avoid having base64 string after
// JSON marshaling.
func normalizePayload(payload interface{}, mime string) interface{} {
if bytePayload, ok := payload.([]byte); ok && len(bytePayload) > 0 {
switch {
case mime == mimeJSON || strings.HasSuffix(mime, "+json"):
var result map[string]interface{}
err := json.Unmarshal(bytePayload, &result)
if err != nil {
return payload
}
return result
case strings.HasPrefix(mime, mimeFormMultipart), mime == mimeFormURLEncoded:
return string(bytePayload)
}
}
return payload
}
// HTTPRequestData is a event schema used for sending events to HTTP subscriptions.
type HTTPRequestData struct {
Headers map[string]string `json:"headers"`
Query map[string][]string `json:"query"`
Body interface{} `json:"body"`
Host string `json:"host"`
Path string `json:"path"`
Method string `json:"method"`
Params map[string]string `json:"params"`
}
// NewHTTPRequestData returns a new instance of HTTPRequestData
func newHTTPRequestData(r *http.Request, eventData interface{}) *HTTPRequestData {
req := &HTTPRequestData{
Headers: flatten(r.Header),
Query: r.URL.Query(),
Body: eventData,
Host: r.Host,
Path: r.URL.Path,
Method: r.Method,
}
req.Body = normalizePayload(req.Body, r.Header.Get("content-type"))
return req
}
+52 -33
View File
@@ -4,7 +4,6 @@ package event
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"path"
"regexp"
@@ -12,16 +11,22 @@ import (
"time"
"github.com/google/uuid"
"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"
"github.com/oxtoacart/bpool"
"go-micro.dev/v4/api/handler"
proto "go-micro.dev/v4/api/proto"
"go-micro.dev/v4/util/ctx"
)
var (
bufferPool = bpool.NewSizedBufferPool(1024, 8)
)
type event struct {
options handler.Options
opts handler.Options
}
var (
// Handler is the name of this handler.
Handler = "event"
versionRe = regexp.MustCompilePOSIX("^v[0-9]+$")
)
@@ -30,48 +35,56 @@ func eventName(parts []string) string {
return strings.Join(parts, ".")
}
func evRoute(ns, p string) (string, string) {
p = path.Clean(p)
p = strings.TrimPrefix(p, "/")
func evRoute(namespace, myPath string) (string, string) {
myPath = path.Clean(myPath)
myPath = strings.TrimPrefix(myPath, "/")
if len(p) == 0 {
return ns, "event"
if len(myPath) == 0 {
return namespace, Handler
}
parts := strings.Split(p, "/")
parts := strings.Split(myPath, "/")
// no path
if len(parts) == 0 {
// topic: namespace
// action: event
return strings.Trim(ns, "."), "event"
return strings.Trim(namespace, "."), Handler
}
// Treat /v[0-9]+ as versioning
// /v1/foo/bar => topic: v1.foo action: bar
if len(parts) >= 2 && versionRe.Match([]byte(parts[0])) {
topic := ns + "." + strings.Join(parts[:2], ".")
topic := namespace + "." + strings.Join(parts[:2], ".")
action := eventName(parts[1:])
return topic, action
}
// /foo => topic: ns.foo action: foo
// /foo/bar => topic: ns.foo action: bar
topic := ns + "." + strings.Join(parts[:1], ".")
topic := namespace + "." + strings.Join(parts[:1], ".")
action := eventName(parts[1:])
return topic, action
}
func (e *event) ServeHTTP(w http.ResponseWriter, r *http.Request) {
func (e *event) ServeHTTP(rsp http.ResponseWriter, req *http.Request) {
bsize := handler.DefaultMaxRecvSize
if e.opts.MaxRecvSize > 0 {
bsize = e.opts.MaxRecvSize
}
req.Body = http.MaxBytesReader(rsp, req.Body, bsize)
// request to topic:event
// create event
// publish to topic
topic, action := evRoute(e.options.Namespace, r.URL.Path)
topic, action := evRoute(e.opts.Namespace, req.URL.Path)
// create event
ev := &proto.Event{
event := &proto.Event{
Name: action,
// TODO: dedupe event
Id: fmt.Sprintf("%s-%s-%s", topic, action, uuid.New().String()),
@@ -80,49 +93,55 @@ func (e *event) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
// set headers
for key, vals := range r.Header {
header, ok := ev.Header[key]
for key, vals := range req.Header {
header, ok := event.Header[key]
if !ok {
header = &proto.Pair{
Key: key,
}
ev.Header[key] = header
event.Header[key] = header
}
header.Values = vals
}
// set body
if r.Method == "GET" {
bytes, _ := json.Marshal(r.URL.Query())
ev.Data = string(bytes)
if req.Method == http.MethodGet {
bytes, _ := json.Marshal(req.URL.Query())
event.Data = string(bytes)
} else {
b, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), 500)
// Read body
buf := bufferPool.Get()
defer bufferPool.Put(buf)
if _, err := buf.ReadFrom(req.Body); err != nil {
http.Error(rsp, err.Error(), http.StatusInternalServerError)
return
}
ev.Data = string(b)
event.Data = buf.String()
}
// get client
c := e.options.Service.Client()
c := e.opts.Client
// create publication
p := c.NewMessage(topic, ev)
p := c.NewMessage(topic, event)
// publish event
if err := c.Publish(ctx.FromRequest(r), p); err != nil {
http.Error(w, err.Error(), 500)
if err := c.Publish(ctx.FromRequest(req), p); err != nil {
http.Error(rsp, err.Error(), http.StatusInternalServerError)
return
}
}
func (e *event) String() string {
return "event"
return Handler
}
// NewHandler returns a new event handler.
func NewHandler(opts ...handler.Option) handler.Handler {
return &event{
options: handler.NewOptions(opts...),
opts: handler.NewOptions(opts...),
}
}
-16
View File
@@ -1,16 +0,0 @@
// Package file serves file relative to the current directory
package file
import (
"net/http"
)
type Handler struct{}
func (h *Handler) Serve(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "."+r.URL.Path)
}
func (h *Handler) String() string {
return "file"
}
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"net/http"
)
// Handler represents a HTTP handler that manages a request
// Handler represents a HTTP handler that manages a request.
type Handler interface {
// standard http handler
http.Handler
+13 -27
View File
@@ -8,56 +8,52 @@ import (
"net/http/httputil"
"net/url"
"github.com/micro/go-micro/v2/api"
"github.com/micro/go-micro/v2/api/handler"
"github.com/micro/go-micro/v2/client/selector"
"go-micro.dev/v4/api/handler"
"go-micro.dev/v4/api/router"
"go-micro.dev/v4/selector"
)
const (
// Handler is the name of the handler.
Handler = "http"
)
type httpHandler struct {
options handler.Options
// set with different initialiser
s *api.Service
}
func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
service, err := h.getService(r)
if err != nil {
w.WriteHeader(500)
w.WriteHeader(http.StatusInternalServerError)
return
}
if len(service) == 0 {
w.WriteHeader(404)
w.WriteHeader(http.StatusNotFound)
return
}
rp, err := url.Parse(service)
if err != nil {
w.WriteHeader(500)
w.WriteHeader(http.StatusInternalServerError)
return
}
httputil.NewSingleHostReverseProxy(rp).ServeHTTP(w, r)
}
// getService returns the service for this request from the selector
// getService returns the service for this request from the selector.
func (h *httpHandler) getService(r *http.Request) (string, error) {
var service *api.Service
var service *router.Route
if h.s != nil {
// we were given the service
service = h.s
} else if h.options.Router != nil {
if h.options.Router != nil {
// try get service from router
s, err := h.options.Router.Route(r)
if err != nil {
return "", err
}
service = s
} else {
// we have no way of routing the request
@@ -65,7 +61,7 @@ func (h *httpHandler) getService(r *http.Request) (string, error) {
}
// create a random selector
next := selector.Random(service.Services)
next := selector.Random(service.Versions)
// get the next node
s, err := next()
@@ -80,7 +76,7 @@ func (h *httpHandler) String() string {
return "http"
}
// NewHandler returns a http proxy handler
// NewHandler returns a http proxy handler.
func NewHandler(opts ...handler.Option) handler.Handler {
options := handler.NewOptions(opts...)
@@ -88,13 +84,3 @@ func NewHandler(opts ...handler.Option) handler.Handler {
options: options,
}
}
// WithService creates a handler with a service
func WithService(s *api.Service, opts ...handler.Option) handler.Handler {
options := handler.NewOptions(opts...)
return &httpHandler{
options: options,
s: s,
}
}
+14 -9
View File
@@ -6,15 +6,16 @@ import (
"net/http/httptest"
"testing"
"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"
"go-micro.dev/v4/api/handler"
"go-micro.dev/v4/api/resolver"
"go-micro.dev/v4/api/resolver/vpath"
"go-micro.dev/v4/api/router"
regRouter "go-micro.dev/v4/api/router/registry"
"go-micro.dev/v4/registry"
)
func testHttp(t *testing.T, path, service, ns string) {
r := memory.NewRegistry()
r := registry.NewMemoryRegistry()
l, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
@@ -51,11 +52,13 @@ func testHttp(t *testing.T, path, service, ns string) {
t.Fatal(err)
}
// initialise the handler
// initialize the handler
rt := regRouter.NewRouter(
router.WithHandler("http"),
router.WithNamespace(ns),
router.WithRegistry(r),
router.WithResolver(vpath.NewResolver(
resolver.WithNamespace(resolver.StaticNamespace(ns)),
)),
)
p := NewHandler(handler.WithRouter(rt))
@@ -116,6 +119,8 @@ func TestHttpHandler(t *testing.T) {
}
for _, d := range testData {
testHttp(t, d.path, d.service, d.namespace)
t.Run(d.service, func(t *testing.T) {
testHttp(t, d.path, d.service, d.namespace)
})
}
}
+47 -18
View File
@@ -1,55 +1,84 @@
package handler
import (
"github.com/micro/go-micro/v2"
"github.com/micro/go-micro/v2/api/router"
"go-micro.dev/v4/api/router"
"go-micro.dev/v4/client"
"go-micro.dev/v4/logger"
)
var (
// DefaultMaxRecvSize is 10MiB.
DefaultMaxRecvSize int64 = 1024 * 1024 * 100
)
// Options is the list of api Options.
type Options struct {
Namespace string
Router router.Router
Service micro.Service
Router router.Router
Client client.Client
Logger logger.Logger
Namespace string
MaxRecvSize int64
}
// Option is a api Option.
type Option func(o *Options)
// NewOptions fills in the blanks
// NewOptions fills in the blanks.
func NewOptions(opts ...Option) Options {
var options Options
options := Options{
Logger: logger.DefaultLogger,
}
for _, o := range opts {
o(&options)
}
// create service if its blank
if options.Service == nil {
WithService(micro.NewService())(&options)
if options.Client == nil {
WithClient(client.DefaultClient)(&options)
}
// set namespace if blank
if len(options.Namespace) == 0 {
WithNamespace("go.micro.api")(&options)
if options.MaxRecvSize == 0 {
options.MaxRecvSize = DefaultMaxRecvSize
}
if options.Logger == nil {
options.Logger = logger.LoggerOrDefault(options.Logger)
}
return options
}
// WithNamespace specifies the namespace for the handler
// WithNamespace specifies the namespace for the handler.
func WithNamespace(s string) Option {
return func(o *Options) {
o.Namespace = s
}
}
// WithRouter specifies a router to be used by the handler
// WithRouter specifies a router to be used by the handler.
func WithRouter(r router.Router) Option {
return func(o *Options) {
o.Router = r
}
}
// WithService specifies a micro.Service
func WithService(s micro.Service) Option {
// WithClient sets the client for the handler.
func WithClient(c client.Client) Option {
return func(o *Options) {
o.Service = s
o.Client = c
}
}
// WithMaxRecvSize specifies max body size.
func WithMaxRecvSize(size int64) Option {
return func(o *Options) {
o.MaxRecvSize = size
}
}
// WithLogger specifies the logger.
func WithLogger(l logger.Logger) Option {
return func(o *Options) {
o.Logger = l
}
}
-211
View File
@@ -1,211 +0,0 @@
// Package registry is a go-micro/registry handler
package registry
import (
"encoding/json"
"io/ioutil"
"net/http"
"strconv"
"time"
"github.com/gorilla/websocket"
"github.com/micro/go-micro/v2/api/handler"
"github.com/micro/go-micro/v2/registry"
)
const (
Handler = "registry"
pingTime = (readDeadline * 9) / 10
readLimit = 16384
readDeadline = 60 * time.Second
writeDeadline = 10 * time.Second
)
type registryHandler struct {
opts handler.Options
reg registry.Registry
}
func (rh *registryHandler) add(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
b, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
defer r.Body.Close()
var opts []registry.RegisterOption
// parse ttl
if ttl := r.Form.Get("ttl"); len(ttl) > 0 {
d, err := time.ParseDuration(ttl)
if err == nil {
opts = append(opts, registry.RegisterTTL(d))
}
}
var service *registry.Service
err = json.Unmarshal(b, &service)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
err = rh.reg.Register(service, opts...)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
}
func (rh *registryHandler) del(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
b, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
defer r.Body.Close()
var service *registry.Service
err = json.Unmarshal(b, &service)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
err = rh.reg.Deregister(service)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
}
func (rh *registryHandler) get(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
service := r.Form.Get("service")
var s []*registry.Service
var err error
if len(service) == 0 {
//
upgrade := r.Header.Get("Upgrade")
connect := r.Header.Get("Connection")
// watch if websockets
if upgrade == "websocket" && connect == "Upgrade" {
rw, err := rh.reg.Watch()
if err != nil {
http.Error(w, err.Error(), 500)
return
}
watch(rw, w, r)
return
}
// otherwise list services
s, err = rh.reg.ListServices()
} else {
s, err = rh.reg.GetService(service)
}
if err != nil {
http.Error(w, err.Error(), 500)
return
}
if s == nil || (len(service) > 0 && (len(s) == 0 || len(s[0].Name) == 0)) {
http.Error(w, "Service not found", 404)
return
}
b, err := json.Marshal(s)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Content-Length", strconv.Itoa(len(b)))
w.Write(b)
}
func ping(ws *websocket.Conn, exit chan bool) {
ticker := time.NewTicker(pingTime)
for {
select {
case <-ticker.C:
ws.SetWriteDeadline(time.Now().Add(writeDeadline))
err := ws.WriteMessage(websocket.PingMessage, []byte{})
if err != nil {
return
}
case <-exit:
return
}
}
}
func watch(rw registry.Watcher, w http.ResponseWriter, r *http.Request) {
upgrader := websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
// we need an exit chan
exit := make(chan bool)
defer func() {
close(exit)
}()
// ping the socket
go ping(ws, exit)
for {
// get next result
r, err := rw.Next()
if err != nil {
http.Error(w, err.Error(), 500)
return
}
// write to client
ws.SetWriteDeadline(time.Now().Add(writeDeadline))
if err := ws.WriteJSON(r); err != nil {
return
}
}
}
func (rh *registryHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
rh.get(w, r)
case "POST":
rh.add(w, r)
case "DELETE":
rh.del(w, r)
}
}
func (rh *registryHandler) String() string {
return "registry"
}
func NewHandler(opts ...handler.Option) handler.Handler {
options := handler.NewOptions(opts...)
return &registryHandler{
opts: options,
reg: options.Service.Client().Options().Registry,
}
}
+355 -100
View File
@@ -4,38 +4,44 @@ package rpc
import (
"encoding/json"
"io"
"io/ioutil"
"net/http"
"net/textproto"
"strconv"
"strings"
"github.com/joncalhoun/qson"
"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"
jsonpatch "github.com/evanphx/json-patch/v5"
"github.com/oxtoacart/bpool"
"go-micro.dev/v4/api/handler"
"go-micro.dev/v4/api/internal/proto"
"go-micro.dev/v4/api/router"
"go-micro.dev/v4/client"
"go-micro.dev/v4/codec"
"go-micro.dev/v4/codec/jsonrpc"
"go-micro.dev/v4/codec/protorpc"
"go-micro.dev/v4/errors"
log "go-micro.dev/v4/logger"
"go-micro.dev/v4/metadata"
"go-micro.dev/v4/registry"
"go-micro.dev/v4/selector"
"go-micro.dev/v4/util/ctx"
"go-micro.dev/v4/util/qson"
)
const (
Handler = "rpc"
// Handler is the name of this handler.
Handler = "rpc"
packageID = "go.micro.api"
)
var (
// supported json codecs
// supported json codecs.
jsonCodecs = []string{
"application/grpc+json",
"application/json",
"application/json-rpc",
}
// support proto codecs
// support proto codecs.
protoCodecs = []string{
"application/grpc",
"application/grpc+proto",
@@ -44,11 +50,12 @@ var (
"application/proto-rpc",
"application/octet-stream",
}
bufferPool = bpool.NewSizedBufferPool(1024, 8)
)
type rpcHandler struct {
opts handler.Options
s *api.Service
}
type buffer struct {
@@ -59,7 +66,7 @@ func (b *buffer) Write(_ []byte) (int, error) {
return 0, nil
}
// strategy is a hack for selection
// strategy is a hack for selection.
func strategy(services []*registry.Service) selector.Strategy {
return func(_ []*registry.Service) selector.Next {
// ignore input to this function, use services above
@@ -68,60 +75,103 @@ func strategy(services []*registry.Service) selector.Strategy {
}
func (h *rpcHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
var service *api.Service
logger := h.opts.Logger
bsize := handler.DefaultMaxRecvSize
if h.s != nil {
// we were given the service
service = h.s
} else if h.opts.Router != nil {
if h.opts.MaxRecvSize > 0 {
bsize = h.opts.MaxRecvSize
}
r.Body = http.MaxBytesReader(w, r.Body, bsize)
defer r.Body.Close()
var service *router.Route
if h.opts.Router != nil {
// try get service from router
s, err := h.opts.Router.Route(r)
if err != nil {
writeError(w, r, errors.InternalServerError("go.micro.api", err.Error()))
werr := writeError(w, r, errors.InternalServerError(packageID, err.Error()))
if werr != nil {
logger.Log(log.ErrorLevel, werr)
}
return
}
service = s
} else {
// we have no way of routing the request
writeError(w, r, errors.InternalServerError("go.micro.api", "no route found"))
werr := writeError(w, r, errors.InternalServerError(packageID, "no route found"))
if werr != nil {
logger.Log(log.ErrorLevel, werr)
}
return
}
// only allow post when we have the router
if r.Method != "GET" && (h.opts.Router != nil && r.Method != "POST") {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
ct := r.Header.Get("Content-Type")
contentType := r.Header.Get("Content-Type")
// Strip charset from Content-Type (like `application/json; charset=UTF-8`)
if idx := strings.IndexRune(ct, ';'); idx >= 0 {
ct = ct[:idx]
if idx := strings.IndexRune(contentType, ';'); idx >= 0 {
contentType = contentType[:idx]
}
// micro client
c := h.opts.Service.Client()
myClient := h.opts.Client
// create strategy
so := selector.WithStrategy(strategy(service.Services))
// create context
myContext := ctx.FromRequest(r)
// get context from http handler wrappers
md, ok := metadata.FromContext(r.Context())
if !ok {
md = make(metadata.Metadata)
}
// fill contex with http headers
md["Host"] = r.Host
md["Method"] = r.Method
// get canonical headers
for k := range r.Header {
// may be need to get all values for key like r.Header.Values() provide in go 1.14
md[textproto.CanonicalMIMEHeaderKey(k)] = r.Header.Get(k)
}
// merge context with overwrite
myContext = metadata.MergeContext(myContext, md, true)
// set merged context to request
*r = *r.Clone(myContext)
// if stream we currently only support json
if isStream(r, service) {
// drop older context as it can have timeouts and create new
// md, _ := metadata.FromContext(cx)
// serveWebsocket(context.TODO(), w, r, service, c)
if err := serveWebsocket(myContext, w, r, service, myClient); err != nil {
logger.Log(log.ErrorLevel, err)
}
// get payload
br, err := requestPayload(r)
if err != nil {
writeError(w, r, err)
return
}
// create context
cx := ctx.FromRequest(r)
// create strategy
mySelector := selector.WithStrategy(strategy(service.Versions))
// walk the standard call path
// get payload
br, err := requestPayload(r)
if err != nil {
if werr := writeError(w, r, err); werr != nil {
logger.Log(log.ErrorLevel, werr)
}
return
}
var rsp []byte
switch {
// proto codecs
case hasCodec(ct, protoCodecs):
case hasCodec(contentType, protoCodecs):
request := &proto.Message{}
// if the extracted payload isn't empty lets use it
if len(br) > 0 {
@@ -131,25 +181,36 @@ func (h *rpcHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// create request/response
response := &proto.Message{}
req := c.NewRequest(
service.Name,
req := myClient.NewRequest(
service.Service,
service.Endpoint.Name,
request,
client.WithContentType(ct),
client.WithContentType(contentType),
)
// make the call
if err := c.Call(cx, req, response, client.WithSelectOption(so)); err != nil {
writeError(w, r, err)
if err := myClient.Call(myContext, req, response, client.WithSelectOption(mySelector)); err != nil {
if werr := writeError(w, r, err); werr != nil {
logger.Log(log.ErrorLevel, werr)
}
return
}
// marshall response
rsp, _ = response.Marshal()
rsp, err = response.Marshal()
if err != nil {
if werr := writeError(w, r, err); werr != nil {
logger.Log(log.ErrorLevel, werr)
}
return
}
default:
// if json codec is not present set to json
if !hasCodec(ct, jsonCodecs) {
ct = "application/json"
if !hasCodec(contentType, jsonCodecs) {
contentType = "application/json"
}
// default to trying json
@@ -162,29 +223,40 @@ func (h *rpcHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// create request/response
var response json.RawMessage
req := c.NewRequest(
service.Name,
req := myClient.NewRequest(
service.Service,
service.Endpoint.Name,
&request,
client.WithContentType(ct),
client.WithContentType(contentType),
)
// make the call
if err := c.Call(cx, req, &response, client.WithSelectOption(so)); err != nil {
writeError(w, r, err)
if err := myClient.Call(myContext, req, &response, client.WithSelectOption(mySelector)); err != nil {
if werr := writeError(w, r, err); werr != nil {
logger.Log(log.ErrorLevel, werr)
}
return
}
// marshall response
rsp, _ = response.MarshalJSON()
rsp, err = response.MarshalJSON()
if err != nil {
if werr := writeError(w, r, err); werr != nil {
logger.Log(log.ErrorLevel, werr)
}
return
}
}
// write the response
writeResponse(w, r, rsp)
if err := writeResponse(w, r, rsp); err != nil {
logger.Log(log.ErrorLevel, err)
}
}
func (rh *rpcHandler) String() string {
return "rpc"
func (h *rpcHandler) String() string {
return Handler
}
func hasCodec(ct string, codecs []string) bool {
@@ -193,91 +265,273 @@ func hasCodec(ct string, codecs []string) bool {
return true
}
}
return false
}
// requestPayload takes a *http.Request.
// If the request is a GET the query string parameters are extracted and marshaled to JSON and the raw bytes are returned.
// If the request method is a POST the request body is read and returned
// If the request method is a POST the request body is read and returned.
func requestPayload(r *http.Request) ([]byte, error) {
var err 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":
myCt := r.Header.Get("Content-Type")
switch {
case strings.Contains(myCt, "application/json-rpc"):
msg := codec.Message{
Type: codec.Request,
Header: make(map[string]string),
}
c := jsonrpc.NewCodec(&buffer{r.Body})
if err := c.ReadHeader(&msg, codec.Request); err != nil {
if err = c.ReadHeader(&msg, codec.Request); err != nil {
return nil, err
}
var raw json.RawMessage
if err := c.ReadBody(&raw); err != nil {
if err = c.ReadBody(&raw); err != nil {
return nil, err
}
return ([]byte)(raw), nil
case "application/proto-rpc", "application/octet-stream":
case strings.Contains(myCt, "application/proto-rpc"), strings.Contains(myCt, "application/octet-stream"):
msg := codec.Message{
Type: codec.Request,
Header: make(map[string]string),
}
c := protorpc.NewCodec(&buffer{r.Body})
if err := c.ReadHeader(&msg, codec.Request); err != nil {
if err = c.ReadHeader(&msg, codec.Request); err != nil {
return nil, err
}
var raw proto.Message
if err := c.ReadBody(&raw); err != nil {
if err = c.ReadBody(&raw); err != nil {
return nil, err
}
b, _ := raw.Marshal()
return b, nil
return raw.Marshal()
case strings.Contains(myCt, "application/www-x-form-urlencoded"), strings.Contains(myCt, "application/x-www-form-urlencoded"):
if err := r.ParseForm(); err != nil {
return nil, err
}
// 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
return json.Marshal(vals)
// TODO: application/grpc
}
// otherwise as per usual
ctx := r.Context()
// dont user meadata.FromContext as it mangles names
md, ok := metadata.FromContext(ctx)
if !ok {
md = make(map[string]string)
}
// allocate maximum
matches := make(map[string]interface{}, len(md))
bodydst := ""
// get fields from url path
for k, v := range md {
k = strings.ToLower(k)
// filter own keys
if strings.HasPrefix(k, "x-api-field-") {
matches[strings.TrimPrefix(k, "x-api-field-")] = v
delete(md, k)
} else if k == "x-api-body" {
bodydst = v
delete(md, k)
}
}
// map of all fields
req := make(map[string]interface{}, len(md))
// get fields from url values
if len(r.URL.RawQuery) > 0 {
umd := make(map[string]interface{})
err = qson.Unmarshal(&umd, r.URL.RawQuery)
if err != nil {
return nil, err
}
for k, v := range umd {
matches[k] = v
}
}
// restore context without fields
*r = *r.Clone(metadata.NewContext(ctx, md))
for k, v := range matches {
ps := strings.Split(k, ".")
if len(ps) == 1 {
req[k] = v
continue
}
em := make(map[string]interface{})
em[ps[len(ps)-1]] = v
for i := len(ps) - 2; i > 0; i-- {
nm := make(map[string]interface{})
nm[ps[i]] = em
em = nm
}
if vm, ok := req[ps[0]]; ok {
// nested map
nm := vm.(map[string]interface{})
for vk, vv := range em {
nm[vk] = vv
}
req[ps[0]] = nm
} else {
req[ps[0]] = em
}
}
pathbuf := []byte("{}")
if len(req) > 0 {
pathbuf, err = json.Marshal(req)
if err != nil {
return nil, err
}
}
urlbuf := []byte("{}")
out, err := jsonpatch.MergeMergePatches(urlbuf, pathbuf)
if err != nil {
return nil, err
}
switch r.Method {
case "GET":
if len(r.URL.RawQuery) > 0 {
return qson.ToJSON(r.URL.RawQuery)
case http.MethodGet:
// empty response
if strings.Contains(myCt, "application/json") && string(out) == "{}" {
return out, nil
} else if string(out) == "{}" && !strings.Contains(myCt, "application/json") {
return []byte{}, nil
}
case "PATCH", "POST":
return ioutil.ReadAll(r.Body)
return out, nil
case http.MethodPatch, http.MethodPost, http.MethodPut, http.MethodDelete:
bodybuf := []byte("{}")
buf := bufferPool.Get()
defer bufferPool.Put(buf)
if _, err := buf.ReadFrom(r.Body); err != nil {
return nil, err
}
if b := buf.Bytes(); len(b) > 0 {
bodybuf = b
}
if bodydst == "" || bodydst == "*" {
if out, err = jsonpatch.MergeMergePatches(out, bodybuf); err == nil {
return out, nil
}
}
var jsonbody map[string]interface{}
if json.Valid(bodybuf) {
if err = json.Unmarshal(bodybuf, &jsonbody); err != nil {
return nil, err
}
}
dstmap := make(map[string]interface{})
ps := strings.Split(bodydst, ".")
if len(ps) == 1 {
if jsonbody != nil {
dstmap[ps[0]] = jsonbody
} else {
// old unexpected behavior
dstmap[ps[0]] = bodybuf
}
} else {
em := make(map[string]interface{})
if jsonbody != nil {
em[ps[len(ps)-1]] = jsonbody
} else {
// old unexpected behavior
em[ps[len(ps)-1]] = bodybuf
}
for i := len(ps) - 2; i > 0; i-- {
nm := make(map[string]interface{})
nm[ps[i]] = em
em = nm
}
dstmap[ps[0]] = em
}
bodyout, err := json.Marshal(dstmap)
if err != nil {
return nil, err
}
if out, err = jsonpatch.MergeMergePatches(out, bodyout); err == nil {
return out, nil
}
return bodybuf, nil
}
return []byte{}, nil
}
func writeError(w http.ResponseWriter, r *http.Request, err error) {
func writeError(rsp http.ResponseWriter, req *http.Request, err error) error {
ce := errors.Parse(err.Error())
switch ce.Code {
case 0:
// assuming it's totally screwed
ce.Code = 500
ce.Id = "go.micro.api"
ce.Status = http.StatusText(500)
ce.Code = http.StatusInternalServerError
ce.Id = packageID
ce.Status = http.StatusText(http.StatusInternalServerError)
ce.Detail = "error during request: " + ce.Detail
w.WriteHeader(500)
rsp.WriteHeader(http.StatusInternalServerError)
default:
w.WriteHeader(int(ce.Code))
rsp.WriteHeader(int(ce.Code))
}
// response content type
w.Header().Set("Content-Type", "application/json")
rsp.Header().Set("Content-Type", "application/json")
// Set trailers
if strings.Contains(r.Header.Get("Content-Type"), "application/grpc") {
w.Header().Set("Trailer", "grpc-status")
w.Header().Set("Trailer", "grpc-message")
w.Header().Set("grpc-status", "13")
w.Header().Set("grpc-message", ce.Detail)
if strings.Contains(req.Header.Get("Content-Type"), "application/grpc") {
rsp.Header().Set("Trailer", "grpc-status")
rsp.Header().Set("Trailer", "grpc-message")
rsp.Header().Set("grpc-status", "13")
rsp.Header().Set("grpc-message", ce.Detail)
}
w.Write([]byte(ce.Error()))
_, werr := rsp.Write([]byte(ce.Error()))
return werr
}
func writeResponse(w http.ResponseWriter, r *http.Request, rsp []byte) {
func writeResponse(w http.ResponseWriter, r *http.Request, rsp []byte) error {
w.Header().Set("Content-Type", r.Header.Get("Content-Type"))
w.Header().Set("Content-Length", strconv.Itoa(len(rsp)))
@@ -289,21 +543,22 @@ func writeResponse(w http.ResponseWriter, r *http.Request, rsp []byte) {
w.Header().Set("grpc-message", "")
}
// write 204 status if rsp is nil
if len(rsp) == 0 {
w.WriteHeader(http.StatusNoContent)
}
// write response
w.Write(rsp)
_, err := w.Write(rsp)
return err
}
// NewHandler returns a new RPC handler.
func NewHandler(opts ...handler.Option) handler.Handler {
options := handler.NewOptions(opts...)
return &rpcHandler{
opts: options,
}
}
func WithService(s *api.Service, opts ...handler.Option) handler.Handler {
options := handler.NewOptions(opts...)
return &rpcHandler{
opts: options,
s: s,
}
}
+29 -5
View File
@@ -4,15 +4,15 @@ import (
"bytes"
"encoding/json"
"net/http"
"reflect"
"testing"
"github.com/golang/protobuf/proto"
go_api "github.com/micro/go-micro/v2/api/proto"
go_api "go-micro.dev/v4/api/proto"
)
func TestRequestPayloadFromRequest(t *testing.T) {
// our test event so that we can validate serialising / deserializing of true protos works
// our test event so that we can validate serializing / deserializing of true protos works
protoEvent := go_api.Event{
Name: "Test",
}
@@ -27,6 +27,32 @@ func TestRequestPayloadFromRequest(t *testing.T) {
t.Fatal("Failed to marshal proto to JSON ", err)
}
type jsonUrl struct {
Key1 string `json:"key1"`
Key2 string `json:"key2"`
Name string `json:"name"`
}
jUrl := &jsonUrl{Key1: "val1", Key2: "val2", Name: "Test"}
t.Run("extracting a json from a POST request with url params", func(t *testing.T) {
r, err := http.NewRequest("POST", "http://localhost/my/path?key1=val1&key2=val2", bytes.NewReader(jsonBytes))
if err != nil {
t.Fatalf("Failed to created http.Request: %v", err)
}
extByte, err := requestPayload(r)
if err != nil {
t.Fatalf("Failed to extract payload from request: %v", err)
}
extJUrl := &jsonUrl{}
if err := json.Unmarshal(extByte, extJUrl); err != nil {
t.Fatalf("Failed to unmarshal payload from request: %v", err)
}
if !reflect.DeepEqual(extJUrl, jUrl) {
t.Fatalf("Expected %v and %v to match", extJUrl, jUrl)
}
})
t.Run("extracting a proto from a POST request", func(t *testing.T) {
r, err := http.NewRequest("POST", "http://localhost/my/path", bytes.NewReader(protoBytes))
if err != nil {
@@ -58,7 +84,6 @@ func TestRequestPayloadFromRequest(t *testing.T) {
})
t.Run("extracting params from a GET request", func(t *testing.T) {
r, err := http.NewRequest("GET", "http://localhost/my/path", nil)
if err != nil {
t.Fatalf("Failed to created http.Request: %v", err)
@@ -78,7 +103,6 @@ func TestRequestPayloadFromRequest(t *testing.T) {
})
t.Run("GET request with no params", func(t *testing.T) {
r, err := http.NewRequest("GET", "http://localhost/my/path", nil)
if err != nil {
t.Fatalf("Failed to created http.Request: %v", err)
+245
View File
@@ -0,0 +1,245 @@
package rpc
import (
"bytes"
"context"
"encoding/json"
"io"
"net/http"
"strings"
"time"
"github.com/gobwas/httphead"
"github.com/gobwas/ws"
"github.com/gobwas/ws/wsutil"
"go-micro.dev/v4/api/router"
"go-micro.dev/v4/client"
raw "go-micro.dev/v4/codec/bytes"
"go-micro.dev/v4/selector"
)
// serveWebsocket will stream rpc back over websockets assuming json.
func serveWebsocket(ctx context.Context, w http.ResponseWriter, r *http.Request, service *router.Route, c client.Client) (err error) {
var opCode ws.OpCode
myCt := r.Header.Get("Content-Type")
// Strip charset from Content-Type (like `application/json; charset=UTF-8`)
if idx := strings.IndexRune(myCt, ';'); idx >= 0 {
myCt = myCt[:idx]
}
// check proto from request
switch myCt {
case "application/json":
opCode = ws.OpText
default:
opCode = ws.OpBinary
}
hdr := make(http.Header)
if proto, ok := r.Header["Sec-Websocket-Protocol"]; ok {
for _, p := range proto {
if p == "binary" {
hdr["Sec-WebSocket-Protocol"] = []string{"binary"}
opCode = ws.OpBinary
}
}
}
payload, err := requestPayload(r)
if err != nil {
return
}
upgrader := ws.HTTPUpgrader{Timeout: 5 * time.Second,
Protocol: func(proto string) bool {
if strings.Contains(proto, "binary") {
return true
}
// fallback to support all protocols now
return true
},
Extension: func(httphead.Option) bool {
// disable extensions for compatibility
return false
},
Header: hdr,
}
conn, uRw, _, err := upgrader.Upgrade(r, w)
if err != nil {
return
}
defer func() {
if cErr := conn.Close(); cErr != nil && err == nil {
err = cErr
}
}()
var request interface{}
if !bytes.Equal(payload, []byte(`{}`)) {
switch myCt {
case "application/json", "":
m := json.RawMessage(payload)
request = &m
default:
request = &raw.Frame{Data: payload}
}
}
// we always need to set content type for message
if myCt == "" {
myCt = "application/json"
}
req := c.NewRequest(
service.Service,
service.Endpoint.Name,
request,
client.WithContentType(myCt),
client.StreamingRequest(),
)
cCtx, cancel := context.WithCancel(ctx)
defer cancel()
so := selector.WithStrategy(strategy(service.Versions))
// create a new stream
stream, err := c.Stream(cCtx, req, client.WithSelectOption(so))
if err != nil {
return
}
if request != nil {
if err = stream.Send(request); err != nil {
return
}
}
go func() {
if wErr := writeLoop(uRw, stream); wErr != nil && err == nil {
err = wErr
}
}()
rsp := stream.Response()
// receive from stream and send to client
for {
select {
case <-ctx.Done():
return nil
case <-stream.Context().Done():
return nil
default:
// read backend response body
buf, err := rsp.Read()
if err != nil {
// wants to avoid import grpc/status.Status
if strings.Contains(err.Error(), "context canceled") {
return nil
}
return err
}
// write the response
if err = wsutil.WriteServerMessage(uRw, opCode, buf); err != nil {
return err
}
if err = uRw.Flush(); err != nil {
return err
}
}
}
}
// writeLoop.
func writeLoop(rw io.ReadWriter, stream client.Stream) error {
// close stream when done
defer stream.Close()
for {
select {
case <-stream.Context().Done():
return nil
default:
buf, op, err := wsutil.ReadClientData(rw)
if err != nil {
if wserr, ok := err.(wsutil.ClosedError); ok {
switch wserr.Code {
case ws.StatusGoingAway:
// this happens when user leave the page
return nil
case ws.StatusNormalClosure, ws.StatusNoStatusRcvd:
// this happens when user close ws connection, or we don't get any status
return nil
default:
return err
}
}
}
switch op {
default:
// not relevant
continue
case ws.OpText, ws.OpBinary:
break
}
// send to backend
// default to trying json
// if the extracted payload isn't empty lets use it
request := &raw.Frame{Data: buf}
if err := stream.Send(request); err != nil {
return err
}
}
}
}
func isStream(r *http.Request, srv *router.Route) bool {
// check if it's a web socket
if !isWebSocket(r) {
return false
}
// check if the endpoint supports streaming
for _, service := range srv.Versions {
for _, ep := range service.Endpoints {
// skip if it doesn't match the name
if ep.Name != srv.Endpoint.Name {
continue
}
// matched if the name
if v := ep.Metadata["stream"]; v == "true" {
return true
}
}
}
return false
}
func isWebSocket(r *http.Request) bool {
contains := func(key, val string) bool {
vv := strings.Split(r.Header.Get(key), ",")
for _, v := range vv {
if val == strings.ToLower(strings.TrimSpace(v)) {
return true
}
}
return false
}
if contains("Connection", "upgrade") && contains("Upgrade", "websocket") {
return true
}
return false
}
-25
View File
@@ -1,25 +0,0 @@
// Package udp reads and write from a udp connection
package udp
import (
"io"
"net"
"net/http"
)
type Handler struct{}
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c, err := net.Dial("udp", r.Host)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
go io.Copy(c, r.Body)
// write response
io.Copy(w, c)
}
func (h *Handler) String() string {
return "udp"
}
-30
View File
@@ -1,30 +0,0 @@
// Package unix reads from a unix socket expecting it to be in /tmp/path
package unix
import (
"fmt"
"io"
"net"
"net/http"
"path/filepath"
)
type Handler struct{}
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
sock := fmt.Sprintf("%s.sock", filepath.Clean(r.URL.Path))
path := filepath.Join("/tmp", sock)
c, err := net.Dial("unix", path)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
go io.Copy(c, r.Body)
// write response
io.Copy(w, c)
}
func (h *Handler) String() string {
return "unix"
}
+21 -29
View File
@@ -11,35 +11,35 @@ import (
"net/url"
"strings"
"github.com/micro/go-micro/v2/api"
"github.com/micro/go-micro/v2/api/handler"
"github.com/micro/go-micro/v2/client/selector"
"go-micro.dev/v4/api/handler"
"go-micro.dev/v4/api/router"
"go-micro.dev/v4/selector"
)
const (
// Handler is the name of the handler.
Handler = "web"
)
type webHandler struct {
opts handler.Options
s *api.Service
}
func (wh *webHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
service, err := wh.getService(r)
if err != nil {
w.WriteHeader(500)
w.WriteHeader(http.StatusInternalServerError)
return
}
if len(service) == 0 {
w.WriteHeader(404)
w.WriteHeader(http.StatusNotFound)
return
}
rp, err := url.Parse(service)
if err != nil {
w.WriteHeader(500)
w.WriteHeader(http.StatusInternalServerError)
return
}
@@ -51,19 +51,17 @@ func (wh *webHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
httputil.NewSingleHostReverseProxy(rp).ServeHTTP(w, r)
}
// getService returns the service for this request from the selector
// getService returns the service for this request from the selector.
func (wh *webHandler) getService(r *http.Request) (string, error) {
var service *api.Service
var service *router.Route
if wh.s != nil {
// we were given the service
service = wh.s
} else if wh.opts.Router != nil {
if wh.opts.Router != nil {
// try get service from router
s, err := wh.opts.Router.Route(r)
if err != nil {
return "", err
}
service = s
} else {
// we have no way of routing the request
@@ -71,7 +69,7 @@ func (wh *webHandler) getService(r *http.Request) (string, error) {
}
// create a random selector
next := selector.Random(service.Services)
next := selector.Random(service.Versions)
// get the next node
s, err := next()
@@ -82,13 +80,13 @@ func (wh *webHandler) getService(r *http.Request) (string, error) {
return fmt.Sprintf("http://%s", s.Address), nil
}
// serveWebSocket used to serve a web socket proxied connection
func (wh *webHandler) serveWebSocket(host string, w http.ResponseWriter, r *http.Request) {
// serveWebSocket used to serve a web socket proxied connection.
func (wh *webHandler) serveWebSocket(host string, rsp http.ResponseWriter, r *http.Request) {
req := new(http.Request)
*req = *r
if len(host) == 0 {
http.Error(w, "invalid host", 500)
http.Error(rsp, "invalid host", http.StatusInternalServerError)
return
}
@@ -97,20 +95,21 @@ func (wh *webHandler) serveWebSocket(host string, w http.ResponseWriter, r *http
if ips, ok := req.Header["X-Forwarded-For"]; ok {
clientIP = strings.Join(ips, ", ") + ", " + clientIP
}
req.Header.Set("X-Forwarded-For", clientIP)
}
// connect to the backend host
conn, err := net.Dial("tcp", host)
if err != nil {
http.Error(w, err.Error(), 500)
http.Error(rsp, err.Error(), http.StatusInternalServerError)
return
}
// hijack the connection
hj, ok := w.(http.Hijacker)
hj, ok := rsp.(http.Hijacker)
if !ok {
http.Error(w, "failed to connect", 500)
http.Error(rsp, "failed to connect", http.StatusInternalServerError)
return
}
@@ -147,6 +146,7 @@ func isWebSocket(r *http.Request) bool {
return true
}
}
return false
}
@@ -161,17 +161,9 @@ func (wh *webHandler) String() string {
return "web"
}
// NewHandler returns a new web handler.
func NewHandler(opts ...handler.Option) handler.Handler {
return &webHandler{
opts: handler.NewOptions(opts...),
}
}
func WithService(s *api.Service, opts ...handler.Option) handler.Handler {
options := handler.NewOptions(opts...)
return &webHandler{
opts: options,
s: s,
}
}
+37
View File
@@ -0,0 +1,37 @@
package api
import (
"go-micro.dev/v4/api/router"
registry2 "go-micro.dev/v4/api/router/registry"
"go-micro.dev/v4/client"
"go-micro.dev/v4/registry"
)
func NewOptions(opts ...Option) Options {
options := Options{
Address: ":8080",
}
for _, o := range opts {
o(&options)
}
return options
}
// WithRouter sets the router to use e.g static or registry.
func WithRouter(r router.Router) Option {
return func(o *Options) error {
o.Router = r
return nil
}
}
// WithRegistry sets the api's client and router to use registry.
func WithRegistry(r registry.Registry) Option {
return func(o *Options) error {
o.Client = client.NewClient(client.Registry(r))
o.Router = registry2.NewRouter(router.WithRegistry(r))
return nil
}
}
+33 -36
View File
@@ -1,5 +1,5 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: github.com/micro/go-micro/v2/api/proto/api.proto
// source: api/proto/api.proto
package go_api
@@ -32,7 +32,7 @@ func (m *Pair) Reset() { *m = Pair{} }
func (m *Pair) String() string { return proto.CompactTextString(m) }
func (*Pair) ProtoMessage() {}
func (*Pair) Descriptor() ([]byte, []int) {
return fileDescriptor_7b6696ef87ec1943, []int{0}
return fileDescriptor_2df576b66d12087a, []int{0}
}
func (m *Pair) XXX_Unmarshal(b []byte) error {
@@ -86,7 +86,7 @@ func (m *Request) Reset() { *m = Request{} }
func (m *Request) String() string { return proto.CompactTextString(m) }
func (*Request) ProtoMessage() {}
func (*Request) Descriptor() ([]byte, []int) {
return fileDescriptor_7b6696ef87ec1943, []int{1}
return fileDescriptor_2df576b66d12087a, []int{1}
}
func (m *Request) XXX_Unmarshal(b []byte) error {
@@ -171,7 +171,7 @@ func (m *Response) Reset() { *m = Response{} }
func (m *Response) String() string { return proto.CompactTextString(m) }
func (*Response) ProtoMessage() {}
func (*Response) Descriptor() ([]byte, []int) {
return fileDescriptor_7b6696ef87ec1943, []int{2}
return fileDescriptor_2df576b66d12087a, []int{2}
}
func (m *Response) XXX_Unmarshal(b []byte) error {
@@ -235,7 +235,7 @@ func (m *Event) Reset() { *m = Event{} }
func (m *Event) String() string { return proto.CompactTextString(m) }
func (*Event) ProtoMessage() {}
func (*Event) Descriptor() ([]byte, []int) {
return fileDescriptor_7b6696ef87ec1943, []int{3}
return fileDescriptor_2df576b66d12087a, []int{3}
}
func (m *Event) XXX_Unmarshal(b []byte) error {
@@ -303,36 +303,33 @@ func init() {
proto.RegisterMapType((map[string]*Pair)(nil), "go.api.Event.HeaderEntry")
}
func init() {
proto.RegisterFile("github.com/micro/go-micro/v2/api/proto/api.proto", fileDescriptor_7b6696ef87ec1943)
}
func init() { proto.RegisterFile("api/proto/api.proto", fileDescriptor_2df576b66d12087a) }
var fileDescriptor_7b6696ef87ec1943 = []byte{
// 408 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x53, 0x4d, 0x8f, 0xd3, 0x30,
0x10, 0x55, 0xe2, 0x24, 0xbb, 0x99, 0x22, 0x84, 0x7c, 0x40, 0x66, 0x59, 0xa1, 0x2a, 0xa7, 0x0a,
0xa9, 0x29, 0xec, 0x72, 0x40, 0x5c, 0xa1, 0x5a, 0x8e, 0x2b, 0xff, 0x03, 0x77, 0x63, 0x25, 0x16,
0x4d, 0x1c, 0x62, 0xa7, 0x52, 0x7f, 0x1c, 0x07, 0x7e, 0x06, 0xff, 0x06, 0x79, 0xec, 0x7e, 0x50,
0x95, 0x0b, 0xf4, 0xf6, 0x62, 0xbf, 0x79, 0xf3, 0xe6, 0x8d, 0x03, 0xf3, 0x5a, 0xd9, 0x66, 0x5c,
0x95, 0x4f, 0xba, 0x5d, 0xb4, 0xea, 0x69, 0xd0, 0x8b, 0x5a, 0xcf, 0x3d, 0x10, 0xbd, 0x5a, 0xf4,
0x83, 0xb6, 0x88, 0x4a, 0x44, 0x34, 0xab, 0x75, 0x29, 0x7a, 0x55, 0xbc, 0x83, 0xe4, 0x51, 0xa8,
0x81, 0xbe, 0x00, 0xf2, 0x4d, 0x6e, 0x59, 0x34, 0x8d, 0x66, 0x39, 0x77, 0x90, 0xbe, 0x84, 0x6c,
0x23, 0xd6, 0xa3, 0x34, 0x2c, 0x9e, 0x92, 0x59, 0xce, 0xc3, 0x57, 0xf1, 0x93, 0xc0, 0x15, 0x97,
0xdf, 0x47, 0x69, 0xac, 0xe3, 0xb4, 0xd2, 0x36, 0xba, 0x0a, 0x85, 0xe1, 0x8b, 0x52, 0x48, 0x7a,
0x61, 0x1b, 0x16, 0xe3, 0x29, 0x62, 0x7a, 0x0f, 0x59, 0x23, 0x45, 0x25, 0x07, 0x46, 0xa6, 0x64,
0x36, 0xb9, 0x7b, 0x5d, 0x7a, 0x0b, 0x65, 0x10, 0x2b, 0xbf, 0xe2, 0xed, 0xb2, 0xb3, 0xc3, 0x96,
0x07, 0x2a, 0x7d, 0x0b, 0xa4, 0x96, 0x96, 0x25, 0x58, 0xc1, 0x4e, 0x2b, 0x1e, 0xa4, 0xf5, 0x74,
0x47, 0xa2, 0x73, 0x48, 0x7a, 0x6d, 0x2c, 0x4b, 0x91, 0xfc, 0xea, 0x94, 0xfc, 0xa8, 0x4d, 0x60,
0x23, 0xcd, 0x79, 0x5c, 0xe9, 0x6a, 0xcb, 0x32, 0xef, 0xd1, 0x61, 0x97, 0xc2, 0x38, 0xac, 0xd9,
0x95, 0x4f, 0x61, 0x1c, 0xd6, 0x37, 0x0f, 0x30, 0x39, 0xf2, 0x75, 0x26, 0xa6, 0x02, 0x52, 0x0c,
0x06, 0x67, 0x9d, 0xdc, 0x3d, 0xdb, 0xb5, 0x75, 0xa9, 0x72, 0x7f, 0xf5, 0x29, 0xfe, 0x18, 0xdd,
0x7c, 0x81, 0xeb, 0x9d, 0xdd, 0xff, 0x50, 0x59, 0x42, 0xbe, 0x9f, 0xe3, 0xdf, 0x65, 0x8a, 0x1f,
0x11, 0x5c, 0x73, 0x69, 0x7a, 0xdd, 0x19, 0x49, 0xdf, 0x00, 0x18, 0x2b, 0xec, 0x68, 0x3e, 0xeb,
0x4a, 0xa2, 0x5a, 0xca, 0x8f, 0x4e, 0xe8, 0x87, 0xfd, 0xe2, 0x62, 0x4c, 0xf6, 0xf6, 0x90, 0xac,
0x57, 0x38, 0xbb, 0xb9, 0x5d, 0xbc, 0xe4, 0x10, 0xef, 0xc5, 0xc2, 0x2c, 0x7e, 0x45, 0x90, 0x2e,
0x37, 0xb2, 0xc3, 0x2d, 0x76, 0xa2, 0x95, 0x41, 0x04, 0x31, 0x7d, 0x0e, 0xb1, 0xaa, 0xc2, 0xdb,
0x8b, 0x55, 0x45, 0x6f, 0x21, 0xb7, 0xaa, 0x95, 0xc6, 0x8a, 0xb6, 0x47, 0x3f, 0x84, 0x1f, 0x0e,
0xe8, 0xfb, 0xfd, 0x78, 0xc9, 0x9f, 0x0f, 0x07, 0x1b, 0xfc, 0x6d, 0xb6, 0x4a, 0x58, 0xc1, 0x52,
0xdf, 0xd4, 0xe1, 0x8b, 0xcd, 0xb6, 0xca, 0xf0, 0x07, 0xbd, 0xff, 0x1d, 0x00, 0x00, 0xff, 0xff,
0x97, 0xf3, 0x59, 0x6e, 0xd1, 0x03, 0x00, 0x00,
var fileDescriptor_2df576b66d12087a = []byte{
// 393 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x53, 0xcd, 0xce, 0xd3, 0x30,
0x10, 0x54, 0xe2, 0x24, 0x6d, 0xb6, 0x08, 0x21, 0x23, 0x21, 0x53, 0x2a, 0x54, 0xe5, 0x54, 0x21,
0x91, 0x42, 0xcb, 0x01, 0x71, 0x85, 0xaa, 0x1c, 0x2b, 0xbf, 0x81, 0xab, 0x58, 0x6d, 0x44, 0x13,
0x9b, 0xd8, 0xa9, 0xd4, 0x87, 0xe3, 0xc0, 0x63, 0xf0, 0x36, 0xc8, 0x1b, 0xf7, 0xe7, 0xab, 0xfa,
0x5d, 0xbe, 0xaf, 0xb7, 0x89, 0x3d, 0x3b, 0x3b, 0x3b, 0xeb, 0xc0, 0x6b, 0xa1, 0xcb, 0xa9, 0x6e,
0x94, 0x55, 0x53, 0xa1, 0xcb, 0x1c, 0x11, 0x4d, 0x36, 0x2a, 0x17, 0xba, 0xcc, 0x3e, 0x41, 0xb4,
0x12, 0x65, 0x43, 0x5f, 0x01, 0xf9, 0x25, 0x0f, 0x2c, 0x18, 0x07, 0x93, 0x94, 0x3b, 0x48, 0xdf,
0x40, 0xb2, 0x17, 0xbb, 0x56, 0x1a, 0x16, 0x8e, 0xc9, 0x24, 0xe5, 0xfe, 0x2b, 0xfb, 0x4b, 0xa0,
0xc7, 0xe5, 0xef, 0x56, 0x1a, 0xeb, 0x38, 0x95, 0xb4, 0x5b, 0x55, 0xf8, 0x42, 0xff, 0x45, 0x29,
0x44, 0x5a, 0xd8, 0x2d, 0x0b, 0xf1, 0x14, 0x31, 0x9d, 0x43, 0xb2, 0x95, 0xa2, 0x90, 0x0d, 0x23,
0x63, 0x32, 0x19, 0xcc, 0xde, 0xe5, 0x9d, 0x85, 0xdc, 0x8b, 0xe5, 0x3f, 0xf1, 0x76, 0x51, 0xdb,
0xe6, 0xc0, 0x3d, 0x95, 0x7e, 0x00, 0xb2, 0x91, 0x96, 0x45, 0x58, 0xc1, 0xae, 0x2b, 0x96, 0xd2,
0x76, 0x74, 0x47, 0xa2, 0x1f, 0x21, 0xd2, 0xca, 0x58, 0x16, 0x23, 0xf9, 0xed, 0x35, 0x79, 0xa5,
0x8c, 0x67, 0x23, 0xcd, 0x79, 0x5c, 0xab, 0xe2, 0xc0, 0x92, 0xce, 0xa3, 0xc3, 0x2e, 0x85, 0xb6,
0xd9, 0xb1, 0x5e, 0x97, 0x42, 0xdb, 0xec, 0x86, 0x4b, 0x18, 0x5c, 0xf8, 0xba, 0x11, 0x53, 0x06,
0x31, 0x06, 0x83, 0xb3, 0x0e, 0x66, 0x2f, 0x8e, 0x6d, 0x5d, 0xaa, 0xbc, 0xbb, 0xfa, 0x16, 0x7e,
0x0d, 0x86, 0x3f, 0xa0, 0x7f, 0xb4, 0xfb, 0x0c, 0x95, 0x05, 0xa4, 0xa7, 0x39, 0x9e, 0x2e, 0x93,
0xfd, 0x09, 0xa0, 0xcf, 0xa5, 0xd1, 0xaa, 0x36, 0x92, 0xbe, 0x07, 0x30, 0x56, 0xd8, 0xd6, 0x7c,
0x57, 0x85, 0x44, 0xb5, 0x98, 0x5f, 0x9c, 0xd0, 0x2f, 0xa7, 0xc5, 0x85, 0x98, 0xec, 0xe8, 0x9c,
0x6c, 0xa7, 0x70, 0x73, 0x73, 0xc7, 0x78, 0xc9, 0x39, 0xde, 0xbb, 0x85, 0x99, 0xfd, 0x0b, 0x20,
0x5e, 0xec, 0x65, 0x8d, 0x5b, 0xac, 0x45, 0x25, 0xbd, 0x08, 0x62, 0xfa, 0x12, 0xc2, 0xb2, 0xf0,
0x6f, 0x2f, 0x2c, 0x0b, 0x3a, 0x82, 0xd4, 0x96, 0x95, 0x34, 0x56, 0x54, 0x1a, 0xfd, 0x10, 0x7e,
0x3e, 0xa0, 0x9f, 0x4f, 0xe3, 0x45, 0x0f, 0x1f, 0x0e, 0x36, 0x78, 0x6c, 0xb6, 0x42, 0x58, 0xc1,
0xe2, 0xae, 0xa9, 0xc3, 0x77, 0x9b, 0x6d, 0x9d, 0xe0, 0x0f, 0x3a, 0xff, 0x1f, 0x00, 0x00, 0xff,
0xff, 0xd4, 0x6d, 0x70, 0x51, 0xb7, 0x03, 0x00, 0x00,
}
+1 -1
View File
@@ -1,5 +1,5 @@
// Code generated by protoc-gen-micro. DO NOT EDIT.
// source: github.com/micro/go-micro/v2/api/proto/api.proto
// source: api/proto/api.proto
package go_api
+5 -1
View File
@@ -6,11 +6,13 @@ import (
"net/http"
"strings"
"github.com/micro/go-micro/v2/api/resolver"
"go-micro.dev/v4/api/resolver"
)
// Resolver is the gRPC Resolver.
type Resolver struct{}
// Resolve resolves a http.Request to an grpc Endpoint.
func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
// /foo.Bar/Service
if req.URL.Path == "/" {
@@ -29,10 +31,12 @@ func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
}, nil
}
// String returns the name of the resolver.
func (r *Resolver) String() string {
return "grpc"
}
// NewResolver creates a new gRPC resolver.
func NewResolver(opts ...resolver.Option) resolver.Resolver {
return &Resolver{}
}
+9 -3
View File
@@ -4,11 +4,15 @@ package host
import (
"net/http"
"github.com/micro/go-micro/v2/api/resolver"
"go-micro.dev/v4/api/resolver"
)
type Resolver struct{}
// Resolver is a host resolver.
type Resolver struct {
opts resolver.Options
}
// Resolve resolves a http.Request to an grpc Endpoint.
func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
return &resolver.Endpoint{
Name: req.Host,
@@ -18,10 +22,12 @@ func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
}, nil
}
// String returns the name of the resolver.
func (r *Resolver) String() string {
return "host"
}
// NewResolver creates a new host resolver.
func NewResolver(opts ...resolver.Option) resolver.Resolver {
return &Resolver{}
return &Resolver{opts: resolver.NewOptions(opts...)}
}
-45
View File
@@ -1,45 +0,0 @@
// Package micro provides a micro rpc resolver which prefixes a namespace
package micro
import (
"net/http"
"github.com/micro/go-micro/v2/api/resolver"
)
// default resolver for legacy purposes
// it uses proxy routing to resolve names
// /foo becomes namespace.foo
// /v1/foo becomes namespace.v1.foo
type Resolver struct {
Options resolver.Options
}
func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
var name, method string
switch r.Options.Handler {
// internal handlers
case "meta", "api", "rpc", "micro":
name, method = apiRoute(req.URL.Path)
default:
method = req.Method
name = proxyRoute(req.URL.Path)
}
return &resolver.Endpoint{
Name: name,
Method: method,
}, nil
}
func (r *Resolver) String() string {
return "micro"
}
// NewResolver creates a new micro resolver
func NewResolver(opts ...resolver.Option) resolver.Resolver {
return &Resolver{
Options: resolver.NewOptions(opts...),
}
}
-90
View File
@@ -1,90 +0,0 @@
package micro
import (
"path"
"regexp"
"strings"
)
var (
proxyRe = regexp.MustCompile("^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$")
versionRe = regexp.MustCompilePOSIX("^v[0-9]+$")
)
// Translates /foo/bar/zool into api service go.micro.api.foo method Bar.Zool
// Translates /foo/bar into api service go.micro.api.foo method Foo.Bar
func apiRoute(p string) (string, string) {
p = path.Clean(p)
p = strings.TrimPrefix(p, "/")
parts := strings.Split(p, "/")
// If we've got two or less parts
// Use first part as service
// Use all parts as method
if len(parts) <= 2 {
name := parts[0]
return name, methodName(parts)
}
// Treat /v[0-9]+ as versioning where we have 3 parts
// /v1/foo/bar => service: v1.foo method: Foo.bar
if len(parts) == 3 && versionRe.Match([]byte(parts[0])) {
name := strings.Join(parts[:len(parts)-1], ".")
return name, methodName(parts[len(parts)-2:])
}
// Service is everything minus last two parts
// Method is the last two parts
name := strings.Join(parts[:len(parts)-2], ".")
return name, methodName(parts[len(parts)-2:])
}
func proxyRoute(p string) string {
parts := strings.Split(p, "/")
if len(parts) < 2 {
return ""
}
var service string
var alias string
// /[service]/methods
if len(parts) > 2 {
// /v1/[service]
if versionRe.MatchString(parts[1]) {
service = parts[1] + "." + parts[2]
alias = parts[2]
} else {
service = parts[1]
alias = parts[1]
}
// /[service]
} else {
service = parts[1]
alias = parts[1]
}
// check service name is valid
if !proxyRe.MatchString(alias) {
return ""
}
return service
}
func methodName(parts []string) string {
for i, part := range parts {
parts[i] = toCamel(part)
}
return strings.Join(parts, ".")
}
func toCamel(s string) string {
words := strings.Split(s, "-")
var out string
for _, word := range words {
out += strings.Title(word)
}
return out
}
-130
View File
@@ -1,130 +0,0 @@
package micro
import (
"testing"
)
func TestApiRoute(t *testing.T) {
testData := []struct {
path string
service string
method string
}{
{
"/foo/bar",
"foo",
"Foo.Bar",
},
{
"/foo/foo/bar",
"foo",
"Foo.Bar",
},
{
"/foo/bar/baz",
"foo",
"Bar.Baz",
},
{
"/foo/bar/baz-xyz",
"foo",
"Bar.BazXyz",
},
{
"/foo/bar/baz/cat",
"foo.bar",
"Baz.Cat",
},
{
"/foo/bar/baz/cat/car",
"foo.bar.baz",
"Cat.Car",
},
{
"/foo/fooBar/bazCat",
"foo",
"FooBar.BazCat",
},
{
"/v1/foo/bar",
"v1.foo",
"Foo.Bar",
},
{
"/v1/foo/bar/baz",
"v1.foo",
"Bar.Baz",
},
{
"/v1/foo/bar/baz/cat",
"v1.foo.bar",
"Baz.Cat",
},
}
for _, d := range testData {
s, m := apiRoute(d.path)
if d.service != s {
t.Fatalf("Expected service: %s for path: %s got: %s %s", d.service, d.path, s, m)
}
if d.method != m {
t.Fatalf("Expected service: %s for path: %s got: %s", d.method, d.path, m)
}
}
}
func TestProxyRoute(t *testing.T) {
testData := []struct {
path string
service string
}{
// no namespace
{
"/f",
"f",
},
{
"/f",
"f",
},
{
"/f-b",
"f-b",
},
{
"/foo/bar",
"foo",
},
{
"/foo-bar",
"foo-bar",
},
{
"/foo-bar-baz",
"foo-bar-baz",
},
{
"/foo/bar/bar",
"foo",
},
{
"/v1/foo/bar",
"v1.foo",
},
{
"/v1/foo/bar/baz",
"v1.foo",
},
{
"/v1/foo/bar/baz/cat",
"v1.foo",
},
}
for _, d := range testData {
s := proxyRoute(d.path)
if d.service != s {
t.Fatalf("Expected service: %s for path: %s got: %s", d.service, d.path, s)
}
}
}
+13 -4
View File
@@ -1,23 +1,32 @@
package resolver
// NewOptions returns new initialised options
import (
"net/http"
)
// NewOptions wires options together.
func NewOptions(opts ...Option) Options {
var options Options
for _, o := range opts {
o(&options)
}
if options.Namespace == nil {
options.Namespace = StaticNamespace("go.micro")
}
return options
}
// WithHandler sets the handler being used
// WithHandler sets the handler being used.
func WithHandler(h string) Option {
return func(o *Options) {
o.Handler = h
}
}
// WithNamespace sets the namespace being used
func WithNamespace(n string) Option {
// WithNamespace sets the function which determines the namespace for a request.
func WithNamespace(n func(*http.Request) string) Option {
return func(o *Options) {
o.Namespace = n
}
+13 -6
View File
@@ -2,22 +2,28 @@
package path
import (
"errors"
"net/http"
"strings"
"github.com/micro/go-micro/v2/api/resolver"
"go-micro.dev/v4/api/resolver"
)
type Resolver struct{}
// Resolver is a path resolver.
type Resolver struct {
opts resolver.Options
}
// Resolve resolves a http.Request to an grpc Endpoint.
func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
if req.URL.Path == "/" {
return nil, errors.New("unknown name")
return nil, resolver.ErrNotFound
}
parts := strings.Split(req.URL.Path[1:], "/")
ns := r.opts.Namespace(req)
return &resolver.Endpoint{
Name: parts[0],
Name: ns + "." + parts[0],
Host: req.Host,
Method: req.Method,
Path: req.URL.Path,
@@ -28,6 +34,7 @@ func (r *Resolver) String() string {
return "path"
}
// NewResolver returns a new path resolver.
func NewResolver(opts ...resolver.Option) resolver.Resolver {
return &Resolver{}
return &Resolver{opts: resolver.NewOptions(opts...)}
}
+18 -3
View File
@@ -2,16 +2,22 @@
package resolver
import (
"errors"
"net/http"
)
// Resolver resolves requests to endpoints
var (
ErrNotFound = errors.New("not found")
ErrInvalidPath = errors.New("invalid path")
)
// Resolver resolves requests to endpoints.
type Resolver interface {
Resolve(r *http.Request) (*Endpoint, error)
String() string
}
// Endpoint is the endpoint for a http request
// Endpoint is the endpoint for a http request.
type Endpoint struct {
// e.g greeter
Name string
@@ -23,9 +29,18 @@ type Endpoint struct {
Path string
}
// Options is a struct of available options.
type Options struct {
Namespace func(*http.Request) string
Handler string
Namespace string
}
// Option is a helper for a single option.
type Option func(o *Options)
// StaticNamespace returns the same namespace for each request.
func StaticNamespace(ns string) func(*http.Request) string {
return func(*http.Request) string {
return ns
}
}
+22 -9
View File
@@ -1,4 +1,4 @@
// Package vpath resolves using http path and recognised versioned urls
// Package vpath resolves using http path and recognized versioned urls
package vpath
import (
@@ -7,25 +7,33 @@ import (
"regexp"
"strings"
"github.com/micro/go-micro/v2/api/resolver"
"go-micro.dev/v4/api/resolver"
)
type Resolver struct{}
// NewResolver returns a new vpath resolver.
func NewResolver(opts ...resolver.Option) resolver.Resolver {
return &Resolver{opts: resolver.NewOptions(opts...)}
}
// Resolver is a vpath resolver.
type Resolver struct {
opts resolver.Options
}
var (
re = regexp.MustCompile("^v[0-9]+$")
)
// Resolve resolves a http.Request to an grpc Endpoint.
func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
if req.URL.Path == "/" {
return nil, errors.New("unknown name")
}
parts := strings.Split(req.URL.Path[1:], "/")
if len(parts) == 1 {
return &resolver.Endpoint{
Name: parts[0],
Name: r.withNamespace(req, parts...),
Host: req.Host,
Method: req.Method,
Path: req.URL.Path,
@@ -35,7 +43,7 @@ func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
// /v1/foo
if re.MatchString(parts[0]) {
return &resolver.Endpoint{
Name: parts[1],
Name: r.withNamespace(req, parts[0:2]...),
Host: req.Host,
Method: req.Method,
Path: req.URL.Path,
@@ -43,7 +51,7 @@ func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
}
return &resolver.Endpoint{
Name: parts[0],
Name: r.withNamespace(req, parts[0]),
Host: req.Host,
Method: req.Method,
Path: req.URL.Path,
@@ -54,6 +62,11 @@ func (r *Resolver) String() string {
return "path"
}
func NewResolver(opts ...resolver.Option) resolver.Resolver {
return &Resolver{}
func (r *Resolver) withNamespace(req *http.Request, parts ...string) string {
ns := r.opts.Namespace(req)
if len(ns) == 0 {
return strings.Join(parts, ".")
}
return strings.Join(append([]string{ns}, parts...), ".")
}
+99
View File
@@ -0,0 +1,99 @@
package router
import (
"errors"
"regexp"
"strings"
)
func strip(s string) string {
return strings.TrimSpace(s)
}
func slice(s string) []string {
var sl []string
for _, p := range strings.Split(s, ",") {
if str := strip(p); len(str) > 0 {
sl = append(sl, strip(p))
}
}
return sl
}
// Encode encodes an endpoint to endpoint metadata.
func Encode(e *Endpoint) map[string]string {
if e == nil {
return nil
}
// endpoint map
ep := make(map[string]string)
// set vals only if they exist
set := func(k, v string) {
if len(v) == 0 {
return
}
ep[k] = v
}
set("endpoint", e.Name)
set("description", e.Description)
set("handler", e.Handler)
set("method", strings.Join(e.Method, ","))
set("path", strings.Join(e.Path, ","))
set("host", strings.Join(e.Host, ","))
return ep
}
// Decode decodes endpoint metadata into an endpoint.
func Decode(e map[string]string) *Endpoint {
if e == nil {
return nil
}
return &Endpoint{
Name: e["endpoint"],
Description: e["description"],
Method: slice(e["method"]),
Path: slice(e["path"]),
Host: slice(e["host"]),
Handler: e["handler"],
}
}
// Validate validates an endpoint to guarantee it won't blow up when being served.
func Validate(e *Endpoint) error {
if e == nil {
return errors.New("endpoint is nil")
}
if len(e.Name) == 0 {
return errors.New("name required")
}
for _, p := range e.Path {
ps := p[0]
pe := p[len(p)-1]
if ps == '^' && pe == '$' {
_, err := regexp.CompilePOSIX(p)
if err != nil {
return err
}
} else if ps == '^' && pe != '$' {
return errors.New("invalid path")
} else if ps != '^' && pe == '$' {
return errors.New("invalid path")
}
}
if len(e.Handler) == 0 {
return errors.New("invalid handler")
}
return nil
}
+20 -15
View File
@@ -1,24 +1,29 @@
package router
import (
"github.com/micro/go-micro/v2/api/resolver"
"github.com/micro/go-micro/v2/api/resolver/micro"
"github.com/micro/go-micro/v2/registry"
"go-micro.dev/v4/api/resolver"
"go-micro.dev/v4/api/resolver/vpath"
"go-micro.dev/v4/logger"
"go-micro.dev/v4/registry"
)
// Options is a struct of options available.
type Options struct {
Namespace string
Handler string
Registry registry.Registry
Resolver resolver.Resolver
Registry registry.Registry
Resolver resolver.Resolver
Logger logger.Logger
Handler string
}
// Option is a helper for a single options.
type Option func(o *Options)
// NewOptions wires options together.
func NewOptions(opts ...Option) Options {
options := Options{
Handler: "meta",
Registry: registry.DefaultRegistry,
Logger: logger.DefaultLogger,
}
for _, o := range opts {
@@ -26,9 +31,8 @@ func NewOptions(opts ...Option) Options {
}
if options.Resolver == nil {
options.Resolver = micro.NewResolver(
options.Resolver = vpath.NewResolver(
resolver.WithHandler(options.Handler),
resolver.WithNamespace(options.Namespace),
)
}
@@ -41,12 +45,6 @@ func WithHandler(h string) Option {
}
}
func WithNamespace(ns string) Option {
return func(o *Options) {
o.Namespace = ns
}
}
func WithRegistry(r registry.Registry) Option {
return func(o *Options) {
o.Registry = r
@@ -58,3 +56,10 @@ func WithResolver(r resolver.Resolver) Option {
o.Resolver = r
}
}
// WithLogger sets the underline logger.
func WithLogger(l logger.Logger) Option {
return func(o *Options) {
o.Logger = l
}
}
+223 -102
View File
@@ -4,54 +4,43 @@ package registry
import (
"errors"
"fmt"
"log"
"net/http"
"regexp"
"strings"
"sync"
"time"
"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"
"go-micro.dev/v4/api/router"
"go-micro.dev/v4/api/router/util"
log "go-micro.dev/v4/logger"
"go-micro.dev/v4/metadata"
"go-micro.dev/v4/registry"
"go-micro.dev/v4/registry/cache"
)
// router is the default router
// endpoint struct, that holds compiled pcre.
type endpoint struct {
hostregs []*regexp.Regexp
pathregs []util.Pattern
pcreregs []*regexp.Regexp
}
// router is the default router.
type registryRouter struct {
exit chan bool
opts router.Options
// registry cache
rc cache.Cache
exit chan bool
eps map[string]*router.Route
// compiled regexp for host and path
ceps map[string]*endpoint
sync.RWMutex
eps map[string]*api.Service
}
func setNamespace(ns, name string) string {
ns = strings.TrimSpace(ns)
name = strings.TrimSpace(name)
// no namespace
if len(ns) == 0 {
return name
}
switch {
// has - suffix
case strings.HasSuffix(ns, "-"):
return strings.Replace(ns+name, ".", "-", -1)
// has . suffix
case strings.HasSuffix(ns, "."):
return ns + name
}
// default join .
return strings.Join([]string{ns, name}, ".")
}
func (r *registryRouter) isClosed() bool {
func (r *registryRouter) isStopped() bool {
select {
case <-r.exit:
return true
@@ -60,16 +49,20 @@ func (r *registryRouter) isClosed() bool {
}
}
// refresh list of api services
// refresh list of api services.
func (r *registryRouter) refresh() {
var attempts int
logger := r.Options().Logger
for {
services, err := r.opts.Registry.ListServices()
if err != nil {
attempts++
log.Println("Error listing endpoints", err)
logger.Logf(log.ErrorLevel, "unable to list services: %v", err)
time.Sleep(time.Duration(attempts) * time.Second)
continue
}
@@ -77,18 +70,17 @@ func (r *registryRouter) refresh() {
// for each service, get service and store endpoints
for _, s := range services {
// only get services for this namespace
if !strings.HasPrefix(s.Name, r.opts.Namespace) {
continue
}
service, err := r.rc.GetService(s.Name)
if err != nil {
logger.Logf(log.ErrorLevel, "unable to get service: %v", err)
continue
}
r.store(service)
}
// refresh list in 10 minutes... cruft
// use registry watching
select {
case <-time.After(time.Minute * 10):
case <-r.exit:
@@ -97,16 +89,18 @@ func (r *registryRouter) refresh() {
}
}
// process watch event
// process watch event.
func (r *registryRouter) process(res *registry.Result) {
logger := r.Options().Logger
// skip these things
if res == nil || res.Service == nil || !strings.HasPrefix(res.Service.Name, r.opts.Namespace) {
if res == nil || res.Service == nil {
return
}
// get entry from cache
service, err := r.rc.GetService(res.Service.Name)
if err != nil {
logger.Logf(log.ErrorLevel, "unable to get service: %v", err)
return
}
@@ -114,10 +108,11 @@ func (r *registryRouter) process(res *registry.Result) {
r.store(service)
}
// store local endpoint cache
// store local endpoint cache.
func (r *registryRouter) store(services []*registry.Service) {
logger := r.Options().Logger
// endpoints
eps := map[string]*api.Service{}
eps := map[string]*router.Route{}
// services
names := map[string]bool{}
@@ -128,27 +123,28 @@ func (r *registryRouter) store(services []*registry.Service) {
names[service.Name] = true
// map per endpoint
for _, endpoint := range service.Endpoints {
for _, sep := range service.Endpoints {
// create a key service:endpoint_name
key := fmt.Sprintf("%s:%s", service.Name, endpoint.Name)
key := fmt.Sprintf("%s.%s", service.Name, sep.Name)
// decode endpoint
end := api.Decode(endpoint.Metadata)
end := router.Decode(sep.Metadata)
// if we got nothing skip
if err := api.Validate(end); err != nil {
if err := router.Validate(end); err != nil {
logger.Logf(log.TraceLevel, "endpoint validation failed: %v", err)
continue
}
// try get endpoint
ep, ok := eps[key]
if !ok {
ep = &api.Service{Name: service.Name}
ep = &router.Route{Service: service.Name}
}
// overwrite the endpoint
ep.Endpoint = end
// append services
ep.Services = append(ep.Services, service)
ep.Versions = append(ep.Versions, service)
// store it
eps[key] = ep
}
@@ -158,9 +154,9 @@ func (r *registryRouter) store(services []*registry.Service) {
defer r.Unlock()
// delete any existing eps for services we know
for key, service := range r.eps {
for key, route := range r.eps {
// skip what we don't care about
if !names[service.Name] {
if !names[route.Service] {
continue
}
@@ -170,17 +166,66 @@ func (r *registryRouter) store(services []*registry.Service) {
}
// now set the eps we have
for name, endpoint := range eps {
r.eps[name] = endpoint
for name, ep := range eps {
r.eps[name] = ep
cep := &endpoint{}
for _, h := range ep.Endpoint.Host {
if h == "" || h == "*" {
continue
}
hostreg, err := regexp.CompilePOSIX(h)
if err != nil {
logger.Logf(log.TraceLevel, "endpoint have invalid host regexp: %v", err)
continue
}
cep.hostregs = append(cep.hostregs, hostreg)
}
for _, p := range ep.Endpoint.Path {
var pcreok bool
if p[0] == '^' && p[len(p)-1] == '$' {
pcrereg, err := regexp.CompilePOSIX(p)
if err == nil {
cep.pcreregs = append(cep.pcreregs, pcrereg)
pcreok = true
}
}
rule, err := util.Parse(p)
if err != nil && !pcreok {
logger.Logf(log.TraceLevel, "endpoint have invalid path pattern: %v", err)
continue
} else if err != nil && pcreok {
continue
}
tpl := rule.Compile()
pathreg, err := util.NewPattern(tpl.Version, tpl.OpCodes, tpl.Pool, "", util.PatternLogger(logger))
if err != nil {
logger.Logf(log.TraceLevel, "endpoint have invalid path pattern: %v", err)
continue
}
cep.pathregs = append(cep.pathregs, pathreg)
}
r.ceps[name] = cep
}
}
// watch for endpoint changes
// watch for endpoint changes.
func (r *registryRouter) watch() {
var attempts int
logger := r.Options().Logger
for {
if r.isClosed() {
if r.isStopped() {
return
}
@@ -188,8 +233,10 @@ func (r *registryRouter) watch() {
w, err := r.opts.Registry.Watch()
if err != nil {
attempts++
log.Println("Error watching endpoints", err)
logger.Logf(log.ErrorLevel, "error watching endpoints: %v", err)
time.Sleep(time.Duration(attempts) * time.Second)
continue
}
@@ -211,10 +258,12 @@ func (r *registryRouter) watch() {
// process next event
res, err := w.Next()
if err != nil {
log.Println("Error getting next endpoint", err)
logger.Logf(log.ErrorLevel, "error getting next endoint: %v", err)
close(ch)
break
}
r.process(res)
}
}
@@ -224,7 +273,7 @@ func (r *registryRouter) Options() router.Options {
return r.opts
}
func (r *registryRouter) Close() error {
func (r *registryRouter) Stop() error {
select {
case <-r.exit:
return nil
@@ -232,81 +281,139 @@ func (r *registryRouter) Close() error {
close(r.exit)
r.rc.Stop()
}
return nil
}
func (r *registryRouter) Endpoint(req *http.Request) (*api.Service, error) {
if r.isClosed() {
func (r *registryRouter) Register(ep *router.Route) error {
return nil
}
func (r *registryRouter) Deregister(ep *router.Route) error {
return nil
}
func (r *registryRouter) Endpoint(req *http.Request) (*router.Route, error) {
logger := r.Options().Logger
if r.isStopped() {
return nil, errors.New("router closed")
}
r.RLock()
defer r.RUnlock()
var idx int
if len(req.URL.Path) > 0 && req.URL.Path != "/" {
idx = 1
}
path := strings.Split(req.URL.Path[idx:], "/")
// use the first match
// TODO: weighted matching
for _, e := range r.eps {
ep := e.Endpoint
for n, endpoint := range r.eps {
cep, ok := r.ceps[n]
if !ok {
continue
}
// match
var pathMatch, hostMatch, methodMatch bool
ep := endpoint.Endpoint
// 1. try method GET, POST, PUT, etc
// 2. try host example.com, foobar.com, etc
// 3. try path /foo/bar, /bar/baz, etc
// 1. try match method
var mMatch, hMatch, pMatch bool
// 1. try method
for _, m := range ep.Method {
if req.Method == m {
methodMatch = true
if m == req.Method {
mMatch = true
break
}
}
// no match on method pass
if len(ep.Method) > 0 && !methodMatch {
if !mMatch {
continue
}
// 2. try match host
for _, h := range ep.Host {
if req.Host == h {
hostMatch = true
break
logger.Logf(log.DebugLevel, "api method match %s", req.Method)
// 2. try host
if len(ep.Host) == 0 {
hMatch = true
} else {
for idx, h := range ep.Host {
if h == "" || h == "*" {
hMatch = true
break
} else if cep.hostregs[idx].MatchString(req.URL.Host) {
hMatch = true
break
}
}
}
// no match on host pass
if len(ep.Host) > 0 && !hostMatch {
if !hMatch {
continue
}
// 3. try match paths
for _, p := range ep.Path {
re, err := regexp.CompilePOSIX(p)
if err == nil && re.MatchString(req.URL.Path) {
pathMatch = true
logger.Logf(log.DebugLevel, "api host match %s", req.URL.Host)
// 3. try path via google.api path matching
for _, pathreg := range cep.pathregs {
matches, err := pathreg.Match(path, "")
if err != nil {
logger.Logf(log.DebugLevel, "api gpath not match %s != %v", path, pathreg)
continue
}
logger.Logf(log.DebugLevel, "api gpath match %s = %v", path, pathreg)
pMatch = true
ctx := req.Context()
md, ok := metadata.FromContext(ctx)
if !ok {
md = make(metadata.Metadata)
}
for k, v := range matches {
md[fmt.Sprintf("x-api-field-%s", k)] = v
}
*req = *req.Clone(metadata.NewContext(ctx, md))
break
}
if !pMatch {
// 4. try path via pcre path matching
for _, pathreg := range cep.pcreregs {
if !pathreg.MatchString(req.URL.Path) {
logger.Logf(log.DebugLevel, "api pcre path not match %s != %v", path, pathreg)
continue
}
logger.Logf(log.DebugLevel, "api pcre path match %s != %v", path, pathreg)
pMatch = true
break
}
}
// no match pass
if len(ep.Path) > 0 && !pathMatch {
if !pMatch {
continue
}
// TODO: Percentage traffic
// we got here, so its a match
return e, nil
return endpoint, nil
}
// no match
return nil, errors.New("not found")
}
func (r *registryRouter) Route(req *http.Request) (*api.Service, error) {
if r.isClosed() {
func (r *registryRouter) Route(req *http.Request) (*router.Route, error) {
if r.isStopped() {
return nil, errors.New("router closed")
}
@@ -321,13 +428,13 @@ func (r *registryRouter) Route(req *http.Request) (*api.Service, error) {
// TODO: don't ignore that shit
// get the service name
rp, err := r.opts.Resolver.Resolve(req)
rsp, err := r.opts.Resolver.Resolve(req)
if err != nil {
return nil, err
}
// service name
name := setNamespace(r.opts.Namespace, rp.Name)
name := rsp.Name
// get service
services, err := r.rc.GetService(name)
@@ -346,28 +453,39 @@ func (r *registryRouter) Route(req *http.Request) (*api.Service, error) {
handler = "rpc"
}
// extract endpoint from Path, case-sensitive
// just test it in this case, maybe should put the code somewhere else
ep_name := rsp.Method
comps := strings.Split(rsp.Path, "/")
switch len(comps) {
case 3:
ep_name = comps[1] + "." + comps[2]
case 4:
ep_name = comps[2] + "." + comps[3]
}
// construct api service
return &api.Service{
Name: name,
Endpoint: &api.Endpoint{
Name: rp.Method,
return &router.Route{
Service: name,
Endpoint: &router.Endpoint{
Name: ep_name,
Handler: handler,
},
Services: services,
Versions: services,
}, nil
// http handler
case "http", "proxy", "web":
// construct api service
return &api.Service{
Name: name,
Endpoint: &api.Endpoint{
return &router.Route{
Service: name,
Endpoint: &router.Endpoint{
Name: req.URL.String(),
Handler: r.opts.Handler,
Host: []string{req.Host},
Method: []string{req.Method},
Path: []string{req.URL.Path},
},
Services: services,
Versions: services,
}, nil
}
@@ -380,14 +498,17 @@ func newRouter(opts ...router.Option) *registryRouter {
exit: make(chan bool),
opts: options,
rc: cache.New(options.Registry),
eps: make(map[string]*api.Service),
eps: make(map[string]*router.Route),
ceps: make(map[string]*endpoint),
}
go r.watch()
go r.refresh()
return r
}
// NewRouter returns the default router
// NewRouter returns the default router.
func NewRouter(opts ...router.Option) router.Router {
return newRouter(opts...)
}
+23 -170
View File
@@ -1,181 +1,34 @@
package registry
import (
"fmt"
"net/http"
"net/url"
"testing"
"github.com/micro/go-micro/v2/api"
"github.com/stretchr/testify/assert"
"go-micro.dev/v4/registry"
)
func TestSetNamespace(t *testing.T) {
testCases := []struct {
namespace string
name string
expected string
}{
// default dotted path
func TestStoreRegex(t *testing.T) {
router := newRouter()
router.store([]*registry.Service{
{
"go.micro.api",
"foo",
"go.micro.api.foo",
Name: "Foobar",
Version: "latest",
Endpoints: []*registry.Endpoint{
{
Name: "foo",
Metadata: map[string]string{
"endpoint": "FooEndpoint",
"description": "Some description",
"method": "POST",
"path": "^/foo/$",
"handler": "rpc",
},
},
},
Metadata: map[string]string{},
},
// dotted end
{
"go.micro.api.",
"foo",
"go.micro.api.foo",
},
// dashed end
{
"go-micro-api-",
"foo",
"go-micro-api-foo",
},
// no namespace
{
"",
"foo",
"foo",
},
{
"go-micro-api-",
"v2.foo",
"go-micro-api-v2-foo",
},
}
for _, test := range testCases {
name := setNamespace(test.namespace, test.name)
if name != test.expected {
t.Fatalf("expected name %s got %s", test.expected, name)
}
}
}
func TestRouter(t *testing.T) {
r := newRouter()
compare := func(expect, got []string) bool {
// no data to compare, return true
if len(expect) == 0 && len(got) == 0 {
return true
}
// no data expected but got some return false
if len(expect) == 0 && len(got) > 0 {
return false
}
// compare expected with what we got
for _, e := range expect {
var seen bool
for _, g := range got {
if e == g {
seen = true
break
}
}
if !seen {
return false
}
}
// we're done, return true
return true
}
testData := []struct {
e *api.Endpoint
r *http.Request
m bool
}{
{
e: &api.Endpoint{
Name: "Foo.Bar",
Host: []string{"example.com"},
Method: []string{"GET"},
Path: []string{"/foo"},
},
r: &http.Request{
Host: "example.com",
Method: "GET",
URL: &url.URL{
Path: "/foo",
},
},
m: true,
},
{
e: &api.Endpoint{
Name: "Bar.Baz",
Host: []string{"example.com", "foo.com"},
Method: []string{"GET", "POST"},
Path: []string{"/foo/bar"},
},
r: &http.Request{
Host: "foo.com",
Method: "POST",
URL: &url.URL{
Path: "/foo/bar",
},
},
m: true,
},
{
e: &api.Endpoint{
Name: "Test.Cruft",
Host: []string{"example.com", "foo.com"},
Method: []string{"GET", "POST"},
Path: []string{"/xyz"},
},
r: &http.Request{
Host: "fail.com",
Method: "DELETE",
URL: &url.URL{
Path: "/test/fail",
},
},
m: false,
},
}
for _, d := range testData {
key := fmt.Sprintf("%s:%s", "test.service", d.e.Name)
r.eps[key] = &api.Service{
Endpoint: d.e,
}
}
for _, d := range testData {
e, err := r.Endpoint(d.r)
if d.m && err != nil {
t.Fatalf("expected match, got %v", err)
}
if !d.m && err == nil {
t.Fatal("expected error got match")
}
// skip testing the non match
if !d.m {
continue
}
ep := e.Endpoint
// test the match
if d.e.Name != ep.Name {
t.Fatalf("expected %v got %v", d.e.Name, ep.Name)
}
if ok := compare(d.e.Method, ep.Method); !ok {
t.Fatalf("expected %v got %v", d.e.Method, ep.Method)
}
if ok := compare(d.e.Path, ep.Path); !ok {
t.Fatalf("expected %v got %v", d.e.Path, ep.Path)
}
if ok := compare(d.e.Host, ep.Host); !ok {
t.Fatalf("expected %v got %v", d.e.Host, ep.Host)
}
}
},
)
assert.Len(t, router.ceps["Foobar.foo"].pcreregs, 1)
}
+36 -7
View File
@@ -4,17 +4,46 @@ package router
import (
"net/http"
"github.com/micro/go-micro/v2/api"
"go-micro.dev/v4/registry"
)
// Router is used to determine an endpoint for a request
// Router is used to determine an endpoint for a request.
type Router interface {
// Returns options
Options() Options
// Stop the router
Close() error
// Endpoint returns an api.Service endpoint or an error if it does not exist
Endpoint(r *http.Request) (*api.Service, error)
// Register endpoint in router
Register(r *Route) error
// Deregister endpoint from router
Deregister(r *Route) error
// Route returns an api.Service route
Route(r *http.Request) (*api.Service, error)
Route(r *http.Request) (*Route, error)
// Stop the router
Stop() error
}
type Route struct {
// Name of service
Service string
// The endpoint for this service
Endpoint *Endpoint
// Versions of this service
Versions []*registry.Service
}
// Endpoint is a mapping between an RPC method and HTTP endpoint.
type Endpoint struct {
// RPC Method e.g. Greeter.Hello
Name string
// What the endpoint is for
Description string
// API Handler e.g rpc, proxy
Handler string
// HTTP Host e.g example.com
Host []string
// HTTP Methods e.g GET, POST
Method []string
// HTTP Path e.g /greeter. Expect POSIX regex
Path []string
// Stream flag
Stream bool
}
+369
View File
@@ -0,0 +1,369 @@
package static
import (
"errors"
"fmt"
"net/http"
"regexp"
"strings"
"sync"
"go-micro.dev/v4/api/router"
"go-micro.dev/v4/api/router/util"
log "go-micro.dev/v4/logger"
"go-micro.dev/v4/metadata"
"go-micro.dev/v4/registry"
rutil "go-micro.dev/v4/util/registry"
)
type endpoint struct {
apiep *router.Endpoint
hostregs []*regexp.Regexp
pathregs []util.Pattern
pcreregs []*regexp.Regexp
}
// Router is the default router.
type Router struct {
opts router.Options
exit chan bool
eps map[string]*endpoint
sync.RWMutex
}
func (r *Router) isStopd() bool {
select {
case <-r.exit:
return true
default:
return false
}
}
/*
// watch for endpoint changes
func (r *staticRouter) watch() {
var attempts int
for {
if r.isStopd() {
return
}
// watch for changes
w, err := r.opts.Registry.Watch()
if err != nil {
attempts++
log.Println("Error watching endpoints", err)
time.Sleep(time.Duration(attempts) * time.Second)
continue
}
ch := make(chan bool)
go func() {
select {
case <-ch:
w.Stop()
case <-r.exit:
w.Stop()
}
}()
// reset if we get here
attempts = 0
for {
// process next event
res, err := w.Next()
if err != nil {
log.Println("Error getting next endpoint", err)
close(ch)
break
}
r.process(res)
}
}
}
*/
func (r *Router) Register(route *router.Route) error {
myEndpoint := route.Endpoint
if err := router.Validate(myEndpoint); err != nil {
return err
}
var (
pathregs []util.Pattern
hostregs []*regexp.Regexp
pcreregs []*regexp.Regexp
)
for _, h := range myEndpoint.Host {
if h == "" || h == "*" {
continue
}
hostreg, err := regexp.CompilePOSIX(h)
if err != nil {
return err
}
hostregs = append(hostregs, hostreg)
}
for _, p := range myEndpoint.Path {
var pcreok bool
// pcre only when we have start and end markers
if p[0] == '^' && p[len(p)-1] == '$' {
pcrereg, err := regexp.CompilePOSIX(p)
if err == nil {
pcreregs = append(pcreregs, pcrereg)
pcreok = true
}
}
rule, err := util.Parse(p)
if err != nil && !pcreok {
return err
} else if err != nil && pcreok {
continue
}
tpl := rule.Compile()
pathreg, err := util.NewPattern(tpl.Version, tpl.OpCodes, tpl.Pool, "", util.PatternLogger(r.Options().Logger))
if err != nil {
return err
}
pathregs = append(pathregs, pathreg)
}
r.Lock()
r.eps[myEndpoint.Name] = &endpoint{
apiep: myEndpoint,
pcreregs: pcreregs,
pathregs: pathregs,
hostregs: hostregs,
}
r.Unlock()
return nil
}
func (r *Router) Deregister(route *router.Route) error {
ep := route.Endpoint
if err := router.Validate(ep); err != nil {
return err
}
r.Lock()
delete(r.eps, ep.Name)
r.Unlock()
return nil
}
func (r *Router) Options() router.Options {
return r.opts
}
func (r *Router) Stop() error {
select {
case <-r.exit:
return nil
default:
close(r.exit)
}
return nil
}
func (r *Router) Endpoint(req *http.Request) (*router.Route, error) {
myEndpoint, err := r.endpoint(req)
if err != nil {
return nil, err
}
epf := strings.Split(myEndpoint.apiep.Name, ".")
services, err := r.opts.Registry.GetService(epf[0])
if err != nil {
return nil, err
}
// hack for stream endpoint
if myEndpoint.apiep.Stream {
svcs := rutil.Copy(services)
for _, svc := range svcs {
if len(svc.Endpoints) == 0 {
e := &registry.Endpoint{}
e.Name = strings.Join(epf[1:], ".")
e.Metadata = make(map[string]string)
e.Metadata["stream"] = "true"
svc.Endpoints = append(svc.Endpoints, e)
}
for _, e := range svc.Endpoints {
e.Name = strings.Join(epf[1:], ".")
e.Metadata = make(map[string]string)
e.Metadata["stream"] = "true"
}
}
services = svcs
}
svc := &router.Route{
Service: epf[0],
Endpoint: &router.Endpoint{
Name: strings.Join(epf[1:], "."),
Handler: "rpc",
Host: myEndpoint.apiep.Host,
Method: myEndpoint.apiep.Method,
Path: myEndpoint.apiep.Path,
Stream: myEndpoint.apiep.Stream,
},
Versions: services,
}
return svc, nil
}
func (r *Router) endpoint(req *http.Request) (*endpoint, error) {
logger := r.Options().Logger
if r.isStopd() {
return nil, errors.New("router closed")
}
r.RLock()
defer r.RUnlock()
var idx int
if len(req.URL.Path) > 0 && req.URL.Path != "/" {
idx = 1
}
path := strings.Split(req.URL.Path[idx:], "/")
// use the first match
// TODO: weighted matching
for _, myEndpoint := range r.eps {
var mMatch, hMatch, pMatch bool
// 1. try method
for _, m := range myEndpoint.apiep.Method {
if m == req.Method {
mMatch = true
break
}
}
if !mMatch {
continue
}
logger.Logf(log.DebugLevel, "api method match %s", req.Method)
// 2. try host
if len(myEndpoint.apiep.Host) == 0 {
hMatch = true
} else {
for idx, h := range myEndpoint.apiep.Host {
if h == "" || h == "*" {
hMatch = true
break
} else if myEndpoint.hostregs[idx].MatchString(req.URL.Host) {
hMatch = true
break
}
}
}
if !hMatch {
continue
}
logger.Logf(log.DebugLevel, "api host match %s", req.URL.Host)
// 3. try google.api path
for _, pathreg := range myEndpoint.pathregs {
matches, err := pathreg.Match(path, "")
if err != nil {
logger.Logf(log.DebugLevel, "api gpath not match %s != %v", path, pathreg)
continue
}
logger.Logf(log.DebugLevel, "api gpath match %s = %v", path, pathreg)
pMatch = true
ctx := req.Context()
md, ok := metadata.FromContext(ctx)
if !ok {
md = make(metadata.Metadata)
}
for k, v := range matches {
md[fmt.Sprintf("x-api-field-%s", k)] = v
}
*req = *req.Clone(metadata.NewContext(ctx, md))
break
}
if !pMatch {
// 4. try path via pcre path matching
for _, pathreg := range myEndpoint.pcreregs {
if !pathreg.MatchString(req.URL.Path) {
logger.Logf(log.DebugLevel, "api pcre path not match %s != %v", req.URL.Path, pathreg)
continue
}
pMatch = true
break
}
}
if !pMatch {
continue
}
// TODO: Percentage traffic
// we got here, so its a match
return myEndpoint, nil
}
// no match
return nil, fmt.Errorf("endpoint not found for %v", req.URL)
}
func (r *Router) Route(req *http.Request) (*router.Route, error) {
if r.isStopd() {
return nil, errors.New("router closed")
}
// try get an endpoint
ep, err := r.Endpoint(req)
if err != nil {
return nil, err
}
return ep, nil
}
// NewRouter returns a new static router.
func NewRouter(opts ...router.Option) *Router {
options := router.NewOptions(opts...)
r := &Router{
exit: make(chan bool),
opts: options,
eps: make(map[string]*endpoint),
}
// go r.watch()
return r
}
+27
View File
@@ -0,0 +1,27 @@
Copyright (c) 2015, Gengo, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Gengo, Inc. nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+122
View File
@@ -0,0 +1,122 @@
package util
// download from
// https://raw.githubusercontent.com/grpc-ecosystem/grpc-gateway/master/protoc-gen-grpc-gateway/httprule/compile.go
const (
opcodeVersion = 1
)
// Template is a compiled representation of path templates.
type Template struct {
// Verb is a VERB part in the template.
Verb string
// Original template (example: /v1/a_bit_of_everything)
Template string
// OpCodes is a sequence of operations.
OpCodes []int
// Pool is a constant pool
Pool []string
// Fields is a list of field paths bound in this template.
Fields []string
// Version is the version number of the format.
Version int
}
// Compiler compiles utilities representation of path templates into marshallable operations.
// They can be unmarshalled by runtime.NewPattern.
type Compiler interface {
Compile() Template
}
type op struct {
// str is a string operand of the code.
// operand is ignored if str is not empty.
str string
// code is the opcode of the operation
code OpCode
// operand is a numeric operand of the code.
operand int
}
func (w wildcard) compile() []op {
return []op{
{code: OpPush},
}
}
func (w deepWildcard) compile() []op {
return []op{
{code: OpPushM},
}
}
func (l literal) compile() []op {
return []op{
{
code: OpLitPush,
str: string(l),
},
}
}
func (v variable) compile() []op {
var ops []op
for _, s := range v.segments {
ops = append(ops, s.compile()...)
}
ops = append(ops, op{
code: OpConcatN,
operand: len(v.segments),
}, op{
code: OpCapture,
str: v.path,
})
return ops
}
func (t template) Compile() Template {
var rawOps []op
for _, s := range t.segments {
rawOps = append(rawOps, s.compile()...)
}
var (
ops []int
pool []string
fields []string
)
consts := make(map[string]int)
for _, op := range rawOps {
ops = append(ops, int(op.code))
if op.str == "" {
ops = append(ops, op.operand)
} else {
if _, ok := consts[op.str]; !ok {
consts[op.str] = len(pool)
pool = append(pool, op.str)
}
ops = append(ops, consts[op.str])
}
if op.code == OpCapture {
fields = append(fields, op.str)
}
}
return Template{
Version: opcodeVersion,
OpCodes: ops,
Pool: pool,
Verb: t.verb,
Fields: fields,
Template: t.template,
}
}
+122
View File
@@ -0,0 +1,122 @@
package util
// download from https://raw.githubusercontent.com/grpc-ecosystem/grpc-gateway/master/protoc-gen-grpc-gateway/httprule/compile_test.go
import (
"reflect"
"testing"
)
const (
operandFiller = 0
)
func TestCompile(t *testing.T) {
for _, spec := range []struct {
segs []segment
verb string
ops []int
pool []string
fields []string
}{
{},
{
segs: []segment{
wildcard{},
},
ops: []int{int(OpPush), operandFiller},
},
{
segs: []segment{
deepWildcard{},
},
ops: []int{int(OpPushM), operandFiller},
},
{
segs: []segment{
literal("v1"),
},
ops: []int{int(OpLitPush), 0},
pool: []string{"v1"},
},
{
segs: []segment{
literal("v1"),
},
verb: "LOCK",
ops: []int{int(OpLitPush), 0},
pool: []string{"v1"},
},
{
segs: []segment{
variable{
path: "name.nested",
segments: []segment{
wildcard{},
},
},
},
ops: []int{
int(OpPush), operandFiller,
int(OpConcatN), 1,
int(OpCapture), 0,
},
pool: []string{"name.nested"},
fields: []string{"name.nested"},
},
{
segs: []segment{
literal("obj"),
variable{
path: "name.nested",
segments: []segment{
literal("a"),
wildcard{},
literal("b"),
},
},
variable{
path: "obj",
segments: []segment{
deepWildcard{},
},
},
},
ops: []int{
int(OpLitPush), 0,
int(OpLitPush), 1,
int(OpPush), operandFiller,
int(OpLitPush), 2,
int(OpConcatN), 3,
int(OpCapture), 3,
int(OpPushM), operandFiller,
int(OpConcatN), 1,
int(OpCapture), 0,
},
pool: []string{"obj", "a", "b", "name.nested"},
fields: []string{"name.nested", "obj"},
},
} {
tmpl := template{
segments: spec.segs,
verb: spec.verb,
}
compiled := tmpl.Compile()
if got, want := compiled.Version, opcodeVersion; got != want {
t.Errorf("tmpl.Compile().Version = %d; want %d; segs=%#v, verb=%q", got, want, spec.segs, spec.verb)
}
if got, want := compiled.OpCodes, spec.ops; !reflect.DeepEqual(got, want) {
t.Errorf("tmpl.Compile().OpCodes = %v; want %v; segs=%#v, verb=%q", got, want, spec.segs, spec.verb)
}
if got, want := compiled.Pool, spec.pool; !reflect.DeepEqual(got, want) {
t.Errorf("tmpl.Compile().Pool = %q; want %q; segs=%#v, verb=%q", got, want, spec.segs, spec.verb)
}
if got, want := compiled.Verb, spec.verb; got != want {
t.Errorf("tmpl.Compile().Verb = %q; want %q; segs=%#v, verb=%q", got, want, spec.segs, spec.verb)
}
if got, want := compiled.Fields, spec.fields; !reflect.DeepEqual(got, want) {
t.Errorf("tmpl.Compile().Fields = %q; want %q; segs=%#v, verb=%q", got, want, spec.segs, spec.verb)
}
}
}
+396
View File
@@ -0,0 +1,396 @@
package util
// download from
// https://raw.githubusercontent.com/grpc-ecosystem/grpc-gateway/master/protoc-gen-grpc-gateway/httprule/parse.go
import (
"fmt"
"strings"
log "go-micro.dev/v4/logger"
)
// InvalidTemplateError indicates that the path template is not valid.
type InvalidTemplateError struct {
tmpl string
msg string
}
func (e InvalidTemplateError) Error() string {
return fmt.Sprintf("%s: %s", e.msg, e.tmpl)
}
// Parse parses the string representation of path template.
func Parse(tmpl string) (Compiler, error) {
if !strings.HasPrefix(tmpl, "/") {
return template{}, InvalidTemplateError{tmpl: tmpl, msg: "no leading /"}
}
tokens, verb := tokenize(tmpl[1:])
p := parser{tokens: tokens}
segs, err := p.topLevelSegments()
if err != nil {
return template{}, InvalidTemplateError{tmpl: tmpl, msg: err.Error()}
}
return template{
segments: segs,
verb: verb,
template: tmpl,
}, nil
}
func tokenize(path string) (tokens []string, verb string) {
if path == "" {
return []string{eof}, ""
}
const (
init = iota
field
nested
)
var (
st = init
)
for path != "" {
var idx int
switch st {
case init:
idx = strings.IndexAny(path, "/{")
case field:
idx = strings.IndexAny(path, ".=}")
case nested:
idx = strings.IndexAny(path, "/}")
}
if idx < 0 {
tokens = append(tokens, path)
break
}
switch r := path[idx]; r {
case '/', '.':
case '{':
st = field
case '=':
st = nested
case '}':
st = init
}
if idx == 0 {
tokens = append(tokens, path[idx:idx+1])
} else {
tokens = append(tokens, path[:idx], path[idx:idx+1])
}
path = path[idx+1:]
}
l := len(tokens)
t := tokens[l-1]
if idx := strings.LastIndex(t, ":"); idx == 0 {
tokens, verb = tokens[:l-1], t[1:]
} else if idx > 0 {
tokens[l-1], verb = t[:idx], t[idx+1:]
}
tokens = append(tokens, eof)
return tokens, verb
}
// parser is a parser of the template syntax defined in github.com/googleapis/googleapis/google/api/http.proto.
type parser struct {
logger log.Logger
tokens []string
accepted []string
}
// topLevelSegments is the target of this parser.
func (p *parser) topLevelSegments() ([]segment, error) {
logger := log.LoggerOrDefault(p.logger)
logger.Logf(log.DebugLevel, "Parsing %q", p.tokens)
segs, err := p.segments()
if err != nil {
return nil, err
}
logger.Logf(log.DebugLevel, "accept segments: %q; %q", p.accepted, p.tokens)
if _, err := p.accept(typeEOF); err != nil {
return nil, fmt.Errorf("unexpected token %q after segments %q", p.tokens[0], strings.Join(p.accepted, ""))
}
logger.Logf(log.DebugLevel, "accept eof: %q; %q", p.accepted, p.tokens)
return segs, nil
}
func (p *parser) segments() ([]segment, error) {
logger := log.LoggerOrDefault(p.logger)
s, err := p.segment()
if err != nil {
return nil, err
}
logger.Logf(log.DebugLevel, "accept segment: %q; %q", p.accepted, p.tokens)
segs := []segment{s}
for {
if _, err := p.accept("/"); err != nil {
return segs, nil
}
s, err := p.segment()
if err != nil {
return segs, err
}
segs = append(segs, s)
logger.Logf(log.DebugLevel, "accept segment: %q; %q", p.accepted, p.tokens)
}
}
func (p *parser) segment() (segment, error) {
if _, err := p.accept("*"); err == nil {
return wildcard{}, nil
}
if _, err := p.accept("**"); err == nil {
return deepWildcard{}, nil
}
if l, err := p.literal(); err == nil {
return l, nil
}
v, err := p.variable()
if err != nil {
return nil, fmt.Errorf("segment neither wildcards, literal or variable: %w", err)
}
return v, err
}
func (p *parser) literal() (segment, error) {
lit, err := p.accept(typeLiteral)
if err != nil {
return nil, err
}
return literal(lit), nil
}
func (p *parser) variable() (segment, error) {
if _, err := p.accept("{"); err != nil {
return nil, err
}
path, err := p.fieldPath()
if err != nil {
return nil, err
}
var segs []segment
if _, err := p.accept("="); err == nil {
segs, err = p.segments()
if err != nil {
return nil, fmt.Errorf("invalid segment in variable %q: %w", path, err)
}
} else {
segs = []segment{wildcard{}}
}
if _, err := p.accept("}"); err != nil {
return nil, fmt.Errorf("unterminated variable segment: %s", path)
}
return variable{
path: path,
segments: segs,
}, nil
}
func (p *parser) fieldPath() (string, error) {
c, err := p.accept(typeIdent)
if err != nil {
return "", err
}
components := []string{c}
for {
if _, err = p.accept("."); err != nil {
return strings.Join(components, "."), nil
}
c, err := p.accept(typeIdent)
if err != nil {
return "", fmt.Errorf("invalid field path component: %v", err)
}
components = append(components, c)
}
}
// A termType is a type of terminal symbols.
type termType string
// These constants define some of valid values of termType.
// They improve readability of parse functions.
//
// You can also use "/", "*", "**", "." or "=" as valid values.
const (
typeIdent = termType("ident")
typeLiteral = termType("literal")
typeEOF = termType("$")
)
const (
// eof is the terminal symbol which always appears at the end of token sequence.
eof = "\u0000"
)
// accept tries to accept a token in "p".
// This function consumes a token and returns it if it matches to the specified "term".
// If it doesn't match, the function does not consume any tokens and return an error.
func (p *parser) accept(term termType) (string, error) {
t := p.tokens[0]
switch term {
case "/", "*", "**", ".", "=", "{", "}":
if t != string(term) && t != "/" {
return "", fmt.Errorf("expected %q but got %q", term, t)
}
case typeEOF:
if t != eof {
return "", fmt.Errorf("expected EOF but got %q", t)
}
case typeIdent:
if err := expectIdent(t); err != nil {
return "", err
}
case typeLiteral:
if err := expectPChars(t); err != nil {
return "", err
}
default:
return "", fmt.Errorf("unknown termType %q", term)
}
p.tokens = p.tokens[1:]
p.accepted = append(p.accepted, t)
return t, nil
}
// expectPChars determines if "t" consists of only pchars defined in RFC3986.
//
// https://www.ietf.org/rfc/rfc3986.txt, P.49
//
// pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
// sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
// / "*" / "+" / "," / ";" / "="
// pct-encoded = "%" HEXDIG HEXDIG
func expectPChars(t string) error {
const (
init = iota
pct1
pct2
)
st := init
for _, r := range t {
if st != init {
if !isHexDigit(r) {
return fmt.Errorf("invalid hexdigit: %c(%U)", r, r)
}
switch st {
case pct1:
st = pct2
case pct2:
st = init
}
continue
}
// unreserved
switch {
case 'A' <= r && r <= 'Z':
continue
case 'a' <= r && r <= 'z':
continue
case '0' <= r && r <= '9':
continue
}
switch r {
case '-', '.', '_', '~':
// unreserved
case '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=':
// sub-delims
case ':', '@':
// rest of pchar
case '%':
// pct-encoded
st = pct1
default:
return fmt.Errorf("invalid character in path segment: %q(%U)", r, r)
}
}
if st != init {
return fmt.Errorf("invalid percent-encoding in %q", t)
}
return nil
}
// expectIdent determines if "ident" is a valid identifier in .proto schema ([[:alpha:]_][[:alphanum:]_]*).
func expectIdent(ident string) error {
if ident == "" {
return fmt.Errorf("empty identifier")
}
for pos, r := range ident {
switch {
case '0' <= r && r <= '9':
if pos == 0 {
return fmt.Errorf("identifier starting with digit: %s", ident)
}
continue
case 'A' <= r && r <= 'Z':
continue
case 'a' <= r && r <= 'z':
continue
case r == '_':
continue
default:
return fmt.Errorf("invalid character %q(%U) in identifier: %s", r, r, ident)
}
}
return nil
}
func isHexDigit(r rune) bool {
switch {
case '0' <= r && r <= '9':
return true
case 'A' <= r && r <= 'F':
return true
case 'a' <= r && r <= 'f':
return true
}
return false
}
+321
View File
@@ -0,0 +1,321 @@
package util
// download from https://raw.githubusercontent.com/grpc-ecosystem/grpc-gateway/master/protoc-gen-grpc-gateway/httprule/parse_test.go
import (
"flag"
"fmt"
"reflect"
"testing"
"go-micro.dev/v4/logger"
)
func TestTokenize(t *testing.T) {
for _, spec := range []struct {
src string
tokens []string
}{
{
src: "",
tokens: []string{eof},
},
{
src: "v1",
tokens: []string{"v1", eof},
},
{
src: "v1/b",
tokens: []string{"v1", "/", "b", eof},
},
{
src: "v1/endpoint/*",
tokens: []string{"v1", "/", "endpoint", "/", "*", eof},
},
{
src: "v1/endpoint/**",
tokens: []string{"v1", "/", "endpoint", "/", "**", eof},
},
{
src: "v1/b/{bucket_name=*}",
tokens: []string{
"v1", "/",
"b", "/",
"{", "bucket_name", "=", "*", "}",
eof,
},
},
{
src: "v1/b/{bucket_name=buckets/*}",
tokens: []string{
"v1", "/",
"b", "/",
"{", "bucket_name", "=", "buckets", "/", "*", "}",
eof,
},
},
{
src: "v1/b/{bucket_name=buckets/*}/o",
tokens: []string{
"v1", "/",
"b", "/",
"{", "bucket_name", "=", "buckets", "/", "*", "}", "/",
"o",
eof,
},
},
{
src: "v1/b/{bucket_name=buckets/*}/o/{name}",
tokens: []string{
"v1", "/",
"b", "/",
"{", "bucket_name", "=", "buckets", "/", "*", "}", "/",
"o", "/", "{", "name", "}",
eof,
},
},
{
src: "v1/a=b&c=d;e=f:g/endpoint.rdf",
tokens: []string{
"v1", "/",
"a=b&c=d;e=f:g", "/",
"endpoint.rdf",
eof,
},
},
} {
tokens, verb := tokenize(spec.src)
if got, want := tokens, spec.tokens; !reflect.DeepEqual(got, want) {
t.Errorf("tokenize(%q) = %q, _; want %q, _", spec.src, got, want)
}
if got, want := verb, ""; got != want {
t.Errorf("tokenize(%q) = _, %q; want _, %q", spec.src, got, want)
}
src := fmt.Sprintf("%s:%s", spec.src, "LOCK")
tokens, verb = tokenize(src)
if got, want := tokens, spec.tokens; !reflect.DeepEqual(got, want) {
t.Errorf("tokenize(%q) = %q, _; want %q, _", src, got, want)
}
if got, want := verb, "LOCK"; got != want {
t.Errorf("tokenize(%q) = _, %q; want _, %q", src, got, want)
}
}
}
func TestParseSegments(t *testing.T) {
flag.Set("v", "3")
for _, spec := range []struct {
tokens []string
want []segment
}{
{
tokens: []string{"v1", eof},
want: []segment{
literal("v1"),
},
},
{
tokens: []string{"/", eof},
want: []segment{
wildcard{},
},
},
{
tokens: []string{"-._~!$&'()*+,;=:@", eof},
want: []segment{
literal("-._~!$&'()*+,;=:@"),
},
},
{
tokens: []string{"%e7%ac%ac%e4%b8%80%e7%89%88", eof},
want: []segment{
literal("%e7%ac%ac%e4%b8%80%e7%89%88"),
},
},
{
tokens: []string{"v1", "/", "*", eof},
want: []segment{
literal("v1"),
wildcard{},
},
},
{
tokens: []string{"v1", "/", "**", eof},
want: []segment{
literal("v1"),
deepWildcard{},
},
},
{
tokens: []string{"{", "name", "}", eof},
want: []segment{
variable{
path: "name",
segments: []segment{
wildcard{},
},
},
},
},
{
tokens: []string{"{", "name", "=", "*", "}", eof},
want: []segment{
variable{
path: "name",
segments: []segment{
wildcard{},
},
},
},
},
{
tokens: []string{"{", "field", ".", "nested", ".", "nested2", "=", "*", "}", eof},
want: []segment{
variable{
path: "field.nested.nested2",
segments: []segment{
wildcard{},
},
},
},
},
{
tokens: []string{"{", "name", "=", "a", "/", "b", "/", "*", "}", eof},
want: []segment{
variable{
path: "name",
segments: []segment{
literal("a"),
literal("b"),
wildcard{},
},
},
},
},
{
tokens: []string{
"v1", "/",
"{",
"name", ".", "nested", ".", "nested2",
"=",
"a", "/", "b", "/", "*",
"}", "/",
"o", "/",
"{",
"another_name",
"=",
"a", "/", "b", "/", "*", "/", "c",
"}", "/",
"**",
eof},
want: []segment{
literal("v1"),
variable{
path: "name.nested.nested2",
segments: []segment{
literal("a"),
literal("b"),
wildcard{},
},
},
literal("o"),
variable{
path: "another_name",
segments: []segment{
literal("a"),
literal("b"),
wildcard{},
literal("c"),
},
},
deepWildcard{},
},
},
} {
p := parser{tokens: spec.tokens}
segs, err := p.topLevelSegments()
if err != nil {
t.Errorf("parser{%q}.segments() failed with %v; want success", spec.tokens, err)
continue
}
if got, want := segs, spec.want; !reflect.DeepEqual(got, want) {
t.Errorf("parser{%q}.segments() = %#v; want %#v", spec.tokens, got, want)
}
if got := p.tokens; len(got) > 0 {
t.Errorf("p.tokens = %q; want []; spec.tokens=%q", got, spec.tokens)
}
}
}
func TestParseSegmentsWithErrors(t *testing.T) {
flag.Set("v", "3")
for _, spec := range []struct {
tokens []string
}{
{
// double slash
tokens: []string{"//", eof},
},
{
// invalid literal
tokens: []string{"a?b", eof},
},
{
// invalid percent-encoding
tokens: []string{"%", eof},
},
{
// invalid percent-encoding
tokens: []string{"%2", eof},
},
{
// invalid percent-encoding
tokens: []string{"a%2z", eof},
},
{
// empty segments
tokens: []string{eof},
},
{
// unterminated variable
tokens: []string{"{", "name", eof},
},
{
// unterminated variable
tokens: []string{"{", "name", "=", eof},
},
{
// unterminated variable
tokens: []string{"{", "name", "=", "*", eof},
},
{
// empty component in field path
tokens: []string{"{", "name", ".", "}", eof},
},
{
// empty component in field path
tokens: []string{"{", "name", ".", ".", "nested", "}", eof},
},
{
// invalid character in identifier
tokens: []string{"{", "field-name", "}", eof},
},
{
// no slash between segments
tokens: []string{"v1", "endpoint", eof},
},
{
// no slash between segments
tokens: []string{"v1", "{", "name", "}", eof},
},
} {
p := parser{tokens: spec.tokens}
segs, err := p.topLevelSegments()
if err == nil {
t.Errorf("parser{%q}.segments() succeeded; want InvalidTemplateError; accepted %#v", spec.tokens, segs)
continue
}
logger.Info(err)
}
}
+24
View File
@@ -0,0 +1,24 @@
package util
// download from https://raw.githubusercontent.com/grpc-ecosystem/grpc-gateway/master/utilities/pattern.go
// An OpCode is a opcode of compiled path patterns.
type OpCode int
// These constants are the valid values of OpCode.
const (
// OpNop does nothing.
OpNop = OpCode(iota)
// OpPush pushes a component to stack.
OpPush
// OpLitPush pushes a component to stack if it matches to the literal.
OpLitPush
// OpPushM concatenates the remaining components and pushes it to stack.
OpPushM
// OpConcatN pops N items from stack, concatenates them and pushes it back to stack.
OpConcatN
// OpCapture pops an item and binds it to the variable.
OpCapture
// OpEnd is the least positive invalid opcode.
OpEnd
)
+282
View File
@@ -0,0 +1,282 @@
package util
// download from https://raw.githubusercontent.com/grpc-ecosystem/grpc-gateway/master/runtime/pattern.go
import (
"errors"
"fmt"
"strings"
log "go-micro.dev/v4/logger"
)
var (
// ErrNotMatch indicates that the given HTTP request path does not match to the pattern.
ErrNotMatch = errors.New("not match to the path pattern")
// ErrInvalidPattern indicates that the given definition of Pattern is not valid.
ErrInvalidPattern = errors.New("invalid pattern")
)
type rop struct {
code OpCode
operand int
}
// Pattern is a template pattern of http request paths defined in github.com/googleapis/googleapis/google/api/http.proto.
type Pattern struct {
// verb is the VERB part of the path pattern. It is empty if the pattern does not have VERB part.
verb string
// ops is a list of operations
ops []rop
// pool is a constant pool indexed by the operands or vars.
pool []string
// vars is a list of variables names to be bound by this pattern
vars []string
// stacksize is the max depth of the stack
stacksize int
// tailLen is the length of the fixed-size segments after a deep wildcard
tailLen int
// assumeColonVerb indicates whether a path suffix after a final
// colon may only be interpreted as a verb.
assumeColonVerb bool
}
type patternOptions struct {
logger log.Logger
assumeColonVerb bool
}
// PatternOpt is an option for creating Patterns.
type PatternOpt func(*patternOptions)
// PatternLogger sets the logger.
func PatternLogger(l log.Logger) PatternOpt {
return func(po *patternOptions) {
po.logger = l
}
}
// NewPattern returns a new Pattern from the given definition values.
// "ops" is a sequence of op codes. "pool" is a constant pool.
// "verb" is the verb part of the pattern. It is empty if the pattern does not have the part.
// "version" must be 1 for now.
// It returns an error if the given definition is invalid.
func NewPattern(version int, ops []int, pool []string, verb string, opts ...PatternOpt) (Pattern, error) {
options := patternOptions{
assumeColonVerb: true,
}
for _, o := range opts {
o(&options)
}
logger := log.LoggerOrDefault(options.logger)
if version != 1 {
logger.Logf(log.DebugLevel, "unsupported version: %d", version)
return Pattern{}, ErrInvalidPattern
}
l := len(ops)
if l%2 != 0 {
logger.Logf(log.DebugLevel, "odd number of ops codes: %d", l)
return Pattern{}, ErrInvalidPattern
}
var (
typedOps []rop
stack, maxstack int
tailLen int
pushMSeen bool
vars []string
)
for i := 0; i < l; i += 2 {
op := rop{code: OpCode(ops[i]), operand: ops[i+1]}
switch op.code {
case OpNop:
continue
case OpPush:
if pushMSeen {
tailLen++
}
stack++
case OpPushM:
if pushMSeen {
logger.Logf(log.DebugLevel, "pushM appears twice")
return Pattern{}, ErrInvalidPattern
}
pushMSeen = true
stack++
case OpLitPush:
if op.operand < 0 || len(pool) <= op.operand {
logger.Logf(log.DebugLevel, "negative literal index: %d", op.operand)
return Pattern{}, ErrInvalidPattern
}
if pushMSeen {
tailLen++
}
stack++
case OpConcatN:
if op.operand <= 0 {
logger.Logf(log.DebugLevel, "negative concat size: %d", op.operand)
return Pattern{}, ErrInvalidPattern
}
stack -= op.operand
if stack < 0 {
logger.Logf(log.DebugLevel, "stack underflow")
return Pattern{}, ErrInvalidPattern
}
stack++
case OpCapture:
if op.operand < 0 || len(pool) <= op.operand {
logger.Logf(log.DebugLevel, "variable name index out of bound: %d", op.operand)
return Pattern{}, ErrInvalidPattern
}
v := pool[op.operand]
op.operand = len(vars)
vars = append(vars, v)
stack--
if stack < 0 {
logger.Logf(log.DebugLevel, "stack underflow")
return Pattern{}, ErrInvalidPattern
}
default:
logger.Logf(log.DebugLevel, "invalid opcode: %d", op.code)
return Pattern{}, ErrInvalidPattern
}
if maxstack < stack {
maxstack = stack
}
typedOps = append(typedOps, op)
}
return Pattern{
ops: typedOps,
pool: pool,
vars: vars,
stacksize: maxstack,
tailLen: tailLen,
verb: verb,
assumeColonVerb: options.assumeColonVerb,
}, nil
}
// MustPattern is a helper function which makes it easier to call NewPattern in variable initialization.
func MustPattern(p Pattern, err error) Pattern {
if err != nil {
log.Logf(log.FatalLevel, "Pattern initialization failed: %v", err)
}
return p
}
// Match examines components if it matches to the Pattern.
// If it matches, the function returns a mapping from field paths to their captured values.
// If otherwise, the function returns an error.
func (p Pattern) Match(components []string, verb string) (map[string]string, error) {
if p.verb != verb {
if p.assumeColonVerb || p.verb != "" {
return nil, ErrNotMatch
}
if len(components) == 0 {
components = []string{":" + verb}
} else {
components = append([]string{}, components...)
components[len(components)-1] += ":" + verb
}
verb = ""
}
var pos int
stack := make([]string, 0, p.stacksize)
captured := make([]string, len(p.vars))
l := len(components)
for _, op := range p.ops {
switch op.code {
case OpNop:
continue
case OpPush, OpLitPush:
if pos >= l {
return nil, ErrNotMatch
}
c := components[pos]
if op.code == OpLitPush {
if lit := p.pool[op.operand]; c != lit {
return nil, ErrNotMatch
}
}
stack = append(stack, c)
pos++
case OpPushM:
end := len(components)
if end < pos+p.tailLen {
return nil, ErrNotMatch
}
end -= p.tailLen
stack = append(stack, strings.Join(components[pos:end], "/"))
pos = end
case OpConcatN:
n := op.operand
l := len(stack) - n
stack = append(stack[:l], strings.Join(stack[l:], "/"))
case OpCapture:
n := len(stack) - 1
captured[op.operand] = stack[n]
stack = stack[:n]
}
}
if pos < l {
return nil, ErrNotMatch
}
bindings := make(map[string]string)
for i, val := range captured {
bindings[p.vars[i]] = val
}
return bindings, nil
}
// Verb returns the verb part of the Pattern.
func (p Pattern) Verb() string { return p.verb }
func (p Pattern) String() string {
var stack []string
for _, op := range p.ops {
switch op.code {
case OpNop:
continue
case OpPush:
stack = append(stack, "*")
case OpLitPush:
stack = append(stack, p.pool[op.operand])
case OpPushM:
stack = append(stack, "**")
case OpConcatN:
n := op.operand
l := len(stack) - n
stack = append(stack[:l], strings.Join(stack[l:], "/"))
case OpCapture:
n := len(stack) - 1
stack[n] = fmt.Sprintf("{%s=%s}", p.vars[op.operand], stack[n])
}
}
segs := strings.Join(stack, "/")
if p.verb != "" {
return fmt.Sprintf("/%s:%s", segs, p.verb)
}
return "/" + segs
}
// AssumeColonVerbOpt indicates whether a path suffix after a final
// colon may only be interpreted as a verb.
func AssumeColonVerbOpt(val bool) PatternOpt {
return PatternOpt(func(o *patternOptions) {
o.assumeColonVerb = val
})
}
+66
View File
@@ -0,0 +1,66 @@
package util
// download from
// https://raw.githubusercontent.com/grpc-ecosystem/grpc-gateway/master/protoc-gen-grpc-gateway/httprule/types.go
import (
"fmt"
"strings"
)
type template struct {
verb string
template string
segments []segment
}
type segment interface {
fmt.Stringer
compile() (ops []op)
}
type wildcard struct{}
type deepWildcard struct{}
type literal string
type variable struct {
path string
segments []segment
}
func (wildcard) String() string {
return "*"
}
func (deepWildcard) String() string {
return "**"
}
func (l literal) String() string {
return string(l)
}
func (v variable) String() string {
var segs []string
for _, s := range v.segments {
segs = append(segs, s.String())
}
return fmt.Sprintf("{%s=%s}", v.path, strings.Join(segs, "/"))
}
func (t template) String() string {
var segs []string
for _, s := range t.segments {
segs = append(segs, s.String())
}
str := strings.Join(segs, "/")
if t.verb != "" {
str = fmt.Sprintf("%s:%s", str, t.verb)
}
return "/" + str
}
+94
View File
@@ -0,0 +1,94 @@
package util
// download from
// https://raw.githubusercontent.com/grpc-ecosystem/grpc-gateway/master/protoc-gen-grpc-gateway/httprule/types_test.go
import (
"fmt"
"testing"
)
func TestTemplateStringer(t *testing.T) {
for _, spec := range []struct {
segs []segment
want string
}{
{
segs: []segment{
literal("v1"),
},
want: "/v1",
},
{
segs: []segment{
wildcard{},
},
want: "/*",
},
{
segs: []segment{
deepWildcard{},
},
want: "/**",
},
{
segs: []segment{
variable{
path: "name",
segments: []segment{
literal("a"),
},
},
},
want: "/{name=a}",
},
{
segs: []segment{
variable{
path: "name",
segments: []segment{
literal("a"),
wildcard{},
literal("b"),
},
},
},
want: "/{name=a/*/b}",
},
{
segs: []segment{
literal("v1"),
variable{
path: "name",
segments: []segment{
literal("a"),
wildcard{},
literal("b"),
},
},
literal("c"),
variable{
path: "field.nested",
segments: []segment{
wildcard{},
literal("d"),
},
},
wildcard{},
literal("e"),
deepWildcard{},
},
want: "/v1/{name=a/*/b}/c/{field.nested=*/d}/*/e/**",
},
} {
tmpl := template{segments: spec.segs}
if got, want := tmpl.String(), spec.want; got != want {
t.Errorf("%#v.String() = %q; want %q", tmpl, got, want)
}
tmpl.verb = "LOCK"
if got, want := tmpl.String(), fmt.Sprintf("%s:LOCK", spec.want); got != want {
t.Errorf("%#v.String() = %q; want %q", tmpl, got, want)
}
}
}
+8 -4
View File
@@ -2,22 +2,26 @@
package acme
import (
"crypto/tls"
"errors"
"net"
)
var (
// ErrProviderNotImplemented can be returned when attempting to
// instantiate an unimplemented provider
// instantiate an unimplemented provider.
ErrProviderNotImplemented = errors.New("Provider not implemented")
)
// Provider is a ACME provider interface
// 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
// The Let's Encrypt ACME endpoints.
const (
LetsEncryptStagingCA = "https://acme-staging-v02.api.letsencrypt.org/directory"
LetsEncryptProductionCA = "https://acme-v02.api.letsencrypt.org/directory"
+33 -9
View File
@@ -3,21 +3,45 @@
package autocert
import (
"crypto/tls"
"net"
"os"
"github.com/micro/go-micro/v2/api/server/acme"
"go-micro.dev/v4/api/server/acme"
log "go-micro.dev/v4/logger"
"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
// autoCertACME is the ACME provider from golang.org/x/crypto/acme/autocert.
type autocertProvider struct {
logger log.Logger
}
// New returns an autocert acme.Provider
func New() acme.Provider {
// 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) {
logger := log.LoggerOrDefault(a.logger)
// 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 {
logger.Logf(log.InfoLevel, "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 NewProvider() acme.Provider {
return &autocertProvider{}
}
+2 -2
View File
@@ -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
View 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)
}
-58
View File
@@ -1,58 +0,0 @@
// Package certmagic is the ACME provider from github.com/mholt/certmagic
package certmagic
import (
"log"
"math/rand"
"net"
"time"
"github.com/mholt/certmagic"
"github.com/micro/go-micro/v2/api/server/acme"
)
type certmagicProvider struct {
opts acme.Options
}
func (c *certmagicProvider) NewListener(ACMEHosts ...string) (net.Listener, error) {
certmagic.Default.CA = c.opts.CA
if c.opts.ChallengeProvider != nil {
// Enabling DNS Challenge disables the other challenges
certmagic.Default.DNSProvider = c.opts.ChallengeProvider
}
if c.opts.OnDemand {
certmagic.Default.OnDemand = new(certmagic.OnDemandConfig)
}
if c.opts.Cache != nil {
// already validated by new()
certmagic.Default.Storage = c.opts.Cache.(certmagic.Storage)
}
// If multiple instances of the provider are running, inject some
// randomness so they don't collide
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)
}
// New returns a certmagic provider
func New(options ...acme.Option) acme.Provider {
opts := acme.DefaultOptions()
for _, o := range options {
o(&opts)
}
if opts.Cache != nil {
if _, ok := opts.Cache.(certmagic.Storage); !ok {
log.Fatal("ACME: cache provided doesn't implement certmagic's Storage interface")
}
}
return &certmagicProvider{
opts: opts,
}
}
-224
View File
@@ -1,224 +0,0 @@
package certmagic
import (
"net/http"
"os"
"reflect"
"sort"
"testing"
"time"
"github.com/go-acme/lego/v3/providers/dns/cloudflare"
"github.com/mholt/certmagic"
"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()
if err != nil {
t.Fatal(err.Error())
}
l.Close()
c := cloudflare.NewDefaultConfig()
c.AuthEmail = ""
c.AuthKey = ""
c.AuthToken = "test"
c.ZoneToken = "test"
p, err := cloudflare.NewDNSProviderConfig(c)
if err != nil {
t.Fatal(err.Error())
}
l, err = New(acme.AcceptToS(true),
acme.CA(acme.LetsEncryptStagingCA),
acme.ChallengeProvider(p),
).NewListener()
if err != nil {
t.Fatal(err.Error())
}
l.Close()
}
func TestStorageImplementation(t *testing.T) {
apiToken, accountID := os.Getenv("CF_API_TOKEN"), os.Getenv("CF_ACCOUNT_ID")
kvID := os.Getenv("KV_NAMESPACE_ID")
if len(apiToken) == 0 || len(accountID) == 0 || len(kvID) == 0 {
t.Skip("No Cloudflare API keys available, skipping test")
}
var s certmagic.Storage
st := cfstore.NewStore(
cfstore.Token(apiToken),
cfstore.Account(accountID),
cfstore.Namespace(kvID),
)
s = &storage{
lock: memory.NewLock(),
store: st,
}
// Test Lock
if err := s.Lock("test"); err != nil {
t.Fatal(err)
}
// Test Unlock
if err := s.Unlock("test"); err != nil {
t.Fatal(err)
}
// Test data
testdata := []struct {
key string
value []byte
}{
{key: "/foo/a", value: []byte("lorem")},
{key: "/foo/b", value: []byte("ipsum")},
{key: "/foo/c", value: []byte("dolor")},
{key: "/foo/d", value: []byte("sit")},
{key: "/bar/a", value: []byte("amet")},
{key: "/bar/b", value: []byte("consectetur")},
{key: "/bar/c", value: []byte("adipiscing")},
{key: "/bar/d", value: []byte("elit")},
{key: "/foo/bar/a", value: []byte("sed")},
{key: "/foo/bar/b", value: []byte("do")},
{key: "/foo/bar/c", value: []byte("eiusmod")},
{key: "/foo/bar/d", value: []byte("tempor")},
{key: "/foo/bar/baz/a", value: []byte("incididunt")},
{key: "/foo/bar/baz/b", value: []byte("ut")},
{key: "/foo/bar/baz/c", value: []byte("labore")},
{key: "/foo/bar/baz/d", value: []byte("et")},
// a duplicate just in case there's any edge cases
{key: "/foo/a", value: []byte("lorem")},
}
// Test Store
for _, d := range testdata {
if err := s.Store(d.key, d.value); err != nil {
t.Fatal(err.Error())
}
}
// Test Load
for _, d := range testdata {
if value, err := s.Load(d.key); err != nil {
t.Fatal(err.Error())
} else {
if !reflect.DeepEqual(value, d.value) {
t.Fatalf("Load %s: expected %v, got %v", d.key, d.value, value)
}
}
}
// Test Exists
for _, d := range testdata {
if !s.Exists(d.key) {
t.Fatalf("%s should exist, but doesn't\n", d.key)
}
}
// Test List
if list, err := s.List("/", true); err != nil {
t.Fatal(err.Error())
} else {
var expected []string
for i, d := range testdata {
if i != len(testdata)-1 {
// Don't store the intentionally duplicated key
expected = append(expected, d.key)
}
}
sort.Strings(expected)
sort.Strings(list)
if !reflect.DeepEqual(expected, list) {
t.Fatalf("List: Expected %v, got %v\n", expected, list)
}
}
if list, err := s.List("/foo", false); err != nil {
t.Fatal(err.Error())
} else {
sort.Strings(list)
expected := []string{"/foo/a", "/foo/b", "/foo/bar", "/foo/c", "/foo/d"}
if !reflect.DeepEqual(expected, list) {
t.Fatalf("List: expected %s, got %s\n", expected, list)
}
}
// Test Stat
for _, d := range testdata {
info, err := s.Stat(d.key)
if err != nil {
t.Fatal(err.Error())
} else {
if info.Key != d.key {
t.Fatalf("Stat().Key: expected %s, got %s\n", d.key, info.Key)
}
if info.Size != int64(len(d.value)) {
t.Fatalf("Stat().Size: expected %d, got %d\n", len(d.value), info.Size)
}
if time.Since(info.Modified) > time.Minute {
t.Fatalf("Stat().Modified: expected time since last modified to be < 1 minute, got %v\n", time.Since(info.Modified))
}
}
}
// Test Delete
for _, d := range testdata {
if err := s.Delete(d.key); err != nil {
t.Fatal(err.Error())
}
}
// New interface doesn't return an error, so call it in case any log.Fatal
// happens
New(acme.Cache(s))
}
// Full test with a real zone, with against LE staging
func TestE2e(t *testing.T) {
apiToken, accountID := os.Getenv("CF_API_TOKEN"), os.Getenv("CF_ACCOUNT_ID")
kvID := os.Getenv("KV_NAMESPACE_ID")
if len(apiToken) == 0 || len(accountID) == 0 || len(kvID) == 0 {
t.Skip("No Cloudflare API keys available, skipping test")
}
testLock := memory.NewLock()
testStore := cfstore.NewStore(
cfstore.Token(apiToken),
cfstore.Account(accountID),
cfstore.Namespace(kvID),
)
testStorage := NewStorage(testLock, testStore)
conf := cloudflare.NewDefaultConfig()
conf.AuthToken = apiToken
conf.ZoneToken = apiToken
testChallengeProvider, err := cloudflare.NewDNSProviderConfig(conf)
if err != nil {
t.Fatal(err.Error())
}
testProvider := New(
acme.AcceptToS(true),
acme.Cache(testStorage),
acme.CA(acme.LetsEncryptStagingCA),
acme.ChallengeProvider(testChallengeProvider),
acme.OnDemand(false),
)
listener, err := testProvider.NewListener("*.micro.mu", "micro.mu")
if err != nil {
t.Fatal(err.Error())
}
go http.Serve(listener, http.NotFoundHandler())
time.Sleep(10 * time.Minute)
}
-147
View File
@@ -1,147 +0,0 @@
package certmagic
import (
"bytes"
"encoding/gob"
"errors"
"fmt"
"path"
"strings"
"time"
"github.com/mholt/certmagic"
"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
type File struct {
// last modified time
LastModified time.Time
// Contents
Contents []byte
}
// storage is an implementation of certmagic.Storage using micro's sync.Map and store.Store interfaces.
// As certmagic storage expects a filesystem (with stat() abilities) we have to implement
// the bare minimum of metadata.
type storage struct {
lock lock.Lock
store store.Store
}
func (s *storage) Lock(key string) error {
return s.lock.Acquire(key, lock.TTL(10*time.Minute))
}
func (s *storage) Unlock(key string) error {
return s.lock.Release(key)
}
func (s *storage) Store(key string, value []byte) error {
f := File{
LastModified: time.Now(),
Contents: value,
}
buf := &bytes.Buffer{}
e := gob.NewEncoder(buf)
if err := e.Encode(f); err != nil {
return err
}
r := &store.Record{
Key: key,
Value: buf.Bytes(),
}
return s.store.Write(r)
}
func (s *storage) Load(key string) ([]byte, error) {
if !s.Exists(key) {
return nil, certmagic.ErrNotExist(errors.New(key + " doesn't exist"))
}
records, err := s.store.Read(key)
if err != nil {
return nil, err
}
if len(records) != 1 {
return nil, fmt.Errorf("ACME Storage: multiple records matched key %s", key)
}
b := bytes.NewBuffer(records[0].Value)
d := gob.NewDecoder(b)
var f File
err = d.Decode(&f)
if err != nil {
return nil, err
}
return f.Contents, nil
}
func (s *storage) Delete(key string) error {
return s.store.Delete(key)
}
func (s *storage) Exists(key string) bool {
if _, err := s.store.Read(key); err != nil {
return false
}
return true
}
func (s *storage) List(prefix string, recursive bool) ([]string, error) {
records, err := s.store.List()
if err != nil {
return nil, err
}
//nolint:prealloc
var results []string
for _, r := range records {
if strings.HasPrefix(r.Key, prefix) {
results = append(results, r.Key)
}
}
if recursive {
return results, nil
}
keysMap := make(map[string]bool)
for _, key := range results {
dir := strings.Split(strings.TrimPrefix(key, prefix+"/"), "/")
keysMap[dir[0]] = true
}
results = make([]string, 0)
for k := range keysMap {
results = append(results, path.Join(prefix, k))
}
return results, nil
}
func (s *storage) Stat(key string) (certmagic.KeyInfo, error) {
records, err := s.store.Read(key)
if err != nil {
return certmagic.KeyInfo{}, err
}
if len(records) != 1 {
return certmagic.KeyInfo{}, fmt.Errorf("ACME Storage: multiple records matched key %s", key)
}
b := bytes.NewBuffer(records[0].Value)
d := gob.NewDecoder(b)
var f File
err = d.Decode(&f)
if err != nil {
return certmagic.KeyInfo{}, err
}
return certmagic.KeyInfo{
Key: key,
Modified: f.LastModified,
Size: int64(len(f.Contents)),
IsTerminal: false,
}, nil
}
// NewStorage returns a certmagic.Storage backed by a go-micro/lock and go-micro/store
func NewStorage(lock lock.Lock, store store.Store) certmagic.Storage {
return &storage{
lock: lock,
store: store,
}
}
+27 -14
View File
@@ -1,37 +1,43 @@
package acme
import "github.com/go-acme/lego/v3/challenge"
import (
"github.com/go-acme/lego/v4/challenge"
"go-micro.dev/v4/logger"
)
// Option (or Options) are passed to New() to configure providers
// Option (or Options) are passed to New() to configure providers.
type Option func(o *Options)
// Options represents various options you can present to ACME providers
// Options represents various options you can present to ACME providers.
type Options struct {
// AcceptTLS must be set to true to indicate that you have read your
// provider's terms of service.
AcceptToS bool
// CA is the CA to use
CA string
// ChallengeProvider is a go-acme/lego challenge provider. Set this if you
// want to use DNS Challenges. Otherwise, tls-alpn-01 will be used
ChallengeProvider challenge.Provider
// Issue certificates for domains on demand. Otherwise, certs will be
// retrieved / issued on start-up.
OnDemand bool
// Cache is a storage interface. Most ACME libraries have an cache, but
// there's no defined interface, so if you consume this option
// sanity check it before using.
Cache interface{}
// Logger is the underling logging framework
Logger logger.Logger
// CA is the CA to use
CA string
// AcceptTLS must be set to true to indicate that you have read your
// provider's terms of service.
AcceptToS bool
// Issue certificates for domains on demand. Otherwise, certs will be
// retrieved / issued on start-up.
OnDemand bool
}
// AcceptToS indicates whether you accept your CA's terms of service
// AcceptToS indicates whether you accept your CA's terms of service.
func AcceptToS(b bool) Option {
return func(o *Options) {
o.AcceptToS = b
}
}
// CA sets the CA of an acme.Options
// CA sets the CA of an acme.Options.
func CA(CA string) Option {
return func(o *Options) {
o.CA = CA
@@ -56,13 +62,20 @@ func OnDemand(b bool) Option {
// Cache provides a cache / storage interface to the underlying ACME library
// as there is no standard, this needs to be validated by the underlying
// implentation.
// implementation.
func Cache(c interface{}) Option {
return func(o *Options) {
o.Cache = c
}
}
// Logger sets the underline logger.
func Logger(l logger.Logger) Option {
return func(o *Options) {
o.Logger = l
}
}
// DefaultOptions uses the Let's Encrypt Production CA, with DNS Challenge disabled.
func DefaultOptions() Options {
return Options{
+57
View File
@@ -0,0 +1,57 @@
package cors
import (
"net/http"
)
type Config struct {
AllowOrigin string
AllowMethods string
AllowHeaders string
AllowCredentials bool
}
// CombinedCORSHandler wraps a server and provides CORS headers.
func CombinedCORSHandler(h http.Handler, config *Config) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if config != nil {
SetHeaders(w, r, config)
}
if r.Method == "OPTIONS" {
return
}
h.ServeHTTP(w, r)
})
}
// SetHeaders sets the CORS headers.
func SetHeaders(w http.ResponseWriter, _ *http.Request, config *Config) {
set := func(w http.ResponseWriter, k, v string) {
if v := w.Header().Get(k); len(v) > 0 {
return
}
w.Header().Set(k, v)
}
// For forward-compatible code, default values may not be provided in the future
if config.AllowCredentials {
set(w, "Access-Control-Allow-Credentials", "true")
} else {
set(w, "Access-Control-Allow-Credentials", "false")
}
if config.AllowOrigin == "" {
set(w, "Access-Control-Allow-Origin", "*")
} else {
set(w, "Access-Control-Allow-Origin", config.AllowOrigin)
}
if config.AllowMethods == "" {
set(w, "Access-Control-Allow-Methods", "POST, PATCH, GET, OPTIONS, PUT, DELETE")
} else {
set(w, "Access-Control-Allow-Methods", config.AllowMethods)
}
if config.AllowHeaders == "" {
set(w, "Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
} else {
set(w, "Access-Control-Allow-Headers", config.AllowHeaders)
}
}
+32 -11
View File
@@ -9,22 +9,26 @@ import (
"sync"
"github.com/gorilla/handlers"
"github.com/micro/go-micro/v2/api/server"
"github.com/micro/go-micro/v2/util/log"
"go-micro.dev/v4/api/server"
"go-micro.dev/v4/api/server/cors"
log "go-micro.dev/v4/logger"
)
type httpServer struct {
mux *http.ServeMux
opts server.Options
mtx sync.RWMutex
address string
mux *http.ServeMux
exit chan chan error
address string
mtx sync.RWMutex
}
func NewServer(address string) server.Server {
func NewServer(address string, opts ...server.Option) server.Server {
options := server.NewOptions(opts...)
return &httpServer{
opts: server.Options{},
opts: options,
mux: http.NewServeMux(),
address: address,
exit: make(chan chan error),
@@ -45,16 +49,32 @@ func (s *httpServer) Init(opts ...server.Option) error {
}
func (s *httpServer) Handle(path string, handler http.Handler) {
s.mux.Handle(path, handlers.CombinedLoggingHandler(os.Stdout, handler))
// TODO: move this stuff out to one place with ServeHTTP
// apply the wrappers, e.g. auth
for _, wrapper := range s.opts.Wrappers {
handler = wrapper(handler)
}
// wrap with cors
if s.opts.EnableCORS {
handler = cors.CombinedCORSHandler(handler, s.opts.CORSConfig)
}
// wrap with logger
handler = handlers.CombinedLoggingHandler(os.Stdout, handler)
s.mux.Handle(path, handler)
}
func (s *httpServer) Start() error {
logger := s.opts.Logger
var l net.Listener
var err 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 +85,7 @@ func (s *httpServer) Start() error {
return err
}
log.Logf("HTTP API Listening on %s", l.Addr().String())
logger.Logf(log.InfoLevel, "HTTP API Listening on %s", l.Addr().String())
s.mtx.Lock()
s.address = l.Addr().String()
@@ -74,7 +94,8 @@ func (s *httpServer) Start() error {
go func() {
if err := http.Serve(l, s.mux); err != nil {
// temporary fix
//log.Fatal(err)
// logger.Log(log.FatalLevel, err)
logger.Log(log.ErrorLevel, err)
}
}()
+76 -2
View File
@@ -2,9 +2,12 @@ package http
import (
"fmt"
"io/ioutil"
"io"
"net/http"
"testing"
"go-micro.dev/v4/api/server"
"go-micro.dev/v4/api/server/cors"
)
func TestHTTPServer(t *testing.T) {
@@ -26,7 +29,7 @@ func TestHTTPServer(t *testing.T) {
}
defer rsp.Body.Close()
b, err := ioutil.ReadAll(rsp.Body)
b, err := io.ReadAll(rsp.Body)
if err != nil {
t.Fatal(err)
}
@@ -39,3 +42,74 @@ func TestHTTPServer(t *testing.T) {
t.Fatal(err)
}
}
func TestCORSHTTPServer(t *testing.T) {
testResponse := "hello world"
testAllowOrigin := "*"
testAllowCredentials := true
testAllowMethods := "GET"
testAllowHeaders := "Accept, Content-Type, Content-Length"
s := NewServer("localhost:0",
server.EnableCORS(true),
server.CORSConfig(&cors.Config{
AllowCredentials: testAllowCredentials,
AllowOrigin: testAllowOrigin,
AllowMethods: testAllowMethods,
AllowHeaders: testAllowHeaders,
}),
)
s.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, testResponse)
}))
if err := s.Start(); err != nil {
t.Fatal(err)
}
rsp, err := http.Get(fmt.Sprintf("http://%s/", s.Address()))
if err != nil {
t.Fatal(err)
}
defer rsp.Body.Close()
b, err := io.ReadAll(rsp.Body)
if err != nil {
t.Fatal(err)
}
if string(b) != testResponse {
t.Fatalf("Unexpected response, got %s, expected %s", string(b), testResponse)
}
allowCredentials := rsp.Header.Get("Access-Control-Allow-Credentials")
getTestCredentialsStr := func() string {
if testAllowCredentials == true {
return "true"
} else {
return "false"
}
}
if getTestCredentialsStr() != allowCredentials {
t.Fatalf("Unexpected Access-Control-Allow-Credentials, got %s, expected %s", allowCredentials, getTestCredentialsStr())
}
allowOrigin := rsp.Header.Get("Access-Control-Allow-Origin")
if testAllowOrigin != allowOrigin {
t.Fatalf("Unexpected Access-Control-Allow-Origins, got %s, expected %s", allowOrigin, testAllowOrigin)
}
allowMethods := rsp.Header.Get("Access-Control-Allow-Methods")
if testAllowMethods != allowMethods {
t.Fatalf("Unexpected Access-Control-Allow-Methods, got %s, expected %s", allowMethods, testAllowMethods)
}
allowHeaders := rsp.Header.Get("Access-Control-Allow-Headers")
if testAllowHeaders != allowHeaders {
t.Fatalf("Unexpected Access-Control-Allow-Headers, got %s, expected %s", allowHeaders, testAllowHeaders)
}
if err := s.Stop(); err != nil {
t.Fatal(err)
}
}
+58 -4
View File
@@ -2,18 +2,59 @@ package server
import (
"crypto/tls"
"net/http"
"github.com/micro/go-micro/v2/api/server/acme"
"go-micro.dev/v4/api/resolver"
"go-micro.dev/v4/api/server/acme"
"go-micro.dev/v4/api/server/cors"
"go-micro.dev/v4/logger"
)
type Option func(o *Options)
type Options struct {
EnableACME bool
ACMEProvider acme.Provider
EnableTLS bool
ACMEHosts []string
Resolver resolver.Resolver
Logger logger.Logger
CORSConfig *cors.Config
TLSConfig *tls.Config
ACMEHosts []string
Wrappers []Wrapper
EnableACME bool
EnableCORS bool
EnableTLS bool
}
type Wrapper func(h http.Handler) http.Handler
func NewOptions(opts ...Option) Options {
options := Options{
Logger: logger.DefaultLogger,
}
for _, o := range opts {
o(&options)
}
return options
}
func WrapHandler(w Wrapper) Option {
return func(o *Options) {
o.Wrappers = append(o.Wrappers, w)
}
}
func EnableCORS(b bool) Option {
return func(o *Options) {
o.EnableCORS = b
}
}
func CORSConfig(c *cors.Config) Option {
return func(o *Options) {
o.CORSConfig = c
}
}
func EnableACME(b bool) Option {
@@ -45,3 +86,16 @@ func TLSConfig(t *tls.Config) Option {
o.TLSConfig = t
}
}
func Resolver(r resolver.Resolver) Option {
return func(o *Options) {
o.Resolver = r
}
}
// Logger sets the underline logging framework.
func Logger(l logger.Logger) Option {
return func(o *Options) {
o.Logger = l
}
}
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"net/http"
)
// Server serves api requests
// Server serves api requests.
type Server interface {
Address() string
Init(opts ...Option) error
+118 -21
View File
@@ -2,39 +2,136 @@
package auth
import (
"context"
"errors"
"time"
)
// Auth providers authentication and authorization
const (
// BearerScheme used for Authorization header.
BearerScheme = "Bearer "
// ScopePublic is the scope applied to a rule to allow access to the public.
ScopePublic = ""
// ScopeAccount is the scope applied to a rule to limit to users with any valid account.
ScopeAccount = "*"
)
var (
// ErrInvalidToken is when the token provided is not valid.
ErrInvalidToken = errors.New("invalid token provided")
// ErrForbidden is when a user does not have the necessary scope to access a resource.
ErrForbidden = errors.New("resource forbidden")
)
// Auth provides authentication and authorization.
type Auth interface {
// Generate a new auth token
Generate(string) (*Token, error)
// Revoke an authorization token
Revoke(*Token) error
// Init the auth
Init(opts ...Option)
// Options set for auth
Options() Options
// Generate a new account
Generate(id string, opts ...GenerateOption) (*Account, error)
// Inspect a token
Inspect(token string) (*Account, error)
// Token generated using refresh token or credentials
Token(opts ...TokenOption) (*Token, error)
// String returns the name of the implementation
String() string
}
// Rules manages access to resources.
type Rules interface {
// Verify an account has access to a resource using the rules
Verify(acc *Account, res *Resource, opts ...VerifyOption) error
// Grant access to a resource
Grant(*Token, *Service) error
// Verify a token can access a resource
Verify(*Token, *Service) error
Grant(rule *Rule) error
// Revoke access to a resource
Revoke(rule *Rule) error
// List returns all the rules used to verify requests
List(...ListOption) ([]*Rule, error)
}
// Service is some thing to provide access to
type Service struct {
// Name of the resource
Name string
// Endpoint is the specific endpoint
Endpoint string
// Account provided by an auth provider.
type Account struct {
// Any other associated metadata
Metadata map[string]string `json:"metadata"`
// ID of the account e.g. email
ID string `json:"id"`
// Type of the account, e.g. service
Type string `json:"type"`
// Issuer of the account
Issuer string `json:"issuer"`
// Secret for the account, e.g. the password
Secret string `json:"secret"`
// Scopes the account has access to
Scopes []string `json:"scopes"`
}
// Token providers by an auth provider
// Token can be short or long lived.
type Token struct {
// Unique token id
Id string `json: "id"`
// Time of token creation
Created time.Time `json:"created"`
// Time of token expiry
Expiry time.Time `json:"expiry"`
// Roles associated with the token
Roles []string `json:"roles"`
// Any other associated metadata
Metadata map[string]string `json:"metadata"`
// The token to be used for accessing resources
AccessToken string `json:"access_token"`
// RefreshToken to be used to generate a new token
RefreshToken string `json:"refresh_token"`
}
// Expired returns a boolean indicating if the token needs to be refreshed.
func (t *Token) Expired() bool {
return t.Expiry.Unix() < time.Now().Unix()
}
// Resource is an entity such as a user or.
type Resource struct {
// Name of the resource, e.g. go.micro.service.notes
Name string `json:"name"`
// Type of resource, e.g. service
Type string `json:"type"`
// Endpoint resource e.g NotesService.Create
Endpoint string `json:"endpoint"`
}
// Access defines the type of access a rule grants.
type Access int
const (
// AccessGranted to a resource.
AccessGranted Access = iota
// AccessDenied to a resource.
AccessDenied
)
// Rule is used to verify access to a resource.
type Rule struct {
// Resource the rule applies to
Resource *Resource
// ID of the rule, e.g. "public"
ID string
// Scope the rule requires, a blank scope indicates open to the public and * indicates the rule
// applies to any valid account
Scope string
// Access determines if the rule grants or denies access to the resource
Access Access
// Priority the rule should take when verifying a request, the higher the value the sooner the
// rule will be applied
Priority int32
}
type accountKey struct{}
// AccountFromContext gets the account from the context, which
// is set by the auth wrapper at the start of a call. If the account
// is not set, a nil account will be returned. The error is only returned
// when there was a problem retrieving an account.
func AccountFromContext(ctx context.Context) (*Account, bool) {
acc, ok := ctx.Value(accountKey{}).(*Account)
return acc, ok
}
// ContextWithAccount sets the account in the context.
func ContextWithAccount(ctx context.Context, account *Account) context.Context {
return context.WithValue(ctx, accountKey{}, account)
}
+91
View File
@@ -0,0 +1,91 @@
package auth
import (
"github.com/google/uuid"
)
var (
DefaultAuth = NewAuth()
)
func NewAuth(opts ...Option) Auth {
options := Options{}
for _, o := range opts {
o(&options)
}
return &noop{
opts: options,
}
}
func NewRules() Rules {
return new(noopRules)
}
type noop struct {
opts Options
}
type noopRules struct{}
// String returns the name of the implementation.
func (n *noop) String() string {
return "noop"
}
// Init the auth.
func (n *noop) Init(opts ...Option) {
for _, o := range opts {
o(&n.opts)
}
}
// Options set for auth.
func (n *noop) Options() Options {
return n.opts
}
// Generate a new account.
func (n *noop) Generate(id string, opts ...GenerateOption) (*Account, error) {
options := NewGenerateOptions(opts...)
return &Account{
ID: id,
Secret: options.Secret,
Metadata: options.Metadata,
Scopes: options.Scopes,
Issuer: n.Options().Namespace,
}, nil
}
// Grant access to a resource.
func (n *noopRules) Grant(rule *Rule) error {
return nil
}
// Revoke access to a resource.
func (n *noopRules) Revoke(rule *Rule) error {
return nil
}
// Rules used to verify requests
// Verify an account has access to a resource.
func (n *noopRules) Verify(acc *Account, res *Resource, opts ...VerifyOption) error {
return nil
}
func (n *noopRules) List(opts ...ListOption) ([]*Rule, error) {
return []*Rule{}, nil
}
// Inspect a token.
func (n *noop) Inspect(token string) (*Account, error) {
return &Account{ID: uuid.New().String(), Issuer: n.Options().Namespace}, nil
}
// Token generation using an account id and secret.
func (n *noop) Token(opts ...TokenOption) (*Token, error) {
return &Token{}, nil
}

Some files were not shown because too many files have changed in this diff Show More