Compare commits

...

96 Commits

Author SHA1 Message Date
3e1ffcb989 add all http request metadata
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-08-11 12:47:44 +03:00
c1e0ce26b5 add ability to register RPC endpoint
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-07-14 13:43:45 +03:00
26e34124e0 update all
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-07-06 19:12:46 +03:00
c1526f70ce dont display unneded error message
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-07-06 19:10:54 +03:00
28d23f388f fixup new codec detection
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-05-14 14:17:33 +03:00
d3d67eca97 allow to response with different content-type
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-05-13 15:46:47 +03:00
919bf1486f fixup
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-05-13 12:11:54 +03:00
88ef21ba9e fix broker disconnect
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-05-13 10:59:38 +03:00
Renovate Bot
254b01f75a Update golang.org/x/net commit hash to 4163338 2021-05-10 13:29:05 +00:00
Renovate Bot
325b8a43ef Update golang.org/x/net commit hash to 81045d8 2021-05-10 12:01:05 +00:00
Renovate Bot
d94860c32d Update golang.org/x/net commit hash to 16afe75 2021-05-08 09:19:14 +00:00
Renovate Bot
778095179d Update golang.org/x/net commit hash to 0714010 2021-05-05 23:20:59 +00:00
f71ae35f12 fix content-type override
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-05-05 13:32:12 +03:00
Renovate Bot
4d27c79081 Update golang.org/x/net commit hash to 0287a6f 2021-05-05 05:21:33 +00:00
Renovate Bot
1eebef8dbc Update golang.org/x/net commit hash to bbd867f 2021-05-04 16:38:19 +00:00
Renovate Bot
cd2c0b65e1 Update golang.org/x/net commit hash to 7fd8e65 2021-05-03 09:44:49 +00:00
Renovate Bot
97e0bf75bb Update golang.org/x/net commit hash to e590880 2021-05-02 05:04:21 +00:00
Renovate Bot
9f56d8b6b5 Update golang.org/x/net commit hash to f8dd838 2021-05-01 23:25:24 +00:00
Renovate Bot
21f608d728 Update golang.org/x/net commit hash to aec3718 2021-05-01 16:57:56 +00:00
ba283695dd fix rsp code for wrappers
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-05-01 01:24:09 +03:00
b18465083b fill metadata early
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-04-30 00:40:15 +03:00
Renovate Bot
11020aa6e5 Update golang.org/x/net commit hash to 89ef3d9 2021-04-28 16:43:11 +00:00
Renovate Bot
43c0eb4fda Update golang.org/x/net commit hash to 85d9c07 2021-04-28 01:42:52 +00:00
5ab606c2b5 update for latest micro
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-04-27 19:10:35 +03:00
6c661c9d72 lint (#57)
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-04-26 00:43:06 +03:00
a215521821 fieldalignment
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-04-25 12:09:09 +03:00
Renovate Bot
ec5af022b3 Update golang.org/x/net commit hash to 5f58ad6 2021-04-23 22:20:32 +00:00
Renovate Bot
bd88f6e485 Update golang.org/x/net commit hash to 4e50805 2021-04-22 02:47:31 +00:00
Renovate Bot
34a39be017 Update golang.org/x/net commit hash to 798c215 2021-04-20 23:49:53 +00:00
Renovate Bot
360703d8bb Update golang.org/x/net commit hash to d25e304 2021-04-20 11:33:44 +00:00
2660a0d94d update for latest micro
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-04-20 12:53:48 +03:00
Renovate Bot
6e9a693b51 Update module github.com/unistack-org/micro/v3 to v3.3.15 2021-04-19 17:06:46 +00:00
renovate[bot]
06d197e356 Update module github.com/unistack-org/micro/v3 to v3.3.14 (#49)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-04-19 02:12:57 +03:00
30609135a4 use DefaultContentType on application/x-www-form-urlencoded
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-04-18 15:50:41 +03:00
84167d359e extract application/x-www-form-urlencoded handling to codec
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-04-17 13:54:32 +03:00
145a0f4aa6 minor content-type fixes
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-04-16 17:14:27 +03:00
Renovate Bot
b2b4d6a5a3 Update golang.org/x/net commit hash to e915ea6 2021-04-16 01:28:59 +00:00
Renovate Bot
f17afa7950 Update golang.org/x/net commit hash to 0645797 2021-04-14 21:16:29 +00:00
bb763c71b5 add content type handlers
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-04-13 23:42:33 +03:00
622a79bd06 add path handler option
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-04-13 11:33:03 +03:00
Renovate Bot
0eb3c0b452 Update golang.org/x/net commit hash to afb366f 2021-04-10 12:19:24 +00:00
676634850e allow to set default content type with charset
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-04-10 12:41:55 +03:00
0d442683ee properly detect content-type
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-04-10 12:38:17 +03:00
Renovate Bot
c8587ec93a Update module github.com/unistack-org/micro/v3 to v3.3.13 2021-04-10 00:02:08 +00:00
7e35316cf2 rewrite x-www-form-urlencoded
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-04-10 01:24:34 +03:00
Renovate Bot
475452a781 Update golang.org/x/net commit hash to a5a99cb 2021-04-05 21:22:50 +00:00
Renovate Bot
dd0bb7c5d4 Update module github.com/unistack-org/micro/v3 to v3.3.11 2021-04-03 11:43:48 +00:00
Renovate Bot
b74f3762dd Update all deps 2021-04-01 00:46:07 +00:00
Renovate Bot
e30590c707 Update golang.org/x/net commit hash to cb1fcc7 2021-03-31 08:14:56 +00:00
Renovate Bot
132e95dec6 Update golang.org/x/net commit hash to e572328 2021-03-31 00:41:40 +00:00
48620e6297 handle x-form-urlencoded content-type
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-03-31 00:50:02 +03:00
Renovate Bot
e31185b6dc Update golang.org/x/net commit hash to c8897c2 2021-03-30 16:23:29 +00:00
Renovate Bot
151e45ca30 Update golang.org/x/net commit hash to 22f4162 2021-03-30 12:06:34 +00:00
Renovate Bot
93c4f219e9 Update all deps 2021-03-30 06:47:00 +00:00
Renovate Bot
396654b066 Update module github.com/unistack-org/micro/v3 to v3.3.8 2021-03-29 03:27:06 +00:00
Renovate Bot
a769031246 Update module github.com/unistack-org/micro/v3 to v3.3.7 2021-03-28 20:50:08 +00:00
Renovate Bot
99915c1633 Update golang.org/x/net commit hash to 61e0566 2021-03-27 01:57:17 +00:00
Renovate Bot
c7759d29b8 Update all deps 2021-03-26 17:42:44 +00:00
Renovate Bot
0f97e432a4 Update module github.com/unistack-org/micro/v3 to v3.3.2 2021-03-25 13:14:58 +00:00
Renovate Bot
713b4f96be Update all deps 2021-03-25 00:08:52 +00:00
360b15a3b6 remove Warn on missing rsp code
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-03-24 23:58:35 +03:00
Renovate Bot
4959b0040b Update golang.org/x/net commit hash to 2c4c8ec 2021-03-24 15:09:22 +00:00
e93c6dc1de cleanup
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-03-24 15:22:20 +03:00
Renovate Bot
9ad01954dc Update all deps 2021-03-23 17:40:45 +00:00
Renovate Bot
8483b85c94 Update module github.com/unistack-org/micro/v3 to v3.2.24 2021-03-21 17:16:53 +00:00
Renovate Bot
d1a8f76d77 Update module github.com/unistack-org/micro/v3 to v3.2.23 2021-03-16 19:22:28 +00:00
Renovate Bot
9d7f4bfa66 Update golang.org/x/net commit hash to d523dce 2021-03-16 13:48:28 +00:00
Renovate Bot
656dfd4d05 Update golang.org/x/net commit hash to 34ac3e1 2021-03-15 22:07:09 +00:00
Renovate Bot
70e14e6592 Update module github.com/unistack-org/micro/v3 to v3.2.22 2021-03-15 02:19:34 +00:00
39e6d9f586 fixes with ErrorHandler and passed *http.Server
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-03-09 23:54:46 +03:00
a46c9d395a fix for multiple server registration
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-03-09 14:20:08 +03:00
Renovate Bot
d3c5a503c6 Update module github.com/unistack-org/micro/v3 to v3.2.20 2021-03-06 23:25:58 +00:00
Renovate Bot
be224692a4 Update module github.com/unistack-org/micro/v3 to v3.2.18 2021-03-06 19:32:16 +00:00
Renovate Bot
0da73b62ae Update module github.com/unistack-org/micro/v3 to v3.2.17 2021-03-05 17:17:15 +00:00
Renovate Bot
a30c2972fd Update module github.com/unistack-org/micro/v3 to v3.2.16 2021-03-04 12:21:58 +00:00
f28de46379 dont panic on nil ErrorHandler
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-03-01 20:25:09 +03:00
af91220a09 fix metadata
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-03-01 20:25:09 +03:00
Renovate Bot
14bf4a9f30 Update module github.com/unistack-org/micro/v3 to v3.2.15 2021-03-01 13:06:52 +00:00
e88f524042 fix handler context metadata passing
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-03-01 13:02:35 +03:00
45670661d0 write all passed header in response
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-03-01 11:35:27 +03:00
Renovate Bot
f7ed037633 Update golang.org/x/net commit hash to e18ecbb 2021-02-26 21:33:25 +00:00
Renovate Bot
8f36e1753a Update golang.org/x/net commit hash to 39120d0 2021-02-26 12:26:48 +00:00
0a59653c70 allow to set any message as error
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-02-25 14:17:20 +03:00
Renovate Bot
cf9d05d4f7 Update golang.org/x/net commit hash to 3d97a24 2021-02-24 10:54:50 +00:00
Renovate Bot
6b6d4eb74b Update golang.org/x/net commit hash to 9060382 2021-02-22 21:50:10 +00:00
Renovate Bot
db28bbb977 Update golang.org/x/net commit hash to 5f55cee 2021-02-20 06:23:49 +00:00
Renovate Bot
6819026d7c Update module unistack-org/micro/v3 to v3.2.14 2021-02-18 18:42:53 +00:00
4ade934d26 update workflows
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-02-18 18:42:38 +03:00
Renovate Bot
d9adfebaf3 Update module unistack-org/micro/v3 to v3.2.11 2021-02-12 15:50:30 +00:00
Renovate Bot
0ff8939a0d Update module unistack-org/micro/v3 to v3.2.9 2021-02-12 12:39:59 +00:00
495e98c3c4 update renovate.json
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-02-12 12:36:58 +03:00
5adaa78c36 move renovate.json
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-02-10 13:16:28 +03:00
renovate[bot]
7b83fc7007 Update golangci/golangci-lint-action action to v2 (#9)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-10 09:23:53 +03:00
renovate[bot]
dcd50c6fa8 Update actions/setup-go action to v2 (#8)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-09 23:03:33 +03:00
renovate[bot]
9d028175f4 Update golang.org/x/net commit hash to 5f4716e (#7)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-09 23:02:00 +03:00
renovate[bot]
a5d7a69d25 Add renovate.json (#6)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-09 23:00:12 +03:00
14 changed files with 538 additions and 302 deletions

20
.github/renovate.json vendored Normal file
View File

@@ -0,0 +1,20 @@
{
"extends": [
"config:base"
],
"postUpdateOptions": ["gomodTidy"],
"packageRules": [
{
"matchUpdateTypes": ["minor", "patch", "pin", "digest"],
"automerge": true
},
{
"groupName": "all deps",
"separateMajorMinor": true,
"groupSlug": "all",
"packagePatterns": [
"*"
]
}
]
}

13
.github/stale.sh vendored
View File

@@ -1,13 +0,0 @@
#!/bin/bash -ex
export PATH=$PATH:$(pwd)/bin
export GO111MODULE=on
export GOBIN=$(pwd)/bin
#go get github.com/rvflash/goup@v0.4.1
#goup -v ./...
#go get github.com/psampaz/go-mod-outdated@v0.6.0
go list -u -m -mod=mod -json all | go-mod-outdated -update -direct -ci || true
#go list -u -m -json all | go-mod-outdated -update

View File

@@ -9,9 +9,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: setup
uses: actions/setup-go@v1
uses: actions/setup-go@v2
with:
go-version: 1.15
go-version: 1.16
- name: checkout
uses: actions/checkout@v2
- name: cache
@@ -33,11 +33,10 @@ jobs:
- name: checkout
uses: actions/checkout@v2
- name: lint
uses: golangci/golangci-lint-action@v1
continue-on-error: true
uses: golangci/golangci-lint-action@v2
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.30
version: v1.39
# Optional: working directory, useful for monorepos
# working-directory: somedir
# Optional: golangci-lint command line arguments.

View File

@@ -9,9 +9,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: setup
uses: actions/setup-go@v1
uses: actions/setup-go@v2
with:
go-version: 1.15
go-version: 1.16
- name: checkout
uses: actions/checkout@v2
- name: cache
@@ -33,11 +33,10 @@ jobs:
- name: checkout
uses: actions/checkout@v2
- name: lint
uses: golangci/golangci-lint-action@v1
continue-on-error: true
uses: golangci/golangci-lint-action@v2
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.30
version: v1.39
# Optional: working directory, useful for monorepos
# working-directory: somedir
# Optional: golangci-lint command line arguments.

44
.golangci.yml Normal file
View File

@@ -0,0 +1,44 @@
run:
concurrency: 4
deadline: 5m
issues-exit-code: 1
tests: true
linters-settings:
govet:
check-shadowing: true
enable:
- fieldalignment
linters:
enable:
- govet
- deadcode
- errcheck
- govet
- ineffassign
- staticcheck
- structcheck
- typecheck
- unused
- varcheck
- bodyclose
- gci
- goconst
- gocritic
- gosimple
- gofmt
- gofumpt
- goimports
- golint
- gosec
- makezero
- misspell
- nakedret
- nestif
- nilerr
- noctx
- prealloc
- unconvert
- unparam
disable-all: false

8
go.mod
View File

@@ -1,10 +1,8 @@
module github.com/unistack-org/micro-server-http/v3
go 1.13
go 1.16
require (
github.com/unistack-org/micro/v3 v3.2.8
golang.org/x/net v0.0.0-20201224014010-6772e930b67b
github.com/unistack-org/micro/v3 v3.4.7
golang.org/x/net v0.0.0-20210614182718-04defd469f4e
)
//replace github.com/unistack-org/micro/v3 => ../../micro

138
go.sum
View File

@@ -1,132 +1,20 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/ef-ds/deque v1.0.4/go.mod h1:gXDnTC3yqvBcHbq2lcExjtAcVrOnJCbMcZXmuj8Z4tg=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/uuid v1.1.5 h1:kxhtnfFVi+rYdOALN0B3k9UT86zVJKfBimRaciULW4I=
github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/unistack-org/micro/v3 v3.2.8 h1:M1qgOz+qgSf/coFeIqDKa7Xc+b3s7du1Yin+i10o3aw=
github.com/unistack-org/micro/v3 v3.2.8/go.mod h1:J8XxJj4Pqa3Ee0a4biRRtut7UwTlfBq8QRe+s4PKGS0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/silas/dag v0.0.0-20210121180416-41cf55125c34/go.mod h1:7RTUFBdIRC9nZ7/3RyRNH1bdqIShrDejd1YbLwgPS+I=
github.com/unistack-org/micro/v3 v3.4.7 h1:zmGFx2J6tIbmr4IGLcc+LNtbftQFZI42bfuNV5xNYM0=
github.com/unistack-org/micro/v3 v3.4.7/go.mod h1:LXmPfbJnJNvL0kQs8HfnkV3Wya2Wb+C7keVq++RCZnk=
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2MY=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@@ -7,8 +7,9 @@ import (
"net/http"
"reflect"
"strings"
"sync"
"github.com/unistack-org/micro/v3/codec"
"github.com/unistack-org/micro/v3/errors"
"github.com/unistack-org/micro/v3/logger"
"github.com/unistack-org/micro/v3/metadata"
"github.com/unistack-org/micro/v3/register"
@@ -20,33 +21,28 @@ import (
var (
DefaultErrorHandler = func(ctx context.Context, s server.Handler, w http.ResponseWriter, r *http.Request, err error, status int) {
w.WriteHeader(status)
w.Write([]byte(err.Error()))
if _, cerr := w.Write([]byte(err.Error())); cerr != nil {
logger.DefaultLogger.Errorf(ctx, "write failed: %v", cerr)
}
}
DefaultContentType = "application/json"
)
type patHandler struct {
pat rutil.Pattern
mtype *methodType
name string
rcvr reflect.Value
name string
pat rutil.Pattern
}
type httpHandler struct {
name string
opts server.HandlerOptions
sopts server.Options
eps []*register.Endpoint
hd interface{}
handlers map[string][]patHandler
errorHandler func(context.Context, server.Handler, http.ResponseWriter, *http.Request, error, int)
}
func (h *httpHandler) newCodec(ct string) (codec.Codec, error) {
if cf, ok := h.sopts.Codecs[ct]; ok {
return cf, nil
}
return nil, codec.ErrUnknownContentType
name string
eps []*register.Endpoint
sopts server.Options
sync.RWMutex
}
func (h *httpHandler) Name() string {
@@ -65,14 +61,12 @@ func (h *httpHandler) Options() server.HandlerOptions {
return h.opts
}
func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
defer r.Body.Close()
path := r.URL.Path
if !strings.HasPrefix(path, "/") {
h.errorHandler(ctx, h, w, r, fmt.Errorf("path must contains /"), http.StatusBadRequest)
func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
for exp, ph := range h.pathHandlers {
if exp.MatchString(r.URL.String()) {
ph(w, r)
return
}
}
ct := DefaultContentType
@@ -80,9 +74,43 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ct = htype
}
if idx := strings.Index(ct, ":"); idx > 0 {
if ph, ok := h.contentTypeHandlers[ct[:idx]]; ok {
ph(w, r)
return
}
}
ctx := context.WithValue(r.Context(), rspCodeKey{}, &rspCodeVal{})
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
md = metadata.New(len(r.Header))
}
for k, v := range r.Header {
md.Set(k, strings.Join(v, ", "))
}
md.Set("RemoteAddr", r.RemoteAddr)
md.Set("Method", r.Method)
md.Set("URL", r.URL.String())
md.Set("Proto", r.Proto)
md.Set("ContentLength", fmt.Sprintf("%d", r.ContentLength))
md.Set("TransferEncoding", strings.Join(r.TransferEncoding, ","))
md.Set("Host", r.Host)
md.Set("RequestURI", r.RequestURI)
ctx = metadata.NewIncomingContext(ctx, md)
defer r.Body.Close()
path := r.URL.Path
if !strings.HasPrefix(path, "/") {
h.errorHandler(ctx, nil, w, r, fmt.Errorf("path must contains /"), http.StatusBadRequest)
return
}
cf, err := h.newCodec(ct)
if err != nil {
h.errorHandler(ctx, h, w, r, err, http.StatusBadRequest)
h.errorHandler(ctx, nil, w, r, err, http.StatusBadRequest)
return
}
components := strings.Split(path[1:], "/")
@@ -90,7 +118,7 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var verb string
idx := strings.LastIndex(components[l-1], ":")
if idx == 0 {
h.errorHandler(ctx, h, w, r, fmt.Errorf("not found"), http.StatusNotFound)
h.errorHandler(ctx, nil, w, r, fmt.Errorf("not found"), http.StatusNotFound)
return
}
if idx > 0 {
@@ -99,38 +127,38 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
matches := make(map[string]interface{})
var match bool
var hldr patHandler
for _, hldr = range h.handlers[r.Method] {
mp, err := hldr.pat.Match(components, verb)
if err == nil {
var handler *httpHandler
for _, hpat := range h.handlers {
handlertmp := hpat.(*httpHandler)
for _, hldrtmp := range handlertmp.handlers[r.Method] {
mp, merr := hldrtmp.pat.Match(components, verb)
if merr == nil {
match = true
for k, v := range mp {
matches[k] = v
}
hldr = hldrtmp
handler = handlertmp
break
}
}
}
if !match {
h.errorHandler(ctx, h, w, r, fmt.Errorf("not matching route found"), http.StatusNotFound)
h.errorHandler(ctx, nil, w, r, fmt.Errorf("not matching route found"), http.StatusNotFound)
return
}
md, ok := metadata.FromContext(ctx)
if !ok {
md = metadata.New(0)
}
for k, v := range r.Header {
md.Set(k, strings.Join(v, ", "))
}
// get fields from url values
if len(r.URL.RawQuery) > 0 {
umd, err := rflutil.URLMap(r.URL.RawQuery)
if err != nil {
h.errorHandler(ctx, h, w, r, err, http.StatusBadRequest)
umd, cerr := rflutil.URLMap(r.URL.RawQuery)
if cerr != nil {
h.errorHandler(ctx, handler, w, r, cerr, http.StatusBadRequest)
return
}
for k, v := range umd {
matches[k] = v
@@ -160,66 +188,110 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var returnValues []reflect.Value
if err = cf.ReadBody(r.Body, argv.Interface()); err != nil && err != io.EOF {
h.errorHandler(ctx, h, w, r, err, http.StatusInternalServerError)
h.errorHandler(ctx, handler, w, r, err, http.StatusInternalServerError)
return
}
matches = rflutil.FlattenMap(matches)
if err = rflutil.MergeMap(argv.Interface(), matches); err != nil {
h.errorHandler(ctx, h, w, r, err, http.StatusBadRequest)
if err = rflutil.Merge(argv.Interface(), matches, rflutil.SliceAppend(true), rflutil.Tags([]string{"protobuf", "json"})); err != nil {
h.errorHandler(ctx, handler, w, r, err, http.StatusBadRequest)
return
}
b, err := cf.Marshal(argv.Interface())
if err != nil {
h.errorHandler(ctx, h, w, r, err, http.StatusBadRequest)
h.errorHandler(ctx, handler, w, r, err, http.StatusBadRequest)
return
}
hr := &rpcRequest{
codec: cf,
service: h.sopts.Name,
service: handler.sopts.Name,
contentType: ct,
method: fmt.Sprintf("%s.%s", hldr.name, hldr.mtype.method.Name),
body: b,
payload: argv.Interface(),
header: md,
}
var scode int
// define the handler func
fn := func(ctx context.Context, req server.Request, rsp interface{}) (err error) {
ctx = context.WithValue(ctx, rspCodeKey{}, &rspCodeVal{})
ctx = metadata.NewContext(ctx, md)
returnValues = function.Call([]reflect.Value{hldr.rcvr, hldr.mtype.prepareContext(ctx), reflect.ValueOf(argv.Interface()), reflect.ValueOf(rsp)})
fn := func(fctx context.Context, req server.Request, rsp interface{}) (err error) {
returnValues = function.Call([]reflect.Value{hldr.rcvr, hldr.mtype.prepareContext(fctx), reflect.ValueOf(argv.Interface()), reflect.ValueOf(rsp)})
scode = GetRspCode(ctx)
// The return value for the method is an error.
if rerr := returnValues[0].Interface(); rerr != nil {
err = rerr.(error)
}
md, ok := metadata.FromOutgoingContext(ctx)
if !ok {
md = metadata.New(0)
}
if nmd, ok := metadata.FromOutgoingContext(fctx); ok {
for k, v := range nmd {
md.Set(k, v)
}
}
metadata.SetOutgoingContext(ctx, md)
return err
}
// wrap the handler func
for i := len(h.sopts.HdlrWrappers); i > 0; i-- {
fn = h.sopts.HdlrWrappers[i-1](fn)
for i := len(handler.sopts.HdlrWrappers); i > 0; i-- {
fn = handler.sopts.HdlrWrappers[i-1](fn)
}
if appErr := fn(ctx, hr, replyv.Interface()); appErr != nil {
if ct == "application/x-www-form-urlencoded" {
cf, err = h.newCodec(DefaultContentType)
if err != nil {
h.errorHandler(ctx, handler, w, r, err, http.StatusInternalServerError)
return
}
ct = DefaultContentType
}
scode := int(200)
appErr := fn(ctx, hr, replyv.Interface())
w.Header().Set("Content-Type", ct)
if md, ok := metadata.FromOutgoingContext(ctx); ok {
for k, v := range md {
w.Header().Set(k, v)
}
}
if nct := w.Header().Get("Content-Type"); nct != ct {
if cf, err = h.newCodec(nct); err != nil {
h.errorHandler(ctx, nil, w, r, err, http.StatusBadRequest)
return
}
}
if appErr != nil {
switch verr := appErr.(type) {
case *errors.Error:
scode = int(verr.Code)
b, err = cf.Marshal(verr)
case *Error:
b, err = cf.Marshal(verr.err)
default:
b, err = cf.Marshal(appErr)
}
} else {
b, err = cf.Marshal(replyv.Interface())
}
if err != nil && h.sopts.Logger.V(logger.ErrorLevel) {
h.sopts.Logger.Errorf(h.sopts.Context, "XXXXX: %v", err)
if err != nil && handler.sopts.Logger.V(logger.ErrorLevel) {
handler.sopts.Logger.Errorf(handler.sopts.Context, "handler err: %v", err)
return
}
w.Header().Set("content-Type", ct)
if scode != 0 {
if nscode := GetRspCode(ctx); nscode != 0 {
scode = nscode
}
w.WriteHeader(scode)
} else {
h.sopts.Logger.Warn(h.sopts.Context, "response code not set in handler via SetRspCode(ctx, http.StatusXXX)")
if _, cerr := w.Write(b); cerr != nil {
logger.DefaultLogger.Errorf(ctx, "write failed: %v", cerr)
}
w.Write(b)
}

225
http.go
View File

@@ -2,12 +2,13 @@
package http
import (
"context"
"crypto/tls"
"errors"
"fmt"
"net"
"net/http"
"reflect"
"regexp"
"sort"
"strings"
"sync"
@@ -23,19 +24,29 @@ import (
)
type httpServer struct {
sync.RWMutex
opts server.Options
hd server.Handler
rsvc *register.Service
handlers map[string]server.Handler
exit chan chan error
subscribers map[*httpSubscriber][]broker.Subscriber
// used for first registration
errorHandler func(context.Context, server.Handler, http.ResponseWriter, *http.Request, error, int)
pathHandlers map[*regexp.Regexp]http.HandlerFunc
contentTypeHandlers map[string]http.HandlerFunc
opts server.Options
registerRPC bool
sync.RWMutex
registered bool
// register service instance
rsvc *register.Service
init bool
}
func (h *httpServer) newCodec(ct string) (codec.Codec, error) {
if cf, ok := h.opts.Codecs[ct]; ok {
if idx := strings.IndexRune(ct, ';'); idx >= 0 {
ct = ct[:idx]
}
h.RLock()
cf, ok := h.opts.Codecs[ct]
h.RUnlock()
if ok {
return cf, nil
}
return nil, codec.ErrUnknownContentType
@@ -49,34 +60,123 @@ func (h *httpServer) Options() server.Options {
}
func (h *httpServer) Init(opts ...server.Option) error {
if len(opts) == 0 && h.init {
return nil
}
h.Lock()
for _, o := range opts {
o(&h.opts)
}
if fn, ok := h.opts.Context.Value(errorHandlerKey{}).(func(ctx context.Context, s server.Handler, w http.ResponseWriter, r *http.Request, err error, status int)); ok && fn != nil {
h.errorHandler = fn
}
if h.handlers == nil {
h.handlers = make(map[string]server.Handler)
}
if h.pathHandlers == nil {
h.pathHandlers = make(map[*regexp.Regexp]http.HandlerFunc)
}
if h.contentTypeHandlers == nil {
h.contentTypeHandlers = make(map[string]http.HandlerFunc)
}
if v, ok := h.opts.Context.Value(registerRPCHandlerKey{}).(bool); ok {
h.registerRPC = v
}
if phs, ok := h.opts.Context.Value(pathHandlerKey{}).(*pathHandlerVal); ok && phs.h != nil {
for pp, ph := range phs.h {
exp, err := regexp.Compile(pp)
if err != nil {
h.Unlock()
return err
}
h.pathHandlers[exp] = ph
}
}
if phs, ok := h.opts.Context.Value(contentTypeHandlerKey{}).(*contentTypeHandlerVal); ok && phs.h != nil {
for pp, ph := range phs.h {
h.contentTypeHandlers[pp] = ph
}
}
h.Unlock()
h.RLock()
if err := h.opts.Register.Init(); err != nil {
h.RUnlock()
return err
}
if err := h.opts.Broker.Init(); err != nil {
h.RUnlock()
return err
}
if err := h.opts.Tracer.Init(); err != nil {
h.RUnlock()
return err
}
if err := h.opts.Auth.Init(); err != nil {
h.RUnlock()
return err
}
if err := h.opts.Logger.Init(); err != nil {
h.RUnlock()
return err
}
if err := h.opts.Meter.Init(); err != nil {
h.RUnlock()
return err
}
if err := h.opts.Transport.Init(); err != nil {
h.RUnlock()
return err
}
h.RUnlock()
h.Lock()
h.init = true
h.Unlock()
return nil
}
func (h *httpServer) Handle(handler server.Handler) error {
hdlr, ok := handler.(*httpHandler)
if !ok {
h.Lock()
h.hd = handler
h.Unlock()
return nil
}
if _, ok := hdlr.hd.(http.Handler); ok {
h.Lock()
h.hd = handler
h.Unlock()
return nil
}
h.Lock()
if h.handlers == nil {
h.handlers = make(map[string]server.Handler)
}
h.handlers[handler.Name()] = handler
h.Unlock()
return nil
}
func (h *httpServer) NewHandler(handler interface{}, opts ...server.HandlerOption) server.Handler {
options := server.NewHandlerOptions(opts...)
var eps []*register.Endpoint
if !options.Internal {
eps := make([]*register.Endpoint, 0, len(options.Metadata))
for name, metadata := range options.Metadata {
eps = append(eps, &register.Endpoint{
Name: name,
Metadata: metadata,
})
}
}
hdlr := &httpHandler{
eps: eps,
@@ -146,6 +246,24 @@ func (h *httpServer) NewHandler(handler interface{}, opts ...server.HandlerOptio
pth := patHandler{pat: pat, mtype: mtype, name: name, rcvr: rcvr}
hdlr.name = name
hdlr.handlers[md["Method"]] = append(hdlr.handlers[md["Method"]], pth)
if !h.registerRPC {
continue
}
cmp, err = rutil.Parse("/" + hn)
if err != nil && h.opts.Logger.V(logger.ErrorLevel) {
h.opts.Logger.Errorf(h.opts.Context, "parsing path pattern err: %v", err)
continue
}
tpl = cmp.Compile()
pat, err = rutil.NewPattern(tpl.Version, tpl.OpCodes, tpl.Pool, tpl.Verb)
if err != nil && h.opts.Logger.V(logger.ErrorLevel) {
h.opts.Logger.Errorf(h.opts.Context, "creating new pattern err: %v", err)
continue
}
pth = patHandler{pat: pat, mtype: mtype, name: name, rcvr: rcvr}
hdlr.handlers[http.MethodPost] = append(hdlr.handlers[http.MethodPost], pth)
}
return hdlr
@@ -168,19 +286,24 @@ func (h *httpServer) Subscribe(sb server.Subscriber) error {
return err
}
h.Lock()
defer h.Unlock()
h.RLock()
_, ok = h.subscribers[sub]
h.RUnlock()
if ok {
return fmt.Errorf("subscriber %v already exists", h)
}
h.Lock()
h.subscribers[sub] = nil
h.Unlock()
return nil
}
func (h *httpServer) Register() error {
var eps []*register.Endpoint
h.RLock()
eps := h.hd.Endpoints()
for _, hdlr := range h.handlers {
eps = append(eps, hdlr.Endpoints()...)
}
rsvc := h.rsvc
config := h.opts
h.RUnlock()
@@ -201,13 +324,11 @@ func (h *httpServer) Register() error {
service.Endpoints = eps
h.Lock()
var subscriberList []*httpSubscriber
subscriberList := make([]*httpSubscriber, 0, len(h.subscribers))
for e := range h.subscribers {
// Only advertise non internal subscribers
if !e.Options().Internal {
subscriberList = append(subscriberList, e)
}
}
sort.Slice(subscriberList, func(i, j int) bool {
return subscriberList[i].topic > subscriberList[j].topic
})
@@ -223,7 +344,7 @@ func (h *httpServer) Register() error {
if !registered {
if config.Logger.V(logger.InfoLevel) {
config.Logger.Infof(config.Context, "Register [%s] Registering node: %s", config.Register.String(), service.Nodes[0].Id)
config.Logger.Infof(config.Context, "Register [%s] Registering node: %s", config.Register.String(), service.Nodes[0].ID)
}
}
@@ -238,8 +359,6 @@ func (h *httpServer) Register() error {
}
h.Lock()
defer h.Unlock()
for sb := range h.subscribers {
handler := h.createSubHandler(sb, config)
var opts []broker.SubscribeOption
@@ -256,6 +375,7 @@ func (h *httpServer) Register() error {
sub, err := config.Broker.Subscribe(subCtx, sb.Topic(), handler, opts...)
if err != nil {
h.Unlock()
return err
}
h.subscribers[sb] = []broker.Subscriber{sub}
@@ -263,6 +383,7 @@ func (h *httpServer) Register() error {
h.registered = true
h.rsvc = service
h.Unlock()
return nil
}
@@ -278,7 +399,7 @@ func (h *httpServer) Deregister() error {
}
if config.Logger.V(logger.InfoLevel) {
config.Logger.Infof(config.Context, "Deregistering node: %s", service.Nodes[0].Id)
config.Logger.Infof(config.Context, "Deregistering node: %s", service.Nodes[0].ID)
}
if err := server.DefaultDeregisterFunc(service, config); err != nil {
@@ -304,6 +425,7 @@ func (h *httpServer) Deregister() error {
for _, sub := range subs {
config.Logger.Infof(config.Context, "Unsubscribing from topic: %s", sub.Topic())
if err := sub.Unsubscribe(subCtx); err != nil {
h.Unlock()
config.Logger.Errorf(config.Context, "failed to unsubscribe topic: %s, error: %v", sb.Topic(), err)
return err
}
@@ -317,7 +439,6 @@ func (h *httpServer) Deregister() error {
func (h *httpServer) Start() error {
h.RLock()
config := h.opts
hd := h.hd
h.RUnlock()
// micro: config.Transport.Listen(config.Address)
@@ -352,13 +473,33 @@ func (h *httpServer) Start() error {
h.opts.Address = ts.Addr().String()
h.Unlock()
handler, ok := hd.Handler().(http.Handler)
if !ok {
handler, ok = hd.(http.Handler)
var handler http.Handler
var srvFunc func(net.Listener) error
// nolint: nestif
if h.opts.Context != nil {
if hs, ok := h.opts.Context.Value(serverKey{}).(*http.Server); ok && hs != nil {
if hs.Handler == nil && h.hd != nil {
if hdlr, ok := h.hd.Handler().(http.Handler); ok {
hs.Handler = hdlr
handler = hs.Handler
}
} else {
handler = hs.Handler
}
}
}
if !ok {
return errors.New("Server required http.Handler")
if handler == nil && h.hd == nil {
handler = h
} else if handler == nil && h.hd != nil {
if hdlr, ok := h.hd.Handler().(http.Handler); ok {
handler = hdlr
}
}
if handler == nil {
return fmt.Errorf("cant process with nil handler")
}
if err := config.Broker.Connect(h.opts.Context); err != nil {
@@ -367,7 +508,7 @@ func (h *httpServer) Start() error {
if err := config.RegisterCheck(h.opts.Context); err != nil {
if config.Logger.V(logger.ErrorLevel) {
config.Logger.Errorf(config.Context, "Server %s-%s register check error: %s", config.Name, config.Id, err)
config.Logger.Errorf(config.Context, "Server %s-%s register check error: %s", config.Name, config.ID, err)
}
} else {
if err = h.Register(); err != nil {
@@ -376,7 +517,6 @@ func (h *httpServer) Start() error {
}
fn := handler
var srvFunc func(net.Listener) error
if h.opts.Context != nil {
if mwf, ok := h.opts.Context.Value(middlewareKey{}).([]func(http.Handler) http.Handler); ok && len(mwf) > 0 {
@@ -392,9 +532,17 @@ func (h *httpServer) Start() error {
}
if srvFunc != nil {
go srvFunc(ts)
go func() {
if cerr := srvFunc(ts); cerr != nil {
h.opts.Logger.Error(h.opts.Context, cerr)
}
}()
} else {
go http.Serve(ts, fn)
go func() {
if cerr := http.Serve(ts, fn); cerr != nil && !strings.Contains(cerr.Error(), "use of closed network connection") {
h.opts.Logger.Error(h.opts.Context, cerr)
}
}()
}
go func() {
@@ -418,25 +566,26 @@ func (h *httpServer) Start() error {
registered := h.registered
h.RUnlock()
rerr := config.RegisterCheck(h.opts.Context)
// nolint: nestif
if rerr != nil && registered {
if config.Logger.V(logger.ErrorLevel) {
config.Logger.Errorf(config.Context, "Server %s-%s register check error: %s, deregister it", config.Name, config.Id, rerr)
config.Logger.Errorf(config.Context, "Server %s-%s register check error: %s, deregister it", config.Name, config.ID, rerr)
}
// deregister self in case of error
if err := h.Deregister(); err != nil {
if config.Logger.V(logger.ErrorLevel) {
config.Logger.Errorf(config.Context, "Server %s-%s deregister error: %s", config.Name, config.Id, err)
config.Logger.Errorf(config.Context, "Server %s-%s deregister error: %s", config.Name, config.ID, err)
}
}
} else if rerr != nil && !registered {
if config.Logger.V(logger.ErrorLevel) {
config.Logger.Errorf(config.Context, "Server %s-%s register check error: %s", config.Name, config.Id, rerr)
config.Logger.Errorf(config.Context, "Server %s-%s register check error: %s", config.Name, config.ID, rerr)
}
continue
}
if err := h.Register(); err != nil {
if config.Logger.V(logger.ErrorLevel) {
config.Logger.Errorf(config.Context, "Server %s-%s register error: %s", config.Name, config.Id, err)
config.Logger.Errorf(config.Context, "Server %s-%s register error: %s", config.Name, config.ID, err)
}
}
@@ -449,8 +598,6 @@ func (h *httpServer) Start() error {
}
}
ch <- ts.Close()
// deregister
if err := h.Deregister(); err != nil {
config.Logger.Errorf(config.Context, "Server deregister error: %s", err)
@@ -459,6 +606,8 @@ func (h *httpServer) Start() error {
if err := config.Broker.Disconnect(config.Context); err != nil {
config.Logger.Errorf(config.Context, "Broker disconnect error: %s", err)
}
ch <- ts.Close()
}()
return nil
@@ -484,5 +633,7 @@ func NewServer(opts ...server.Option) server.Server {
opts: options,
exit: make(chan chan error),
subscribers: make(map[*httpSubscriber][]broker.Subscriber),
errorHandler: DefaultErrorHandler,
pathHandlers: make(map[*regexp.Regexp]http.HandlerFunc),
}
}

View File

@@ -6,12 +6,12 @@ import (
)
type httpMessage struct {
topic string
payload interface{}
contentType string
header metadata.Metadata
body []byte
codec codec.Codec
header metadata.Metadata
topic string
contentType string
body []byte
}
func (r *httpMessage) Topic() string {

View File

@@ -2,15 +2,33 @@ package http
import (
"context"
"fmt"
"net/http"
"github.com/unistack-org/micro/v3/server"
)
type rspCodeKey struct{}
type rspCodeVal struct {
// SetError pass error to caller
func SetError(err interface{}) error {
return &Error{err: err}
}
// Error struct holds error
type Error struct {
err interface{}
}
// Error func for error interface
func (err *Error) Error() string {
return fmt.Sprintf("%v", err.err)
}
type (
rspCodeKey struct{}
rspCodeVal struct {
code int
}
)
// SetRspCode saves response code in context, must be used by handler to specify http code
func SetRspCode(ctx context.Context, code int) {
@@ -30,12 +48,72 @@ func GetRspCode(ctx context.Context) int {
type middlewareKey struct{}
// Middleware passes http middlewares
func Middleware(mw ...func(http.Handler) http.Handler) server.Option {
return server.SetOption(middlewareKey{}, mw)
}
type serverKey struct{}
// Server provide ability to pass *http.Server
func Server(hs *http.Server) server.Option {
return server.SetOption(serverKey{}, hs)
}
type errorHandlerKey struct{}
// ErrorHandler specifies handler for errors
func ErrorHandler(fn func(ctx context.Context, s server.Handler, w http.ResponseWriter, r *http.Request, err error, status int)) server.Option {
return server.SetOption(errorHandlerKey{}, fn)
}
type (
pathHandlerKey struct{}
pathHandlerVal struct {
h map[string]http.HandlerFunc
}
)
// PathHandler specifies http handler for path regexp
func PathHandler(path string, h http.HandlerFunc) server.Option {
return func(o *server.Options) {
if o.Context == nil {
o.Context = context.Background()
}
v, ok := o.Context.Value(pathHandlerKey{}).(*pathHandlerVal)
if !ok {
v = &pathHandlerVal{h: make(map[string]http.HandlerFunc)}
}
v.h[path] = h
o.Context = context.WithValue(o.Context, pathHandlerKey{}, v)
}
}
type (
contentTypeHandlerKey struct{}
contentTypeHandlerVal struct {
h map[string]http.HandlerFunc
}
)
// ContentTypeHandler specifies http handler for Content-Type
func ContentTypeHandler(ct string, h http.HandlerFunc) server.Option {
return func(o *server.Options) {
if o.Context == nil {
o.Context = context.Background()
}
v, ok := o.Context.Value(contentTypeHandlerKey{}).(*contentTypeHandlerVal)
if !ok {
v = &contentTypeHandlerVal{h: make(map[string]http.HandlerFunc)}
}
v.h[ct] = h
o.Context = context.WithValue(o.Context, contentTypeHandlerKey{}, v)
}
}
type registerRPCHandlerKey struct{}
// RegisterRPCHandler registers compatibility endpoints with /ServiceName.ServiceEndpoint method POST
func RegisterRPCHandler(b bool) server.Option {
return server.SetOption(registerRPCHandlerKey{}, b)
}

View File

@@ -5,29 +5,34 @@ import (
"github.com/unistack-org/micro/v3/codec"
"github.com/unistack-org/micro/v3/metadata"
"github.com/unistack-org/micro/v3/server"
)
var (
_ server.Request = &rpcRequest{}
_ server.Message = &rpcMessage{}
)
type rpcRequest struct {
rw io.ReadWriter
service string
method string
endpoint string
target string
contentType string
payload interface{}
codec codec.Codec
header metadata.Metadata
method string
endpoint string
contentType string
service string
body []byte
stream bool
payload interface{}
}
type rpcMessage struct {
payload interface{}
codec codec.Codec
header metadata.Metadata
topic string
contentType string
payload interface{}
header metadata.Metadata
body []byte
codec codec.Codec
}
func (r *rpcRequest) ContentType() string {
@@ -43,7 +48,7 @@ func (r *rpcRequest) Method() string {
}
func (r *rpcRequest) Endpoint() string {
return r.method
return r.endpoint
}
func (r *rpcRequest) Codec() codec.Codec {

View File

@@ -11,10 +11,10 @@ import (
)
type methodType struct {
method reflect.Method
ArgType reflect.Type
ReplyType reflect.Type
ContextType reflect.Type
method reflect.Method
stream bool
}
@@ -62,15 +62,14 @@ func prepareEndpoint(method reflect.Method) (*methodType, error) {
return nil, fmt.Errorf("method %v of %v has wrong number of ins: %v", mname, mtype, mtype.NumIn())
}
if stream {
switch stream {
case true:
// check stream type
streamType := reflect.TypeOf((*server.Stream)(nil)).Elem()
if !argType.Implements(streamType) {
return nil, fmt.Errorf("%v argument does not implement Streamer interface: %v", mname, argType)
}
} else {
// if not stream check the replyType
default:
// First arg need not be a pointer.
if !isExportedOrBuiltinType(argType) {
return nil, fmt.Errorf("%v argument type not exported: %v", mname, argType)

View File

@@ -14,16 +14,12 @@ import (
"github.com/unistack-org/micro/v3/server"
)
const (
subSig = "func(context.Context, interface{}) error"
)
var typeOfError = reflect.TypeOf((*error)(nil)).Elem()
type handler struct {
method reflect.Value
reqType reflect.Type
ctxType reflect.Type
method reflect.Value
}
type httpSubscriber struct {
@@ -116,7 +112,7 @@ func (s *httpServer) createSubHandler(sb *httpSubscriber, opts server.Options) b
hdr := metadata.Copy(msg.Header)
delete(hdr, "Content-Type")
ctx := metadata.NewContext(context.Background(), hdr)
ctx := metadata.NewIncomingContext(context.Background(), hdr)
results := make(chan error, len(sb.handlers))