forked from mystiq/dex
Merge pull request #728 from ericchiang/document-managing-dependencies
Document managing dependencies
This commit is contained in:
commit
9e6d8689c3
1133 changed files with 62 additions and 249966 deletions
36
Documentation/dev-dependencies.md
Normal file
36
Documentation/dev-dependencies.md
Normal file
|
@ -0,0 +1,36 @@
|
|||
# Managing dependencies
|
||||
|
||||
Dex uses [glide][glide] and [glide-vc][glide-vc] to manage its [`vendor` directory][go-vendor]. A recent version of these are preferred but dex doesn't require any bleeding edge features. Either install these tools using `go get` or take an opportunity to update to a more recent version.
|
||||
|
||||
```
|
||||
go get -u github.com/Masterminds/glide
|
||||
go get -u github.com/sgotti/glide-vc
|
||||
```
|
||||
|
||||
To add a new dependency to dex or update an existing one:
|
||||
|
||||
* Make changes to dex's source code importing the new dependency.
|
||||
* Edit `glide.yaml` to include the new dependency at a given commit SHA or change a SHA.
|
||||
* Add all transitive dependencies of the package to prevent unpinned packages.
|
||||
|
||||
Tests will fail if transitive dependencies aren't included.
|
||||
|
||||
Once `glide.yaml` describes the desired state use glide and glide-vc to update `glide.lock` and `vendor`.
|
||||
|
||||
```
|
||||
glide up -v
|
||||
glide-vc
|
||||
```
|
||||
|
||||
When composing commits make sure that updates to `vendor` are in a separate commit from the main changes. GitHub's UI makes commits with a large number of changes unreviewable.
|
||||
|
||||
Commit histories should look like the following:
|
||||
|
||||
```
|
||||
connector/ldap: add a LDAP connector
|
||||
vendor: revendor
|
||||
```
|
||||
|
||||
[glide]: https://github.com/Masterminds/glide
|
||||
[glide-vc]: https://github.com/sgotti/glide-vc
|
||||
[go-vendor]: https://golang.org/cmd/go/#hdr-Vendor_Directories
|
4
glide.lock
generated
4
glide.lock
generated
|
@ -1,5 +1,5 @@
|
|||
hash: 773c45cb2136423f907496cc1ba67e0c58b35e237b15b0d5f212dce598265442
|
||||
updated: 2016-12-01T13:12:54.401738528-08:00
|
||||
hash: 2d3cc27484f672337349fffc8d7839462df7b1fbedc9200ae0a87a84afeed896
|
||||
updated: 2016-12-07T13:06:21.940111139-08:00
|
||||
imports:
|
||||
- name: github.com/cockroachdb/cockroach-go
|
||||
version: 31611c0501c812f437d4861d87d117053967c955
|
||||
|
|
33
glide.yaml
33
glide.yaml
|
@ -1,5 +1,11 @@
|
|||
# NOTE(ericchiang): Create a separate block for each dependency so it's clear
|
||||
# which dependencies require which transitive dependencies.
|
||||
# For detailed docs on how to add new dependencies or
|
||||
# update dependencies see Documentation/dev-dependencies.md
|
||||
#
|
||||
# The TL;DR is:
|
||||
# * Use glide and glide-vc.
|
||||
# * List transitive dependencies.
|
||||
# * Create a separate block for each dependency group.
|
||||
# * Keep updates to "vendor/" in a seperate commit from actual changes.
|
||||
|
||||
package: github.com/coreos/dex
|
||||
import:
|
||||
|
@ -11,17 +17,20 @@ import:
|
|||
- package: github.com/inconshreveable/mousetrap
|
||||
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
|
||||
|
||||
# LDAP dependencies.
|
||||
- package: gopkg.in/ldap.v2
|
||||
version: 0e7db8eb77695b5a952f0e5d78df9ab160050c73
|
||||
- package: gopkg.in/asn1-ber.v1
|
||||
version: 4e86f4367175e39f69d9358a5f17b4dda270378d
|
||||
|
||||
# Used for JOSE functionality (JWKs, JWTs, etc.).
|
||||
- package: gopkg.in/square/go-jose.v2
|
||||
version: v2.0.0
|
||||
subpackages:
|
||||
- cipher
|
||||
- json
|
||||
|
||||
# Imported directly and by several third party packages.
|
||||
- package: golang.org/x/net
|
||||
version: 6a513affb38dc9788b449d59ffed099b8de18fa0
|
||||
subpackages:
|
||||
|
@ -33,16 +42,21 @@ import:
|
|||
- lex/httplex
|
||||
- trace
|
||||
|
||||
# Used for parsing configs.
|
||||
- package: github.com/ghodss/yaml
|
||||
version: bea76d6a4713e18b7f5321a2b020738552def3ea
|
||||
- package: gopkg.in/yaml.v2
|
||||
version: a83829b6f1293c91addabc89d0571c246397bbf4
|
||||
|
||||
# Router used by the server.
|
||||
- package: github.com/gorilla/mux
|
||||
version: 9fa818a44c2bf1396a17f9d5a3c0f6dd39d2ff8e
|
||||
- package: github.com/gorilla/context
|
||||
version: aed02d124ae4a0e94fea4541c8effd05bf0c8296
|
||||
|
||||
# Package with a bunch of sane crypto defaults. Consider just
|
||||
# copy the code (as recommended by the repo itself) instead
|
||||
# of importing.
|
||||
- package: github.com/gtank/cryptopasta
|
||||
version: e7e23673cac3f529f49e22f94e4af6d12bb49dba
|
||||
- package: golang.org/x/crypto
|
||||
|
@ -50,6 +64,7 @@ import:
|
|||
subpackages:
|
||||
- bcrypt
|
||||
|
||||
# Used for server integration tests and OpenID Connect connector.
|
||||
- package: github.com/coreos/go-oidc
|
||||
version: dedb650fb29c39c2f21aa88c1e4cec66da8754d1
|
||||
- package: github.com/pquerna/cachecontrol
|
||||
|
@ -71,13 +86,8 @@ import:
|
|||
- internal/datastore
|
||||
- internal/log
|
||||
- internal/remote_api
|
||||
# Go's protobuf generator is also a direct dependency of this repo.
|
||||
- package: github.com/golang/protobuf
|
||||
version: 874264fbbb43f4d91e999fecb4b40143ed611400
|
||||
subpackages:
|
||||
- proto
|
||||
- protoc-gen-go
|
||||
|
||||
# Testing conveniences.
|
||||
- package: github.com/kylelemons/godebug
|
||||
subpackages:
|
||||
- diff
|
||||
|
@ -96,7 +106,7 @@ import:
|
|||
subpackages:
|
||||
- crdb
|
||||
|
||||
# gRPC also imports protobuf and the x/net/http2 stack.
|
||||
# gRPC and protobuf are use for the API. Also import x/net/http2 stack.
|
||||
- package: google.golang.org/grpc
|
||||
version: b1a2821ca5a4fd6b6e48ddfbb7d6d7584d839d21
|
||||
subpackages:
|
||||
|
@ -108,3 +118,8 @@ import:
|
|||
- naming
|
||||
- peer
|
||||
- transport
|
||||
- package: github.com/golang/protobuf
|
||||
version: 874264fbbb43f4d91e999fecb4b40143ed611400
|
||||
subpackages:
|
||||
- proto
|
||||
- protoc-gen-go
|
||||
|
|
3
vendor/github.com/cockroachdb/cockroach-go/.gitignore
generated
vendored
3
vendor/github.com/cockroachdb/cockroach-go/.gitignore
generated
vendored
|
@ -1,3 +0,0 @@
|
|||
*~
|
||||
.#*
|
||||
*.test
|
55
vendor/github.com/cockroachdb/cockroach-go/Makefile
generated
vendored
55
vendor/github.com/cockroachdb/cockroach-go/Makefile
generated
vendored
|
@ -1,55 +0,0 @@
|
|||
# Copyright 2016 The Cockroach Authors.
|
||||
#
|
||||
# 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. See the AUTHORS file
|
||||
# for names of contributors.
|
||||
#
|
||||
# Author: Spencer Kimball (spencer.kimball@gmail.com)
|
||||
#
|
||||
|
||||
# Cockroach build rules.
|
||||
GO ?= go
|
||||
# Allow setting of go build flags from the command line.
|
||||
GOFLAGS :=
|
||||
|
||||
.PHONY: all
|
||||
all: test check
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
$(GO) test -v -i ./...
|
||||
$(GO) test -v ./...
|
||||
|
||||
.PHONY: deps
|
||||
deps:
|
||||
$(GO) get -d -t ./...
|
||||
|
||||
.PHONY: check
|
||||
check:
|
||||
@echo "checking for \"path\" imports"
|
||||
@! git grep -F '"path"' -- '*.go'
|
||||
@echo "errcheck"
|
||||
@errcheck ./...
|
||||
@echo "vet"
|
||||
@! go tool vet . 2>&1 | \
|
||||
grep -vE '^vet: cannot process directory .git'
|
||||
@echo "vet --shadow"
|
||||
@! go tool vet --shadow . 2>&1 | \
|
||||
grep -vE '(declaration of err shadows|^vet: cannot process directory \.git)'
|
||||
@echo "golint"
|
||||
@! golint ./... | grep -vE '(\.pb\.go)'
|
||||
@echo "varcheck"
|
||||
@varcheck -e ./...
|
||||
@echo "gofmt (simplify)"
|
||||
@! gofmt -s -d -l . 2>&1 | grep -vE '^\.git/'
|
||||
@echo "goimports"
|
||||
@! goimports -l . | grep -vF 'No Exceptions'
|
2
vendor/github.com/cockroachdb/cockroach-go/README.md
generated
vendored
2
vendor/github.com/cockroachdb/cockroach-go/README.md
generated
vendored
|
@ -1,2 +0,0 @@
|
|||
# testing
|
||||
Testing helpers for cockroach clients.
|
18
vendor/github.com/cockroachdb/cockroach-go/circle.yml
generated
vendored
18
vendor/github.com/cockroachdb/cockroach-go/circle.yml
generated
vendored
|
@ -1,18 +0,0 @@
|
|||
machine:
|
||||
environment:
|
||||
GOROOT: ${HOME}/go
|
||||
PATH: ${PATH}:${HOME}/go/bin
|
||||
post:
|
||||
- sudo rm -rf /usr/local/go
|
||||
- if [ ! -e go1.6.linux-amd64.tar.gz ]; then curl -O https://storage.googleapis.com/golang/go1.6.linux-amd64.tar.gz; fi
|
||||
- tar -C ${HOME} -xzf go1.6.linux-amd64.tar.gz
|
||||
|
||||
dependencies:
|
||||
override:
|
||||
- make deps
|
||||
cache_directories:
|
||||
- ~/go1.6.linux-amd64.tar.gz
|
||||
|
||||
test:
|
||||
override:
|
||||
- make test
|
119
vendor/github.com/cockroachdb/cockroach-go/testserver/binaries.go
generated
vendored
119
vendor/github.com/cockroachdb/cockroach-go/testserver/binaries.go
generated
vendored
|
@ -1,119 +0,0 @@
|
|||
package testserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
awsBaseURL = "https://s3.amazonaws.com/cockroach/cockroach"
|
||||
latestSuffix = "LATEST"
|
||||
localBinaryPath = "/var/tmp"
|
||||
finishedFileMode = 0555
|
||||
)
|
||||
|
||||
func binaryName() string {
|
||||
return fmt.Sprintf("cockroach.%s-%s", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
|
||||
func binaryNameWithSha(sha string) string {
|
||||
return fmt.Sprintf("%s.%s", binaryName(), sha)
|
||||
}
|
||||
|
||||
func binaryPath(sha string) string {
|
||||
return filepath.Join(localBinaryPath, binaryNameWithSha(sha))
|
||||
}
|
||||
|
||||
func latestMarkerURL() string {
|
||||
return fmt.Sprintf("%s/%s.%s", awsBaseURL, binaryName(), latestSuffix)
|
||||
}
|
||||
|
||||
func binaryURL(sha string) string {
|
||||
return fmt.Sprintf("%s/%s.%s", awsBaseURL, binaryName(), sha)
|
||||
}
|
||||
|
||||
func findLatestSha() (string, error) {
|
||||
markerURL := latestMarkerURL()
|
||||
marker, err := http.Get(markerURL)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("could not download %s: %s", markerURL)
|
||||
}
|
||||
if marker.StatusCode == 404 {
|
||||
return "", fmt.Errorf("for 404 from GET %s: make sure OS and ARCH are supported",
|
||||
markerURL)
|
||||
} else if marker.StatusCode != 200 {
|
||||
return "", fmt.Errorf("bad response got GET %s: %d (%s)",
|
||||
markerURL, marker.StatusCode, marker.Status)
|
||||
}
|
||||
|
||||
defer marker.Body.Close()
|
||||
body, err := ioutil.ReadAll(marker.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.TrimSpace(string(body)), nil
|
||||
}
|
||||
|
||||
func downloadFile(url, filePath string) error {
|
||||
output, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0200)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating %s: %s", filePath, "-", err)
|
||||
}
|
||||
defer output.Close()
|
||||
|
||||
log.Printf("downloading %s to %s, this may take some time", url, filePath)
|
||||
|
||||
response, err := http.Get(url)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error downloading %s: %s", url, err)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
if response.StatusCode != 200 {
|
||||
return fmt.Errorf("error downloading %s: %d (%s)", url, response.StatusCode, response.Status)
|
||||
}
|
||||
|
||||
_, err = io.Copy(output, response.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("problem downloading %s to %s: %s", url, filePath, err)
|
||||
}
|
||||
|
||||
// Download was successful, add the rw bits.
|
||||
return os.Chmod(filePath, finishedFileMode)
|
||||
}
|
||||
|
||||
func downloadLatestBinary() (string, error) {
|
||||
sha, err := findLatestSha()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
localFile := binaryPath(sha)
|
||||
for {
|
||||
finfo, err := os.Stat(localFile)
|
||||
if err != nil {
|
||||
// File does not exist: download it.
|
||||
break
|
||||
}
|
||||
// File already present: check mode.
|
||||
if finfo.Mode().Perm() == finishedFileMode {
|
||||
return localFile, nil
|
||||
}
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
}
|
||||
|
||||
err = downloadFile(binaryURL(sha), localFile)
|
||||
if err != nil {
|
||||
_ = os.Remove(localFile)
|
||||
return "", err
|
||||
}
|
||||
|
||||
return localFile, nil
|
||||
}
|
415
vendor/github.com/cockroachdb/cockroach-go/testserver/testserver.go
generated
vendored
415
vendor/github.com/cockroachdb/cockroach-go/testserver/testserver.go
generated
vendored
|
@ -1,415 +0,0 @@
|
|||
// Copyright 2016 The Cockroach Authors.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Author: Marc Berhault (marc@cockroachlabs.com)
|
||||
|
||||
// Package testserver provides helpers to run a cockroach binary within tests.
|
||||
// It automatically downloads the latest cockroach binary for your platform
|
||||
// (Linux-amd64 and Darwin-amd64 only for now), or attempts to run "cockroach"
|
||||
// from your PATH.
|
||||
//
|
||||
// A normal invocation is (check err every time):
|
||||
// ts, err := testserver.NewTestServer()
|
||||
// err = ts.Start()
|
||||
// defer ts.Stop()
|
||||
// url := ts.PGURL()
|
||||
//
|
||||
// To use, run as follows:
|
||||
// import "github.com/cockroachdb/cockroach-go/testserver"
|
||||
// import "testing"
|
||||
// import "time"
|
||||
//
|
||||
// func TestRunServer(t *testing.T) {
|
||||
// ts, err := testserver.NewTestServer()
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// err := ts.Start()
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// defer ts.Stop()
|
||||
//
|
||||
// url := ts.PGURL()
|
||||
// if url != nil {
|
||||
// t.FatalF("url not found")
|
||||
// }
|
||||
// t.Logf("URL: %s", url.String())
|
||||
//
|
||||
// db, err := sql.Open("postgres", url.String())
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// }
|
||||
package testserver
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var sqlURLRegexp = regexp.MustCompile("sql:\\s+(postgresql:.+)\n")
|
||||
|
||||
const (
|
||||
stateNew = iota
|
||||
stateRunning = iota
|
||||
stateStopped = iota
|
||||
stateFailed = iota
|
||||
|
||||
socketPort = 26257
|
||||
socketFileBase = ".s.PGSQL"
|
||||
)
|
||||
|
||||
// TestServer is a helper to run a real cockroach node.
|
||||
type TestServer struct {
|
||||
mu sync.RWMutex
|
||||
state int
|
||||
baseDir string
|
||||
pgURL *url.URL
|
||||
cmd *exec.Cmd
|
||||
args []string
|
||||
stdout string
|
||||
stderr string
|
||||
stdoutBuf logWriter
|
||||
stderrBuf logWriter
|
||||
}
|
||||
|
||||
// NewDBForTest creates a new CockroachDB TestServer instance and
|
||||
// opens a SQL database connection to it. Returns a sql *DB instance a
|
||||
// shutdown function. The caller is responsible for executing the
|
||||
// returned shutdown function on exit.
|
||||
func NewDBForTest(t *testing.T) (*sql.DB, func()) {
|
||||
return NewDBForTestWithDatabase(t, "")
|
||||
}
|
||||
|
||||
// NewDBForTestWithDatabase creates a new CockroachDB TestServer
|
||||
// instance and opens a SQL database connection to it. If database is
|
||||
// specified, the returned connection will explicitly connect to
|
||||
// it. Returns a sql *DB instance a shutdown function. The caller is
|
||||
// responsible for executing the returned shutdown function on exit.
|
||||
func NewDBForTestWithDatabase(t *testing.T, database string) (*sql.DB, func()) {
|
||||
ts, err := NewTestServer()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = ts.Start()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
url := ts.PGURL()
|
||||
if url == nil {
|
||||
t.Fatalf("url not found")
|
||||
}
|
||||
if len(database) > 0 {
|
||||
url.Path = database
|
||||
}
|
||||
|
||||
db, err := sql.Open("postgres", url.String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ts.WaitForInit(db)
|
||||
|
||||
return db, func() {
|
||||
_ = db.Close()
|
||||
ts.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
// NewTestServer creates a new TestServer, but does not start it.
|
||||
// The cockroach binary for your OS and ARCH is downloaded automatically.
|
||||
// If the download fails, we attempt just call "cockroach", hoping it is
|
||||
// found in your path.
|
||||
func NewTestServer() (*TestServer, error) {
|
||||
cockroachBinary, err := downloadLatestBinary()
|
||||
if err == nil {
|
||||
log.Printf("Using automatically-downloaded binary: %s", cockroachBinary)
|
||||
} else {
|
||||
log.Printf("Attempting to use cockroach binary from your PATH")
|
||||
cockroachBinary = "cockroach"
|
||||
}
|
||||
|
||||
// Force "/tmp/" so avoid OSX's really long temp directory names
|
||||
// which get us over the socket filename length limit.
|
||||
baseDir, err := ioutil.TempDir("/tmp", "cockroach-testserver")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create temp directory: %s", err)
|
||||
}
|
||||
|
||||
logDir := filepath.Join(baseDir, "logs")
|
||||
if err := os.MkdirAll(logDir, 0755); err != nil {
|
||||
return nil, fmt.Errorf("could not create logs directory: %s: %s", logDir, err)
|
||||
}
|
||||
|
||||
options := url.Values{
|
||||
"host": []string{baseDir},
|
||||
}
|
||||
pgurl := &url.URL{
|
||||
Scheme: "postgres",
|
||||
User: url.User("root"),
|
||||
Host: fmt.Sprintf(":%d", socketPort),
|
||||
RawQuery: options.Encode(),
|
||||
}
|
||||
socketPath := filepath.Join(baseDir, fmt.Sprintf("%s.%d", socketFileBase, socketPort))
|
||||
|
||||
args := []string{
|
||||
cockroachBinary,
|
||||
"start",
|
||||
"--logtostderr",
|
||||
"--insecure",
|
||||
"--port=0",
|
||||
"--http-port=0",
|
||||
"--socket=" + socketPath,
|
||||
"--store=" + baseDir,
|
||||
}
|
||||
|
||||
ts := &TestServer{
|
||||
baseDir: baseDir,
|
||||
pgURL: pgurl,
|
||||
args: args,
|
||||
stdout: filepath.Join(logDir, "cockroach.stdout"),
|
||||
stderr: filepath.Join(logDir, "cockroach.stderr"),
|
||||
}
|
||||
return ts, nil
|
||||
}
|
||||
|
||||
// Stdout returns the entire contents of the process' stdout.
|
||||
func (ts *TestServer) Stdout() string {
|
||||
return ts.stdoutBuf.String()
|
||||
}
|
||||
|
||||
// Stderr returns the entire contents of the process' stderr.
|
||||
func (ts *TestServer) Stderr() string {
|
||||
return ts.stderrBuf.String()
|
||||
}
|
||||
|
||||
// PGURL returns the postgres connection URL to reach the started
|
||||
// cockroach node.
|
||||
// It loops until the expected unix socket file exists.
|
||||
// This does not timeout, relying instead on test timeouts.
|
||||
func (ts *TestServer) PGURL() *url.URL {
|
||||
socketPath := filepath.Join(ts.baseDir, fmt.Sprintf("%s.%d", socketFileBase, socketPort))
|
||||
for {
|
||||
if _, err := os.Stat(socketPath); err == nil {
|
||||
return ts.pgURL
|
||||
}
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WaitForInit repeatedly looks up the list of databases until
|
||||
// the "system" database exists. It ignores all errors as we are
|
||||
// waiting for the process to start and complete initialization.
|
||||
// This does not timeout, relying instead on test timeouts.
|
||||
func (ts *TestServer) WaitForInit(db *sql.DB) {
|
||||
for {
|
||||
// We issue a query that fails both on connection errors and on the
|
||||
// system database not existing.
|
||||
if _, err := db.Query("SHOW DATABASES"); err == nil {
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
}
|
||||
}
|
||||
|
||||
// Start runs the process, returning an error on any problems,
|
||||
// including being unable to start, but not unexpected failure.
|
||||
// It should only be called once in the lifetime of a TestServer object.
|
||||
func (ts *TestServer) Start() error {
|
||||
ts.mu.Lock()
|
||||
if ts.state != stateNew {
|
||||
ts.mu.Unlock()
|
||||
return errors.New("Start() can only be called once")
|
||||
}
|
||||
ts.state = stateRunning
|
||||
ts.mu.Unlock()
|
||||
|
||||
ts.cmd = exec.Command(ts.args[0], ts.args[1:]...)
|
||||
ts.cmd.Env = []string{"COCKROACH_MAX_OFFSET=1ns"}
|
||||
|
||||
if len(ts.stdout) > 0 {
|
||||
wr, err := newFileLogWriter(ts.stdout)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to open file %s: %s", ts.stdout, err)
|
||||
}
|
||||
ts.stdoutBuf = wr
|
||||
}
|
||||
ts.cmd.Stdout = ts.stdoutBuf
|
||||
|
||||
if len(ts.stderr) > 0 {
|
||||
wr, err := newFileLogWriter(ts.stderr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to open file %s: %s", ts.stderr, err)
|
||||
}
|
||||
ts.stderrBuf = wr
|
||||
}
|
||||
ts.cmd.Stderr = ts.stderrBuf
|
||||
|
||||
for k, v := range defaultEnv() {
|
||||
ts.cmd.Env = append(ts.cmd.Env, k+"="+v)
|
||||
}
|
||||
|
||||
err := ts.cmd.Start()
|
||||
if ts.cmd.Process != nil {
|
||||
log.Printf("process %d started: %s", ts.cmd.Process.Pid, strings.Join(ts.args, " "))
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf(err.Error())
|
||||
ts.stdoutBuf.Close()
|
||||
ts.stderrBuf.Close()
|
||||
|
||||
ts.mu.Lock()
|
||||
ts.state = stateFailed
|
||||
ts.mu.Unlock()
|
||||
|
||||
return fmt.Errorf("failure starting process: %s", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
ts.cmd.Wait()
|
||||
|
||||
ts.stdoutBuf.Close()
|
||||
ts.stderrBuf.Close()
|
||||
|
||||
ps := ts.cmd.ProcessState
|
||||
sy := ps.Sys().(syscall.WaitStatus)
|
||||
|
||||
log.Printf("Process %d exited with status %d", ps.Pid(), sy.ExitStatus())
|
||||
log.Printf(ps.String())
|
||||
|
||||
ts.mu.Lock()
|
||||
if sy.ExitStatus() == 0 {
|
||||
ts.state = stateStopped
|
||||
} else {
|
||||
ts.state = stateFailed
|
||||
}
|
||||
ts.mu.Unlock()
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop kills the process if it is still running and cleans its directory.
|
||||
// It should only be called once in the lifetime of a TestServer object.
|
||||
// Logs fatal if the process has already failed.
|
||||
func (ts *TestServer) Stop() {
|
||||
ts.mu.RLock()
|
||||
defer ts.mu.RUnlock()
|
||||
|
||||
if ts.state == stateNew {
|
||||
log.Fatal("Stop() called, but Start() was never called")
|
||||
}
|
||||
if ts.state == stateFailed {
|
||||
log.Fatalf("Stop() called, but process exited unexpectedly. Stdout:\n%s\nStderr:\n%s\n",
|
||||
ts.Stdout(), ts.Stderr())
|
||||
return
|
||||
}
|
||||
|
||||
if ts.state != stateStopped {
|
||||
// Only call kill if not running. It could have exited properly.
|
||||
ts.cmd.Process.Kill()
|
||||
}
|
||||
|
||||
// Only cleanup on intentional stops.
|
||||
_ = os.RemoveAll(ts.baseDir)
|
||||
}
|
||||
|
||||
type logWriter interface {
|
||||
Write(p []byte) (n int, err error)
|
||||
String() string
|
||||
Len() int64
|
||||
Close()
|
||||
}
|
||||
|
||||
type fileLogWriter struct {
|
||||
filename string
|
||||
file *os.File
|
||||
}
|
||||
|
||||
func newFileLogWriter(file string) (*fileLogWriter, error) {
|
||||
f, err := os.Create(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &fileLogWriter{
|
||||
filename: file,
|
||||
file: f,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (w fileLogWriter) Close() {
|
||||
w.file.Close()
|
||||
}
|
||||
|
||||
func (w fileLogWriter) Write(p []byte) (n int, err error) {
|
||||
return w.file.Write(p)
|
||||
}
|
||||
|
||||
func (w fileLogWriter) String() string {
|
||||
b, err := ioutil.ReadFile(w.filename)
|
||||
if err == nil {
|
||||
return string(b)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (w fileLogWriter) Len() int64 {
|
||||
s, err := os.Stat(w.filename)
|
||||
if err == nil {
|
||||
return s.Size()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func defaultEnv() map[string]string {
|
||||
vars := map[string]string{}
|
||||
u, err := user.Current()
|
||||
if err == nil {
|
||||
if _, ok := vars["USER"]; !ok {
|
||||
vars["USER"] = u.Username
|
||||
}
|
||||
if _, ok := vars["UID"]; !ok {
|
||||
vars["UID"] = u.Uid
|
||||
}
|
||||
if _, ok := vars["GID"]; !ok {
|
||||
vars["GID"] = u.Gid
|
||||
}
|
||||
if _, ok := vars["HOME"]; !ok {
|
||||
vars["HOME"] = u.HomeDir
|
||||
}
|
||||
}
|
||||
if _, ok := vars["PATH"]; !ok {
|
||||
vars["PATH"] = os.Getenv("PATH")
|
||||
}
|
||||
return vars
|
||||
}
|
35
vendor/github.com/cockroachdb/cockroach-go/testserver/testserver_test.go
generated
vendored
35
vendor/github.com/cockroachdb/cockroach-go/testserver/testserver_test.go
generated
vendored
|
@ -1,35 +0,0 @@
|
|||
// Copyright 2016 The Cockroach Authors.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Author: Marc Berhault (marc@cockroachlabs.com)
|
||||
|
||||
package testserver_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
// Needed for postgres driver test.
|
||||
"github.com/cockroachdb/cockroach-go/testserver"
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
func TestRunServer(t *testing.T) {
|
||||
db, stop := testserver.NewDBForTest(t)
|
||||
defer stop()
|
||||
|
||||
_, err := db.Exec("SELECT 1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
21
vendor/github.com/coreos/go-oidc/example/README.md
generated
vendored
21
vendor/github.com/coreos/go-oidc/example/README.md
generated
vendored
|
@ -1,21 +0,0 @@
|
|||
# Examples
|
||||
|
||||
These are example uses of the oidc package. Each requires a Google account and the client ID and secret of a registered OAuth2 application. To create one:
|
||||
|
||||
1. Visit your [Google Developer Console][google-developer-console].
|
||||
2. Click "Credentials" on the left column.
|
||||
3. Click the "Create credentials" button followed by "OAuth client ID".
|
||||
4. Select "Web application" and add "http://127.0.0.1:5556/auth/google/callback" as an authorized redirect URI.
|
||||
5. Click create and add the printed client ID and secret to your environment using the following variables:
|
||||
|
||||
```
|
||||
GOOGLE_OAUTH2_CLIENT_ID
|
||||
GOOGLE_OAUTH2_CLIENT_SECRET
|
||||
```
|
||||
|
||||
Finally run the examples using the Go tool and navigate to http://127.0.0.1:5556.
|
||||
|
||||
```
|
||||
go run ./examples/idtoken/app.go
|
||||
```
|
||||
[google-developer-console]: https://console.developers.google.com/apis/dashboard
|
89
vendor/github.com/coreos/go-oidc/example/idtoken/app.go
generated
vendored
89
vendor/github.com/coreos/go-oidc/example/idtoken/app.go
generated
vendored
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
This is an example application to demonstrate parsing an ID Token.
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
oidc "github.com/coreos/go-oidc"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
var (
|
||||
clientID = os.Getenv("GOOGLE_OAUTH2_CLIENT_ID")
|
||||
clientSecret = os.Getenv("GOOGLE_OAUTH2_CLIENT_SECRET")
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
|
||||
provider, err := oidc.NewProvider(ctx, "https://accounts.google.com")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
verifier := provider.Verifier()
|
||||
|
||||
config := oauth2.Config{
|
||||
ClientID: clientID,
|
||||
ClientSecret: clientSecret,
|
||||
Endpoint: provider.Endpoint(),
|
||||
RedirectURL: "http://127.0.0.1:5556/auth/google/callback",
|
||||
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
|
||||
}
|
||||
|
||||
state := "foobar" // Don't do this in production.
|
||||
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, config.AuthCodeURL(state), http.StatusFound)
|
||||
})
|
||||
|
||||
http.HandleFunc("/auth/google/callback", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Query().Get("state") != state {
|
||||
http.Error(w, "state did not match", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
oauth2Token, err := config.Exchange(ctx, r.URL.Query().Get("code"))
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to exchange token: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
rawIDToken, ok := oauth2Token.Extra("id_token").(string)
|
||||
if !ok {
|
||||
http.Error(w, "No id_token field in oauth2 token.", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
idToken, err := verifier.Verify(ctx, rawIDToken)
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to verify ID Token: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
oauth2Token.AccessToken = "*REDACTED*"
|
||||
|
||||
resp := struct {
|
||||
OAuth2Token *oauth2.Token
|
||||
IDTokenClaims *json.RawMessage // ID Token payload is just JSON.
|
||||
}{oauth2Token, new(json.RawMessage)}
|
||||
|
||||
if err := idToken.Claims(&resp.IDTokenClaims); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
data, err := json.MarshalIndent(resp, "", " ")
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Write(data)
|
||||
})
|
||||
|
||||
log.Printf("listening on http://%s/", "127.0.0.1:5556")
|
||||
log.Fatal(http.ListenAndServe("127.0.0.1:5556", nil))
|
||||
}
|
104
vendor/github.com/coreos/go-oidc/example/nonce/app.go
generated
vendored
104
vendor/github.com/coreos/go-oidc/example/nonce/app.go
generated
vendored
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
This is an example application to demonstrate verifying an ID Token with a nonce.
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
oidc "github.com/coreos/go-oidc"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
var (
|
||||
clientID = os.Getenv("GOOGLE_OAUTH2_CLIENT_ID")
|
||||
clientSecret = os.Getenv("GOOGLE_OAUTH2_CLIENT_SECRET")
|
||||
)
|
||||
|
||||
const appNonce = "a super secret nonce"
|
||||
|
||||
// Create a nonce source.
|
||||
type nonceSource struct{}
|
||||
|
||||
func (n nonceSource) ClaimNonce(nonce string) error {
|
||||
if nonce != appNonce {
|
||||
return errors.New("unregonized nonce")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
|
||||
provider, err := oidc.NewProvider(ctx, "https://accounts.google.com")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Use the nonce source to create a custom ID Token verifier.
|
||||
nonceEnabledVerifier := provider.Verifier(oidc.VerifyNonce(nonceSource{}))
|
||||
|
||||
config := oauth2.Config{
|
||||
ClientID: clientID,
|
||||
ClientSecret: clientSecret,
|
||||
Endpoint: provider.Endpoint(),
|
||||
RedirectURL: "http://127.0.0.1:5556/auth/google/callback",
|
||||
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
|
||||
}
|
||||
|
||||
state := "foobar" // Don't do this in production.
|
||||
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, config.AuthCodeURL(state, oidc.Nonce(appNonce)), http.StatusFound)
|
||||
})
|
||||
|
||||
http.HandleFunc("/auth/google/callback", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Query().Get("state") != state {
|
||||
http.Error(w, "state did not match", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
oauth2Token, err := config.Exchange(ctx, r.URL.Query().Get("code"))
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to exchange token: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
rawIDToken, ok := oauth2Token.Extra("id_token").(string)
|
||||
if !ok {
|
||||
http.Error(w, "No id_token field in oauth2 token.", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
// Verify the ID Token signature and nonce.
|
||||
idToken, err := nonceEnabledVerifier.Verify(ctx, rawIDToken)
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to verify ID Token: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
resp := struct {
|
||||
OAuth2Token *oauth2.Token
|
||||
IDTokenClaims *json.RawMessage // ID Token payload is just JSON.
|
||||
}{oauth2Token, new(json.RawMessage)}
|
||||
|
||||
if err := idToken.Claims(&resp.IDTokenClaims); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
data, err := json.MarshalIndent(resp, "", " ")
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Write(data)
|
||||
})
|
||||
|
||||
log.Printf("listening on http://%s/", "127.0.0.1:5556")
|
||||
log.Fatal(http.ListenAndServe("127.0.0.1:5556", nil))
|
||||
}
|
76
vendor/github.com/coreos/go-oidc/example/userinfo/app.go
generated
vendored
76
vendor/github.com/coreos/go-oidc/example/userinfo/app.go
generated
vendored
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
This is an example application to demonstrate querying the user info endpoint.
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
oidc "github.com/coreos/go-oidc"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
var (
|
||||
clientID = os.Getenv("GOOGLE_OAUTH2_CLIENT_ID")
|
||||
clientSecret = os.Getenv("GOOGLE_OAUTH2_CLIENT_SECRET")
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
|
||||
provider, err := oidc.NewProvider(ctx, "https://accounts.google.com")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
config := oauth2.Config{
|
||||
ClientID: clientID,
|
||||
ClientSecret: clientSecret,
|
||||
Endpoint: provider.Endpoint(),
|
||||
RedirectURL: "http://127.0.0.1:5556/auth/google/callback",
|
||||
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
|
||||
}
|
||||
|
||||
state := "foobar" // Don't do this in production.
|
||||
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, config.AuthCodeURL(state), http.StatusFound)
|
||||
})
|
||||
|
||||
http.HandleFunc("/auth/google/callback", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Query().Get("state") != state {
|
||||
http.Error(w, "state did not match", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
oauth2Token, err := config.Exchange(ctx, r.URL.Query().Get("code"))
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to exchange token: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
userInfo, err := provider.UserInfo(ctx, oauth2.StaticTokenSource(oauth2Token))
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to get userinfo: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
resp := struct {
|
||||
OAuth2Token *oauth2.Token
|
||||
UserInfo *oidc.UserInfo
|
||||
}{oauth2Token, userInfo}
|
||||
data, err := json.MarshalIndent(resp, "", " ")
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Write(data)
|
||||
})
|
||||
|
||||
log.Printf("listening on http://%s/", "127.0.0.1:5556")
|
||||
log.Fatal(http.ListenAndServe("127.0.0.1:5556", nil))
|
||||
}
|
7
vendor/github.com/coreos/go-oidc/http/client.go
generated
vendored
7
vendor/github.com/coreos/go-oidc/http/client.go
generated
vendored
|
@ -1,7 +0,0 @@
|
|||
package http
|
||||
|
||||
import "net/http"
|
||||
|
||||
type Client interface {
|
||||
Do(*http.Request) (*http.Response, error)
|
||||
}
|
2
vendor/github.com/coreos/go-oidc/http/doc.go
generated
vendored
2
vendor/github.com/coreos/go-oidc/http/doc.go
generated
vendored
|
@ -1,2 +0,0 @@
|
|||
// Package http is DEPRECATED. Use net/http instead.
|
||||
package http
|
156
vendor/github.com/coreos/go-oidc/http/http.go
generated
vendored
156
vendor/github.com/coreos/go-oidc/http/http.go
generated
vendored
|
@ -1,156 +0,0 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func WriteError(w http.ResponseWriter, code int, msg string) {
|
||||
e := struct {
|
||||
Error string `json:"error"`
|
||||
}{
|
||||
Error: msg,
|
||||
}
|
||||
b, err := json.Marshal(e)
|
||||
if err != nil {
|
||||
log.Printf("go-oidc: failed to marshal %#v: %v", e, err)
|
||||
code = http.StatusInternalServerError
|
||||
b = []byte(`{"error":"server_error"}`)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(code)
|
||||
w.Write(b)
|
||||
}
|
||||
|
||||
// BasicAuth parses a username and password from the request's
|
||||
// Authorization header. This was pulled from golang master:
|
||||
// https://codereview.appspot.com/76540043
|
||||
func BasicAuth(r *http.Request) (username, password string, ok bool) {
|
||||
auth := r.Header.Get("Authorization")
|
||||
if auth == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(auth, "Basic ") {
|
||||
return
|
||||
}
|
||||
c, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(auth, "Basic "))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cs := string(c)
|
||||
s := strings.IndexByte(cs, ':')
|
||||
if s < 0 {
|
||||
return
|
||||
}
|
||||
return cs[:s], cs[s+1:], true
|
||||
}
|
||||
|
||||
func cacheControlMaxAge(hdr string) (time.Duration, bool, error) {
|
||||
for _, field := range strings.Split(hdr, ",") {
|
||||
parts := strings.SplitN(strings.TrimSpace(field), "=", 2)
|
||||
k := strings.ToLower(strings.TrimSpace(parts[0]))
|
||||
if k != "max-age" {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(parts) == 1 {
|
||||
return 0, false, errors.New("max-age has no value")
|
||||
}
|
||||
|
||||
v := strings.TrimSpace(parts[1])
|
||||
if v == "" {
|
||||
return 0, false, errors.New("max-age has empty value")
|
||||
}
|
||||
|
||||
age, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
|
||||
if age <= 0 {
|
||||
return 0, false, nil
|
||||
}
|
||||
|
||||
return time.Duration(age) * time.Second, true, nil
|
||||
}
|
||||
|
||||
return 0, false, nil
|
||||
}
|
||||
|
||||
func expires(date, expires string) (time.Duration, bool, error) {
|
||||
if date == "" || expires == "" {
|
||||
return 0, false, nil
|
||||
}
|
||||
|
||||
te, err := time.Parse(time.RFC1123, expires)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
|
||||
td, err := time.Parse(time.RFC1123, date)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
|
||||
ttl := te.Sub(td)
|
||||
|
||||
// headers indicate data already expired, caller should not
|
||||
// have to care about this case
|
||||
if ttl <= 0 {
|
||||
return 0, false, nil
|
||||
}
|
||||
|
||||
return ttl, true, nil
|
||||
}
|
||||
|
||||
func Cacheable(hdr http.Header) (time.Duration, bool, error) {
|
||||
ttl, ok, err := cacheControlMaxAge(hdr.Get("Cache-Control"))
|
||||
if err != nil || ok {
|
||||
return ttl, ok, err
|
||||
}
|
||||
|
||||
return expires(hdr.Get("Date"), hdr.Get("Expires"))
|
||||
}
|
||||
|
||||
// MergeQuery appends additional query values to an existing URL.
|
||||
func MergeQuery(u url.URL, q url.Values) url.URL {
|
||||
uv := u.Query()
|
||||
for k, vs := range q {
|
||||
for _, v := range vs {
|
||||
uv.Add(k, v)
|
||||
}
|
||||
}
|
||||
u.RawQuery = uv.Encode()
|
||||
return u
|
||||
}
|
||||
|
||||
// NewResourceLocation appends a resource id to the end of the requested URL path.
|
||||
func NewResourceLocation(reqURL *url.URL, id string) string {
|
||||
var u url.URL
|
||||
u = *reqURL
|
||||
u.Path = path.Join(u.Path, id)
|
||||
u.RawQuery = ""
|
||||
u.Fragment = ""
|
||||
return u.String()
|
||||
}
|
||||
|
||||
// CopyRequest returns a clone of the provided *http.Request.
|
||||
// The returned object is a shallow copy of the struct and a
|
||||
// deep copy of its Header field.
|
||||
func CopyRequest(r *http.Request) *http.Request {
|
||||
r2 := *r
|
||||
r2.Header = make(http.Header)
|
||||
for k, s := range r.Header {
|
||||
r2.Header[k] = s
|
||||
}
|
||||
return &r2
|
||||
}
|
380
vendor/github.com/coreos/go-oidc/http/http_test.go
generated
vendored
380
vendor/github.com/coreos/go-oidc/http/http_test.go
generated
vendored
|
@ -1,380 +0,0 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCacheControlMaxAgeSuccess(t *testing.T) {
|
||||
tests := []struct {
|
||||
hdr string
|
||||
wantAge time.Duration
|
||||
wantOK bool
|
||||
}{
|
||||
{"max-age=12", 12 * time.Second, true},
|
||||
{"max-age=-12", 0, false},
|
||||
{"max-age=0", 0, false},
|
||||
{"public, max-age=12", 12 * time.Second, true},
|
||||
{"public, max-age=40192, must-revalidate", 40192 * time.Second, true},
|
||||
{"public, not-max-age=12, must-revalidate", time.Duration(0), false},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
maxAge, ok, err := cacheControlMaxAge(tt.hdr)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: err=%v", i, err)
|
||||
}
|
||||
if tt.wantAge != maxAge {
|
||||
t.Errorf("case %d: want=%d got=%d", i, tt.wantAge, maxAge)
|
||||
}
|
||||
if tt.wantOK != ok {
|
||||
t.Errorf("case %d: incorrect ok value: want=%t got=%t", i, tt.wantOK, ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCacheControlMaxAgeFail(t *testing.T) {
|
||||
tests := []string{
|
||||
"max-age=aasdf",
|
||||
"max-age=",
|
||||
"max-age",
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
_, ok, err := cacheControlMaxAge(tt)
|
||||
if ok {
|
||||
t.Errorf("case %d: want ok=false, got true", i)
|
||||
}
|
||||
if err == nil {
|
||||
t.Errorf("case %d: want non-nil err", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergeQuery(t *testing.T) {
|
||||
tests := []struct {
|
||||
u string
|
||||
q url.Values
|
||||
w string
|
||||
}{
|
||||
// No values
|
||||
{
|
||||
u: "http://example.com",
|
||||
q: nil,
|
||||
w: "http://example.com",
|
||||
},
|
||||
// No additional values
|
||||
{
|
||||
u: "http://example.com?foo=bar",
|
||||
q: nil,
|
||||
w: "http://example.com?foo=bar",
|
||||
},
|
||||
// Simple addition
|
||||
{
|
||||
u: "http://example.com",
|
||||
q: url.Values{
|
||||
"foo": []string{"bar"},
|
||||
},
|
||||
w: "http://example.com?foo=bar",
|
||||
},
|
||||
// Addition with existing values
|
||||
{
|
||||
u: "http://example.com?dog=boo",
|
||||
q: url.Values{
|
||||
"foo": []string{"bar"},
|
||||
},
|
||||
w: "http://example.com?dog=boo&foo=bar",
|
||||
},
|
||||
// Merge
|
||||
{
|
||||
u: "http://example.com?dog=boo",
|
||||
q: url.Values{
|
||||
"dog": []string{"elroy"},
|
||||
},
|
||||
w: "http://example.com?dog=boo&dog=elroy",
|
||||
},
|
||||
// Add and merge
|
||||
{
|
||||
u: "http://example.com?dog=boo",
|
||||
q: url.Values{
|
||||
"dog": []string{"elroy"},
|
||||
"foo": []string{"bar"},
|
||||
},
|
||||
w: "http://example.com?dog=boo&dog=elroy&foo=bar",
|
||||
},
|
||||
// Multivalue merge
|
||||
{
|
||||
u: "http://example.com?dog=boo",
|
||||
q: url.Values{
|
||||
"dog": []string{"elroy", "penny"},
|
||||
},
|
||||
w: "http://example.com?dog=boo&dog=elroy&dog=penny",
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
ur, err := url.Parse(tt.u)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: failed parsing test url: %v, error: %v", i, tt.u, err)
|
||||
}
|
||||
|
||||
got := MergeQuery(*ur, tt.q)
|
||||
want, err := url.Parse(tt.w)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: failed parsing want url: %v, error: %v", i, tt.w, err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(*want, got) {
|
||||
t.Errorf("case %d: want: %v, got: %v", i, *want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestExpiresPass(t *testing.T) {
|
||||
tests := []struct {
|
||||
date string
|
||||
exp string
|
||||
wantTTL time.Duration
|
||||
wantOK bool
|
||||
}{
|
||||
// Expires and Date properly set
|
||||
{
|
||||
date: "Thu, 01 Dec 1983 22:00:00 GMT",
|
||||
exp: "Fri, 02 Dec 1983 01:00:00 GMT",
|
||||
wantTTL: 10800 * time.Second,
|
||||
wantOK: true,
|
||||
},
|
||||
// empty headers
|
||||
{
|
||||
date: "",
|
||||
exp: "",
|
||||
wantOK: false,
|
||||
},
|
||||
// lack of Expirs short-ciruits Date parsing
|
||||
{
|
||||
date: "foo",
|
||||
exp: "",
|
||||
wantOK: false,
|
||||
},
|
||||
// lack of Date short-ciruits Expires parsing
|
||||
{
|
||||
date: "",
|
||||
exp: "foo",
|
||||
wantOK: false,
|
||||
},
|
||||
// no Date
|
||||
{
|
||||
exp: "Thu, 01 Dec 1983 22:00:00 GMT",
|
||||
wantTTL: 0,
|
||||
wantOK: false,
|
||||
},
|
||||
// no Expires
|
||||
{
|
||||
date: "Thu, 01 Dec 1983 22:00:00 GMT",
|
||||
wantTTL: 0,
|
||||
wantOK: false,
|
||||
},
|
||||
// Expires < Date
|
||||
{
|
||||
date: "Fri, 02 Dec 1983 01:00:00 GMT",
|
||||
exp: "Thu, 01 Dec 1983 22:00:00 GMT",
|
||||
wantTTL: 0,
|
||||
wantOK: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
ttl, ok, err := expires(tt.date, tt.exp)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: err=%v", i, err)
|
||||
}
|
||||
if tt.wantTTL != ttl {
|
||||
t.Errorf("case %d: want=%d got=%d", i, tt.wantTTL, ttl)
|
||||
}
|
||||
if tt.wantOK != ok {
|
||||
t.Errorf("case %d: incorrect ok value: want=%t got=%t", i, tt.wantOK, ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestExpiresFail(t *testing.T) {
|
||||
tests := []struct {
|
||||
date string
|
||||
exp string
|
||||
}{
|
||||
// malformed Date header
|
||||
{
|
||||
date: "foo",
|
||||
exp: "Fri, 02 Dec 1983 01:00:00 GMT",
|
||||
},
|
||||
// malformed exp header
|
||||
{
|
||||
date: "Fri, 02 Dec 1983 01:00:00 GMT",
|
||||
exp: "bar",
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
_, _, err := expires(tt.date, tt.exp)
|
||||
if err == nil {
|
||||
t.Errorf("case %d: expected non-nil error", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCacheablePass(t *testing.T) {
|
||||
tests := []struct {
|
||||
headers http.Header
|
||||
wantTTL time.Duration
|
||||
wantOK bool
|
||||
}{
|
||||
// valid Cache-Control
|
||||
{
|
||||
headers: http.Header{
|
||||
"Cache-Control": []string{"max-age=100"},
|
||||
},
|
||||
wantTTL: 100 * time.Second,
|
||||
wantOK: true,
|
||||
},
|
||||
// valid Date/Expires
|
||||
{
|
||||
headers: http.Header{
|
||||
"Date": []string{"Thu, 01 Dec 1983 22:00:00 GMT"},
|
||||
"Expires": []string{"Fri, 02 Dec 1983 01:00:00 GMT"},
|
||||
},
|
||||
wantTTL: 10800 * time.Second,
|
||||
wantOK: true,
|
||||
},
|
||||
// Cache-Control supersedes Date/Expires
|
||||
{
|
||||
headers: http.Header{
|
||||
"Cache-Control": []string{"max-age=100"},
|
||||
"Date": []string{"Thu, 01 Dec 1983 22:00:00 GMT"},
|
||||
"Expires": []string{"Fri, 02 Dec 1983 01:00:00 GMT"},
|
||||
},
|
||||
wantTTL: 100 * time.Second,
|
||||
wantOK: true,
|
||||
},
|
||||
// no caching headers
|
||||
{
|
||||
headers: http.Header{},
|
||||
wantOK: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
ttl, ok, err := Cacheable(tt.headers)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: err=%v", i, err)
|
||||
continue
|
||||
}
|
||||
if tt.wantTTL != ttl {
|
||||
t.Errorf("case %d: want=%d got=%d", i, tt.wantTTL, ttl)
|
||||
}
|
||||
if tt.wantOK != ok {
|
||||
t.Errorf("case %d: incorrect ok value: want=%t got=%t", i, tt.wantOK, ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCacheableFail(t *testing.T) {
|
||||
tests := []http.Header{
|
||||
// invalid Cache-Control short-circuits
|
||||
http.Header{
|
||||
"Cache-Control": []string{"max-age"},
|
||||
"Date": []string{"Thu, 01 Dec 1983 22:00:00 GMT"},
|
||||
"Expires": []string{"Fri, 02 Dec 1983 01:00:00 GMT"},
|
||||
},
|
||||
// no Cache-Control, invalid Expires
|
||||
http.Header{
|
||||
"Date": []string{"Thu, 01 Dec 1983 22:00:00 GMT"},
|
||||
"Expires": []string{"boo"},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
_, _, err := Cacheable(tt)
|
||||
if err == nil {
|
||||
t.Errorf("case %d: want non-nil err", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewResourceLocation(t *testing.T) {
|
||||
tests := []struct {
|
||||
ru *url.URL
|
||||
id string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
ru: &url.URL{
|
||||
Scheme: "http",
|
||||
Host: "example.com",
|
||||
},
|
||||
id: "foo",
|
||||
want: "http://example.com/foo",
|
||||
},
|
||||
// https
|
||||
{
|
||||
ru: &url.URL{
|
||||
Scheme: "https",
|
||||
Host: "example.com",
|
||||
},
|
||||
id: "foo",
|
||||
want: "https://example.com/foo",
|
||||
},
|
||||
// with path
|
||||
{
|
||||
ru: &url.URL{
|
||||
Scheme: "http",
|
||||
Host: "example.com",
|
||||
Path: "one/two/three",
|
||||
},
|
||||
id: "foo",
|
||||
want: "http://example.com/one/two/three/foo",
|
||||
},
|
||||
// with fragment
|
||||
{
|
||||
ru: &url.URL{
|
||||
Scheme: "http",
|
||||
Host: "example.com",
|
||||
Fragment: "frag",
|
||||
},
|
||||
id: "foo",
|
||||
want: "http://example.com/foo",
|
||||
},
|
||||
// with query
|
||||
{
|
||||
ru: &url.URL{
|
||||
Scheme: "http",
|
||||
Host: "example.com",
|
||||
RawQuery: "dog=elroy",
|
||||
},
|
||||
id: "foo",
|
||||
want: "http://example.com/foo",
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
got := NewResourceLocation(tt.ru, tt.id)
|
||||
if tt.want != got {
|
||||
t.Errorf("case %d: want=%s, got=%s", i, tt.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCopyRequest(t *testing.T) {
|
||||
r1, err := http.NewRequest("GET", "http://example.com", strings.NewReader("foo"))
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
r2 := CopyRequest(r1)
|
||||
if !reflect.DeepEqual(r1, r2) {
|
||||
t.Fatalf("Result of CopyRequest incorrect: %#v != %#v", r1, r2)
|
||||
}
|
||||
}
|
29
vendor/github.com/coreos/go-oidc/http/url.go
generated
vendored
29
vendor/github.com/coreos/go-oidc/http/url.go
generated
vendored
|
@ -1,29 +0,0 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// ParseNonEmptyURL checks that a string is a parsable URL which is also not empty
|
||||
// since `url.Parse("")` does not return an error. Must contian a scheme and a host.
|
||||
func ParseNonEmptyURL(u string) (*url.URL, error) {
|
||||
if u == "" {
|
||||
return nil, errors.New("url is empty")
|
||||
}
|
||||
|
||||
ur, err := url.Parse(u)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if ur.Scheme == "" {
|
||||
return nil, errors.New("url scheme is empty")
|
||||
}
|
||||
|
||||
if ur.Host == "" {
|
||||
return nil, errors.New("url host is empty")
|
||||
}
|
||||
|
||||
return ur, nil
|
||||
}
|
49
vendor/github.com/coreos/go-oidc/http/url_test.go
generated
vendored
49
vendor/github.com/coreos/go-oidc/http/url_test.go
generated
vendored
|
@ -1,49 +0,0 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseNonEmptyURL(t *testing.T) {
|
||||
tests := []struct {
|
||||
u string
|
||||
ok bool
|
||||
}{
|
||||
{"", false},
|
||||
{"http://", false},
|
||||
{"example.com", false},
|
||||
{"example", false},
|
||||
{"http://example", true},
|
||||
{"http://example:1234", true},
|
||||
{"http://example.com", true},
|
||||
{"http://example.com:1234", true},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
u, err := ParseNonEmptyURL(tt.u)
|
||||
if err != nil {
|
||||
t.Logf("err: %v", err)
|
||||
if tt.ok {
|
||||
t.Errorf("case %d: unexpected error: %v", i, err)
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if !tt.ok {
|
||||
t.Errorf("case %d: expected error but got none", i)
|
||||
continue
|
||||
}
|
||||
|
||||
uu, err := url.Parse(tt.u)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if uu.String() != u.String() {
|
||||
t.Errorf("case %d: incorrect url value, want: %q, got: %q", i, uu.String(), u.String())
|
||||
}
|
||||
}
|
||||
}
|
126
vendor/github.com/coreos/go-oidc/jose/claims.go
generated
vendored
126
vendor/github.com/coreos/go-oidc/jose/claims.go
generated
vendored
|
@ -1,126 +0,0 @@
|
|||
package jose
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Claims map[string]interface{}
|
||||
|
||||
func (c Claims) Add(name string, value interface{}) {
|
||||
c[name] = value
|
||||
}
|
||||
|
||||
func (c Claims) StringClaim(name string) (string, bool, error) {
|
||||
cl, ok := c[name]
|
||||
if !ok {
|
||||
return "", false, nil
|
||||
}
|
||||
|
||||
v, ok := cl.(string)
|
||||
if !ok {
|
||||
return "", false, fmt.Errorf("unable to parse claim as string: %v", name)
|
||||
}
|
||||
|
||||
return v, true, nil
|
||||
}
|
||||
|
||||
func (c Claims) StringsClaim(name string) ([]string, bool, error) {
|
||||
cl, ok := c[name]
|
||||
if !ok {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
if v, ok := cl.([]string); ok {
|
||||
return v, true, nil
|
||||
}
|
||||
|
||||
// When unmarshaled, []string will become []interface{}.
|
||||
if v, ok := cl.([]interface{}); ok {
|
||||
var ret []string
|
||||
for _, vv := range v {
|
||||
str, ok := vv.(string)
|
||||
if !ok {
|
||||
return nil, false, fmt.Errorf("unable to parse claim as string array: %v", name)
|
||||
}
|
||||
ret = append(ret, str)
|
||||
}
|
||||
return ret, true, nil
|
||||
}
|
||||
|
||||
return nil, false, fmt.Errorf("unable to parse claim as string array: %v", name)
|
||||
}
|
||||
|
||||
func (c Claims) Int64Claim(name string) (int64, bool, error) {
|
||||
cl, ok := c[name]
|
||||
if !ok {
|
||||
return 0, false, nil
|
||||
}
|
||||
|
||||
v, ok := cl.(int64)
|
||||
if !ok {
|
||||
vf, ok := cl.(float64)
|
||||
if !ok {
|
||||
return 0, false, fmt.Errorf("unable to parse claim as int64: %v", name)
|
||||
}
|
||||
v = int64(vf)
|
||||
}
|
||||
|
||||
return v, true, nil
|
||||
}
|
||||
|
||||
func (c Claims) Float64Claim(name string) (float64, bool, error) {
|
||||
cl, ok := c[name]
|
||||
if !ok {
|
||||
return 0, false, nil
|
||||
}
|
||||
|
||||
v, ok := cl.(float64)
|
||||
if !ok {
|
||||
vi, ok := cl.(int64)
|
||||
if !ok {
|
||||
return 0, false, fmt.Errorf("unable to parse claim as float64: %v", name)
|
||||
}
|
||||
v = float64(vi)
|
||||
}
|
||||
|
||||
return v, true, nil
|
||||
}
|
||||
|
||||
func (c Claims) TimeClaim(name string) (time.Time, bool, error) {
|
||||
v, ok, err := c.Float64Claim(name)
|
||||
if !ok || err != nil {
|
||||
return time.Time{}, ok, err
|
||||
}
|
||||
|
||||
s := math.Trunc(v)
|
||||
ns := (v - s) * math.Pow(10, 9)
|
||||
return time.Unix(int64(s), int64(ns)).UTC(), true, nil
|
||||
}
|
||||
|
||||
func decodeClaims(payload []byte) (Claims, error) {
|
||||
var c Claims
|
||||
if err := json.Unmarshal(payload, &c); err != nil {
|
||||
return nil, fmt.Errorf("malformed JWT claims, unable to decode: %v", err)
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func marshalClaims(c Claims) ([]byte, error) {
|
||||
b, err := json.Marshal(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func encodeClaims(c Claims) (string, error) {
|
||||
b, err := marshalClaims(c)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return encodeSegment(b), nil
|
||||
}
|
328
vendor/github.com/coreos/go-oidc/jose/claims_test.go
generated
vendored
328
vendor/github.com/coreos/go-oidc/jose/claims_test.go
generated
vendored
|
@ -1,328 +0,0 @@
|
|||
package jose
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestString(t *testing.T) {
|
||||
tests := []struct {
|
||||
cl Claims
|
||||
key string
|
||||
ok bool
|
||||
err bool
|
||||
val string
|
||||
}{
|
||||
// ok, no err, claim exists
|
||||
{
|
||||
cl: Claims{
|
||||
"foo": "bar",
|
||||
},
|
||||
key: "foo",
|
||||
val: "bar",
|
||||
ok: true,
|
||||
err: false,
|
||||
},
|
||||
// no claims
|
||||
{
|
||||
cl: Claims{},
|
||||
key: "foo",
|
||||
val: "",
|
||||
ok: false,
|
||||
err: false,
|
||||
},
|
||||
// missing claim
|
||||
{
|
||||
cl: Claims{
|
||||
"foo": "bar",
|
||||
},
|
||||
key: "xxx",
|
||||
val: "",
|
||||
ok: false,
|
||||
err: false,
|
||||
},
|
||||
// unparsable: type
|
||||
{
|
||||
cl: Claims{
|
||||
"foo": struct{}{},
|
||||
},
|
||||
key: "foo",
|
||||
val: "",
|
||||
ok: false,
|
||||
err: true,
|
||||
},
|
||||
// unparsable: nil value
|
||||
{
|
||||
cl: Claims{
|
||||
"foo": nil,
|
||||
},
|
||||
key: "foo",
|
||||
val: "",
|
||||
ok: false,
|
||||
err: true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
val, ok, err := tt.cl.StringClaim(tt.key)
|
||||
|
||||
if tt.err && err == nil {
|
||||
t.Errorf("case %d: want err=non-nil, got err=nil", i)
|
||||
} else if !tt.err && err != nil {
|
||||
t.Errorf("case %d: want err=nil, got err=%v", i, err)
|
||||
}
|
||||
|
||||
if tt.ok != ok {
|
||||
t.Errorf("case %d: want ok=%v, got ok=%v", i, tt.ok, ok)
|
||||
}
|
||||
|
||||
if tt.val != val {
|
||||
t.Errorf("case %d: want val=%v, got val=%v", i, tt.val, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInt64(t *testing.T) {
|
||||
tests := []struct {
|
||||
cl Claims
|
||||
key string
|
||||
ok bool
|
||||
err bool
|
||||
val int64
|
||||
}{
|
||||
// ok, no err, claim exists
|
||||
{
|
||||
cl: Claims{
|
||||
"foo": int64(100),
|
||||
},
|
||||
key: "foo",
|
||||
val: int64(100),
|
||||
ok: true,
|
||||
err: false,
|
||||
},
|
||||
// no claims
|
||||
{
|
||||
cl: Claims{},
|
||||
key: "foo",
|
||||
val: 0,
|
||||
ok: false,
|
||||
err: false,
|
||||
},
|
||||
// missing claim
|
||||
{
|
||||
cl: Claims{
|
||||
"foo": "bar",
|
||||
},
|
||||
key: "xxx",
|
||||
val: 0,
|
||||
ok: false,
|
||||
err: false,
|
||||
},
|
||||
// unparsable: type
|
||||
{
|
||||
cl: Claims{
|
||||
"foo": struct{}{},
|
||||
},
|
||||
key: "foo",
|
||||
val: 0,
|
||||
ok: false,
|
||||
err: true,
|
||||
},
|
||||
// unparsable: nil value
|
||||
{
|
||||
cl: Claims{
|
||||
"foo": nil,
|
||||
},
|
||||
key: "foo",
|
||||
val: 0,
|
||||
ok: false,
|
||||
err: true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
val, ok, err := tt.cl.Int64Claim(tt.key)
|
||||
|
||||
if tt.err && err == nil {
|
||||
t.Errorf("case %d: want err=non-nil, got err=nil", i)
|
||||
} else if !tt.err && err != nil {
|
||||
t.Errorf("case %d: want err=nil, got err=%v", i, err)
|
||||
}
|
||||
|
||||
if tt.ok != ok {
|
||||
t.Errorf("case %d: want ok=%v, got ok=%v", i, tt.ok, ok)
|
||||
}
|
||||
|
||||
if tt.val != val {
|
||||
t.Errorf("case %d: want val=%v, got val=%v", i, tt.val, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTime(t *testing.T) {
|
||||
now := time.Now().UTC()
|
||||
unixNow := now.Unix()
|
||||
|
||||
tests := []struct {
|
||||
cl Claims
|
||||
key string
|
||||
ok bool
|
||||
err bool
|
||||
val time.Time
|
||||
}{
|
||||
// ok, no err, claim exists
|
||||
{
|
||||
cl: Claims{
|
||||
"foo": unixNow,
|
||||
},
|
||||
key: "foo",
|
||||
val: time.Unix(now.Unix(), 0).UTC(),
|
||||
ok: true,
|
||||
err: false,
|
||||
},
|
||||
// no claims
|
||||
{
|
||||
cl: Claims{},
|
||||
key: "foo",
|
||||
val: time.Time{},
|
||||
ok: false,
|
||||
err: false,
|
||||
},
|
||||
// missing claim
|
||||
{
|
||||
cl: Claims{
|
||||
"foo": "bar",
|
||||
},
|
||||
key: "xxx",
|
||||
val: time.Time{},
|
||||
ok: false,
|
||||
err: false,
|
||||
},
|
||||
// unparsable: type
|
||||
{
|
||||
cl: Claims{
|
||||
"foo": struct{}{},
|
||||
},
|
||||
key: "foo",
|
||||
val: time.Time{},
|
||||
ok: false,
|
||||
err: true,
|
||||
},
|
||||
// unparsable: nil value
|
||||
{
|
||||
cl: Claims{
|
||||
"foo": nil,
|
||||
},
|
||||
key: "foo",
|
||||
val: time.Time{},
|
||||
ok: false,
|
||||
err: true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
val, ok, err := tt.cl.TimeClaim(tt.key)
|
||||
|
||||
if tt.err && err == nil {
|
||||
t.Errorf("case %d: want err=non-nil, got err=nil", i)
|
||||
} else if !tt.err && err != nil {
|
||||
t.Errorf("case %d: want err=nil, got err=%v", i, err)
|
||||
}
|
||||
|
||||
if tt.ok != ok {
|
||||
t.Errorf("case %d: want ok=%v, got ok=%v", i, tt.ok, ok)
|
||||
}
|
||||
|
||||
if tt.val != val {
|
||||
t.Errorf("case %d: want val=%v, got val=%v", i, tt.val, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringArray(t *testing.T) {
|
||||
tests := []struct {
|
||||
cl Claims
|
||||
key string
|
||||
ok bool
|
||||
err bool
|
||||
val []string
|
||||
}{
|
||||
// ok, no err, claim exists
|
||||
{
|
||||
cl: Claims{
|
||||
"foo": []string{"bar", "faf"},
|
||||
},
|
||||
key: "foo",
|
||||
val: []string{"bar", "faf"},
|
||||
ok: true,
|
||||
err: false,
|
||||
},
|
||||
// ok, no err, []interface{}
|
||||
{
|
||||
cl: Claims{
|
||||
"foo": []interface{}{"bar", "faf"},
|
||||
},
|
||||
key: "foo",
|
||||
val: []string{"bar", "faf"},
|
||||
ok: true,
|
||||
err: false,
|
||||
},
|
||||
// no claims
|
||||
{
|
||||
cl: Claims{},
|
||||
key: "foo",
|
||||
val: nil,
|
||||
ok: false,
|
||||
err: false,
|
||||
},
|
||||
// missing claim
|
||||
{
|
||||
cl: Claims{
|
||||
"foo": "bar",
|
||||
},
|
||||
key: "xxx",
|
||||
val: nil,
|
||||
ok: false,
|
||||
err: false,
|
||||
},
|
||||
// unparsable: type
|
||||
{
|
||||
cl: Claims{
|
||||
"foo": struct{}{},
|
||||
},
|
||||
key: "foo",
|
||||
val: nil,
|
||||
ok: false,
|
||||
err: true,
|
||||
},
|
||||
// unparsable: nil value
|
||||
{
|
||||
cl: Claims{
|
||||
"foo": nil,
|
||||
},
|
||||
key: "foo",
|
||||
val: nil,
|
||||
ok: false,
|
||||
err: true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
val, ok, err := tt.cl.StringsClaim(tt.key)
|
||||
|
||||
if tt.err && err == nil {
|
||||
t.Errorf("case %d: want err=non-nil, got err=nil", i)
|
||||
} else if !tt.err && err != nil {
|
||||
t.Errorf("case %d: want err=nil, got err=%v", i, err)
|
||||
}
|
||||
|
||||
if tt.ok != ok {
|
||||
t.Errorf("case %d: want ok=%v, got ok=%v", i, tt.ok, ok)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(tt.val, val) {
|
||||
t.Errorf("case %d: want val=%v, got val=%v", i, tt.val, val)
|
||||
}
|
||||
}
|
||||
}
|
2
vendor/github.com/coreos/go-oidc/jose/doc.go
generated
vendored
2
vendor/github.com/coreos/go-oidc/jose/doc.go
generated
vendored
|
@ -1,2 +0,0 @@
|
|||
// Package jose is DEPRECATED. Use gopkg.in/square/go-jose.v2 instead.
|
||||
package jose
|
112
vendor/github.com/coreos/go-oidc/jose/jose.go
generated
vendored
112
vendor/github.com/coreos/go-oidc/jose/jose.go
generated
vendored
|
@ -1,112 +0,0 @@
|
|||
package jose
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
HeaderMediaType = "typ"
|
||||
HeaderKeyAlgorithm = "alg"
|
||||
HeaderKeyID = "kid"
|
||||
)
|
||||
|
||||
const (
|
||||
// Encryption Algorithm Header Parameter Values for JWS
|
||||
// See: https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40#page-6
|
||||
AlgHS256 = "HS256"
|
||||
AlgHS384 = "HS384"
|
||||
AlgHS512 = "HS512"
|
||||
AlgRS256 = "RS256"
|
||||
AlgRS384 = "RS384"
|
||||
AlgRS512 = "RS512"
|
||||
AlgES256 = "ES256"
|
||||
AlgES384 = "ES384"
|
||||
AlgES512 = "ES512"
|
||||
AlgPS256 = "PS256"
|
||||
AlgPS384 = "PS384"
|
||||
AlgPS512 = "PS512"
|
||||
AlgNone = "none"
|
||||
)
|
||||
|
||||
const (
|
||||
// Algorithm Header Parameter Values for JWE
|
||||
// See: https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40#section-4.1
|
||||
AlgRSA15 = "RSA1_5"
|
||||
AlgRSAOAEP = "RSA-OAEP"
|
||||
AlgRSAOAEP256 = "RSA-OAEP-256"
|
||||
AlgA128KW = "A128KW"
|
||||
AlgA192KW = "A192KW"
|
||||
AlgA256KW = "A256KW"
|
||||
AlgDir = "dir"
|
||||
AlgECDHES = "ECDH-ES"
|
||||
AlgECDHESA128KW = "ECDH-ES+A128KW"
|
||||
AlgECDHESA192KW = "ECDH-ES+A192KW"
|
||||
AlgECDHESA256KW = "ECDH-ES+A256KW"
|
||||
AlgA128GCMKW = "A128GCMKW"
|
||||
AlgA192GCMKW = "A192GCMKW"
|
||||
AlgA256GCMKW = "A256GCMKW"
|
||||
AlgPBES2HS256A128KW = "PBES2-HS256+A128KW"
|
||||
AlgPBES2HS384A192KW = "PBES2-HS384+A192KW"
|
||||
AlgPBES2HS512A256KW = "PBES2-HS512+A256KW"
|
||||
)
|
||||
|
||||
const (
|
||||
// Encryption Algorithm Header Parameter Values for JWE
|
||||
// See: https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40#page-22
|
||||
EncA128CBCHS256 = "A128CBC-HS256"
|
||||
EncA128CBCHS384 = "A128CBC-HS384"
|
||||
EncA256CBCHS512 = "A256CBC-HS512"
|
||||
EncA128GCM = "A128GCM"
|
||||
EncA192GCM = "A192GCM"
|
||||
EncA256GCM = "A256GCM"
|
||||
)
|
||||
|
||||
type JOSEHeader map[string]string
|
||||
|
||||
func (j JOSEHeader) Validate() error {
|
||||
if _, exists := j[HeaderKeyAlgorithm]; !exists {
|
||||
return fmt.Errorf("header missing %q parameter", HeaderKeyAlgorithm)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeHeader(seg string) (JOSEHeader, error) {
|
||||
b, err := decodeSegment(seg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var h JOSEHeader
|
||||
err = json.Unmarshal(b, &h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func encodeHeader(h JOSEHeader) (string, error) {
|
||||
b, err := json.Marshal(h)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return encodeSegment(b), nil
|
||||
}
|
||||
|
||||
// Decode JWT specific base64url encoding with padding stripped
|
||||
func decodeSegment(seg string) ([]byte, error) {
|
||||
if l := len(seg) % 4; l != 0 {
|
||||
seg += strings.Repeat("=", 4-l)
|
||||
}
|
||||
return base64.URLEncoding.DecodeString(seg)
|
||||
}
|
||||
|
||||
// Encode JWT specific base64url encoding with padding stripped
|
||||
func encodeSegment(seg []byte) string {
|
||||
return strings.TrimRight(base64.URLEncoding.EncodeToString(seg), "=")
|
||||
}
|
135
vendor/github.com/coreos/go-oidc/jose/jwk.go
generated
vendored
135
vendor/github.com/coreos/go-oidc/jose/jwk.go
generated
vendored
|
@ -1,135 +0,0 @@
|
|||
package jose
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// JSON Web Key
|
||||
// https://tools.ietf.org/html/draft-ietf-jose-json-web-key-36#page-5
|
||||
type JWK struct {
|
||||
ID string
|
||||
Type string
|
||||
Alg string
|
||||
Use string
|
||||
Exponent int
|
||||
Modulus *big.Int
|
||||
Secret []byte
|
||||
}
|
||||
|
||||
type jwkJSON struct {
|
||||
ID string `json:"kid"`
|
||||
Type string `json:"kty"`
|
||||
Alg string `json:"alg"`
|
||||
Use string `json:"use"`
|
||||
Exponent string `json:"e"`
|
||||
Modulus string `json:"n"`
|
||||
}
|
||||
|
||||
func (j *JWK) MarshalJSON() ([]byte, error) {
|
||||
t := jwkJSON{
|
||||
ID: j.ID,
|
||||
Type: j.Type,
|
||||
Alg: j.Alg,
|
||||
Use: j.Use,
|
||||
Exponent: encodeExponent(j.Exponent),
|
||||
Modulus: encodeModulus(j.Modulus),
|
||||
}
|
||||
|
||||
return json.Marshal(&t)
|
||||
}
|
||||
|
||||
func (j *JWK) UnmarshalJSON(data []byte) error {
|
||||
var t jwkJSON
|
||||
err := json.Unmarshal(data, &t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
e, err := decodeExponent(t.Exponent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n, err := decodeModulus(t.Modulus)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
j.ID = t.ID
|
||||
j.Type = t.Type
|
||||
j.Alg = t.Alg
|
||||
j.Use = t.Use
|
||||
j.Exponent = e
|
||||
j.Modulus = n
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type JWKSet struct {
|
||||
Keys []JWK `json:"keys"`
|
||||
}
|
||||
|
||||
func decodeExponent(e string) (int, error) {
|
||||
decE, err := decodeBase64URLPaddingOptional(e)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var eBytes []byte
|
||||
if len(decE) < 8 {
|
||||
eBytes = make([]byte, 8-len(decE), 8)
|
||||
eBytes = append(eBytes, decE...)
|
||||
} else {
|
||||
eBytes = decE
|
||||
}
|
||||
eReader := bytes.NewReader(eBytes)
|
||||
var E uint64
|
||||
err = binary.Read(eReader, binary.BigEndian, &E)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int(E), nil
|
||||
}
|
||||
|
||||
func encodeExponent(e int) string {
|
||||
b := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(b, uint64(e))
|
||||
var idx int
|
||||
for ; idx < 8; idx++ {
|
||||
if b[idx] != 0x0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return base64.RawURLEncoding.EncodeToString(b[idx:])
|
||||
}
|
||||
|
||||
// Turns a URL encoded modulus of a key into a big int.
|
||||
func decodeModulus(n string) (*big.Int, error) {
|
||||
decN, err := decodeBase64URLPaddingOptional(n)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
N := big.NewInt(0)
|
||||
N.SetBytes(decN)
|
||||
return N, nil
|
||||
}
|
||||
|
||||
func encodeModulus(n *big.Int) string {
|
||||
return base64.RawURLEncoding.EncodeToString(n.Bytes())
|
||||
}
|
||||
|
||||
// decodeBase64URLPaddingOptional decodes Base64 whether there is padding or not.
|
||||
// The stdlib version currently doesn't handle this.
|
||||
// We can get rid of this is if this bug:
|
||||
// https://github.com/golang/go/issues/4237
|
||||
// ever closes.
|
||||
func decodeBase64URLPaddingOptional(e string) ([]byte, error) {
|
||||
if m := len(e) % 4; m != 0 {
|
||||
e += strings.Repeat("=", 4-m)
|
||||
}
|
||||
return base64.URLEncoding.DecodeString(e)
|
||||
}
|
64
vendor/github.com/coreos/go-oidc/jose/jwk_test.go
generated
vendored
64
vendor/github.com/coreos/go-oidc/jose/jwk_test.go
generated
vendored
|
@ -1,64 +0,0 @@
|
|||
package jose
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDecodeBase64URLPaddingOptional(t *testing.T) {
|
||||
tests := []struct {
|
||||
encoded string
|
||||
decoded string
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
// With padding
|
||||
encoded: "VGVjdG9uaWM=",
|
||||
decoded: "Tectonic",
|
||||
},
|
||||
{
|
||||
// Without padding
|
||||
encoded: "VGVjdG9uaWM",
|
||||
decoded: "Tectonic",
|
||||
},
|
||||
{
|
||||
// Even More padding
|
||||
encoded: "VGVjdG9uaQ==",
|
||||
decoded: "Tectoni",
|
||||
},
|
||||
{
|
||||
// And take it away!
|
||||
encoded: "VGVjdG9uaQ",
|
||||
decoded: "Tectoni",
|
||||
},
|
||||
{
|
||||
// Too much padding.
|
||||
encoded: "VGVjdG9uaWNh=",
|
||||
decoded: "",
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
// Too much padding.
|
||||
encoded: "VGVjdG9uaWNh=",
|
||||
decoded: "",
|
||||
err: true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
got, err := decodeBase64URLPaddingOptional(tt.encoded)
|
||||
if tt.err {
|
||||
if err == nil {
|
||||
t.Errorf("case %d: expected non-nil err", i)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("case %d: want nil err, got: %v", i, err)
|
||||
}
|
||||
|
||||
if string(got) != tt.decoded {
|
||||
t.Errorf("case %d: want=%q, got=%q", i, tt.decoded, got)
|
||||
}
|
||||
}
|
||||
}
|
51
vendor/github.com/coreos/go-oidc/jose/jws.go
generated
vendored
51
vendor/github.com/coreos/go-oidc/jose/jws.go
generated
vendored
|
@ -1,51 +0,0 @@
|
|||
package jose
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type JWS struct {
|
||||
RawHeader string
|
||||
Header JOSEHeader
|
||||
RawPayload string
|
||||
Payload []byte
|
||||
Signature []byte
|
||||
}
|
||||
|
||||
// Given a raw encoded JWS token parses it and verifies the structure.
|
||||
func ParseJWS(raw string) (JWS, error) {
|
||||
parts := strings.Split(raw, ".")
|
||||
if len(parts) != 3 {
|
||||
return JWS{}, fmt.Errorf("malformed JWS, only %d segments", len(parts))
|
||||
}
|
||||
|
||||
rawSig := parts[2]
|
||||
jws := JWS{
|
||||
RawHeader: parts[0],
|
||||
RawPayload: parts[1],
|
||||
}
|
||||
|
||||
header, err := decodeHeader(jws.RawHeader)
|
||||
if err != nil {
|
||||
return JWS{}, fmt.Errorf("malformed JWS, unable to decode header, %s", err)
|
||||
}
|
||||
if err = header.Validate(); err != nil {
|
||||
return JWS{}, fmt.Errorf("malformed JWS, %s", err)
|
||||
}
|
||||
jws.Header = header
|
||||
|
||||
payload, err := decodeSegment(jws.RawPayload)
|
||||
if err != nil {
|
||||
return JWS{}, fmt.Errorf("malformed JWS, unable to decode payload: %s", err)
|
||||
}
|
||||
jws.Payload = payload
|
||||
|
||||
sig, err := decodeSegment(rawSig)
|
||||
if err != nil {
|
||||
return JWS{}, fmt.Errorf("malformed JWS, unable to decode signature: %s", err)
|
||||
}
|
||||
jws.Signature = sig
|
||||
|
||||
return jws, nil
|
||||
}
|
74
vendor/github.com/coreos/go-oidc/jose/jws_test.go
generated
vendored
74
vendor/github.com/coreos/go-oidc/jose/jws_test.go
generated
vendored
|
@ -1,74 +0,0 @@
|
|||
package jose
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type testCase struct{ t string }
|
||||
|
||||
var validInput []testCase
|
||||
|
||||
var invalidInput []testCase
|
||||
|
||||
func init() {
|
||||
validInput = []testCase{
|
||||
{
|
||||
"eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
|
||||
},
|
||||
}
|
||||
|
||||
invalidInput = []testCase{
|
||||
// empty
|
||||
{
|
||||
"",
|
||||
},
|
||||
// undecodeable
|
||||
{
|
||||
"aaa.bbb.ccc",
|
||||
},
|
||||
// missing parts
|
||||
{
|
||||
"aaa",
|
||||
},
|
||||
// missing parts
|
||||
{
|
||||
"aaa.bbb",
|
||||
},
|
||||
// too many parts
|
||||
{
|
||||
"aaa.bbb.ccc.ddd",
|
||||
},
|
||||
// invalid header
|
||||
// EncodeHeader(map[string]string{"foo": "bar"})
|
||||
{
|
||||
"eyJmb28iOiJiYXIifQ.bbb.ccc",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseJWS(t *testing.T) {
|
||||
for i, tt := range validInput {
|
||||
jws, err := ParseJWS(tt.t)
|
||||
if err != nil {
|
||||
t.Errorf("test: %d. expected: valid, actual: invalid", i)
|
||||
}
|
||||
|
||||
expectedHeader := strings.Split(tt.t, ".")[0]
|
||||
if jws.RawHeader != expectedHeader {
|
||||
t.Errorf("test: %d. expected: %s, actual: %s", i, expectedHeader, jws.RawHeader)
|
||||
}
|
||||
|
||||
expectedPayload := strings.Split(tt.t, ".")[1]
|
||||
if jws.RawPayload != expectedPayload {
|
||||
t.Errorf("test: %d. expected: %s, actual: %s", i, expectedPayload, jws.RawPayload)
|
||||
}
|
||||
}
|
||||
|
||||
for i, tt := range invalidInput {
|
||||
_, err := ParseJWS(tt.t)
|
||||
if err == nil {
|
||||
t.Errorf("test: %d. expected: invalid, actual: valid", i)
|
||||
}
|
||||
}
|
||||
}
|
82
vendor/github.com/coreos/go-oidc/jose/jwt.go
generated
vendored
82
vendor/github.com/coreos/go-oidc/jose/jwt.go
generated
vendored
|
@ -1,82 +0,0 @@
|
|||
package jose
|
||||
|
||||
import "strings"
|
||||
|
||||
type JWT JWS
|
||||
|
||||
func ParseJWT(token string) (jwt JWT, err error) {
|
||||
jws, err := ParseJWS(token)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return JWT(jws), nil
|
||||
}
|
||||
|
||||
func NewJWT(header JOSEHeader, claims Claims) (jwt JWT, err error) {
|
||||
jwt = JWT{}
|
||||
|
||||
jwt.Header = header
|
||||
jwt.Header[HeaderMediaType] = "JWT"
|
||||
|
||||
claimBytes, err := marshalClaims(claims)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
jwt.Payload = claimBytes
|
||||
|
||||
eh, err := encodeHeader(header)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
jwt.RawHeader = eh
|
||||
|
||||
ec, err := encodeClaims(claims)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
jwt.RawPayload = ec
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (j *JWT) KeyID() (string, bool) {
|
||||
kID, ok := j.Header[HeaderKeyID]
|
||||
return kID, ok
|
||||
}
|
||||
|
||||
func (j *JWT) Claims() (Claims, error) {
|
||||
return decodeClaims(j.Payload)
|
||||
}
|
||||
|
||||
// Encoded data part of the token which may be signed.
|
||||
func (j *JWT) Data() string {
|
||||
return strings.Join([]string{j.RawHeader, j.RawPayload}, ".")
|
||||
}
|
||||
|
||||
// Full encoded JWT token string in format: header.claims.signature
|
||||
func (j *JWT) Encode() string {
|
||||
d := j.Data()
|
||||
s := encodeSegment(j.Signature)
|
||||
return strings.Join([]string{d, s}, ".")
|
||||
}
|
||||
|
||||
func NewSignedJWT(claims Claims, s Signer) (*JWT, error) {
|
||||
header := JOSEHeader{
|
||||
HeaderKeyAlgorithm: s.Alg(),
|
||||
HeaderKeyID: s.ID(),
|
||||
}
|
||||
|
||||
jwt, err := NewJWT(header, claims)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sig, err := s.Sign([]byte(jwt.Data()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
jwt.Signature = sig
|
||||
|
||||
return &jwt, nil
|
||||
}
|
94
vendor/github.com/coreos/go-oidc/jose/jwt_test.go
generated
vendored
94
vendor/github.com/coreos/go-oidc/jose/jwt_test.go
generated
vendored
|
@ -1,94 +0,0 @@
|
|||
package jose
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseJWT(t *testing.T) {
|
||||
tests := []struct {
|
||||
r string
|
||||
h JOSEHeader
|
||||
c Claims
|
||||
}{
|
||||
{
|
||||
// Example from JWT spec:
|
||||
// http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#ExampleJWT
|
||||
"eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
|
||||
JOSEHeader{
|
||||
HeaderMediaType: "JWT",
|
||||
HeaderKeyAlgorithm: "HS256",
|
||||
},
|
||||
Claims{
|
||||
"iss": "joe",
|
||||
// NOTE: test numbers must be floats for equality checks to work since values are converted form interface{} to float64 by default.
|
||||
"exp": 1300819380.0,
|
||||
"http://example.com/is_root": true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
jwt, err := ParseJWT(tt.r)
|
||||
if err != nil {
|
||||
t.Errorf("raw token should parse. test: %d. expected: valid, actual: invalid. err=%v", i, err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(tt.h, jwt.Header) {
|
||||
t.Errorf("JOSE headers should match. test: %d. expected: %v, actual: %v", i, tt.h, jwt.Header)
|
||||
}
|
||||
|
||||
claims, err := jwt.Claims()
|
||||
if err != nil {
|
||||
t.Errorf("test: %d. expected: valid claim parsing. err=%v", i, err)
|
||||
}
|
||||
if !reflect.DeepEqual(tt.c, claims) {
|
||||
t.Errorf("claims should match. test: %d. expected: %v, actual: %v", i, tt.c, claims)
|
||||
}
|
||||
|
||||
enc := jwt.Encode()
|
||||
if enc != tt.r {
|
||||
t.Errorf("encoded jwt should match raw jwt. test: %d. expected: %v, actual: %v", i, tt.r, enc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewJWTHeaderType(t *testing.T) {
|
||||
jwt, err := NewJWT(JOSEHeader{}, Claims{})
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
want := "JWT"
|
||||
got := jwt.Header[HeaderMediaType]
|
||||
if want != got {
|
||||
t.Fatalf("Header %q incorrect: want=%s got=%s", HeaderMediaType, want, got)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNewJWTHeaderKeyID(t *testing.T) {
|
||||
jwt, err := NewJWT(JOSEHeader{HeaderKeyID: "foo"}, Claims{})
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
want := "foo"
|
||||
got, ok := jwt.KeyID()
|
||||
if !ok {
|
||||
t.Fatalf("KeyID not set")
|
||||
} else if want != got {
|
||||
t.Fatalf("KeyID incorrect: want=%s got=%s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewJWTHeaderKeyIDNotSet(t *testing.T) {
|
||||
jwt, err := NewJWT(JOSEHeader{}, Claims{})
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if _, ok := jwt.KeyID(); ok {
|
||||
t.Fatalf("KeyID set, but should not be")
|
||||
}
|
||||
}
|
24
vendor/github.com/coreos/go-oidc/jose/sig.go
generated
vendored
24
vendor/github.com/coreos/go-oidc/jose/sig.go
generated
vendored
|
@ -1,24 +0,0 @@
|
|||
package jose
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Verifier interface {
|
||||
ID() string
|
||||
Alg() string
|
||||
Verify(sig []byte, data []byte) error
|
||||
}
|
||||
|
||||
type Signer interface {
|
||||
Verifier
|
||||
Sign(data []byte) (sig []byte, err error)
|
||||
}
|
||||
|
||||
func NewVerifier(jwk JWK) (Verifier, error) {
|
||||
if jwk.Type != "RSA" {
|
||||
return nil, fmt.Errorf("unsupported key type %q", jwk.Type)
|
||||
}
|
||||
|
||||
return NewVerifierRSA(jwk)
|
||||
}
|
67
vendor/github.com/coreos/go-oidc/jose/sig_rsa.go
generated
vendored
67
vendor/github.com/coreos/go-oidc/jose/sig_rsa.go
generated
vendored
|
@ -1,67 +0,0 @@
|
|||
package jose
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type VerifierRSA struct {
|
||||
KeyID string
|
||||
Hash crypto.Hash
|
||||
PublicKey rsa.PublicKey
|
||||
}
|
||||
|
||||
type SignerRSA struct {
|
||||
PrivateKey rsa.PrivateKey
|
||||
VerifierRSA
|
||||
}
|
||||
|
||||
func NewVerifierRSA(jwk JWK) (*VerifierRSA, error) {
|
||||
if jwk.Alg != "" && jwk.Alg != "RS256" {
|
||||
return nil, fmt.Errorf("unsupported key algorithm %q", jwk.Alg)
|
||||
}
|
||||
|
||||
v := VerifierRSA{
|
||||
KeyID: jwk.ID,
|
||||
PublicKey: rsa.PublicKey{
|
||||
N: jwk.Modulus,
|
||||
E: jwk.Exponent,
|
||||
},
|
||||
Hash: crypto.SHA256,
|
||||
}
|
||||
|
||||
return &v, nil
|
||||
}
|
||||
|
||||
func NewSignerRSA(kid string, key rsa.PrivateKey) *SignerRSA {
|
||||
return &SignerRSA{
|
||||
PrivateKey: key,
|
||||
VerifierRSA: VerifierRSA{
|
||||
KeyID: kid,
|
||||
PublicKey: key.PublicKey,
|
||||
Hash: crypto.SHA256,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (v *VerifierRSA) ID() string {
|
||||
return v.KeyID
|
||||
}
|
||||
|
||||
func (v *VerifierRSA) Alg() string {
|
||||
return "RS256"
|
||||
}
|
||||
|
||||
func (v *VerifierRSA) Verify(sig []byte, data []byte) error {
|
||||
h := v.Hash.New()
|
||||
h.Write(data)
|
||||
return rsa.VerifyPKCS1v15(&v.PublicKey, v.Hash, h.Sum(nil), sig)
|
||||
}
|
||||
|
||||
func (s *SignerRSA) Sign(data []byte) ([]byte, error) {
|
||||
h := s.Hash.New()
|
||||
h.Write(data)
|
||||
return rsa.SignPKCS1v15(rand.Reader, &s.PrivateKey, s.Hash, h.Sum(nil))
|
||||
}
|
2
vendor/github.com/coreos/go-oidc/key/doc.go
generated
vendored
2
vendor/github.com/coreos/go-oidc/key/doc.go
generated
vendored
|
@ -1,2 +0,0 @@
|
|||
// Package key is DEPRECATED. Use github.com/coreos/go-oidc instead.
|
||||
package key
|
153
vendor/github.com/coreos/go-oidc/key/key.go
generated
vendored
153
vendor/github.com/coreos/go-oidc/key/key.go
generated
vendored
|
@ -1,153 +0,0 @@
|
|||
package key
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-oidc/jose"
|
||||
)
|
||||
|
||||
func NewPublicKey(jwk jose.JWK) *PublicKey {
|
||||
return &PublicKey{jwk: jwk}
|
||||
}
|
||||
|
||||
type PublicKey struct {
|
||||
jwk jose.JWK
|
||||
}
|
||||
|
||||
func (k *PublicKey) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(&k.jwk)
|
||||
}
|
||||
|
||||
func (k *PublicKey) UnmarshalJSON(data []byte) error {
|
||||
var jwk jose.JWK
|
||||
if err := json.Unmarshal(data, &jwk); err != nil {
|
||||
return err
|
||||
}
|
||||
k.jwk = jwk
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *PublicKey) ID() string {
|
||||
return k.jwk.ID
|
||||
}
|
||||
|
||||
func (k *PublicKey) Verifier() (jose.Verifier, error) {
|
||||
return jose.NewVerifierRSA(k.jwk)
|
||||
}
|
||||
|
||||
type PrivateKey struct {
|
||||
KeyID string
|
||||
PrivateKey *rsa.PrivateKey
|
||||
}
|
||||
|
||||
func (k *PrivateKey) ID() string {
|
||||
return k.KeyID
|
||||
}
|
||||
|
||||
func (k *PrivateKey) Signer() jose.Signer {
|
||||
return jose.NewSignerRSA(k.ID(), *k.PrivateKey)
|
||||
}
|
||||
|
||||
func (k *PrivateKey) JWK() jose.JWK {
|
||||
return jose.JWK{
|
||||
ID: k.KeyID,
|
||||
Type: "RSA",
|
||||
Alg: "RS256",
|
||||
Use: "sig",
|
||||
Exponent: k.PrivateKey.PublicKey.E,
|
||||
Modulus: k.PrivateKey.PublicKey.N,
|
||||
}
|
||||
}
|
||||
|
||||
type KeySet interface {
|
||||
ExpiresAt() time.Time
|
||||
}
|
||||
|
||||
type PublicKeySet struct {
|
||||
keys []PublicKey
|
||||
index map[string]*PublicKey
|
||||
expiresAt time.Time
|
||||
}
|
||||
|
||||
func NewPublicKeySet(jwks []jose.JWK, exp time.Time) *PublicKeySet {
|
||||
keys := make([]PublicKey, len(jwks))
|
||||
index := make(map[string]*PublicKey)
|
||||
for i, jwk := range jwks {
|
||||
keys[i] = *NewPublicKey(jwk)
|
||||
index[keys[i].ID()] = &keys[i]
|
||||
}
|
||||
return &PublicKeySet{
|
||||
keys: keys,
|
||||
index: index,
|
||||
expiresAt: exp,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *PublicKeySet) ExpiresAt() time.Time {
|
||||
return s.expiresAt
|
||||
}
|
||||
|
||||
func (s *PublicKeySet) Keys() []PublicKey {
|
||||
return s.keys
|
||||
}
|
||||
|
||||
func (s *PublicKeySet) Key(id string) *PublicKey {
|
||||
return s.index[id]
|
||||
}
|
||||
|
||||
type PrivateKeySet struct {
|
||||
keys []*PrivateKey
|
||||
ActiveKeyID string
|
||||
expiresAt time.Time
|
||||
}
|
||||
|
||||
func NewPrivateKeySet(keys []*PrivateKey, exp time.Time) *PrivateKeySet {
|
||||
return &PrivateKeySet{
|
||||
keys: keys,
|
||||
ActiveKeyID: keys[0].ID(),
|
||||
expiresAt: exp.UTC(),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *PrivateKeySet) Keys() []*PrivateKey {
|
||||
return s.keys
|
||||
}
|
||||
|
||||
func (s *PrivateKeySet) ExpiresAt() time.Time {
|
||||
return s.expiresAt
|
||||
}
|
||||
|
||||
func (s *PrivateKeySet) Active() *PrivateKey {
|
||||
for i, k := range s.keys {
|
||||
if k.ID() == s.ActiveKeyID {
|
||||
return s.keys[i]
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type GeneratePrivateKeyFunc func() (*PrivateKey, error)
|
||||
|
||||
func GeneratePrivateKey() (*PrivateKey, error) {
|
||||
pk, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keyID := make([]byte, 20)
|
||||
if _, err := io.ReadFull(rand.Reader, keyID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
k := PrivateKey{
|
||||
KeyID: hex.EncodeToString(keyID),
|
||||
PrivateKey: pk,
|
||||
}
|
||||
|
||||
return &k, nil
|
||||
}
|
103
vendor/github.com/coreos/go-oidc/key/key_test.go
generated
vendored
103
vendor/github.com/coreos/go-oidc/key/key_test.go
generated
vendored
|
@ -1,103 +0,0 @@
|
|||
package key
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-oidc/jose"
|
||||
)
|
||||
|
||||
func TestPrivateRSAKeyJWK(t *testing.T) {
|
||||
n := big.NewInt(int64(17))
|
||||
if n == nil {
|
||||
panic("NewInt returned nil")
|
||||
}
|
||||
|
||||
k := &PrivateKey{
|
||||
KeyID: "foo",
|
||||
PrivateKey: &rsa.PrivateKey{
|
||||
PublicKey: rsa.PublicKey{N: n, E: 65537},
|
||||
},
|
||||
}
|
||||
|
||||
want := jose.JWK{
|
||||
ID: "foo",
|
||||
Type: "RSA",
|
||||
Alg: "RS256",
|
||||
Use: "sig",
|
||||
Modulus: n,
|
||||
Exponent: 65537,
|
||||
}
|
||||
|
||||
got := k.JWK()
|
||||
if !reflect.DeepEqual(want, got) {
|
||||
t.Fatalf("JWK mismatch: want=%#v got=%#v", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPublicKeySetKey(t *testing.T) {
|
||||
n := big.NewInt(int64(17))
|
||||
if n == nil {
|
||||
panic("NewInt returned nil")
|
||||
}
|
||||
|
||||
k := jose.JWK{
|
||||
ID: "foo",
|
||||
Type: "RSA",
|
||||
Alg: "RS256",
|
||||
Use: "sig",
|
||||
Modulus: n,
|
||||
Exponent: 65537,
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
ks := NewPublicKeySet([]jose.JWK{k}, now)
|
||||
|
||||
want := &PublicKey{jwk: k}
|
||||
got := ks.Key("foo")
|
||||
if !reflect.DeepEqual(want, got) {
|
||||
t.Errorf("Unexpected response from PublicKeySet.Key: want=%#v got=%#v", want, got)
|
||||
}
|
||||
|
||||
got = ks.Key("bar")
|
||||
if got != nil {
|
||||
t.Errorf("Expected nil response from PublicKeySet.Key, got %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPublicKeyMarshalJSON(t *testing.T) {
|
||||
k := jose.JWK{
|
||||
ID: "foo",
|
||||
Type: "RSA",
|
||||
Alg: "RS256",
|
||||
Use: "sig",
|
||||
Modulus: big.NewInt(int64(17)),
|
||||
Exponent: 65537,
|
||||
}
|
||||
want := `{"kid":"foo","kty":"RSA","alg":"RS256","use":"sig","e":"AQAB","n":"EQ"}`
|
||||
pubKey := NewPublicKey(k)
|
||||
gotBytes, err := pubKey.MarshalJSON()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to marshal public key: %v", err)
|
||||
}
|
||||
got := string(gotBytes)
|
||||
if got != want {
|
||||
t.Errorf("got != want:\n%s\n%s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGeneratePrivateKeyIDs(t *testing.T) {
|
||||
key1, err := GeneratePrivateKey()
|
||||
if err != nil {
|
||||
t.Fatalf("GeneratePrivateKey(): %v", err)
|
||||
}
|
||||
key2, err := GeneratePrivateKey()
|
||||
if err != nil {
|
||||
t.Fatalf("GeneratePrivateKey(): %v", err)
|
||||
}
|
||||
if key1.KeyID == key2.KeyID {
|
||||
t.Fatalf("expected different keys to have different key IDs")
|
||||
}
|
||||
}
|
99
vendor/github.com/coreos/go-oidc/key/manager.go
generated
vendored
99
vendor/github.com/coreos/go-oidc/key/manager.go
generated
vendored
|
@ -1,99 +0,0 @@
|
|||
package key
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/jonboulle/clockwork"
|
||||
|
||||
"github.com/coreos/go-oidc/jose"
|
||||
"github.com/coreos/pkg/health"
|
||||
)
|
||||
|
||||
type PrivateKeyManager interface {
|
||||
ExpiresAt() time.Time
|
||||
Signer() (jose.Signer, error)
|
||||
JWKs() ([]jose.JWK, error)
|
||||
PublicKeys() ([]PublicKey, error)
|
||||
|
||||
WritableKeySetRepo
|
||||
health.Checkable
|
||||
}
|
||||
|
||||
func NewPrivateKeyManager() PrivateKeyManager {
|
||||
return &privateKeyManager{
|
||||
clock: clockwork.NewRealClock(),
|
||||
}
|
||||
}
|
||||
|
||||
type privateKeyManager struct {
|
||||
keySet *PrivateKeySet
|
||||
clock clockwork.Clock
|
||||
}
|
||||
|
||||
func (m *privateKeyManager) ExpiresAt() time.Time {
|
||||
if m.keySet == nil {
|
||||
return m.clock.Now().UTC()
|
||||
}
|
||||
|
||||
return m.keySet.ExpiresAt()
|
||||
}
|
||||
|
||||
func (m *privateKeyManager) Signer() (jose.Signer, error) {
|
||||
if err := m.Healthy(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return m.keySet.Active().Signer(), nil
|
||||
}
|
||||
|
||||
func (m *privateKeyManager) JWKs() ([]jose.JWK, error) {
|
||||
if err := m.Healthy(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keys := m.keySet.Keys()
|
||||
jwks := make([]jose.JWK, len(keys))
|
||||
for i, k := range keys {
|
||||
jwks[i] = k.JWK()
|
||||
}
|
||||
return jwks, nil
|
||||
}
|
||||
|
||||
func (m *privateKeyManager) PublicKeys() ([]PublicKey, error) {
|
||||
jwks, err := m.JWKs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keys := make([]PublicKey, len(jwks))
|
||||
for i, jwk := range jwks {
|
||||
keys[i] = *NewPublicKey(jwk)
|
||||
}
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
func (m *privateKeyManager) Healthy() error {
|
||||
if m.keySet == nil {
|
||||
return errors.New("private key manager uninitialized")
|
||||
}
|
||||
|
||||
if len(m.keySet.Keys()) == 0 {
|
||||
return errors.New("private key manager zero keys")
|
||||
}
|
||||
|
||||
if m.keySet.ExpiresAt().Before(m.clock.Now().UTC()) {
|
||||
return errors.New("private key manager keys expired")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *privateKeyManager) Set(keySet KeySet) error {
|
||||
privKeySet, ok := keySet.(*PrivateKeySet)
|
||||
if !ok {
|
||||
return errors.New("unable to cast to PrivateKeySet")
|
||||
}
|
||||
|
||||
m.keySet = privKeySet
|
||||
return nil
|
||||
}
|
225
vendor/github.com/coreos/go-oidc/key/manager_test.go
generated
vendored
225
vendor/github.com/coreos/go-oidc/key/manager_test.go
generated
vendored
|
@ -1,225 +0,0 @@
|
|||
package key
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/jonboulle/clockwork"
|
||||
|
||||
"github.com/coreos/go-oidc/jose"
|
||||
)
|
||||
|
||||
var (
|
||||
jwk1 jose.JWK
|
||||
jwk2 jose.JWK
|
||||
jwk3 jose.JWK
|
||||
)
|
||||
|
||||
func init() {
|
||||
jwk1 = jose.JWK{
|
||||
ID: "1",
|
||||
Type: "RSA",
|
||||
Alg: "RS256",
|
||||
Use: "sig",
|
||||
Modulus: big.NewInt(1),
|
||||
Exponent: 65537,
|
||||
}
|
||||
|
||||
jwk2 = jose.JWK{
|
||||
ID: "2",
|
||||
Type: "RSA",
|
||||
Alg: "RS256",
|
||||
Use: "sig",
|
||||
Modulus: big.NewInt(2),
|
||||
Exponent: 65537,
|
||||
}
|
||||
|
||||
jwk3 = jose.JWK{
|
||||
ID: "3",
|
||||
Type: "RSA",
|
||||
Alg: "RS256",
|
||||
Use: "sig",
|
||||
Modulus: big.NewInt(3),
|
||||
Exponent: 65537,
|
||||
}
|
||||
}
|
||||
|
||||
func generatePrivateKeyStatic(t *testing.T, idAndN int) *PrivateKey {
|
||||
n := big.NewInt(int64(idAndN))
|
||||
if n == nil {
|
||||
t.Fatalf("Call to NewInt(%d) failed", idAndN)
|
||||
}
|
||||
|
||||
pk := &rsa.PrivateKey{
|
||||
PublicKey: rsa.PublicKey{N: n, E: 65537},
|
||||
}
|
||||
|
||||
return &PrivateKey{
|
||||
KeyID: strconv.Itoa(idAndN),
|
||||
PrivateKey: pk,
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrivateKeyManagerJWKsRotate(t *testing.T) {
|
||||
k1 := generatePrivateKeyStatic(t, 1)
|
||||
k2 := generatePrivateKeyStatic(t, 2)
|
||||
k3 := generatePrivateKeyStatic(t, 3)
|
||||
km := NewPrivateKeyManager()
|
||||
err := km.Set(&PrivateKeySet{
|
||||
keys: []*PrivateKey{k1, k2, k3},
|
||||
ActiveKeyID: k1.KeyID,
|
||||
expiresAt: time.Now().Add(time.Minute),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
want := []jose.JWK{jwk1, jwk2, jwk3}
|
||||
got, err := km.JWKs()
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(want, got) {
|
||||
t.Fatalf("JWK mismatch: want=%#v got=%#v", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrivateKeyManagerSigner(t *testing.T) {
|
||||
k := generatePrivateKeyStatic(t, 13)
|
||||
|
||||
km := NewPrivateKeyManager()
|
||||
err := km.Set(&PrivateKeySet{
|
||||
keys: []*PrivateKey{k},
|
||||
ActiveKeyID: k.KeyID,
|
||||
expiresAt: time.Now().Add(time.Minute),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
signer, err := km.Signer()
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
wantID := "13"
|
||||
gotID := signer.ID()
|
||||
if wantID != gotID {
|
||||
t.Fatalf("Signer has incorrect ID: want=%s got=%s", wantID, gotID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrivateKeyManagerHealthyFail(t *testing.T) {
|
||||
keyFixture := generatePrivateKeyStatic(t, 1)
|
||||
tests := []*privateKeyManager{
|
||||
// keySet nil
|
||||
&privateKeyManager{
|
||||
keySet: nil,
|
||||
clock: clockwork.NewRealClock(),
|
||||
},
|
||||
// zero keys
|
||||
&privateKeyManager{
|
||||
keySet: &PrivateKeySet{
|
||||
keys: []*PrivateKey{},
|
||||
expiresAt: time.Now().Add(time.Minute),
|
||||
},
|
||||
clock: clockwork.NewRealClock(),
|
||||
},
|
||||
// key set expired
|
||||
&privateKeyManager{
|
||||
keySet: &PrivateKeySet{
|
||||
keys: []*PrivateKey{keyFixture},
|
||||
expiresAt: time.Now().Add(-1 * time.Minute),
|
||||
},
|
||||
clock: clockwork.NewRealClock(),
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
if err := tt.Healthy(); err == nil {
|
||||
t.Errorf("case %d: nil error", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrivateKeyManagerHealthyFailsOtherMethods(t *testing.T) {
|
||||
km := NewPrivateKeyManager()
|
||||
if _, err := km.JWKs(); err == nil {
|
||||
t.Fatalf("Expected non-nil error")
|
||||
}
|
||||
if _, err := km.Signer(); err == nil {
|
||||
t.Fatalf("Expected non-nil error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrivateKeyManagerExpiresAt(t *testing.T) {
|
||||
fc := clockwork.NewFakeClock()
|
||||
now := fc.Now().UTC()
|
||||
|
||||
k := generatePrivateKeyStatic(t, 17)
|
||||
km := &privateKeyManager{
|
||||
clock: fc,
|
||||
}
|
||||
|
||||
want := fc.Now().UTC()
|
||||
got := km.ExpiresAt()
|
||||
if want != got {
|
||||
t.Fatalf("Incorrect expiration time: want=%v got=%v", want, got)
|
||||
}
|
||||
|
||||
err := km.Set(&PrivateKeySet{
|
||||
keys: []*PrivateKey{k},
|
||||
ActiveKeyID: k.KeyID,
|
||||
expiresAt: now.Add(2 * time.Minute),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
want = fc.Now().UTC().Add(2 * time.Minute)
|
||||
got = km.ExpiresAt()
|
||||
if want != got {
|
||||
t.Fatalf("Incorrect expiration time: want=%v got=%v", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPublicKeys(t *testing.T) {
|
||||
km := NewPrivateKeyManager()
|
||||
k1 := generatePrivateKeyStatic(t, 1)
|
||||
k2 := generatePrivateKeyStatic(t, 2)
|
||||
k3 := generatePrivateKeyStatic(t, 3)
|
||||
|
||||
tests := [][]*PrivateKey{
|
||||
[]*PrivateKey{k1},
|
||||
[]*PrivateKey{k1, k2},
|
||||
[]*PrivateKey{k1, k2, k3},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
ks := &PrivateKeySet{
|
||||
keys: tt,
|
||||
expiresAt: time.Now().Add(time.Hour),
|
||||
}
|
||||
km.Set(ks)
|
||||
|
||||
jwks, err := km.JWKs()
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
pks := NewPublicKeySet(jwks, time.Now().Add(time.Hour))
|
||||
want := pks.Keys()
|
||||
got, err := km.PublicKeys()
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(want, got) {
|
||||
t.Errorf("case %d: Invalid public keys: want=%v got=%v", i, want, got)
|
||||
}
|
||||
}
|
||||
}
|
55
vendor/github.com/coreos/go-oidc/key/repo.go
generated
vendored
55
vendor/github.com/coreos/go-oidc/key/repo.go
generated
vendored
|
@ -1,55 +0,0 @@
|
|||
package key
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var ErrorNoKeys = errors.New("no keys found")
|
||||
|
||||
type WritableKeySetRepo interface {
|
||||
Set(KeySet) error
|
||||
}
|
||||
|
||||
type ReadableKeySetRepo interface {
|
||||
Get() (KeySet, error)
|
||||
}
|
||||
|
||||
type PrivateKeySetRepo interface {
|
||||
WritableKeySetRepo
|
||||
ReadableKeySetRepo
|
||||
}
|
||||
|
||||
func NewPrivateKeySetRepo() PrivateKeySetRepo {
|
||||
return &memPrivateKeySetRepo{}
|
||||
}
|
||||
|
||||
type memPrivateKeySetRepo struct {
|
||||
mu sync.RWMutex
|
||||
pks PrivateKeySet
|
||||
}
|
||||
|
||||
func (r *memPrivateKeySetRepo) Set(ks KeySet) error {
|
||||
pks, ok := ks.(*PrivateKeySet)
|
||||
if !ok {
|
||||
return errors.New("unable to cast to PrivateKeySet")
|
||||
} else if pks == nil {
|
||||
return errors.New("nil KeySet")
|
||||
}
|
||||
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
r.pks = *pks
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *memPrivateKeySetRepo) Get() (KeySet, error) {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
|
||||
if r.pks.keys == nil {
|
||||
return nil, ErrorNoKeys
|
||||
}
|
||||
return KeySet(&r.pks), nil
|
||||
}
|
159
vendor/github.com/coreos/go-oidc/key/rotate.go
generated
vendored
159
vendor/github.com/coreos/go-oidc/key/rotate.go
generated
vendored
|
@ -1,159 +0,0 @@
|
|||
package key
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
ptime "github.com/coreos/pkg/timeutil"
|
||||
"github.com/jonboulle/clockwork"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrorPrivateKeysExpired = errors.New("private keys have expired")
|
||||
)
|
||||
|
||||
func NewPrivateKeyRotator(repo PrivateKeySetRepo, ttl time.Duration) *PrivateKeyRotator {
|
||||
return &PrivateKeyRotator{
|
||||
repo: repo,
|
||||
ttl: ttl,
|
||||
|
||||
keep: 2,
|
||||
generateKey: GeneratePrivateKey,
|
||||
clock: clockwork.NewRealClock(),
|
||||
}
|
||||
}
|
||||
|
||||
type PrivateKeyRotator struct {
|
||||
repo PrivateKeySetRepo
|
||||
generateKey GeneratePrivateKeyFunc
|
||||
clock clockwork.Clock
|
||||
keep int
|
||||
ttl time.Duration
|
||||
}
|
||||
|
||||
func (r *PrivateKeyRotator) expiresAt() time.Time {
|
||||
return r.clock.Now().UTC().Add(r.ttl)
|
||||
}
|
||||
|
||||
func (r *PrivateKeyRotator) Healthy() error {
|
||||
pks, err := r.privateKeySet()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if r.clock.Now().After(pks.ExpiresAt()) {
|
||||
return ErrorPrivateKeysExpired
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *PrivateKeyRotator) privateKeySet() (*PrivateKeySet, error) {
|
||||
ks, err := r.repo.Get()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pks, ok := ks.(*PrivateKeySet)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to cast to PrivateKeySet")
|
||||
}
|
||||
return pks, nil
|
||||
}
|
||||
|
||||
func (r *PrivateKeyRotator) nextRotation() (time.Duration, error) {
|
||||
pks, err := r.privateKeySet()
|
||||
if err == ErrorNoKeys {
|
||||
return 0, nil
|
||||
}
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
now := r.clock.Now()
|
||||
|
||||
// Ideally, we want to rotate after half the TTL has elapsed.
|
||||
idealRotationTime := pks.ExpiresAt().Add(-r.ttl / 2)
|
||||
|
||||
// If we are past the ideal rotation time, rotate immediatly.
|
||||
return max(0, idealRotationTime.Sub(now)), nil
|
||||
}
|
||||
|
||||
func max(a, b time.Duration) time.Duration {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (r *PrivateKeyRotator) Run() chan struct{} {
|
||||
attempt := func() {
|
||||
k, err := r.generateKey()
|
||||
if err != nil {
|
||||
log.Printf("go-oidc: failed generating signing key: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
exp := r.expiresAt()
|
||||
if err := rotatePrivateKeys(r.repo, k, r.keep, exp); err != nil {
|
||||
log.Printf("go-oidc: key rotation failed: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
stop := make(chan struct{})
|
||||
go func() {
|
||||
for {
|
||||
var nextRotation time.Duration
|
||||
var sleep time.Duration
|
||||
var err error
|
||||
for {
|
||||
if nextRotation, err = r.nextRotation(); err == nil {
|
||||
break
|
||||
}
|
||||
sleep = ptime.ExpBackoff(sleep, time.Minute)
|
||||
log.Printf("go-oidc: error getting nextRotation, retrying in %v: %v", sleep, err)
|
||||
time.Sleep(sleep)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-r.clock.After(nextRotation):
|
||||
attempt()
|
||||
case <-stop:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return stop
|
||||
}
|
||||
|
||||
func rotatePrivateKeys(repo PrivateKeySetRepo, k *PrivateKey, keep int, exp time.Time) error {
|
||||
ks, err := repo.Get()
|
||||
if err != nil && err != ErrorNoKeys {
|
||||
return err
|
||||
}
|
||||
|
||||
var keys []*PrivateKey
|
||||
if ks != nil {
|
||||
pks, ok := ks.(*PrivateKeySet)
|
||||
if !ok {
|
||||
return errors.New("unable to cast to PrivateKeySet")
|
||||
}
|
||||
keys = pks.Keys()
|
||||
}
|
||||
|
||||
keys = append([]*PrivateKey{k}, keys...)
|
||||
if l := len(keys); l > keep {
|
||||
keys = keys[0:keep]
|
||||
}
|
||||
|
||||
nks := PrivateKeySet{
|
||||
keys: keys,
|
||||
ActiveKeyID: k.ID(),
|
||||
expiresAt: exp,
|
||||
}
|
||||
|
||||
return repo.Set(KeySet(&nks))
|
||||
}
|
311
vendor/github.com/coreos/go-oidc/key/rotate_test.go
generated
vendored
311
vendor/github.com/coreos/go-oidc/key/rotate_test.go
generated
vendored
|
@ -1,311 +0,0 @@
|
|||
package key
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/jonboulle/clockwork"
|
||||
)
|
||||
|
||||
func generatePrivateKeySerialFunc(t *testing.T) GeneratePrivateKeyFunc {
|
||||
var n int
|
||||
return func() (*PrivateKey, error) {
|
||||
n++
|
||||
return generatePrivateKeyStatic(t, n), nil
|
||||
}
|
||||
}
|
||||
|
||||
func TestRotate(t *testing.T) {
|
||||
now := time.Now()
|
||||
k1 := generatePrivateKeyStatic(t, 1)
|
||||
k2 := generatePrivateKeyStatic(t, 2)
|
||||
k3 := generatePrivateKeyStatic(t, 3)
|
||||
|
||||
tests := []struct {
|
||||
start *PrivateKeySet
|
||||
key *PrivateKey
|
||||
keep int
|
||||
exp time.Time
|
||||
want *PrivateKeySet
|
||||
}{
|
||||
// start with nil keys
|
||||
{
|
||||
start: nil,
|
||||
key: k1,
|
||||
keep: 2,
|
||||
exp: now.Add(time.Second),
|
||||
want: &PrivateKeySet{
|
||||
keys: []*PrivateKey{k1},
|
||||
ActiveKeyID: k1.KeyID,
|
||||
expiresAt: now.Add(time.Second),
|
||||
},
|
||||
},
|
||||
// start with zero keys
|
||||
{
|
||||
start: &PrivateKeySet{},
|
||||
key: k1,
|
||||
keep: 2,
|
||||
exp: now.Add(time.Second),
|
||||
want: &PrivateKeySet{
|
||||
keys: []*PrivateKey{k1},
|
||||
ActiveKeyID: k1.KeyID,
|
||||
expiresAt: now.Add(time.Second),
|
||||
},
|
||||
},
|
||||
// add second key
|
||||
{
|
||||
start: &PrivateKeySet{
|
||||
keys: []*PrivateKey{k1},
|
||||
ActiveKeyID: k1.KeyID,
|
||||
expiresAt: now,
|
||||
},
|
||||
key: k2,
|
||||
keep: 2,
|
||||
exp: now.Add(time.Second),
|
||||
want: &PrivateKeySet{
|
||||
keys: []*PrivateKey{k2, k1},
|
||||
ActiveKeyID: k2.KeyID,
|
||||
expiresAt: now.Add(time.Second),
|
||||
},
|
||||
},
|
||||
// rotate in third key
|
||||
{
|
||||
start: &PrivateKeySet{
|
||||
keys: []*PrivateKey{k2, k1},
|
||||
ActiveKeyID: k2.KeyID,
|
||||
expiresAt: now,
|
||||
},
|
||||
key: k3,
|
||||
keep: 2,
|
||||
exp: now.Add(time.Second),
|
||||
want: &PrivateKeySet{
|
||||
keys: []*PrivateKey{k3, k2},
|
||||
ActiveKeyID: k3.KeyID,
|
||||
expiresAt: now.Add(time.Second),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
repo := NewPrivateKeySetRepo()
|
||||
if tt.start != nil {
|
||||
err := repo.Set(tt.start)
|
||||
if err != nil {
|
||||
t.Fatalf("case %d: unexpected error: %v", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
rotatePrivateKeys(repo, tt.key, tt.keep, tt.exp)
|
||||
got, err := repo.Get()
|
||||
if err != nil {
|
||||
t.Errorf("case %d: unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(tt.want, got) {
|
||||
t.Errorf("case %d: unexpected result: want=%#v got=%#v", i, tt.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrivateKeyRotatorRun(t *testing.T) {
|
||||
fc := clockwork.NewFakeClock()
|
||||
now := fc.Now().UTC()
|
||||
|
||||
k1 := generatePrivateKeyStatic(t, 1)
|
||||
k2 := generatePrivateKeyStatic(t, 2)
|
||||
k3 := generatePrivateKeyStatic(t, 3)
|
||||
k4 := generatePrivateKeyStatic(t, 4)
|
||||
|
||||
kRepo := NewPrivateKeySetRepo()
|
||||
krot := NewPrivateKeyRotator(kRepo, 4*time.Second)
|
||||
krot.clock = fc
|
||||
krot.generateKey = generatePrivateKeySerialFunc(t)
|
||||
|
||||
steps := []*PrivateKeySet{
|
||||
&PrivateKeySet{
|
||||
keys: []*PrivateKey{k1},
|
||||
ActiveKeyID: k1.KeyID,
|
||||
expiresAt: now.Add(4 * time.Second),
|
||||
},
|
||||
&PrivateKeySet{
|
||||
keys: []*PrivateKey{k2, k1},
|
||||
ActiveKeyID: k2.KeyID,
|
||||
expiresAt: now.Add(6 * time.Second),
|
||||
},
|
||||
&PrivateKeySet{
|
||||
keys: []*PrivateKey{k3, k2},
|
||||
ActiveKeyID: k3.KeyID,
|
||||
expiresAt: now.Add(8 * time.Second),
|
||||
},
|
||||
&PrivateKeySet{
|
||||
keys: []*PrivateKey{k4, k3},
|
||||
ActiveKeyID: k4.KeyID,
|
||||
expiresAt: now.Add(10 * time.Second),
|
||||
},
|
||||
}
|
||||
|
||||
stop := krot.Run()
|
||||
defer close(stop)
|
||||
|
||||
for i, st := range steps {
|
||||
// wait for the rotater to get sleepy
|
||||
fc.BlockUntil(1)
|
||||
|
||||
got, err := kRepo.Get()
|
||||
if err != nil {
|
||||
t.Fatalf("step %d: unexpected error: %v", i, err)
|
||||
}
|
||||
if !reflect.DeepEqual(st, got) {
|
||||
t.Fatalf("step %d: unexpected state: want=%#v got=%#v", i, st, got)
|
||||
}
|
||||
fc.Advance(2 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrivateKeyRotatorExpiresAt(t *testing.T) {
|
||||
fc := clockwork.NewFakeClock()
|
||||
krot := &PrivateKeyRotator{
|
||||
clock: fc,
|
||||
ttl: time.Minute,
|
||||
}
|
||||
got := krot.expiresAt()
|
||||
want := fc.Now().UTC().Add(time.Minute)
|
||||
if !reflect.DeepEqual(want, got) {
|
||||
t.Errorf("Incorrect expiration time: want=%v got=%v", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNextRotation(t *testing.T) {
|
||||
fc := clockwork.NewFakeClock()
|
||||
now := fc.Now().UTC()
|
||||
|
||||
tests := []struct {
|
||||
expiresAt time.Time
|
||||
ttl time.Duration
|
||||
numKeys int
|
||||
expected time.Duration
|
||||
}{
|
||||
{
|
||||
// closest to prod
|
||||
expiresAt: now.Add(time.Hour * 24),
|
||||
ttl: time.Hour * 24,
|
||||
numKeys: 2,
|
||||
expected: time.Hour * 12,
|
||||
},
|
||||
{
|
||||
expiresAt: now.Add(time.Hour * 2),
|
||||
ttl: time.Hour * 4,
|
||||
numKeys: 2,
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
// No keys.
|
||||
expiresAt: now.Add(time.Hour * 2),
|
||||
ttl: time.Hour * 4,
|
||||
numKeys: 0,
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
// Nil keyset.
|
||||
expiresAt: now.Add(time.Hour * 2),
|
||||
ttl: time.Hour * 4,
|
||||
numKeys: -1,
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
// KeySet expired.
|
||||
expiresAt: now.Add(time.Hour * -2),
|
||||
ttl: time.Hour * 4,
|
||||
numKeys: 2,
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
// Expiry past now + TTL
|
||||
expiresAt: now.Add(time.Hour * 5),
|
||||
ttl: time.Hour * 4,
|
||||
numKeys: 2,
|
||||
expected: 3 * time.Hour,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
kRepo := NewPrivateKeySetRepo()
|
||||
krot := NewPrivateKeyRotator(kRepo, tt.ttl)
|
||||
krot.clock = fc
|
||||
pks := &PrivateKeySet{
|
||||
expiresAt: tt.expiresAt,
|
||||
}
|
||||
if tt.numKeys != -1 {
|
||||
for n := 0; n < tt.numKeys; n++ {
|
||||
pks.keys = append(pks.keys, generatePrivateKeyStatic(t, n))
|
||||
}
|
||||
err := kRepo.Set(pks)
|
||||
if err != nil {
|
||||
t.Fatalf("case %d: unexpected error: %v", i, err)
|
||||
}
|
||||
|
||||
}
|
||||
actual, err := krot.nextRotation()
|
||||
if err != nil {
|
||||
t.Errorf("case %d: error calling shouldRotate(): %v", i, err)
|
||||
}
|
||||
if actual != tt.expected {
|
||||
t.Errorf("case %d: actual == %v, want %v", i, actual, tt.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHealthy(t *testing.T) {
|
||||
fc := clockwork.NewFakeClock()
|
||||
now := fc.Now().UTC()
|
||||
|
||||
tests := []struct {
|
||||
expiresAt time.Time
|
||||
numKeys int
|
||||
expected error
|
||||
}{
|
||||
{
|
||||
expiresAt: now.Add(time.Hour),
|
||||
numKeys: 2,
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
expiresAt: now.Add(time.Hour),
|
||||
numKeys: -1,
|
||||
expected: ErrorNoKeys,
|
||||
},
|
||||
{
|
||||
expiresAt: now.Add(time.Hour),
|
||||
numKeys: 0,
|
||||
expected: ErrorNoKeys,
|
||||
},
|
||||
{
|
||||
expiresAt: now.Add(-time.Hour),
|
||||
numKeys: 2,
|
||||
expected: ErrorPrivateKeysExpired,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
kRepo := NewPrivateKeySetRepo()
|
||||
krot := NewPrivateKeyRotator(kRepo, time.Hour)
|
||||
krot.clock = fc
|
||||
pks := &PrivateKeySet{
|
||||
expiresAt: tt.expiresAt,
|
||||
}
|
||||
if tt.numKeys != -1 {
|
||||
for n := 0; n < tt.numKeys; n++ {
|
||||
pks.keys = append(pks.keys, generatePrivateKeyStatic(t, n))
|
||||
}
|
||||
err := kRepo.Set(pks)
|
||||
if err != nil {
|
||||
t.Fatalf("case %d: unexpected error: %v", i, err)
|
||||
}
|
||||
|
||||
}
|
||||
if err := krot.Healthy(); err != tt.expected {
|
||||
t.Errorf("case %d: got==%q, want==%q", i, err, tt.expected)
|
||||
}
|
||||
}
|
||||
}
|
91
vendor/github.com/coreos/go-oidc/key/sync.go
generated
vendored
91
vendor/github.com/coreos/go-oidc/key/sync.go
generated
vendored
|
@ -1,91 +0,0 @@
|
|||
package key
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/jonboulle/clockwork"
|
||||
|
||||
"github.com/coreos/pkg/timeutil"
|
||||
)
|
||||
|
||||
func NewKeySetSyncer(r ReadableKeySetRepo, w WritableKeySetRepo) *KeySetSyncer {
|
||||
return &KeySetSyncer{
|
||||
readable: r,
|
||||
writable: w,
|
||||
clock: clockwork.NewRealClock(),
|
||||
}
|
||||
}
|
||||
|
||||
type KeySetSyncer struct {
|
||||
readable ReadableKeySetRepo
|
||||
writable WritableKeySetRepo
|
||||
clock clockwork.Clock
|
||||
}
|
||||
|
||||
func (s *KeySetSyncer) Run() chan struct{} {
|
||||
stop := make(chan struct{})
|
||||
go func() {
|
||||
var failing bool
|
||||
var next time.Duration
|
||||
for {
|
||||
exp, err := syncKeySet(s.readable, s.writable, s.clock)
|
||||
if err != nil || exp == 0 {
|
||||
if !failing {
|
||||
failing = true
|
||||
next = time.Second
|
||||
} else {
|
||||
next = timeutil.ExpBackoff(next, time.Minute)
|
||||
}
|
||||
if exp == 0 {
|
||||
log.Printf("Synced to already expired key set, retrying in %v: %v", next, err)
|
||||
|
||||
} else {
|
||||
log.Printf("Failed syncing key set, retrying in %v: %v", next, err)
|
||||
}
|
||||
} else {
|
||||
failing = false
|
||||
next = exp / 2
|
||||
}
|
||||
|
||||
select {
|
||||
case <-s.clock.After(next):
|
||||
continue
|
||||
case <-stop:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return stop
|
||||
}
|
||||
|
||||
func Sync(r ReadableKeySetRepo, w WritableKeySetRepo) (time.Duration, error) {
|
||||
return syncKeySet(r, w, clockwork.NewRealClock())
|
||||
}
|
||||
|
||||
// syncKeySet copies the keyset from r to the KeySet at w and returns the duration in which the KeySet will expire.
|
||||
// If keyset has already expired, returns a zero duration.
|
||||
func syncKeySet(r ReadableKeySetRepo, w WritableKeySetRepo, clock clockwork.Clock) (exp time.Duration, err error) {
|
||||
var ks KeySet
|
||||
ks, err = r.Get()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if ks == nil {
|
||||
err = errors.New("no source KeySet")
|
||||
return
|
||||
}
|
||||
|
||||
if err = w.Set(ks); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
now := clock.Now()
|
||||
if ks.ExpiresAt().After(now) {
|
||||
exp = ks.ExpiresAt().Sub(now)
|
||||
}
|
||||
return
|
||||
}
|
214
vendor/github.com/coreos/go-oidc/key/sync_test.go
generated
vendored
214
vendor/github.com/coreos/go-oidc/key/sync_test.go
generated
vendored
|
@ -1,214 +0,0 @@
|
|||
package key
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/jonboulle/clockwork"
|
||||
)
|
||||
|
||||
type staticReadableKeySetRepo struct {
|
||||
mu sync.RWMutex
|
||||
ks KeySet
|
||||
err error
|
||||
}
|
||||
|
||||
func (r *staticReadableKeySetRepo) Get() (KeySet, error) {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
return r.ks, r.err
|
||||
}
|
||||
|
||||
func (r *staticReadableKeySetRepo) set(ks KeySet, err error) {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
r.ks, r.err = ks, err
|
||||
}
|
||||
|
||||
func TestKeySyncerSync(t *testing.T) {
|
||||
fc := clockwork.NewFakeClock()
|
||||
now := fc.Now().UTC()
|
||||
|
||||
k1 := generatePrivateKeyStatic(t, 1)
|
||||
k2 := generatePrivateKeyStatic(t, 2)
|
||||
k3 := generatePrivateKeyStatic(t, 3)
|
||||
|
||||
steps := []struct {
|
||||
fromKS KeySet
|
||||
fromErr error
|
||||
advance time.Duration
|
||||
want *PrivateKeySet
|
||||
}{
|
||||
// on startup, first sync should trigger within a second
|
||||
{
|
||||
fromKS: &PrivateKeySet{
|
||||
keys: []*PrivateKey{k1},
|
||||
ActiveKeyID: k1.KeyID,
|
||||
expiresAt: now.Add(10 * time.Second),
|
||||
},
|
||||
advance: time.Second,
|
||||
want: &PrivateKeySet{
|
||||
keys: []*PrivateKey{k1},
|
||||
ActiveKeyID: k1.KeyID,
|
||||
expiresAt: now.Add(10 * time.Second),
|
||||
},
|
||||
},
|
||||
// advance halfway into TTL, triggering sync
|
||||
{
|
||||
fromKS: &PrivateKeySet{
|
||||
keys: []*PrivateKey{k2, k1},
|
||||
ActiveKeyID: k2.KeyID,
|
||||
expiresAt: now.Add(15 * time.Second),
|
||||
},
|
||||
advance: 5 * time.Second,
|
||||
want: &PrivateKeySet{
|
||||
keys: []*PrivateKey{k2, k1},
|
||||
ActiveKeyID: k2.KeyID,
|
||||
expiresAt: now.Add(15 * time.Second),
|
||||
},
|
||||
},
|
||||
|
||||
// advance halfway into TTL, triggering sync that fails
|
||||
{
|
||||
fromErr: errors.New("fail!"),
|
||||
advance: 10 * time.Second,
|
||||
want: &PrivateKeySet{
|
||||
keys: []*PrivateKey{k2, k1},
|
||||
ActiveKeyID: k2.KeyID,
|
||||
expiresAt: now.Add(15 * time.Second),
|
||||
},
|
||||
},
|
||||
|
||||
// sync retries quickly, and succeeds with fixed data
|
||||
{
|
||||
fromKS: &PrivateKeySet{
|
||||
keys: []*PrivateKey{k3, k2, k1},
|
||||
ActiveKeyID: k3.KeyID,
|
||||
expiresAt: now.Add(25 * time.Second),
|
||||
},
|
||||
advance: 3 * time.Second,
|
||||
want: &PrivateKeySet{
|
||||
keys: []*PrivateKey{k3, k2, k1},
|
||||
ActiveKeyID: k3.KeyID,
|
||||
expiresAt: now.Add(25 * time.Second),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
from := &staticReadableKeySetRepo{}
|
||||
to := NewPrivateKeySetRepo()
|
||||
|
||||
syncer := NewKeySetSyncer(from, to)
|
||||
syncer.clock = fc
|
||||
stop := syncer.Run()
|
||||
defer close(stop)
|
||||
|
||||
for i, st := range steps {
|
||||
from.set(st.fromKS, st.fromErr)
|
||||
|
||||
fc.Advance(st.advance)
|
||||
fc.BlockUntil(1)
|
||||
|
||||
ks, err := to.Get()
|
||||
if err != nil {
|
||||
t.Fatalf("step %d: unable to get keys: %v", i, err)
|
||||
}
|
||||
if !reflect.DeepEqual(st.want, ks) {
|
||||
t.Fatalf("step %d: incorrect state: want=%#v got=%#v", i, st.want, ks)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSync(t *testing.T) {
|
||||
fc := clockwork.NewFakeClock()
|
||||
now := fc.Now().UTC()
|
||||
|
||||
k1 := generatePrivateKeyStatic(t, 1)
|
||||
k2 := generatePrivateKeyStatic(t, 2)
|
||||
k3 := generatePrivateKeyStatic(t, 3)
|
||||
|
||||
tests := []struct {
|
||||
keySet *PrivateKeySet
|
||||
want time.Duration
|
||||
}{
|
||||
{
|
||||
keySet: &PrivateKeySet{
|
||||
keys: []*PrivateKey{k1},
|
||||
ActiveKeyID: k1.KeyID,
|
||||
expiresAt: now.Add(time.Minute),
|
||||
},
|
||||
want: time.Minute,
|
||||
},
|
||||
{
|
||||
keySet: &PrivateKeySet{
|
||||
keys: []*PrivateKey{k2, k1},
|
||||
ActiveKeyID: k2.KeyID,
|
||||
expiresAt: now.Add(time.Minute),
|
||||
},
|
||||
want: time.Minute,
|
||||
},
|
||||
{
|
||||
keySet: &PrivateKeySet{
|
||||
keys: []*PrivateKey{k3, k2, k1},
|
||||
ActiveKeyID: k2.KeyID,
|
||||
expiresAt: now.Add(time.Minute),
|
||||
},
|
||||
want: time.Minute,
|
||||
},
|
||||
{
|
||||
keySet: &PrivateKeySet{
|
||||
keys: []*PrivateKey{k2, k1},
|
||||
ActiveKeyID: k2.KeyID,
|
||||
expiresAt: now.Add(time.Hour),
|
||||
},
|
||||
want: time.Hour,
|
||||
},
|
||||
{
|
||||
keySet: &PrivateKeySet{
|
||||
keys: []*PrivateKey{k1},
|
||||
ActiveKeyID: k1.KeyID,
|
||||
expiresAt: now.Add(-time.Hour),
|
||||
},
|
||||
want: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
from := NewPrivateKeySetRepo()
|
||||
to := NewPrivateKeySetRepo()
|
||||
|
||||
err := from.Set(tt.keySet)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
exp, err := syncKeySet(from, to, fc)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if tt.want != exp {
|
||||
t.Errorf("case %d: want=%v got=%v", i, tt.want, exp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSyncFail(t *testing.T) {
|
||||
tests := []error{
|
||||
nil,
|
||||
errors.New("fail!"),
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
from := &staticReadableKeySetRepo{ks: nil, err: tt}
|
||||
to := NewPrivateKeySetRepo()
|
||||
|
||||
if _, err := syncKeySet(from, to, clockwork.NewFakeClock()); err == nil {
|
||||
t.Errorf("case %d: expected non-nil error", i)
|
||||
}
|
||||
}
|
||||
}
|
2
vendor/github.com/coreos/go-oidc/oauth2/doc.go
generated
vendored
2
vendor/github.com/coreos/go-oidc/oauth2/doc.go
generated
vendored
|
@ -1,2 +0,0 @@
|
|||
// Package oauth2 is DEPRECATED. Use golang.org/x/oauth instead.
|
||||
package oauth2
|
29
vendor/github.com/coreos/go-oidc/oauth2/error.go
generated
vendored
29
vendor/github.com/coreos/go-oidc/oauth2/error.go
generated
vendored
|
@ -1,29 +0,0 @@
|
|||
package oauth2
|
||||
|
||||
const (
|
||||
ErrorAccessDenied = "access_denied"
|
||||
ErrorInvalidClient = "invalid_client"
|
||||
ErrorInvalidGrant = "invalid_grant"
|
||||
ErrorInvalidRequest = "invalid_request"
|
||||
ErrorServerError = "server_error"
|
||||
ErrorUnauthorizedClient = "unauthorized_client"
|
||||
ErrorUnsupportedGrantType = "unsupported_grant_type"
|
||||
ErrorUnsupportedResponseType = "unsupported_response_type"
|
||||
)
|
||||
|
||||
type Error struct {
|
||||
Type string `json:"error"`
|
||||
Description string `json:"error_description,omitempty"`
|
||||
State string `json:"state,omitempty"`
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
if e.Description != "" {
|
||||
return e.Type + ": " + e.Description
|
||||
}
|
||||
return e.Type
|
||||
}
|
||||
|
||||
func NewError(typ string) *Error {
|
||||
return &Error{Type: typ}
|
||||
}
|
416
vendor/github.com/coreos/go-oidc/oauth2/oauth2.go
generated
vendored
416
vendor/github.com/coreos/go-oidc/oauth2/oauth2.go
generated
vendored
|
@ -1,416 +0,0 @@
|
|||
package oauth2
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"mime"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
phttp "github.com/coreos/go-oidc/http"
|
||||
)
|
||||
|
||||
// ResponseTypesEqual compares two response_type values. If either
|
||||
// contains a space, it is treated as an unordered list. For example,
|
||||
// comparing "code id_token" and "id_token code" would evaluate to true.
|
||||
func ResponseTypesEqual(r1, r2 string) bool {
|
||||
if !strings.Contains(r1, " ") || !strings.Contains(r2, " ") {
|
||||
// fast route, no split needed
|
||||
return r1 == r2
|
||||
}
|
||||
|
||||
// split, sort, and compare
|
||||
r1Fields := strings.Fields(r1)
|
||||
r2Fields := strings.Fields(r2)
|
||||
if len(r1Fields) != len(r2Fields) {
|
||||
return false
|
||||
}
|
||||
sort.Strings(r1Fields)
|
||||
sort.Strings(r2Fields)
|
||||
for i, r1Field := range r1Fields {
|
||||
if r1Field != r2Fields[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const (
|
||||
// OAuth2.0 response types registered by OIDC.
|
||||
//
|
||||
// See: https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#RegistryContents
|
||||
ResponseTypeCode = "code"
|
||||
ResponseTypeCodeIDToken = "code id_token"
|
||||
ResponseTypeCodeIDTokenToken = "code id_token token"
|
||||
ResponseTypeIDToken = "id_token"
|
||||
ResponseTypeIDTokenToken = "id_token token"
|
||||
ResponseTypeToken = "token"
|
||||
ResponseTypeNone = "none"
|
||||
)
|
||||
|
||||
const (
|
||||
GrantTypeAuthCode = "authorization_code"
|
||||
GrantTypeClientCreds = "client_credentials"
|
||||
GrantTypeUserCreds = "password"
|
||||
GrantTypeImplicit = "implicit"
|
||||
GrantTypeRefreshToken = "refresh_token"
|
||||
|
||||
AuthMethodClientSecretPost = "client_secret_post"
|
||||
AuthMethodClientSecretBasic = "client_secret_basic"
|
||||
AuthMethodClientSecretJWT = "client_secret_jwt"
|
||||
AuthMethodPrivateKeyJWT = "private_key_jwt"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Credentials ClientCredentials
|
||||
Scope []string
|
||||
RedirectURL string
|
||||
AuthURL string
|
||||
TokenURL string
|
||||
|
||||
// Must be one of the AuthMethodXXX methods above. Right now, only
|
||||
// AuthMethodClientSecretPost and AuthMethodClientSecretBasic are supported.
|
||||
AuthMethod string
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
hc phttp.Client
|
||||
creds ClientCredentials
|
||||
scope []string
|
||||
authURL *url.URL
|
||||
redirectURL *url.URL
|
||||
tokenURL *url.URL
|
||||
authMethod string
|
||||
}
|
||||
|
||||
type ClientCredentials struct {
|
||||
ID string
|
||||
Secret string
|
||||
}
|
||||
|
||||
func NewClient(hc phttp.Client, cfg Config) (c *Client, err error) {
|
||||
if len(cfg.Credentials.ID) == 0 {
|
||||
err = errors.New("missing client id")
|
||||
return
|
||||
}
|
||||
|
||||
if len(cfg.Credentials.Secret) == 0 {
|
||||
err = errors.New("missing client secret")
|
||||
return
|
||||
}
|
||||
|
||||
if cfg.AuthMethod == "" {
|
||||
cfg.AuthMethod = AuthMethodClientSecretBasic
|
||||
} else if cfg.AuthMethod != AuthMethodClientSecretPost && cfg.AuthMethod != AuthMethodClientSecretBasic {
|
||||
err = fmt.Errorf("auth method %q is not supported", cfg.AuthMethod)
|
||||
return
|
||||
}
|
||||
|
||||
au, err := phttp.ParseNonEmptyURL(cfg.AuthURL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
tu, err := phttp.ParseNonEmptyURL(cfg.TokenURL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Allow empty redirect URL in the case where the client
|
||||
// only needs to verify a given token.
|
||||
ru, err := url.Parse(cfg.RedirectURL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c = &Client{
|
||||
creds: cfg.Credentials,
|
||||
scope: cfg.Scope,
|
||||
redirectURL: ru,
|
||||
authURL: au,
|
||||
tokenURL: tu,
|
||||
hc: hc,
|
||||
authMethod: cfg.AuthMethod,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Return the embedded HTTP client
|
||||
func (c *Client) HttpClient() phttp.Client {
|
||||
return c.hc
|
||||
}
|
||||
|
||||
// Generate the url for initial redirect to oauth provider.
|
||||
func (c *Client) AuthCodeURL(state, accessType, prompt string) string {
|
||||
v := c.commonURLValues()
|
||||
v.Set("state", state)
|
||||
if strings.ToLower(accessType) == "offline" {
|
||||
v.Set("access_type", "offline")
|
||||
}
|
||||
|
||||
if prompt != "" {
|
||||
v.Set("prompt", prompt)
|
||||
}
|
||||
v.Set("response_type", "code")
|
||||
|
||||
q := v.Encode()
|
||||
u := *c.authURL
|
||||
if u.RawQuery == "" {
|
||||
u.RawQuery = q
|
||||
} else {
|
||||
u.RawQuery += "&" + q
|
||||
}
|
||||
return u.String()
|
||||
}
|
||||
|
||||
func (c *Client) commonURLValues() url.Values {
|
||||
return url.Values{
|
||||
"redirect_uri": {c.redirectURL.String()},
|
||||
"scope": {strings.Join(c.scope, " ")},
|
||||
"client_id": {c.creds.ID},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) newAuthenticatedRequest(urlToken string, values url.Values) (*http.Request, error) {
|
||||
var req *http.Request
|
||||
var err error
|
||||
switch c.authMethod {
|
||||
case AuthMethodClientSecretPost:
|
||||
values.Set("client_secret", c.creds.Secret)
|
||||
req, err = http.NewRequest("POST", urlToken, strings.NewReader(values.Encode()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case AuthMethodClientSecretBasic:
|
||||
req, err = http.NewRequest("POST", urlToken, strings.NewReader(values.Encode()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
encodedID := url.QueryEscape(c.creds.ID)
|
||||
encodedSecret := url.QueryEscape(c.creds.Secret)
|
||||
req.SetBasicAuth(encodedID, encodedSecret)
|
||||
default:
|
||||
panic("misconfigured client: auth method not supported")
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
return req, nil
|
||||
|
||||
}
|
||||
|
||||
// ClientCredsToken posts the client id and secret to obtain a token scoped to the OAuth2 client via the "client_credentials" grant type.
|
||||
// May not be supported by all OAuth2 servers.
|
||||
func (c *Client) ClientCredsToken(scope []string) (result TokenResponse, err error) {
|
||||
v := url.Values{
|
||||
"scope": {strings.Join(scope, " ")},
|
||||
"grant_type": {GrantTypeClientCreds},
|
||||
}
|
||||
|
||||
req, err := c.newAuthenticatedRequest(c.tokenURL.String(), v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := c.hc.Do(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return parseTokenResponse(resp)
|
||||
}
|
||||
|
||||
// UserCredsToken posts the username and password to obtain a token scoped to the OAuth2 client via the "password" grant_type
|
||||
// May not be supported by all OAuth2 servers.
|
||||
func (c *Client) UserCredsToken(username, password string) (result TokenResponse, err error) {
|
||||
v := url.Values{
|
||||
"scope": {strings.Join(c.scope, " ")},
|
||||
"grant_type": {GrantTypeUserCreds},
|
||||
"username": {username},
|
||||
"password": {password},
|
||||
}
|
||||
|
||||
req, err := c.newAuthenticatedRequest(c.tokenURL.String(), v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := c.hc.Do(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return parseTokenResponse(resp)
|
||||
}
|
||||
|
||||
// RequestToken requests a token from the Token Endpoint with the specified grantType.
|
||||
// If 'grantType' == GrantTypeAuthCode, then 'value' should be the authorization code.
|
||||
// If 'grantType' == GrantTypeRefreshToken, then 'value' should be the refresh token.
|
||||
func (c *Client) RequestToken(grantType, value string) (result TokenResponse, err error) {
|
||||
v := c.commonURLValues()
|
||||
|
||||
v.Set("grant_type", grantType)
|
||||
v.Set("client_secret", c.creds.Secret)
|
||||
switch grantType {
|
||||
case GrantTypeAuthCode:
|
||||
v.Set("code", value)
|
||||
case GrantTypeRefreshToken:
|
||||
v.Set("refresh_token", value)
|
||||
default:
|
||||
err = fmt.Errorf("unsupported grant_type: %v", grantType)
|
||||
return
|
||||
}
|
||||
|
||||
req, err := c.newAuthenticatedRequest(c.tokenURL.String(), v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := c.hc.Do(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return parseTokenResponse(resp)
|
||||
}
|
||||
|
||||
func parseTokenResponse(resp *http.Response) (result TokenResponse, err error) {
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
badStatusCode := resp.StatusCode < 200 || resp.StatusCode > 299
|
||||
|
||||
contentType, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
result = TokenResponse{
|
||||
RawBody: body,
|
||||
}
|
||||
|
||||
newError := func(typ, desc, state string) error {
|
||||
if typ == "" {
|
||||
return fmt.Errorf("unrecognized error %s", body)
|
||||
}
|
||||
return &Error{typ, desc, state}
|
||||
}
|
||||
|
||||
if contentType == "application/x-www-form-urlencoded" || contentType == "text/plain" {
|
||||
var vals url.Values
|
||||
vals, err = url.ParseQuery(string(body))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if error := vals.Get("error"); error != "" || badStatusCode {
|
||||
err = newError(error, vals.Get("error_description"), vals.Get("state"))
|
||||
return
|
||||
}
|
||||
e := vals.Get("expires_in")
|
||||
if e == "" {
|
||||
e = vals.Get("expires")
|
||||
}
|
||||
if e != "" {
|
||||
result.Expires, err = strconv.Atoi(e)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
result.AccessToken = vals.Get("access_token")
|
||||
result.TokenType = vals.Get("token_type")
|
||||
result.IDToken = vals.Get("id_token")
|
||||
result.RefreshToken = vals.Get("refresh_token")
|
||||
result.Scope = vals.Get("scope")
|
||||
} else {
|
||||
var r struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
TokenType string `json:"token_type"`
|
||||
IDToken string `json:"id_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
Scope string `json:"scope"`
|
||||
State string `json:"state"`
|
||||
ExpiresIn json.Number `json:"expires_in"` // Azure AD returns string
|
||||
Expires int `json:"expires"`
|
||||
Error string `json:"error"`
|
||||
Desc string `json:"error_description"`
|
||||
}
|
||||
if err = json.Unmarshal(body, &r); err != nil {
|
||||
return
|
||||
}
|
||||
if r.Error != "" || badStatusCode {
|
||||
err = newError(r.Error, r.Desc, r.State)
|
||||
return
|
||||
}
|
||||
result.AccessToken = r.AccessToken
|
||||
result.TokenType = r.TokenType
|
||||
result.IDToken = r.IDToken
|
||||
result.RefreshToken = r.RefreshToken
|
||||
result.Scope = r.Scope
|
||||
if expiresIn, err := r.ExpiresIn.Int64(); err != nil {
|
||||
result.Expires = r.Expires
|
||||
} else {
|
||||
result.Expires = int(expiresIn)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type TokenResponse struct {
|
||||
AccessToken string
|
||||
TokenType string
|
||||
Expires int
|
||||
IDToken string
|
||||
RefreshToken string // OPTIONAL.
|
||||
Scope string // OPTIONAL, if identical to the scope requested by the client, otherwise, REQUIRED.
|
||||
RawBody []byte // In case callers need some other non-standard info from the token response
|
||||
}
|
||||
|
||||
type AuthCodeRequest struct {
|
||||
ResponseType string
|
||||
ClientID string
|
||||
RedirectURL *url.URL
|
||||
Scope []string
|
||||
State string
|
||||
}
|
||||
|
||||
func ParseAuthCodeRequest(q url.Values) (AuthCodeRequest, error) {
|
||||
acr := AuthCodeRequest{
|
||||
ResponseType: q.Get("response_type"),
|
||||
ClientID: q.Get("client_id"),
|
||||
State: q.Get("state"),
|
||||
Scope: make([]string, 0),
|
||||
}
|
||||
|
||||
qs := strings.TrimSpace(q.Get("scope"))
|
||||
if qs != "" {
|
||||
acr.Scope = strings.Split(qs, " ")
|
||||
}
|
||||
|
||||
err := func() error {
|
||||
if acr.ClientID == "" {
|
||||
return NewError(ErrorInvalidRequest)
|
||||
}
|
||||
|
||||
redirectURL := q.Get("redirect_uri")
|
||||
if redirectURL != "" {
|
||||
ru, err := url.Parse(redirectURL)
|
||||
if err != nil {
|
||||
return NewError(ErrorInvalidRequest)
|
||||
}
|
||||
acr.RedirectURL = ru
|
||||
}
|
||||
|
||||
return nil
|
||||
}()
|
||||
|
||||
return acr, err
|
||||
}
|
518
vendor/github.com/coreos/go-oidc/oauth2/oauth2_test.go
generated
vendored
518
vendor/github.com/coreos/go-oidc/oauth2/oauth2_test.go
generated
vendored
|
@ -1,518 +0,0 @@
|
|||
package oauth2
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
phttp "github.com/coreos/go-oidc/http"
|
||||
)
|
||||
|
||||
func TestResponseTypesEqual(t *testing.T) {
|
||||
tests := []struct {
|
||||
r1, r2 string
|
||||
want bool
|
||||
}{
|
||||
{"code", "code", true},
|
||||
{"id_token", "code", false},
|
||||
{"code token", "token code", true},
|
||||
{"code token", "code token", true},
|
||||
{"foo", "bar code", false},
|
||||
{"code token id_token", "token id_token code", true},
|
||||
{"code token id_token", "token id_token code zoo", false},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
got1 := ResponseTypesEqual(tt.r1, tt.r2)
|
||||
got2 := ResponseTypesEqual(tt.r2, tt.r1)
|
||||
if got1 != got2 {
|
||||
t.Errorf("case %d: got different answers with different orders", i)
|
||||
}
|
||||
if tt.want != got1 {
|
||||
t.Errorf("case %d: want=%t, got=%t", i, tt.want, got1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseAuthCodeRequest(t *testing.T) {
|
||||
tests := []struct {
|
||||
query url.Values
|
||||
wantACR AuthCodeRequest
|
||||
wantErr error
|
||||
}{
|
||||
// no redirect_uri
|
||||
{
|
||||
query: url.Values{
|
||||
"response_type": []string{"code"},
|
||||
"scope": []string{"foo bar baz"},
|
||||
"client_id": []string{"XXX"},
|
||||
"state": []string{"pants"},
|
||||
},
|
||||
wantACR: AuthCodeRequest{
|
||||
ResponseType: "code",
|
||||
ClientID: "XXX",
|
||||
Scope: []string{"foo", "bar", "baz"},
|
||||
State: "pants",
|
||||
RedirectURL: nil,
|
||||
},
|
||||
},
|
||||
|
||||
// with redirect_uri
|
||||
{
|
||||
query: url.Values{
|
||||
"response_type": []string{"code"},
|
||||
"redirect_uri": []string{"https://127.0.0.1:5555/callback?foo=bar"},
|
||||
"scope": []string{"foo bar baz"},
|
||||
"client_id": []string{"XXX"},
|
||||
"state": []string{"pants"},
|
||||
},
|
||||
wantACR: AuthCodeRequest{
|
||||
ResponseType: "code",
|
||||
ClientID: "XXX",
|
||||
Scope: []string{"foo", "bar", "baz"},
|
||||
State: "pants",
|
||||
RedirectURL: &url.URL{
|
||||
Scheme: "https",
|
||||
Host: "127.0.0.1:5555",
|
||||
Path: "/callback",
|
||||
RawQuery: "foo=bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// unsupported response_type doesn't trigger error
|
||||
{
|
||||
query: url.Values{
|
||||
"response_type": []string{"token"},
|
||||
"redirect_uri": []string{"https://127.0.0.1:5555/callback?foo=bar"},
|
||||
"scope": []string{"foo bar baz"},
|
||||
"client_id": []string{"XXX"},
|
||||
"state": []string{"pants"},
|
||||
},
|
||||
wantACR: AuthCodeRequest{
|
||||
ResponseType: "token",
|
||||
ClientID: "XXX",
|
||||
Scope: []string{"foo", "bar", "baz"},
|
||||
State: "pants",
|
||||
RedirectURL: &url.URL{
|
||||
Scheme: "https",
|
||||
Host: "127.0.0.1:5555",
|
||||
Path: "/callback",
|
||||
RawQuery: "foo=bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// unparseable redirect_uri
|
||||
{
|
||||
query: url.Values{
|
||||
"response_type": []string{"code"},
|
||||
"redirect_uri": []string{":"},
|
||||
"scope": []string{"foo bar baz"},
|
||||
"client_id": []string{"XXX"},
|
||||
"state": []string{"pants"},
|
||||
},
|
||||
wantACR: AuthCodeRequest{
|
||||
ResponseType: "code",
|
||||
ClientID: "XXX",
|
||||
Scope: []string{"foo", "bar", "baz"},
|
||||
State: "pants",
|
||||
},
|
||||
wantErr: NewError(ErrorInvalidRequest),
|
||||
},
|
||||
|
||||
// no client_id, redirect_uri not parsed
|
||||
{
|
||||
query: url.Values{
|
||||
"response_type": []string{"code"},
|
||||
"redirect_uri": []string{"https://127.0.0.1:5555/callback?foo=bar"},
|
||||
"scope": []string{"foo bar baz"},
|
||||
"client_id": []string{},
|
||||
"state": []string{"pants"},
|
||||
},
|
||||
wantACR: AuthCodeRequest{
|
||||
ResponseType: "code",
|
||||
ClientID: "",
|
||||
Scope: []string{"foo", "bar", "baz"},
|
||||
State: "pants",
|
||||
RedirectURL: nil,
|
||||
},
|
||||
wantErr: NewError(ErrorInvalidRequest),
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
got, err := ParseAuthCodeRequest(tt.query)
|
||||
if !reflect.DeepEqual(tt.wantErr, err) {
|
||||
t.Errorf("case %d: incorrect error value: want=%q got=%q", i, tt.wantErr, err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(tt.wantACR, got) {
|
||||
t.Errorf("case %d: incorrect AuthCodeRequest value: want=%#v got=%#v", i, tt.wantACR, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type fakeBadClient struct {
|
||||
Request *http.Request
|
||||
err error
|
||||
}
|
||||
|
||||
func (f *fakeBadClient) Do(r *http.Request) (*http.Response, error) {
|
||||
f.Request = r
|
||||
return nil, f.err
|
||||
}
|
||||
|
||||
func TestClientCredsToken(t *testing.T) {
|
||||
hc := &fakeBadClient{nil, errors.New("error")}
|
||||
cfg := Config{
|
||||
Credentials: ClientCredentials{ID: "c#id", Secret: "c secret"},
|
||||
Scope: []string{"foo-scope", "bar-scope"},
|
||||
TokenURL: "http://example.com/token",
|
||||
AuthMethod: AuthMethodClientSecretBasic,
|
||||
RedirectURL: "http://example.com/redirect",
|
||||
AuthURL: "http://example.com/auth",
|
||||
}
|
||||
|
||||
c, err := NewClient(hc, cfg)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
scope := []string{"openid"}
|
||||
c.ClientCredsToken(scope)
|
||||
if hc.Request == nil {
|
||||
t.Error("request is empty")
|
||||
}
|
||||
|
||||
tu := hc.Request.URL.String()
|
||||
if cfg.TokenURL != tu {
|
||||
t.Errorf("wrong token url, want=%v, got=%v", cfg.TokenURL, tu)
|
||||
}
|
||||
|
||||
ct := hc.Request.Header.Get("Content-Type")
|
||||
if ct != "application/x-www-form-urlencoded" {
|
||||
t.Errorf("wrong content-type, want=application/x-www-form-urlencoded, got=%v", ct)
|
||||
}
|
||||
|
||||
cid, secret, ok := phttp.BasicAuth(hc.Request)
|
||||
if !ok {
|
||||
t.Error("unexpected error parsing basic auth")
|
||||
}
|
||||
|
||||
if url.QueryEscape(cfg.Credentials.ID) != cid {
|
||||
t.Errorf("wrong client ID, want=%v, got=%v", cfg.Credentials.ID, cid)
|
||||
}
|
||||
|
||||
if url.QueryEscape(cfg.Credentials.Secret) != secret {
|
||||
t.Errorf("wrong client secret, want=%v, got=%v", cfg.Credentials.Secret, secret)
|
||||
}
|
||||
|
||||
err = hc.Request.ParseForm()
|
||||
if err != nil {
|
||||
t.Error("unexpected error parsing form")
|
||||
}
|
||||
|
||||
gt := hc.Request.PostForm.Get("grant_type")
|
||||
if gt != GrantTypeClientCreds {
|
||||
t.Errorf("wrong grant_type, want=%v, got=%v", GrantTypeClientCreds, gt)
|
||||
}
|
||||
|
||||
sc := strings.Split(hc.Request.PostForm.Get("scope"), " ")
|
||||
if !reflect.DeepEqual(scope, sc) {
|
||||
t.Errorf("wrong scope, want=%v, got=%v", scope, sc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserCredsToken(t *testing.T) {
|
||||
hc := &fakeBadClient{nil, errors.New("error")}
|
||||
cfg := Config{
|
||||
Credentials: ClientCredentials{ID: "c#id", Secret: "c secret"},
|
||||
Scope: []string{"foo-scope", "bar-scope"},
|
||||
TokenURL: "http://example.com/token",
|
||||
AuthMethod: AuthMethodClientSecretBasic,
|
||||
RedirectURL: "http://example.com/redirect",
|
||||
AuthURL: "http://example.com/auth",
|
||||
}
|
||||
|
||||
c, err := NewClient(hc, cfg)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
c.UserCredsToken("username", "password")
|
||||
if hc.Request == nil {
|
||||
t.Error("request is empty")
|
||||
}
|
||||
|
||||
tu := hc.Request.URL.String()
|
||||
if cfg.TokenURL != tu {
|
||||
t.Errorf("wrong token url, want=%v, got=%v", cfg.TokenURL, tu)
|
||||
}
|
||||
|
||||
ct := hc.Request.Header.Get("Content-Type")
|
||||
if ct != "application/x-www-form-urlencoded" {
|
||||
t.Errorf("wrong content-type, want=application/x-www-form-urlencoded, got=%v", ct)
|
||||
}
|
||||
|
||||
cid, secret, ok := phttp.BasicAuth(hc.Request)
|
||||
if !ok {
|
||||
t.Error("unexpected error parsing basic auth")
|
||||
}
|
||||
|
||||
if url.QueryEscape(cfg.Credentials.ID) != cid {
|
||||
t.Errorf("wrong client ID, want=%v, got=%v", cfg.Credentials.ID, cid)
|
||||
}
|
||||
|
||||
if url.QueryEscape(cfg.Credentials.Secret) != secret {
|
||||
t.Errorf("wrong client secret, want=%v, got=%v", cfg.Credentials.Secret, secret)
|
||||
}
|
||||
|
||||
err = hc.Request.ParseForm()
|
||||
if err != nil {
|
||||
t.Error("unexpected error parsing form")
|
||||
}
|
||||
|
||||
gt := hc.Request.PostForm.Get("grant_type")
|
||||
if gt != GrantTypeUserCreds {
|
||||
t.Errorf("wrong grant_type, want=%v, got=%v", GrantTypeUserCreds, gt)
|
||||
}
|
||||
|
||||
sc := strings.Split(hc.Request.PostForm.Get("scope"), " ")
|
||||
if !reflect.DeepEqual(c.scope, sc) {
|
||||
t.Errorf("wrong scope, want=%v, got=%v", c.scope, sc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewAuthenticatedRequest(t *testing.T) {
|
||||
tests := []struct {
|
||||
authMethod string
|
||||
url string
|
||||
values url.Values
|
||||
}{
|
||||
{
|
||||
authMethod: AuthMethodClientSecretBasic,
|
||||
url: "http://example.com/token",
|
||||
values: url.Values{},
|
||||
},
|
||||
{
|
||||
authMethod: AuthMethodClientSecretPost,
|
||||
url: "http://example.com/token",
|
||||
values: url.Values{},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
cfg := Config{
|
||||
Credentials: ClientCredentials{ID: "c#id", Secret: "c secret"},
|
||||
Scope: []string{"foo-scope", "bar-scope"},
|
||||
TokenURL: "http://example.com/token",
|
||||
AuthURL: "http://example.com/auth",
|
||||
RedirectURL: "http://example.com/redirect",
|
||||
AuthMethod: tt.authMethod,
|
||||
}
|
||||
c, err := NewClient(nil, cfg)
|
||||
req, err := c.newAuthenticatedRequest(tt.url, tt.values)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
err = req.ParseForm()
|
||||
if err != nil {
|
||||
t.Errorf("case %d: want nil err, got %v", i, err)
|
||||
}
|
||||
|
||||
if tt.authMethod == AuthMethodClientSecretBasic {
|
||||
cid, secret, ok := phttp.BasicAuth(req)
|
||||
if !ok {
|
||||
t.Errorf("case %d: !ok parsing Basic Auth headers", i)
|
||||
continue
|
||||
}
|
||||
if cid != url.QueryEscape(cfg.Credentials.ID) {
|
||||
t.Errorf("case %d: want CID == %q, got CID == %q", i, cfg.Credentials.ID, cid)
|
||||
}
|
||||
if secret != url.QueryEscape(cfg.Credentials.Secret) {
|
||||
t.Errorf("case %d: want secret == %q, got secret == %q", i, cfg.Credentials.Secret, secret)
|
||||
}
|
||||
} else if tt.authMethod == AuthMethodClientSecretPost {
|
||||
if req.PostFormValue("client_secret") != cfg.Credentials.Secret {
|
||||
t.Errorf("case %d: want client_secret == %q, got client_secret == %q",
|
||||
i, cfg.Credentials.Secret, req.PostFormValue("client_secret"))
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range tt.values {
|
||||
if !reflect.DeepEqual(v, req.PostForm[k]) {
|
||||
t.Errorf("case %d: key:%q want==%q, got==%q", i, k, v, req.PostForm[k])
|
||||
}
|
||||
}
|
||||
|
||||
if req.URL.String() != tt.url {
|
||||
t.Errorf("case %d: want URL==%q, got URL==%q", i, tt.url, req.URL.String())
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseTokenResponse(t *testing.T) {
|
||||
type response struct {
|
||||
body string
|
||||
contentType string
|
||||
statusCode int // defaults to http.StatusOK
|
||||
}
|
||||
tests := []struct {
|
||||
resp response
|
||||
wantResp TokenResponse
|
||||
wantError *Error
|
||||
}{
|
||||
{
|
||||
resp: response{
|
||||
body: "{ \"error\": \"invalid_client\", \"state\": \"foo\" }",
|
||||
contentType: "application/json",
|
||||
statusCode: http.StatusBadRequest,
|
||||
},
|
||||
wantError: &Error{Type: "invalid_client", State: "foo"},
|
||||
},
|
||||
{
|
||||
resp: response{
|
||||
body: "{ \"error\": \"invalid_request\", \"state\": \"bar\" }",
|
||||
contentType: "application/json",
|
||||
statusCode: http.StatusBadRequest,
|
||||
},
|
||||
wantError: &Error{Type: "invalid_request", State: "bar"},
|
||||
},
|
||||
{
|
||||
// Actual response from bitbucket
|
||||
resp: response{
|
||||
body: `{"error_description": "Invalid OAuth client credentials", "error": "unauthorized_client"}`,
|
||||
contentType: "application/json",
|
||||
statusCode: http.StatusBadRequest,
|
||||
},
|
||||
wantError: &Error{Type: "unauthorized_client", Description: "Invalid OAuth client credentials"},
|
||||
},
|
||||
{
|
||||
// Actual response from github
|
||||
resp: response{
|
||||
body: `error=incorrect_client_credentials&error_description=The+client_id+and%2For+client_secret+passed+are+incorrect.&error_uri=https%3A%2F%2Fdeveloper.github.com%2Fv3%2Foauth%2F%23incorrect-client-credentials`,
|
||||
contentType: "application/x-www-form-urlencoded; charset=utf-8",
|
||||
},
|
||||
wantError: &Error{Type: "incorrect_client_credentials", Description: "The client_id and/or client_secret passed are incorrect."},
|
||||
},
|
||||
{
|
||||
resp: response{
|
||||
body: `{"access_token":"e72e16c7e42f292c6912e7710c838347ae178b4a", "scope":"repo,gist", "token_type":"bearer"}`,
|
||||
contentType: "application/json",
|
||||
},
|
||||
wantResp: TokenResponse{
|
||||
AccessToken: "e72e16c7e42f292c6912e7710c838347ae178b4a",
|
||||
TokenType: "bearer",
|
||||
Scope: "repo,gist",
|
||||
},
|
||||
},
|
||||
{
|
||||
resp: response{
|
||||
body: `access_token=e72e16c7e42f292c6912e7710c838347ae178b4a&scope=user%2Cgist&token_type=bearer`,
|
||||
contentType: "application/x-www-form-urlencoded",
|
||||
},
|
||||
wantResp: TokenResponse{
|
||||
AccessToken: "e72e16c7e42f292c6912e7710c838347ae178b4a",
|
||||
TokenType: "bearer",
|
||||
Scope: "user,gist",
|
||||
},
|
||||
},
|
||||
{
|
||||
resp: response{
|
||||
body: `{"access_token":"foo","id_token":"bar","expires_in":200,"token_type":"bearer","refresh_token":"spam"}`,
|
||||
contentType: "application/json; charset=utf-8",
|
||||
},
|
||||
wantResp: TokenResponse{
|
||||
AccessToken: "foo",
|
||||
IDToken: "bar",
|
||||
Expires: 200,
|
||||
TokenType: "bearer",
|
||||
RefreshToken: "spam",
|
||||
},
|
||||
},
|
||||
{
|
||||
// Azure AD returns "expires_in" value as string
|
||||
resp: response{
|
||||
body: `{"access_token":"foo","id_token":"bar","expires_in":"300","token_type":"bearer","refresh_token":"spam"}`,
|
||||
contentType: "application/json; charset=utf-8",
|
||||
},
|
||||
wantResp: TokenResponse{
|
||||
AccessToken: "foo",
|
||||
IDToken: "bar",
|
||||
Expires: 300,
|
||||
TokenType: "bearer",
|
||||
RefreshToken: "spam",
|
||||
},
|
||||
},
|
||||
{
|
||||
resp: response{
|
||||
body: `{"access_token":"foo","id_token":"bar","expires":200,"token_type":"bearer","refresh_token":"spam"}`,
|
||||
contentType: "application/json; charset=utf-8",
|
||||
},
|
||||
wantResp: TokenResponse{
|
||||
AccessToken: "foo",
|
||||
IDToken: "bar",
|
||||
Expires: 200,
|
||||
TokenType: "bearer",
|
||||
RefreshToken: "spam",
|
||||
},
|
||||
},
|
||||
{
|
||||
resp: response{
|
||||
body: `access_token=foo&id_token=bar&expires_in=200&token_type=bearer&refresh_token=spam`,
|
||||
contentType: "application/x-www-form-urlencoded",
|
||||
},
|
||||
wantResp: TokenResponse{
|
||||
AccessToken: "foo",
|
||||
IDToken: "bar",
|
||||
Expires: 200,
|
||||
TokenType: "bearer",
|
||||
RefreshToken: "spam",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
r := &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Header: http.Header{
|
||||
"Content-Type": []string{tt.resp.contentType},
|
||||
"Content-Length": []string{strconv.Itoa(len([]byte(tt.resp.body)))},
|
||||
},
|
||||
Body: ioutil.NopCloser(strings.NewReader(tt.resp.body)),
|
||||
ContentLength: int64(len([]byte(tt.resp.body))),
|
||||
}
|
||||
if tt.resp.statusCode != 0 {
|
||||
r.StatusCode = tt.resp.statusCode
|
||||
}
|
||||
|
||||
result, err := parseTokenResponse(r)
|
||||
if err != nil {
|
||||
if tt.wantError == nil {
|
||||
t.Errorf("case %d: got error==%v", i, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(tt.wantError, err) {
|
||||
t.Errorf("case %d: want=%+v, got=%+v", i, tt.wantError, err)
|
||||
}
|
||||
} else {
|
||||
if tt.wantError != nil {
|
||||
t.Errorf("case %d: want error==%v, got==nil", i, tt.wantError)
|
||||
continue
|
||||
}
|
||||
// don't compare the raw body (it's really big and clogs error messages)
|
||||
result.RawBody = tt.wantResp.RawBody
|
||||
if !reflect.DeepEqual(tt.wantResp, result) {
|
||||
t.Errorf("case %d: want=%+v, got=%+v", i, tt.wantResp, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
846
vendor/github.com/coreos/go-oidc/oidc/client.go
generated
vendored
846
vendor/github.com/coreos/go-oidc/oidc/client.go
generated
vendored
|
@ -1,846 +0,0 @@
|
|||
package oidc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/mail"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
phttp "github.com/coreos/go-oidc/http"
|
||||
"github.com/coreos/go-oidc/jose"
|
||||
"github.com/coreos/go-oidc/key"
|
||||
"github.com/coreos/go-oidc/oauth2"
|
||||
)
|
||||
|
||||
const (
|
||||
// amount of time that must pass after the last key sync
|
||||
// completes before another attempt may begin
|
||||
keySyncWindow = 5 * time.Second
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultScope = []string{"openid", "email", "profile"}
|
||||
|
||||
supportedAuthMethods = map[string]struct{}{
|
||||
oauth2.AuthMethodClientSecretBasic: struct{}{},
|
||||
oauth2.AuthMethodClientSecretPost: struct{}{},
|
||||
}
|
||||
)
|
||||
|
||||
type ClientCredentials oauth2.ClientCredentials
|
||||
|
||||
type ClientIdentity struct {
|
||||
Credentials ClientCredentials
|
||||
Metadata ClientMetadata
|
||||
}
|
||||
|
||||
type JWAOptions struct {
|
||||
// SigningAlg specifies an JWA alg for signing JWTs.
|
||||
//
|
||||
// Specifying this field implies different actions depending on the context. It may
|
||||
// require objects be serialized and signed as a JWT instead of plain JSON, or
|
||||
// require an existing JWT object use the specified alg.
|
||||
//
|
||||
// See: http://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata
|
||||
SigningAlg string
|
||||
// EncryptionAlg, if provided, specifies that the returned or sent object be stored
|
||||
// (or nested) within a JWT object and encrypted with the provided JWA alg.
|
||||
EncryptionAlg string
|
||||
// EncryptionEnc specifies the JWA enc algorithm to use with EncryptionAlg. If
|
||||
// EncryptionAlg is provided and EncryptionEnc is omitted, this field defaults
|
||||
// to A128CBC-HS256.
|
||||
//
|
||||
// If EncryptionEnc is provided EncryptionAlg must also be specified.
|
||||
EncryptionEnc string
|
||||
}
|
||||
|
||||
func (opt JWAOptions) valid() error {
|
||||
if opt.EncryptionEnc != "" && opt.EncryptionAlg == "" {
|
||||
return errors.New("encryption encoding provided with no encryption algorithm")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (opt JWAOptions) defaults() JWAOptions {
|
||||
if opt.EncryptionAlg != "" && opt.EncryptionEnc == "" {
|
||||
opt.EncryptionEnc = jose.EncA128CBCHS256
|
||||
}
|
||||
return opt
|
||||
}
|
||||
|
||||
var (
|
||||
// Ensure ClientMetadata satisfies these interfaces.
|
||||
_ json.Marshaler = &ClientMetadata{}
|
||||
_ json.Unmarshaler = &ClientMetadata{}
|
||||
)
|
||||
|
||||
// ClientMetadata holds metadata that the authorization server associates
|
||||
// with a client identifier. The fields range from human-facing display
|
||||
// strings such as client name, to items that impact the security of the
|
||||
// protocol, such as the list of valid redirect URIs.
|
||||
//
|
||||
// See http://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata
|
||||
//
|
||||
// TODO: support language specific claim representations
|
||||
// http://openid.net/specs/openid-connect-registration-1_0.html#LanguagesAndScripts
|
||||
type ClientMetadata struct {
|
||||
RedirectURIs []url.URL // Required
|
||||
|
||||
// A list of OAuth 2.0 "response_type" values that the client wishes to restrict
|
||||
// itself to. Either "code", "token", or another registered extension.
|
||||
//
|
||||
// If omitted, only "code" will be used.
|
||||
ResponseTypes []string
|
||||
// A list of OAuth 2.0 grant types the client wishes to restrict itself to.
|
||||
// The grant type values used by OIDC are "authorization_code", "implicit",
|
||||
// and "refresh_token".
|
||||
//
|
||||
// If ommitted, only "authorization_code" will be used.
|
||||
GrantTypes []string
|
||||
// "native" or "web". If omitted, "web".
|
||||
ApplicationType string
|
||||
|
||||
// List of email addresses.
|
||||
Contacts []mail.Address
|
||||
// Name of client to be presented to the end-user.
|
||||
ClientName string
|
||||
// URL that references a logo for the Client application.
|
||||
LogoURI *url.URL
|
||||
// URL of the home page of the Client.
|
||||
ClientURI *url.URL
|
||||
// Profile data policies and terms of use to be provided to the end user.
|
||||
PolicyURI *url.URL
|
||||
TermsOfServiceURI *url.URL
|
||||
|
||||
// URL to or the value of the client's JSON Web Key Set document.
|
||||
JWKSURI *url.URL
|
||||
JWKS *jose.JWKSet
|
||||
|
||||
// URL referencing a flie with a single JSON array of redirect URIs.
|
||||
SectorIdentifierURI *url.URL
|
||||
|
||||
SubjectType string
|
||||
|
||||
// Options to restrict the JWS alg and enc values used for server responses and requests.
|
||||
IDTokenResponseOptions JWAOptions
|
||||
UserInfoResponseOptions JWAOptions
|
||||
RequestObjectOptions JWAOptions
|
||||
|
||||
// Client requested authorization method and signing options for the token endpoint.
|
||||
//
|
||||
// Defaults to "client_secret_basic"
|
||||
TokenEndpointAuthMethod string
|
||||
TokenEndpointAuthSigningAlg string
|
||||
|
||||
// DefaultMaxAge specifies the maximum amount of time in seconds before an authorized
|
||||
// user must reauthroize.
|
||||
//
|
||||
// If 0, no limitation is placed on the maximum.
|
||||
DefaultMaxAge int64
|
||||
// RequireAuthTime specifies if the auth_time claim in the ID token is required.
|
||||
RequireAuthTime bool
|
||||
|
||||
// Default Authentication Context Class Reference values for authentication requests.
|
||||
DefaultACRValues []string
|
||||
|
||||
// URI that a third party can use to initiate a login by the relaying party.
|
||||
//
|
||||
// See: http://openid.net/specs/openid-connect-core-1_0.html#ThirdPartyInitiatedLogin
|
||||
InitiateLoginURI *url.URL
|
||||
// Pre-registered request_uri values that may be cached by the server.
|
||||
RequestURIs []url.URL
|
||||
}
|
||||
|
||||
// Defaults returns a shallow copy of ClientMetadata with default
|
||||
// values replacing omitted fields.
|
||||
func (m ClientMetadata) Defaults() ClientMetadata {
|
||||
if len(m.ResponseTypes) == 0 {
|
||||
m.ResponseTypes = []string{oauth2.ResponseTypeCode}
|
||||
}
|
||||
if len(m.GrantTypes) == 0 {
|
||||
m.GrantTypes = []string{oauth2.GrantTypeAuthCode}
|
||||
}
|
||||
if m.ApplicationType == "" {
|
||||
m.ApplicationType = "web"
|
||||
}
|
||||
if m.TokenEndpointAuthMethod == "" {
|
||||
m.TokenEndpointAuthMethod = oauth2.AuthMethodClientSecretBasic
|
||||
}
|
||||
m.IDTokenResponseOptions = m.IDTokenResponseOptions.defaults()
|
||||
m.UserInfoResponseOptions = m.UserInfoResponseOptions.defaults()
|
||||
m.RequestObjectOptions = m.RequestObjectOptions.defaults()
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *ClientMetadata) MarshalJSON() ([]byte, error) {
|
||||
e := m.toEncodableStruct()
|
||||
return json.Marshal(&e)
|
||||
}
|
||||
|
||||
func (m *ClientMetadata) UnmarshalJSON(data []byte) error {
|
||||
var e encodableClientMetadata
|
||||
if err := json.Unmarshal(data, &e); err != nil {
|
||||
return err
|
||||
}
|
||||
meta, err := e.toStruct()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := meta.Valid(); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = meta
|
||||
return nil
|
||||
}
|
||||
|
||||
type encodableClientMetadata struct {
|
||||
RedirectURIs []string `json:"redirect_uris"` // Required
|
||||
ResponseTypes []string `json:"response_types,omitempty"`
|
||||
GrantTypes []string `json:"grant_types,omitempty"`
|
||||
ApplicationType string `json:"application_type,omitempty"`
|
||||
Contacts []string `json:"contacts,omitempty"`
|
||||
ClientName string `json:"client_name,omitempty"`
|
||||
LogoURI string `json:"logo_uri,omitempty"`
|
||||
ClientURI string `json:"client_uri,omitempty"`
|
||||
PolicyURI string `json:"policy_uri,omitempty"`
|
||||
TermsOfServiceURI string `json:"tos_uri,omitempty"`
|
||||
JWKSURI string `json:"jwks_uri,omitempty"`
|
||||
JWKS *jose.JWKSet `json:"jwks,omitempty"`
|
||||
SectorIdentifierURI string `json:"sector_identifier_uri,omitempty"`
|
||||
SubjectType string `json:"subject_type,omitempty"`
|
||||
IDTokenSignedResponseAlg string `json:"id_token_signed_response_alg,omitempty"`
|
||||
IDTokenEncryptedResponseAlg string `json:"id_token_encrypted_response_alg,omitempty"`
|
||||
IDTokenEncryptedResponseEnc string `json:"id_token_encrypted_response_enc,omitempty"`
|
||||
UserInfoSignedResponseAlg string `json:"userinfo_signed_response_alg,omitempty"`
|
||||
UserInfoEncryptedResponseAlg string `json:"userinfo_encrypted_response_alg,omitempty"`
|
||||
UserInfoEncryptedResponseEnc string `json:"userinfo_encrypted_response_enc,omitempty"`
|
||||
RequestObjectSigningAlg string `json:"request_object_signing_alg,omitempty"`
|
||||
RequestObjectEncryptionAlg string `json:"request_object_encryption_alg,omitempty"`
|
||||
RequestObjectEncryptionEnc string `json:"request_object_encryption_enc,omitempty"`
|
||||
TokenEndpointAuthMethod string `json:"token_endpoint_auth_method,omitempty"`
|
||||
TokenEndpointAuthSigningAlg string `json:"token_endpoint_auth_signing_alg,omitempty"`
|
||||
DefaultMaxAge int64 `json:"default_max_age,omitempty"`
|
||||
RequireAuthTime bool `json:"require_auth_time,omitempty"`
|
||||
DefaultACRValues []string `json:"default_acr_values,omitempty"`
|
||||
InitiateLoginURI string `json:"initiate_login_uri,omitempty"`
|
||||
RequestURIs []string `json:"request_uris,omitempty"`
|
||||
}
|
||||
|
||||
func (c *encodableClientMetadata) toStruct() (ClientMetadata, error) {
|
||||
p := stickyErrParser{}
|
||||
m := ClientMetadata{
|
||||
RedirectURIs: p.parseURIs(c.RedirectURIs, "redirect_uris"),
|
||||
ResponseTypes: c.ResponseTypes,
|
||||
GrantTypes: c.GrantTypes,
|
||||
ApplicationType: c.ApplicationType,
|
||||
Contacts: p.parseEmails(c.Contacts, "contacts"),
|
||||
ClientName: c.ClientName,
|
||||
LogoURI: p.parseURI(c.LogoURI, "logo_uri"),
|
||||
ClientURI: p.parseURI(c.ClientURI, "client_uri"),
|
||||
PolicyURI: p.parseURI(c.PolicyURI, "policy_uri"),
|
||||
TermsOfServiceURI: p.parseURI(c.TermsOfServiceURI, "tos_uri"),
|
||||
JWKSURI: p.parseURI(c.JWKSURI, "jwks_uri"),
|
||||
JWKS: c.JWKS,
|
||||
SectorIdentifierURI: p.parseURI(c.SectorIdentifierURI, "sector_identifier_uri"),
|
||||
SubjectType: c.SubjectType,
|
||||
TokenEndpointAuthMethod: c.TokenEndpointAuthMethod,
|
||||
TokenEndpointAuthSigningAlg: c.TokenEndpointAuthSigningAlg,
|
||||
DefaultMaxAge: c.DefaultMaxAge,
|
||||
RequireAuthTime: c.RequireAuthTime,
|
||||
DefaultACRValues: c.DefaultACRValues,
|
||||
InitiateLoginURI: p.parseURI(c.InitiateLoginURI, "initiate_login_uri"),
|
||||
RequestURIs: p.parseURIs(c.RequestURIs, "request_uris"),
|
||||
IDTokenResponseOptions: JWAOptions{
|
||||
c.IDTokenSignedResponseAlg,
|
||||
c.IDTokenEncryptedResponseAlg,
|
||||
c.IDTokenEncryptedResponseEnc,
|
||||
},
|
||||
UserInfoResponseOptions: JWAOptions{
|
||||
c.UserInfoSignedResponseAlg,
|
||||
c.UserInfoEncryptedResponseAlg,
|
||||
c.UserInfoEncryptedResponseEnc,
|
||||
},
|
||||
RequestObjectOptions: JWAOptions{
|
||||
c.RequestObjectSigningAlg,
|
||||
c.RequestObjectEncryptionAlg,
|
||||
c.RequestObjectEncryptionEnc,
|
||||
},
|
||||
}
|
||||
if p.firstErr != nil {
|
||||
return ClientMetadata{}, p.firstErr
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// stickyErrParser parses URIs and email addresses. Once it encounters
|
||||
// a parse error, subsequent calls become no-op.
|
||||
type stickyErrParser struct {
|
||||
firstErr error
|
||||
}
|
||||
|
||||
func (p *stickyErrParser) parseURI(s, field string) *url.URL {
|
||||
if p.firstErr != nil || s == "" {
|
||||
return nil
|
||||
}
|
||||
u, err := url.Parse(s)
|
||||
if err == nil {
|
||||
if u.Host == "" {
|
||||
err = errors.New("no host in URI")
|
||||
} else if u.Scheme != "http" && u.Scheme != "https" {
|
||||
err = errors.New("invalid URI scheme")
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
p.firstErr = fmt.Errorf("failed to parse %s: %v", field, err)
|
||||
return nil
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
func (p *stickyErrParser) parseURIs(s []string, field string) []url.URL {
|
||||
if p.firstErr != nil || len(s) == 0 {
|
||||
return nil
|
||||
}
|
||||
uris := make([]url.URL, len(s))
|
||||
for i, val := range s {
|
||||
if val == "" {
|
||||
p.firstErr = fmt.Errorf("invalid URI in field %s", field)
|
||||
return nil
|
||||
}
|
||||
if u := p.parseURI(val, field); u != nil {
|
||||
uris[i] = *u
|
||||
}
|
||||
}
|
||||
return uris
|
||||
}
|
||||
|
||||
func (p *stickyErrParser) parseEmails(s []string, field string) []mail.Address {
|
||||
if p.firstErr != nil || len(s) == 0 {
|
||||
return nil
|
||||
}
|
||||
addrs := make([]mail.Address, len(s))
|
||||
for i, addr := range s {
|
||||
if addr == "" {
|
||||
p.firstErr = fmt.Errorf("invalid email in field %s", field)
|
||||
return nil
|
||||
}
|
||||
a, err := mail.ParseAddress(addr)
|
||||
if err != nil {
|
||||
p.firstErr = fmt.Errorf("invalid email in field %s: %v", field, err)
|
||||
return nil
|
||||
}
|
||||
addrs[i] = *a
|
||||
}
|
||||
return addrs
|
||||
}
|
||||
|
||||
func (m *ClientMetadata) toEncodableStruct() encodableClientMetadata {
|
||||
return encodableClientMetadata{
|
||||
RedirectURIs: urisToStrings(m.RedirectURIs),
|
||||
ResponseTypes: m.ResponseTypes,
|
||||
GrantTypes: m.GrantTypes,
|
||||
ApplicationType: m.ApplicationType,
|
||||
Contacts: emailsToStrings(m.Contacts),
|
||||
ClientName: m.ClientName,
|
||||
LogoURI: uriToString(m.LogoURI),
|
||||
ClientURI: uriToString(m.ClientURI),
|
||||
PolicyURI: uriToString(m.PolicyURI),
|
||||
TermsOfServiceURI: uriToString(m.TermsOfServiceURI),
|
||||
JWKSURI: uriToString(m.JWKSURI),
|
||||
JWKS: m.JWKS,
|
||||
SectorIdentifierURI: uriToString(m.SectorIdentifierURI),
|
||||
SubjectType: m.SubjectType,
|
||||
IDTokenSignedResponseAlg: m.IDTokenResponseOptions.SigningAlg,
|
||||
IDTokenEncryptedResponseAlg: m.IDTokenResponseOptions.EncryptionAlg,
|
||||
IDTokenEncryptedResponseEnc: m.IDTokenResponseOptions.EncryptionEnc,
|
||||
UserInfoSignedResponseAlg: m.UserInfoResponseOptions.SigningAlg,
|
||||
UserInfoEncryptedResponseAlg: m.UserInfoResponseOptions.EncryptionAlg,
|
||||
UserInfoEncryptedResponseEnc: m.UserInfoResponseOptions.EncryptionEnc,
|
||||
RequestObjectSigningAlg: m.RequestObjectOptions.SigningAlg,
|
||||
RequestObjectEncryptionAlg: m.RequestObjectOptions.EncryptionAlg,
|
||||
RequestObjectEncryptionEnc: m.RequestObjectOptions.EncryptionEnc,
|
||||
TokenEndpointAuthMethod: m.TokenEndpointAuthMethod,
|
||||
TokenEndpointAuthSigningAlg: m.TokenEndpointAuthSigningAlg,
|
||||
DefaultMaxAge: m.DefaultMaxAge,
|
||||
RequireAuthTime: m.RequireAuthTime,
|
||||
DefaultACRValues: m.DefaultACRValues,
|
||||
InitiateLoginURI: uriToString(m.InitiateLoginURI),
|
||||
RequestURIs: urisToStrings(m.RequestURIs),
|
||||
}
|
||||
}
|
||||
|
||||
func uriToString(u *url.URL) string {
|
||||
if u == nil {
|
||||
return ""
|
||||
}
|
||||
return u.String()
|
||||
}
|
||||
|
||||
func urisToStrings(urls []url.URL) []string {
|
||||
if len(urls) == 0 {
|
||||
return nil
|
||||
}
|
||||
sli := make([]string, len(urls))
|
||||
for i, u := range urls {
|
||||
sli[i] = u.String()
|
||||
}
|
||||
return sli
|
||||
}
|
||||
|
||||
func emailsToStrings(addrs []mail.Address) []string {
|
||||
if len(addrs) == 0 {
|
||||
return nil
|
||||
}
|
||||
sli := make([]string, len(addrs))
|
||||
for i, addr := range addrs {
|
||||
sli[i] = addr.String()
|
||||
}
|
||||
return sli
|
||||
}
|
||||
|
||||
// Valid determines if a ClientMetadata conforms with the OIDC specification.
|
||||
//
|
||||
// Valid is called by UnmarshalJSON.
|
||||
//
|
||||
// NOTE(ericchiang): For development purposes Valid does not mandate 'https' for
|
||||
// URLs fields where the OIDC spec requires it. This may change in future releases
|
||||
// of this package. See: https://github.com/coreos/go-oidc/issues/34
|
||||
func (m *ClientMetadata) Valid() error {
|
||||
if len(m.RedirectURIs) == 0 {
|
||||
return errors.New("zero redirect URLs")
|
||||
}
|
||||
|
||||
validURI := func(u *url.URL, fieldName string) error {
|
||||
if u.Host == "" {
|
||||
return fmt.Errorf("no host for uri field %s", fieldName)
|
||||
}
|
||||
if u.Scheme != "http" && u.Scheme != "https" {
|
||||
return fmt.Errorf("uri field %s scheme is not http or https", fieldName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
uris := []struct {
|
||||
val *url.URL
|
||||
name string
|
||||
}{
|
||||
{m.LogoURI, "logo_uri"},
|
||||
{m.ClientURI, "client_uri"},
|
||||
{m.PolicyURI, "policy_uri"},
|
||||
{m.TermsOfServiceURI, "tos_uri"},
|
||||
{m.JWKSURI, "jwks_uri"},
|
||||
{m.SectorIdentifierURI, "sector_identifier_uri"},
|
||||
{m.InitiateLoginURI, "initiate_login_uri"},
|
||||
}
|
||||
|
||||
for _, uri := range uris {
|
||||
if uri.val == nil {
|
||||
continue
|
||||
}
|
||||
if err := validURI(uri.val, uri.name); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
uriLists := []struct {
|
||||
vals []url.URL
|
||||
name string
|
||||
}{
|
||||
{m.RedirectURIs, "redirect_uris"},
|
||||
{m.RequestURIs, "request_uris"},
|
||||
}
|
||||
for _, list := range uriLists {
|
||||
for _, uri := range list.vals {
|
||||
if err := validURI(&uri, list.name); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
options := []struct {
|
||||
option JWAOptions
|
||||
name string
|
||||
}{
|
||||
{m.IDTokenResponseOptions, "id_token response"},
|
||||
{m.UserInfoResponseOptions, "userinfo response"},
|
||||
{m.RequestObjectOptions, "request_object"},
|
||||
}
|
||||
for _, option := range options {
|
||||
if err := option.option.valid(); err != nil {
|
||||
return fmt.Errorf("invalid JWA values for %s: %v", option.name, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ClientRegistrationResponse struct {
|
||||
ClientID string // Required
|
||||
ClientSecret string
|
||||
RegistrationAccessToken string
|
||||
RegistrationClientURI string
|
||||
// If IsZero is true, unspecified.
|
||||
ClientIDIssuedAt time.Time
|
||||
// Time at which the client_secret will expire.
|
||||
// If IsZero is true, it will not expire.
|
||||
ClientSecretExpiresAt time.Time
|
||||
|
||||
ClientMetadata
|
||||
}
|
||||
|
||||
type encodableClientRegistrationResponse struct {
|
||||
ClientID string `json:"client_id"` // Required
|
||||
ClientSecret string `json:"client_secret,omitempty"`
|
||||
RegistrationAccessToken string `json:"registration_access_token,omitempty"`
|
||||
RegistrationClientURI string `json:"registration_client_uri,omitempty"`
|
||||
ClientIDIssuedAt int64 `json:"client_id_issued_at,omitempty"`
|
||||
// Time at which the client_secret will expire, in seconds since the epoch.
|
||||
// If 0 it will not expire.
|
||||
ClientSecretExpiresAt int64 `json:"client_secret_expires_at"` // Required
|
||||
|
||||
encodableClientMetadata
|
||||
}
|
||||
|
||||
func unixToSec(t time.Time) int64 {
|
||||
if t.IsZero() {
|
||||
return 0
|
||||
}
|
||||
return t.Unix()
|
||||
}
|
||||
|
||||
func (c *ClientRegistrationResponse) MarshalJSON() ([]byte, error) {
|
||||
e := encodableClientRegistrationResponse{
|
||||
ClientID: c.ClientID,
|
||||
ClientSecret: c.ClientSecret,
|
||||
RegistrationAccessToken: c.RegistrationAccessToken,
|
||||
RegistrationClientURI: c.RegistrationClientURI,
|
||||
ClientIDIssuedAt: unixToSec(c.ClientIDIssuedAt),
|
||||
ClientSecretExpiresAt: unixToSec(c.ClientSecretExpiresAt),
|
||||
encodableClientMetadata: c.ClientMetadata.toEncodableStruct(),
|
||||
}
|
||||
return json.Marshal(&e)
|
||||
}
|
||||
|
||||
func secToUnix(sec int64) time.Time {
|
||||
if sec == 0 {
|
||||
return time.Time{}
|
||||
}
|
||||
return time.Unix(sec, 0)
|
||||
}
|
||||
|
||||
func (c *ClientRegistrationResponse) UnmarshalJSON(data []byte) error {
|
||||
var e encodableClientRegistrationResponse
|
||||
if err := json.Unmarshal(data, &e); err != nil {
|
||||
return err
|
||||
}
|
||||
if e.ClientID == "" {
|
||||
return errors.New("no client_id in client registration response")
|
||||
}
|
||||
metadata, err := e.encodableClientMetadata.toStruct()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*c = ClientRegistrationResponse{
|
||||
ClientID: e.ClientID,
|
||||
ClientSecret: e.ClientSecret,
|
||||
RegistrationAccessToken: e.RegistrationAccessToken,
|
||||
RegistrationClientURI: e.RegistrationClientURI,
|
||||
ClientIDIssuedAt: secToUnix(e.ClientIDIssuedAt),
|
||||
ClientSecretExpiresAt: secToUnix(e.ClientSecretExpiresAt),
|
||||
ClientMetadata: metadata,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ClientConfig struct {
|
||||
HTTPClient phttp.Client
|
||||
Credentials ClientCredentials
|
||||
Scope []string
|
||||
RedirectURL string
|
||||
ProviderConfig ProviderConfig
|
||||
KeySet key.PublicKeySet
|
||||
}
|
||||
|
||||
func NewClient(cfg ClientConfig) (*Client, error) {
|
||||
// Allow empty redirect URL in the case where the client
|
||||
// only needs to verify a given token.
|
||||
ru, err := url.Parse(cfg.RedirectURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid redirect URL: %v", err)
|
||||
}
|
||||
|
||||
c := Client{
|
||||
credentials: cfg.Credentials,
|
||||
httpClient: cfg.HTTPClient,
|
||||
scope: cfg.Scope,
|
||||
redirectURL: ru.String(),
|
||||
providerConfig: newProviderConfigRepo(cfg.ProviderConfig),
|
||||
keySet: cfg.KeySet,
|
||||
}
|
||||
|
||||
if c.httpClient == nil {
|
||||
c.httpClient = http.DefaultClient
|
||||
}
|
||||
|
||||
if c.scope == nil {
|
||||
c.scope = make([]string, len(DefaultScope))
|
||||
copy(c.scope, DefaultScope)
|
||||
}
|
||||
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
httpClient phttp.Client
|
||||
providerConfig *providerConfigRepo
|
||||
credentials ClientCredentials
|
||||
redirectURL string
|
||||
scope []string
|
||||
keySet key.PublicKeySet
|
||||
providerSyncer *ProviderConfigSyncer
|
||||
|
||||
keySetSyncMutex sync.RWMutex
|
||||
lastKeySetSync time.Time
|
||||
}
|
||||
|
||||
func (c *Client) Healthy() error {
|
||||
now := time.Now().UTC()
|
||||
|
||||
cfg := c.providerConfig.Get()
|
||||
|
||||
if cfg.Empty() {
|
||||
return errors.New("oidc client provider config empty")
|
||||
}
|
||||
|
||||
if !cfg.ExpiresAt.IsZero() && cfg.ExpiresAt.Before(now) {
|
||||
return errors.New("oidc client provider config expired")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) OAuthClient() (*oauth2.Client, error) {
|
||||
cfg := c.providerConfig.Get()
|
||||
authMethod, err := chooseAuthMethod(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ocfg := oauth2.Config{
|
||||
Credentials: oauth2.ClientCredentials(c.credentials),
|
||||
RedirectURL: c.redirectURL,
|
||||
AuthURL: cfg.AuthEndpoint.String(),
|
||||
TokenURL: cfg.TokenEndpoint.String(),
|
||||
Scope: c.scope,
|
||||
AuthMethod: authMethod,
|
||||
}
|
||||
|
||||
return oauth2.NewClient(c.httpClient, ocfg)
|
||||
}
|
||||
|
||||
func chooseAuthMethod(cfg ProviderConfig) (string, error) {
|
||||
if len(cfg.TokenEndpointAuthMethodsSupported) == 0 {
|
||||
return oauth2.AuthMethodClientSecretBasic, nil
|
||||
}
|
||||
|
||||
for _, authMethod := range cfg.TokenEndpointAuthMethodsSupported {
|
||||
if _, ok := supportedAuthMethods[authMethod]; ok {
|
||||
return authMethod, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", errors.New("no supported auth methods")
|
||||
}
|
||||
|
||||
// SyncProviderConfig starts the provider config syncer
|
||||
func (c *Client) SyncProviderConfig(discoveryURL string) chan struct{} {
|
||||
r := NewHTTPProviderConfigGetter(c.httpClient, discoveryURL)
|
||||
s := NewProviderConfigSyncer(r, c.providerConfig)
|
||||
stop := s.Run()
|
||||
s.WaitUntilInitialSync()
|
||||
return stop
|
||||
}
|
||||
|
||||
func (c *Client) maybeSyncKeys() error {
|
||||
tooSoon := func() bool {
|
||||
return time.Now().UTC().Before(c.lastKeySetSync.Add(keySyncWindow))
|
||||
}
|
||||
|
||||
// ignore request to sync keys if a sync operation has been
|
||||
// attempted too recently
|
||||
if tooSoon() {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.keySetSyncMutex.Lock()
|
||||
defer c.keySetSyncMutex.Unlock()
|
||||
|
||||
// check again, as another goroutine may have been holding
|
||||
// the lock while updating the keys
|
||||
if tooSoon() {
|
||||
return nil
|
||||
}
|
||||
|
||||
cfg := c.providerConfig.Get()
|
||||
r := NewRemotePublicKeyRepo(c.httpClient, cfg.KeysEndpoint.String())
|
||||
w := &clientKeyRepo{client: c}
|
||||
_, err := key.Sync(r, w)
|
||||
c.lastKeySetSync = time.Now().UTC()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
type clientKeyRepo struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
func (r *clientKeyRepo) Set(ks key.KeySet) error {
|
||||
pks, ok := ks.(*key.PublicKeySet)
|
||||
if !ok {
|
||||
return errors.New("unable to cast to PublicKey")
|
||||
}
|
||||
r.client.keySet = *pks
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) ClientCredsToken(scope []string) (jose.JWT, error) {
|
||||
cfg := c.providerConfig.Get()
|
||||
|
||||
if !cfg.SupportsGrantType(oauth2.GrantTypeClientCreds) {
|
||||
return jose.JWT{}, fmt.Errorf("%v grant type is not supported", oauth2.GrantTypeClientCreds)
|
||||
}
|
||||
|
||||
oac, err := c.OAuthClient()
|
||||
if err != nil {
|
||||
return jose.JWT{}, err
|
||||
}
|
||||
|
||||
t, err := oac.ClientCredsToken(scope)
|
||||
if err != nil {
|
||||
return jose.JWT{}, err
|
||||
}
|
||||
|
||||
jwt, err := jose.ParseJWT(t.IDToken)
|
||||
if err != nil {
|
||||
return jose.JWT{}, err
|
||||
}
|
||||
|
||||
return jwt, c.VerifyJWT(jwt)
|
||||
}
|
||||
|
||||
// ExchangeAuthCode exchanges an OAuth2 auth code for an OIDC JWT ID token.
|
||||
func (c *Client) ExchangeAuthCode(code string) (jose.JWT, error) {
|
||||
oac, err := c.OAuthClient()
|
||||
if err != nil {
|
||||
return jose.JWT{}, err
|
||||
}
|
||||
|
||||
t, err := oac.RequestToken(oauth2.GrantTypeAuthCode, code)
|
||||
if err != nil {
|
||||
return jose.JWT{}, err
|
||||
}
|
||||
|
||||
jwt, err := jose.ParseJWT(t.IDToken)
|
||||
if err != nil {
|
||||
return jose.JWT{}, err
|
||||
}
|
||||
|
||||
return jwt, c.VerifyJWT(jwt)
|
||||
}
|
||||
|
||||
// RefreshToken uses a refresh token to exchange for a new OIDC JWT ID Token.
|
||||
func (c *Client) RefreshToken(refreshToken string) (jose.JWT, error) {
|
||||
oac, err := c.OAuthClient()
|
||||
if err != nil {
|
||||
return jose.JWT{}, err
|
||||
}
|
||||
|
||||
t, err := oac.RequestToken(oauth2.GrantTypeRefreshToken, refreshToken)
|
||||
if err != nil {
|
||||
return jose.JWT{}, err
|
||||
}
|
||||
|
||||
jwt, err := jose.ParseJWT(t.IDToken)
|
||||
if err != nil {
|
||||
return jose.JWT{}, err
|
||||
}
|
||||
|
||||
return jwt, c.VerifyJWT(jwt)
|
||||
}
|
||||
|
||||
func (c *Client) VerifyJWT(jwt jose.JWT) error {
|
||||
var keysFunc func() []key.PublicKey
|
||||
if kID, ok := jwt.KeyID(); ok {
|
||||
keysFunc = c.keysFuncWithID(kID)
|
||||
} else {
|
||||
keysFunc = c.keysFuncAll()
|
||||
}
|
||||
|
||||
v := NewJWTVerifier(
|
||||
c.providerConfig.Get().Issuer.String(),
|
||||
c.credentials.ID,
|
||||
c.maybeSyncKeys, keysFunc)
|
||||
|
||||
return v.Verify(jwt)
|
||||
}
|
||||
|
||||
// keysFuncWithID returns a function that retrieves at most unexpired
|
||||
// public key from the Client that matches the provided ID
|
||||
func (c *Client) keysFuncWithID(kID string) func() []key.PublicKey {
|
||||
return func() []key.PublicKey {
|
||||
c.keySetSyncMutex.RLock()
|
||||
defer c.keySetSyncMutex.RUnlock()
|
||||
|
||||
if c.keySet.ExpiresAt().Before(time.Now()) {
|
||||
return []key.PublicKey{}
|
||||
}
|
||||
|
||||
k := c.keySet.Key(kID)
|
||||
if k == nil {
|
||||
return []key.PublicKey{}
|
||||
}
|
||||
|
||||
return []key.PublicKey{*k}
|
||||
}
|
||||
}
|
||||
|
||||
// keysFuncAll returns a function that retrieves all unexpired public
|
||||
// keys from the Client
|
||||
func (c *Client) keysFuncAll() func() []key.PublicKey {
|
||||
return func() []key.PublicKey {
|
||||
c.keySetSyncMutex.RLock()
|
||||
defer c.keySetSyncMutex.RUnlock()
|
||||
|
||||
if c.keySet.ExpiresAt().Before(time.Now()) {
|
||||
return []key.PublicKey{}
|
||||
}
|
||||
|
||||
return c.keySet.Keys()
|
||||
}
|
||||
}
|
||||
|
||||
type providerConfigRepo struct {
|
||||
mu sync.RWMutex
|
||||
config ProviderConfig // do not access directly, use Get()
|
||||
}
|
||||
|
||||
func newProviderConfigRepo(pc ProviderConfig) *providerConfigRepo {
|
||||
return &providerConfigRepo{sync.RWMutex{}, pc}
|
||||
}
|
||||
|
||||
// returns an error to implement ProviderConfigSetter
|
||||
func (r *providerConfigRepo) Set(cfg ProviderConfig) error {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
r.config = cfg
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *providerConfigRepo) Get() ProviderConfig {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
return r.config
|
||||
}
|
81
vendor/github.com/coreos/go-oidc/oidc/client_race_test.go
generated
vendored
81
vendor/github.com/coreos/go-oidc/oidc/client_race_test.go
generated
vendored
|
@ -1,81 +0,0 @@
|
|||
// This file contains tests which depend on the race detector being enabled.
|
||||
// +build race
|
||||
|
||||
package oidc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type testProvider struct {
|
||||
baseURL *url.URL
|
||||
}
|
||||
|
||||
func (p *testProvider) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != discoveryConfigPath {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
cfg := ProviderConfig{
|
||||
Issuer: p.baseURL,
|
||||
ExpiresAt: time.Now().Add(time.Second),
|
||||
}
|
||||
cfg = fillRequiredProviderFields(cfg)
|
||||
json.NewEncoder(w).Encode(&cfg)
|
||||
}
|
||||
|
||||
// This test fails by triggering the race detector, not by calling t.Error or t.Fatal.
|
||||
func TestProviderSyncRace(t *testing.T) {
|
||||
|
||||
prov := &testProvider{}
|
||||
|
||||
s := httptest.NewServer(prov)
|
||||
defer s.Close()
|
||||
u, err := url.Parse(s.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
prov.baseURL = u
|
||||
|
||||
prevValue := minimumProviderConfigSyncInterval
|
||||
defer func() { minimumProviderConfigSyncInterval = prevValue }()
|
||||
|
||||
// Reduce the sync interval to increase the write frequencey.
|
||||
minimumProviderConfigSyncInterval = 5 * time.Millisecond
|
||||
|
||||
cliCfg := ClientConfig{
|
||||
HTTPClient: http.DefaultClient,
|
||||
}
|
||||
cli, err := NewClient(cliCfg)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if !cli.providerConfig.Get().Empty() {
|
||||
t.Errorf("want c.ProviderConfig == nil, got c.ProviderConfig=%#v")
|
||||
}
|
||||
|
||||
// SyncProviderConfig beings a goroutine which writes to the client's provider config.
|
||||
c := cli.SyncProviderConfig(s.URL)
|
||||
if cli.providerConfig.Get().Empty() {
|
||||
t.Errorf("want c.ProviderConfig != nil")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
// stop the background process
|
||||
c <- struct{}{}
|
||||
}()
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
// Creating an OAuth client reads from the provider config.
|
||||
cli.OAuthClient()
|
||||
}
|
||||
}
|
654
vendor/github.com/coreos/go-oidc/oidc/client_test.go
generated
vendored
654
vendor/github.com/coreos/go-oidc/oidc/client_test.go
generated
vendored
|
@ -1,654 +0,0 @@
|
|||
package oidc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/mail"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-oidc/jose"
|
||||
"github.com/coreos/go-oidc/key"
|
||||
"github.com/coreos/go-oidc/oauth2"
|
||||
"github.com/kylelemons/godebug/pretty"
|
||||
)
|
||||
|
||||
func TestNewClientScopeDefault(t *testing.T) {
|
||||
tests := []struct {
|
||||
c ClientConfig
|
||||
e []string
|
||||
}{
|
||||
{
|
||||
// No scope
|
||||
c: ClientConfig{RedirectURL: "http://example.com/redirect"},
|
||||
e: DefaultScope,
|
||||
},
|
||||
{
|
||||
// Nil scope
|
||||
c: ClientConfig{RedirectURL: "http://example.com/redirect", Scope: nil},
|
||||
e: DefaultScope,
|
||||
},
|
||||
{
|
||||
// Empty scope
|
||||
c: ClientConfig{RedirectURL: "http://example.com/redirect", Scope: []string{}},
|
||||
e: []string{},
|
||||
},
|
||||
{
|
||||
// Custom scope equal to default
|
||||
c: ClientConfig{RedirectURL: "http://example.com/redirect", Scope: []string{"openid", "email", "profile"}},
|
||||
e: DefaultScope,
|
||||
},
|
||||
{
|
||||
// Custom scope not including defaults
|
||||
c: ClientConfig{RedirectURL: "http://example.com/redirect", Scope: []string{"foo", "bar"}},
|
||||
e: []string{"foo", "bar"},
|
||||
},
|
||||
{
|
||||
// Custom scopes overlapping with defaults
|
||||
c: ClientConfig{RedirectURL: "http://example.com/redirect", Scope: []string{"openid", "foo"}},
|
||||
e: []string{"openid", "foo"},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
c, err := NewClient(tt.c)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: unexpected error from NewClient: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(tt.e, c.scope) {
|
||||
t.Errorf("case %d: want: %v, got: %v", i, tt.e, c.scope)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHealthy(t *testing.T) {
|
||||
now := time.Now().UTC()
|
||||
|
||||
tests := []struct {
|
||||
p ProviderConfig
|
||||
h bool
|
||||
}{
|
||||
// all ok
|
||||
{
|
||||
p: ProviderConfig{
|
||||
Issuer: &url.URL{Scheme: "http", Host: "example.com"},
|
||||
ExpiresAt: now.Add(time.Hour),
|
||||
},
|
||||
h: true,
|
||||
},
|
||||
// zero-value ProviderConfig.ExpiresAt
|
||||
{
|
||||
p: ProviderConfig{
|
||||
Issuer: &url.URL{Scheme: "http", Host: "example.com"},
|
||||
},
|
||||
h: true,
|
||||
},
|
||||
// expired ProviderConfig
|
||||
{
|
||||
p: ProviderConfig{
|
||||
Issuer: &url.URL{Scheme: "http", Host: "example.com"},
|
||||
ExpiresAt: now.Add(time.Hour * -1),
|
||||
},
|
||||
h: false,
|
||||
},
|
||||
// empty ProviderConfig
|
||||
{
|
||||
p: ProviderConfig{},
|
||||
h: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
c := &Client{providerConfig: newProviderConfigRepo(tt.p)}
|
||||
err := c.Healthy()
|
||||
want := tt.h
|
||||
got := (err == nil)
|
||||
|
||||
if want != got {
|
||||
t.Errorf("case %d: want: healthy=%v, got: healhty=%v, err: %v", i, want, got, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientKeysFuncAll(t *testing.T) {
|
||||
priv1, err := key.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to generate private key, error=%v", err)
|
||||
}
|
||||
|
||||
priv2, err := key.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to generate private key, error=%v", err)
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
future := now.Add(time.Hour)
|
||||
past := now.Add(-1 * time.Hour)
|
||||
|
||||
tests := []struct {
|
||||
keySet *key.PublicKeySet
|
||||
want []key.PublicKey
|
||||
}{
|
||||
// two keys, non-expired set
|
||||
{
|
||||
keySet: key.NewPublicKeySet([]jose.JWK{priv2.JWK(), priv1.JWK()}, future),
|
||||
want: []key.PublicKey{*key.NewPublicKey(priv2.JWK()), *key.NewPublicKey(priv1.JWK())},
|
||||
},
|
||||
|
||||
// no keys, non-expired set
|
||||
{
|
||||
keySet: key.NewPublicKeySet([]jose.JWK{}, future),
|
||||
want: []key.PublicKey{},
|
||||
},
|
||||
|
||||
// two keys, expired set
|
||||
{
|
||||
keySet: key.NewPublicKeySet([]jose.JWK{priv2.JWK(), priv1.JWK()}, past),
|
||||
want: []key.PublicKey{},
|
||||
},
|
||||
|
||||
// no keys, expired set
|
||||
{
|
||||
keySet: key.NewPublicKeySet([]jose.JWK{}, past),
|
||||
want: []key.PublicKey{},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
var c Client
|
||||
c.keySet = *tt.keySet
|
||||
keysFunc := c.keysFuncAll()
|
||||
got := keysFunc()
|
||||
if !reflect.DeepEqual(tt.want, got) {
|
||||
t.Errorf("case %d: want=%#v got=%#v", i, tt.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientKeysFuncWithID(t *testing.T) {
|
||||
priv1, err := key.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to generate private key, error=%v", err)
|
||||
}
|
||||
|
||||
priv2, err := key.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to generate private key, error=%v", err)
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
future := now.Add(time.Hour)
|
||||
past := now.Add(-1 * time.Hour)
|
||||
|
||||
tests := []struct {
|
||||
keySet *key.PublicKeySet
|
||||
argID string
|
||||
want []key.PublicKey
|
||||
}{
|
||||
// two keys, match, non-expired set
|
||||
{
|
||||
keySet: key.NewPublicKeySet([]jose.JWK{priv2.JWK(), priv1.JWK()}, future),
|
||||
argID: priv2.ID(),
|
||||
want: []key.PublicKey{*key.NewPublicKey(priv2.JWK())},
|
||||
},
|
||||
|
||||
// two keys, no match, non-expired set
|
||||
{
|
||||
keySet: key.NewPublicKeySet([]jose.JWK{priv2.JWK(), priv1.JWK()}, future),
|
||||
argID: "XXX",
|
||||
want: []key.PublicKey{},
|
||||
},
|
||||
|
||||
// no keys, no match, non-expired set
|
||||
{
|
||||
keySet: key.NewPublicKeySet([]jose.JWK{}, future),
|
||||
argID: priv2.ID(),
|
||||
want: []key.PublicKey{},
|
||||
},
|
||||
|
||||
// two keys, match, expired set
|
||||
{
|
||||
keySet: key.NewPublicKeySet([]jose.JWK{priv2.JWK(), priv1.JWK()}, past),
|
||||
argID: priv2.ID(),
|
||||
want: []key.PublicKey{},
|
||||
},
|
||||
|
||||
// no keys, no match, expired set
|
||||
{
|
||||
keySet: key.NewPublicKeySet([]jose.JWK{}, past),
|
||||
argID: priv2.ID(),
|
||||
want: []key.PublicKey{},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
var c Client
|
||||
c.keySet = *tt.keySet
|
||||
keysFunc := c.keysFuncWithID(tt.argID)
|
||||
got := keysFunc()
|
||||
if !reflect.DeepEqual(tt.want, got) {
|
||||
t.Errorf("case %d: want=%#v got=%#v", i, tt.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientMetadataValid(t *testing.T) {
|
||||
tests := []ClientMetadata{
|
||||
// one RedirectURL
|
||||
ClientMetadata{
|
||||
RedirectURIs: []url.URL{url.URL{Scheme: "http", Host: "example.com"}},
|
||||
},
|
||||
|
||||
// one RedirectURL w/ nonempty path
|
||||
ClientMetadata{
|
||||
RedirectURIs: []url.URL{url.URL{Scheme: "http", Host: "example.com", Path: "/foo"}},
|
||||
},
|
||||
|
||||
// two RedirectURIs
|
||||
ClientMetadata{
|
||||
RedirectURIs: []url.URL{
|
||||
url.URL{Scheme: "http", Host: "foo.example.com"},
|
||||
url.URL{Scheme: "http", Host: "bar.example.com"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
if err := tt.Valid(); err != nil {
|
||||
t.Errorf("case %d: unexpected error: %v", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientMetadataInvalid(t *testing.T) {
|
||||
tests := []ClientMetadata{
|
||||
// nil RedirectURls slice
|
||||
ClientMetadata{
|
||||
RedirectURIs: nil,
|
||||
},
|
||||
|
||||
// empty RedirectURIs slice
|
||||
ClientMetadata{
|
||||
RedirectURIs: []url.URL{},
|
||||
},
|
||||
|
||||
// empty url.URL
|
||||
ClientMetadata{
|
||||
RedirectURIs: []url.URL{url.URL{}},
|
||||
},
|
||||
|
||||
// empty url.URL following OK item
|
||||
ClientMetadata{
|
||||
RedirectURIs: []url.URL{url.URL{Scheme: "http", Host: "example.com"}, url.URL{}},
|
||||
},
|
||||
|
||||
// url.URL with empty Host
|
||||
ClientMetadata{
|
||||
RedirectURIs: []url.URL{url.URL{Scheme: "http", Host: ""}},
|
||||
},
|
||||
|
||||
// url.URL with empty Scheme
|
||||
ClientMetadata{
|
||||
RedirectURIs: []url.URL{url.URL{Scheme: "", Host: "example.com"}},
|
||||
},
|
||||
|
||||
// url.URL with non-HTTP(S) Scheme
|
||||
ClientMetadata{
|
||||
RedirectURIs: []url.URL{url.URL{Scheme: "tcp", Host: "127.0.0.1"}},
|
||||
},
|
||||
|
||||
// EncryptionEnc without EncryptionAlg
|
||||
ClientMetadata{
|
||||
RedirectURIs: []url.URL{url.URL{Scheme: "http", Host: "example.com"}},
|
||||
IDTokenResponseOptions: JWAOptions{
|
||||
EncryptionEnc: "A128CBC-HS256",
|
||||
},
|
||||
},
|
||||
|
||||
// List of URIs with one empty element
|
||||
ClientMetadata{
|
||||
RedirectURIs: []url.URL{url.URL{Scheme: "http", Host: "example.com"}},
|
||||
RequestURIs: []url.URL{
|
||||
url.URL{Scheme: "http", Host: "example.com"},
|
||||
url.URL{},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
if err := tt.Valid(); err == nil {
|
||||
t.Errorf("case %d: expected non-nil error", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestChooseAuthMethod(t *testing.T) {
|
||||
tests := []struct {
|
||||
supported []string
|
||||
chosen string
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
supported: []string{},
|
||||
chosen: oauth2.AuthMethodClientSecretBasic,
|
||||
},
|
||||
{
|
||||
supported: []string{oauth2.AuthMethodClientSecretBasic},
|
||||
chosen: oauth2.AuthMethodClientSecretBasic,
|
||||
},
|
||||
{
|
||||
supported: []string{oauth2.AuthMethodClientSecretPost},
|
||||
chosen: oauth2.AuthMethodClientSecretPost,
|
||||
},
|
||||
{
|
||||
supported: []string{oauth2.AuthMethodClientSecretPost, oauth2.AuthMethodClientSecretBasic},
|
||||
chosen: oauth2.AuthMethodClientSecretPost,
|
||||
},
|
||||
{
|
||||
supported: []string{oauth2.AuthMethodClientSecretBasic, oauth2.AuthMethodClientSecretPost},
|
||||
chosen: oauth2.AuthMethodClientSecretBasic,
|
||||
},
|
||||
{
|
||||
supported: []string{oauth2.AuthMethodClientSecretJWT, oauth2.AuthMethodClientSecretPost},
|
||||
chosen: oauth2.AuthMethodClientSecretPost,
|
||||
},
|
||||
{
|
||||
supported: []string{oauth2.AuthMethodClientSecretJWT},
|
||||
chosen: "",
|
||||
err: true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
cfg := ProviderConfig{
|
||||
TokenEndpointAuthMethodsSupported: tt.supported,
|
||||
}
|
||||
got, err := chooseAuthMethod(cfg)
|
||||
if tt.err {
|
||||
if err == nil {
|
||||
t.Errorf("case %d: expected non-nil err", i)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if got != tt.chosen {
|
||||
t.Errorf("case %d: want=%q, got=%q", i, tt.chosen, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientMetadataUnmarshal(t *testing.T) {
|
||||
tests := []struct {
|
||||
data string
|
||||
want ClientMetadata
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
`{"redirect_uris":["https://example.com"]}`,
|
||||
ClientMetadata{
|
||||
RedirectURIs: []url.URL{
|
||||
{Scheme: "https", Host: "example.com"},
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
// redirect_uris required
|
||||
`{}`,
|
||||
ClientMetadata{},
|
||||
true,
|
||||
},
|
||||
{
|
||||
// must have at least one redirect_uris
|
||||
`{"redirect_uris":[]}`,
|
||||
ClientMetadata{},
|
||||
true,
|
||||
},
|
||||
{
|
||||
`{"redirect_uris":["https://example.com"],"contacts":["Ms. Foo <foo@example.com>"]}`,
|
||||
ClientMetadata{
|
||||
RedirectURIs: []url.URL{
|
||||
{Scheme: "https", Host: "example.com"},
|
||||
},
|
||||
Contacts: []mail.Address{
|
||||
{Name: "Ms. Foo", Address: "foo@example.com"},
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
// invalid URI provided for field
|
||||
`{"redirect_uris":["https://example.com"],"logo_uri":"not a valid uri"}`,
|
||||
ClientMetadata{},
|
||||
true,
|
||||
},
|
||||
{
|
||||
// logo_uri can't be a list
|
||||
`{"redirect_uris":["https://example.com"],"logo_uri":["https://example.com/logo"]}`,
|
||||
ClientMetadata{},
|
||||
true,
|
||||
},
|
||||
{
|
||||
`{
|
||||
"redirect_uris":["https://example.com"],
|
||||
"userinfo_encrypted_response_alg":"RSA1_5",
|
||||
"userinfo_encrypted_response_enc":"A128CBC-HS256",
|
||||
"contacts": [
|
||||
"jane doe <jane.doe@example.com>", "john doe <john.doe@example.com>"
|
||||
]
|
||||
}`,
|
||||
ClientMetadata{
|
||||
RedirectURIs: []url.URL{
|
||||
{Scheme: "https", Host: "example.com"},
|
||||
},
|
||||
UserInfoResponseOptions: JWAOptions{
|
||||
EncryptionAlg: "RSA1_5",
|
||||
EncryptionEnc: "A128CBC-HS256",
|
||||
},
|
||||
Contacts: []mail.Address{
|
||||
{Name: "jane doe", Address: "jane.doe@example.com"},
|
||||
{Name: "john doe", Address: "john.doe@example.com"},
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
// If encrypted_response_enc is provided encrypted_response_alg must also be.
|
||||
`{
|
||||
"redirect_uris":["https://example.com"],
|
||||
"userinfo_encrypted_response_enc":"A128CBC-HS256"
|
||||
}`,
|
||||
ClientMetadata{},
|
||||
true,
|
||||
},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
var got ClientMetadata
|
||||
if err := got.UnmarshalJSON([]byte(tt.data)); err != nil {
|
||||
if !tt.wantErr {
|
||||
t.Errorf("case %d: unmarshal failed: %v", i, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if tt.wantErr {
|
||||
t.Errorf("case %d: expected unmarshal to produce error", i)
|
||||
continue
|
||||
}
|
||||
|
||||
if diff := pretty.Compare(tt.want, got); diff != "" {
|
||||
t.Errorf("case %d: results not equal: %s", i, diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientMetadataMarshal(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
metadata ClientMetadata
|
||||
want string
|
||||
}{
|
||||
{
|
||||
ClientMetadata{
|
||||
RedirectURIs: []url.URL{
|
||||
{Scheme: "https", Host: "example.com", Path: "/callback"},
|
||||
},
|
||||
},
|
||||
`{"redirect_uris":["https://example.com/callback"]}`,
|
||||
},
|
||||
{
|
||||
ClientMetadata{
|
||||
RedirectURIs: []url.URL{
|
||||
{Scheme: "https", Host: "example.com", Path: "/callback"},
|
||||
},
|
||||
RequestObjectOptions: JWAOptions{
|
||||
EncryptionAlg: "RSA1_5",
|
||||
EncryptionEnc: "A128CBC-HS256",
|
||||
},
|
||||
},
|
||||
`{"redirect_uris":["https://example.com/callback"],"request_object_encryption_alg":"RSA1_5","request_object_encryption_enc":"A128CBC-HS256"}`,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
got, err := json.Marshal(&tt.metadata)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: failed to marshal metadata: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if string(got) != tt.want {
|
||||
t.Errorf("case %d: marshaled string did not match expected string", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientMetadataMarshalRoundTrip(t *testing.T) {
|
||||
tests := []ClientMetadata{
|
||||
{
|
||||
RedirectURIs: []url.URL{
|
||||
{Scheme: "https", Host: "example.com", Path: "/callback"},
|
||||
},
|
||||
LogoURI: &url.URL{Scheme: "https", Host: "example.com", Path: "/logo"},
|
||||
RequestObjectOptions: JWAOptions{
|
||||
EncryptionAlg: "RSA1_5",
|
||||
EncryptionEnc: "A128CBC-HS256",
|
||||
},
|
||||
ApplicationType: "native",
|
||||
TokenEndpointAuthMethod: "client_secret_basic",
|
||||
},
|
||||
}
|
||||
|
||||
for i, want := range tests {
|
||||
data, err := json.Marshal(&want)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: failed to marshal metadata: %v", i, err)
|
||||
continue
|
||||
}
|
||||
var got ClientMetadata
|
||||
if err := json.Unmarshal(data, &got); err != nil {
|
||||
t.Errorf("case %d: failed to unmarshal metadata: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if diff := pretty.Compare(want, got); diff != "" {
|
||||
t.Errorf("case %d: struct did not survive a marshaling round trip: %s", i, diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientRegistrationResponseUnmarshal(t *testing.T) {
|
||||
tests := []struct {
|
||||
data string
|
||||
want ClientRegistrationResponse
|
||||
wantErr bool
|
||||
secretExpires bool
|
||||
}{
|
||||
{
|
||||
`{
|
||||
"client_id":"foo",
|
||||
"client_secret":"bar",
|
||||
"client_secret_expires_at": 1577858400,
|
||||
"redirect_uris":[
|
||||
"https://client.example.org/callback",
|
||||
"https://client.example.org/callback2"
|
||||
],
|
||||
"client_name":"my_example"
|
||||
}`,
|
||||
ClientRegistrationResponse{
|
||||
ClientID: "foo",
|
||||
ClientSecret: "bar",
|
||||
ClientSecretExpiresAt: time.Unix(1577858400, 0),
|
||||
ClientMetadata: ClientMetadata{
|
||||
RedirectURIs: []url.URL{
|
||||
{Scheme: "https", Host: "client.example.org", Path: "/callback"},
|
||||
{Scheme: "https", Host: "client.example.org", Path: "/callback2"},
|
||||
},
|
||||
ClientName: "my_example",
|
||||
},
|
||||
},
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
`{
|
||||
"client_id":"foo",
|
||||
"client_secret_expires_at": 0,
|
||||
"redirect_uris":[
|
||||
"https://client.example.org/callback",
|
||||
"https://client.example.org/callback2"
|
||||
],
|
||||
"client_name":"my_example"
|
||||
}`,
|
||||
ClientRegistrationResponse{
|
||||
ClientID: "foo",
|
||||
ClientMetadata: ClientMetadata{
|
||||
RedirectURIs: []url.URL{
|
||||
{Scheme: "https", Host: "client.example.org", Path: "/callback"},
|
||||
{Scheme: "https", Host: "client.example.org", Path: "/callback2"},
|
||||
},
|
||||
ClientName: "my_example",
|
||||
},
|
||||
},
|
||||
false,
|
||||
false,
|
||||
},
|
||||
{
|
||||
// no client id
|
||||
`{
|
||||
"client_secret_expires_at": 0,
|
||||
"redirect_uris":[
|
||||
"https://client.example.org/callback",
|
||||
"https://client.example.org/callback2"
|
||||
],
|
||||
"client_name":"my_example"
|
||||
}`,
|
||||
ClientRegistrationResponse{},
|
||||
true,
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
var got ClientRegistrationResponse
|
||||
if err := json.Unmarshal([]byte(tt.data), &got); err != nil {
|
||||
if !tt.wantErr {
|
||||
t.Errorf("case %d: unmarshal failed: %v", i, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if tt.wantErr {
|
||||
t.Errorf("case %d: expected unmarshal to produce error", i)
|
||||
continue
|
||||
}
|
||||
|
||||
if diff := pretty.Compare(tt.want, got); diff != "" {
|
||||
t.Errorf("case %d: results not equal: %s", i, diff)
|
||||
}
|
||||
if tt.secretExpires && got.ClientSecretExpiresAt.IsZero() {
|
||||
t.Errorf("case %d: expected client_secret to expire, but it doesn't", i)
|
||||
} else if !tt.secretExpires && !got.ClientSecretExpiresAt.IsZero() {
|
||||
t.Errorf("case %d: expected client_secret to not expire, but it does", i)
|
||||
}
|
||||
}
|
||||
}
|
2
vendor/github.com/coreos/go-oidc/oidc/doc.go
generated
vendored
2
vendor/github.com/coreos/go-oidc/oidc/doc.go
generated
vendored
|
@ -1,2 +0,0 @@
|
|||
// Package oidc is DEPRECATED. Use github.com/coreos/go-oidc instead.
|
||||
package oidc
|
44
vendor/github.com/coreos/go-oidc/oidc/identity.go
generated
vendored
44
vendor/github.com/coreos/go-oidc/oidc/identity.go
generated
vendored
|
@ -1,44 +0,0 @@
|
|||
package oidc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-oidc/jose"
|
||||
)
|
||||
|
||||
type Identity struct {
|
||||
ID string
|
||||
Name string
|
||||
Email string
|
||||
ExpiresAt time.Time
|
||||
}
|
||||
|
||||
func IdentityFromClaims(claims jose.Claims) (*Identity, error) {
|
||||
if claims == nil {
|
||||
return nil, errors.New("nil claim set")
|
||||
}
|
||||
|
||||
var ident Identity
|
||||
var err error
|
||||
var ok bool
|
||||
|
||||
if ident.ID, ok, err = claims.StringClaim("sub"); err != nil {
|
||||
return nil, err
|
||||
} else if !ok {
|
||||
return nil, errors.New("missing required claim: sub")
|
||||
}
|
||||
|
||||
if ident.Email, _, err = claims.StringClaim("email"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
exp, ok, err := claims.TimeClaim("exp")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if ok {
|
||||
ident.ExpiresAt = exp
|
||||
}
|
||||
|
||||
return &ident, nil
|
||||
}
|
113
vendor/github.com/coreos/go-oidc/oidc/identity_test.go
generated
vendored
113
vendor/github.com/coreos/go-oidc/oidc/identity_test.go
generated
vendored
|
@ -1,113 +0,0 @@
|
|||
package oidc
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-oidc/jose"
|
||||
)
|
||||
|
||||
func TestIdentityFromClaims(t *testing.T) {
|
||||
tests := []struct {
|
||||
claims jose.Claims
|
||||
want Identity
|
||||
}{
|
||||
{
|
||||
claims: jose.Claims{
|
||||
"sub": "123850281",
|
||||
"name": "Elroy",
|
||||
"email": "elroy@example.com",
|
||||
"exp": float64(1.416935146e+09),
|
||||
},
|
||||
want: Identity{
|
||||
ID: "123850281",
|
||||
Name: "",
|
||||
Email: "elroy@example.com",
|
||||
ExpiresAt: time.Date(2014, time.November, 25, 17, 05, 46, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
{
|
||||
claims: jose.Claims{
|
||||
"sub": "123850281",
|
||||
"name": "Elroy",
|
||||
"exp": float64(1.416935146e+09),
|
||||
},
|
||||
want: Identity{
|
||||
ID: "123850281",
|
||||
Name: "",
|
||||
Email: "",
|
||||
ExpiresAt: time.Date(2014, time.November, 25, 17, 05, 46, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
{
|
||||
claims: jose.Claims{
|
||||
"sub": "123850281",
|
||||
"name": "Elroy",
|
||||
"email": "elroy@example.com",
|
||||
"exp": int64(1416935146),
|
||||
},
|
||||
want: Identity{
|
||||
ID: "123850281",
|
||||
Name: "",
|
||||
Email: "elroy@example.com",
|
||||
ExpiresAt: time.Date(2014, time.November, 25, 17, 05, 46, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
{
|
||||
claims: jose.Claims{
|
||||
"sub": "123850281",
|
||||
"name": "Elroy",
|
||||
"email": "elroy@example.com",
|
||||
},
|
||||
want: Identity{
|
||||
ID: "123850281",
|
||||
Name: "",
|
||||
Email: "elroy@example.com",
|
||||
ExpiresAt: time.Time{},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
got, err := IdentityFromClaims(tt.claims)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(tt.want, *got) {
|
||||
t.Errorf("case %d: want=%#v got=%#v", i, tt.want, *got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIdentityFromClaimsFail(t *testing.T) {
|
||||
tests := []jose.Claims{
|
||||
// sub incorrect type
|
||||
jose.Claims{
|
||||
"sub": 123,
|
||||
"name": "foo",
|
||||
"email": "elroy@example.com",
|
||||
},
|
||||
// email incorrect type
|
||||
jose.Claims{
|
||||
"sub": "123850281",
|
||||
"name": "Elroy",
|
||||
"email": false,
|
||||
},
|
||||
// exp incorrect type
|
||||
jose.Claims{
|
||||
"sub": "123850281",
|
||||
"name": "Elroy",
|
||||
"email": "elroy@example.com",
|
||||
"exp": "2014-11-25 18:05:46 +0000 UTC",
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
_, err := IdentityFromClaims(tt)
|
||||
if err == nil {
|
||||
t.Errorf("case %d: expected non-nil error", i)
|
||||
}
|
||||
}
|
||||
}
|
3
vendor/github.com/coreos/go-oidc/oidc/interface.go
generated
vendored
3
vendor/github.com/coreos/go-oidc/oidc/interface.go
generated
vendored
|
@ -1,3 +0,0 @@
|
|||
package oidc
|
||||
|
||||
type LoginFunc func(ident Identity, sessionKey string) (redirectURL string, err error)
|
67
vendor/github.com/coreos/go-oidc/oidc/key.go
generated
vendored
67
vendor/github.com/coreos/go-oidc/oidc/key.go
generated
vendored
|
@ -1,67 +0,0 @@
|
|||
package oidc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
phttp "github.com/coreos/go-oidc/http"
|
||||
"github.com/coreos/go-oidc/jose"
|
||||
"github.com/coreos/go-oidc/key"
|
||||
)
|
||||
|
||||
// DefaultPublicKeySetTTL is the default TTL set on the PublicKeySet if no
|
||||
// Cache-Control header is provided by the JWK Set document endpoint.
|
||||
const DefaultPublicKeySetTTL = 24 * time.Hour
|
||||
|
||||
// NewRemotePublicKeyRepo is responsible for fetching the JWK Set document.
|
||||
func NewRemotePublicKeyRepo(hc phttp.Client, ep string) *remotePublicKeyRepo {
|
||||
return &remotePublicKeyRepo{hc: hc, ep: ep}
|
||||
}
|
||||
|
||||
type remotePublicKeyRepo struct {
|
||||
hc phttp.Client
|
||||
ep string
|
||||
}
|
||||
|
||||
// Get returns a PublicKeySet fetched from the JWK Set document endpoint. A TTL
|
||||
// is set on the Key Set to avoid it having to be re-retrieved for every
|
||||
// encryption event. This TTL is typically controlled by the endpoint returning
|
||||
// a Cache-Control header, but defaults to 24 hours if no Cache-Control header
|
||||
// is found.
|
||||
func (r *remotePublicKeyRepo) Get() (key.KeySet, error) {
|
||||
req, err := http.NewRequest("GET", r.ep, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := r.hc.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var d struct {
|
||||
Keys []jose.JWK `json:"keys"`
|
||||
}
|
||||
if err := json.NewDecoder(resp.Body).Decode(&d); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(d.Keys) == 0 {
|
||||
return nil, errors.New("zero keys in response")
|
||||
}
|
||||
|
||||
ttl, ok, err := phttp.Cacheable(resp.Header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !ok {
|
||||
ttl = DefaultPublicKeySetTTL
|
||||
}
|
||||
|
||||
exp := time.Now().UTC().Add(ttl)
|
||||
ks := key.NewPublicKeySet(d.Keys, exp)
|
||||
return ks, nil
|
||||
}
|
690
vendor/github.com/coreos/go-oidc/oidc/provider.go
generated
vendored
690
vendor/github.com/coreos/go-oidc/oidc/provider.go
generated
vendored
|
@ -1,690 +0,0 @@
|
|||
package oidc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/pkg/timeutil"
|
||||
"github.com/jonboulle/clockwork"
|
||||
|
||||
phttp "github.com/coreos/go-oidc/http"
|
||||
"github.com/coreos/go-oidc/oauth2"
|
||||
)
|
||||
|
||||
const (
|
||||
// Subject Identifier types defined by the OIDC spec. Specifies if the provider
|
||||
// should provide the same sub claim value to all clients (public) or a unique
|
||||
// value for each client (pairwise).
|
||||
//
|
||||
// See: http://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes
|
||||
SubjectTypePublic = "public"
|
||||
SubjectTypePairwise = "pairwise"
|
||||
)
|
||||
|
||||
var (
|
||||
// Default values for omitted provider config fields.
|
||||
//
|
||||
// Use ProviderConfig's Defaults method to fill a provider config with these values.
|
||||
DefaultGrantTypesSupported = []string{oauth2.GrantTypeAuthCode, oauth2.GrantTypeImplicit}
|
||||
DefaultResponseModesSupported = []string{"query", "fragment"}
|
||||
DefaultTokenEndpointAuthMethodsSupported = []string{oauth2.AuthMethodClientSecretBasic}
|
||||
DefaultClaimTypesSupported = []string{"normal"}
|
||||
)
|
||||
|
||||
const (
|
||||
MaximumProviderConfigSyncInterval = 24 * time.Hour
|
||||
MinimumProviderConfigSyncInterval = time.Minute
|
||||
|
||||
discoveryConfigPath = "/.well-known/openid-configuration"
|
||||
)
|
||||
|
||||
// internally configurable for tests
|
||||
var minimumProviderConfigSyncInterval = MinimumProviderConfigSyncInterval
|
||||
|
||||
var (
|
||||
// Ensure ProviderConfig satisfies these interfaces.
|
||||
_ json.Marshaler = &ProviderConfig{}
|
||||
_ json.Unmarshaler = &ProviderConfig{}
|
||||
)
|
||||
|
||||
// ProviderConfig represents the OpenID Provider Metadata specifying what
|
||||
// configurations a provider supports.
|
||||
//
|
||||
// See: http://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
|
||||
type ProviderConfig struct {
|
||||
Issuer *url.URL // Required
|
||||
AuthEndpoint *url.URL // Required
|
||||
TokenEndpoint *url.URL // Required if grant types other than "implicit" are supported
|
||||
UserInfoEndpoint *url.URL
|
||||
KeysEndpoint *url.URL // Required
|
||||
RegistrationEndpoint *url.URL
|
||||
EndSessionEndpoint *url.URL
|
||||
CheckSessionIFrame *url.URL
|
||||
|
||||
// Servers MAY choose not to advertise some supported scope values even when this
|
||||
// parameter is used, although those defined in OpenID Core SHOULD be listed, if supported.
|
||||
ScopesSupported []string
|
||||
// OAuth2.0 response types supported.
|
||||
ResponseTypesSupported []string // Required
|
||||
// OAuth2.0 response modes supported.
|
||||
//
|
||||
// If omitted, defaults to DefaultResponseModesSupported.
|
||||
ResponseModesSupported []string
|
||||
// OAuth2.0 grant types supported.
|
||||
//
|
||||
// If omitted, defaults to DefaultGrantTypesSupported.
|
||||
GrantTypesSupported []string
|
||||
ACRValuesSupported []string
|
||||
// SubjectTypesSupported specifies strategies for providing values for the sub claim.
|
||||
SubjectTypesSupported []string // Required
|
||||
|
||||
// JWA signing and encryption algorith values supported for ID tokens.
|
||||
IDTokenSigningAlgValues []string // Required
|
||||
IDTokenEncryptionAlgValues []string
|
||||
IDTokenEncryptionEncValues []string
|
||||
|
||||
// JWA signing and encryption algorith values supported for user info responses.
|
||||
UserInfoSigningAlgValues []string
|
||||
UserInfoEncryptionAlgValues []string
|
||||
UserInfoEncryptionEncValues []string
|
||||
|
||||
// JWA signing and encryption algorith values supported for request objects.
|
||||
ReqObjSigningAlgValues []string
|
||||
ReqObjEncryptionAlgValues []string
|
||||
ReqObjEncryptionEncValues []string
|
||||
|
||||
TokenEndpointAuthMethodsSupported []string
|
||||
TokenEndpointAuthSigningAlgValuesSupported []string
|
||||
DisplayValuesSupported []string
|
||||
ClaimTypesSupported []string
|
||||
ClaimsSupported []string
|
||||
ServiceDocs *url.URL
|
||||
ClaimsLocalsSupported []string
|
||||
UILocalsSupported []string
|
||||
ClaimsParameterSupported bool
|
||||
RequestParameterSupported bool
|
||||
RequestURIParamaterSupported bool
|
||||
RequireRequestURIRegistration bool
|
||||
|
||||
Policy *url.URL
|
||||
TermsOfService *url.URL
|
||||
|
||||
// Not part of the OpenID Provider Metadata
|
||||
ExpiresAt time.Time
|
||||
}
|
||||
|
||||
// Defaults returns a shallow copy of ProviderConfig with default
|
||||
// values replacing omitted fields.
|
||||
//
|
||||
// var cfg oidc.ProviderConfig
|
||||
// // Fill provider config with default values for omitted fields.
|
||||
// cfg = cfg.Defaults()
|
||||
//
|
||||
func (p ProviderConfig) Defaults() ProviderConfig {
|
||||
setDefault := func(val *[]string, defaultVal []string) {
|
||||
if len(*val) == 0 {
|
||||
*val = defaultVal
|
||||
}
|
||||
}
|
||||
setDefault(&p.GrantTypesSupported, DefaultGrantTypesSupported)
|
||||
setDefault(&p.ResponseModesSupported, DefaultResponseModesSupported)
|
||||
setDefault(&p.TokenEndpointAuthMethodsSupported, DefaultTokenEndpointAuthMethodsSupported)
|
||||
setDefault(&p.ClaimTypesSupported, DefaultClaimTypesSupported)
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *ProviderConfig) MarshalJSON() ([]byte, error) {
|
||||
e := p.toEncodableStruct()
|
||||
return json.Marshal(&e)
|
||||
}
|
||||
|
||||
func (p *ProviderConfig) UnmarshalJSON(data []byte) error {
|
||||
var e encodableProviderConfig
|
||||
if err := json.Unmarshal(data, &e); err != nil {
|
||||
return err
|
||||
}
|
||||
conf, err := e.toStruct()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := conf.Valid(); err != nil {
|
||||
return err
|
||||
}
|
||||
*p = conf
|
||||
return nil
|
||||
}
|
||||
|
||||
type encodableProviderConfig struct {
|
||||
Issuer string `json:"issuer"`
|
||||
AuthEndpoint string `json:"authorization_endpoint"`
|
||||
TokenEndpoint string `json:"token_endpoint"`
|
||||
UserInfoEndpoint string `json:"userinfo_endpoint,omitempty"`
|
||||
KeysEndpoint string `json:"jwks_uri"`
|
||||
RegistrationEndpoint string `json:"registration_endpoint,omitempty"`
|
||||
EndSessionEndpoint string `json:"end_session_endpoint,omitempty"`
|
||||
CheckSessionIFrame string `json:"check_session_iframe,omitempty"`
|
||||
|
||||
// Use 'omitempty' for all slices as per OIDC spec:
|
||||
// "Claims that return multiple values are represented as JSON arrays.
|
||||
// Claims with zero elements MUST be omitted from the response."
|
||||
// http://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse
|
||||
|
||||
ScopesSupported []string `json:"scopes_supported,omitempty"`
|
||||
ResponseTypesSupported []string `json:"response_types_supported,omitempty"`
|
||||
ResponseModesSupported []string `json:"response_modes_supported,omitempty"`
|
||||
GrantTypesSupported []string `json:"grant_types_supported,omitempty"`
|
||||
ACRValuesSupported []string `json:"acr_values_supported,omitempty"`
|
||||
SubjectTypesSupported []string `json:"subject_types_supported,omitempty"`
|
||||
|
||||
IDTokenSigningAlgValues []string `json:"id_token_signing_alg_values_supported,omitempty"`
|
||||
IDTokenEncryptionAlgValues []string `json:"id_token_encryption_alg_values_supported,omitempty"`
|
||||
IDTokenEncryptionEncValues []string `json:"id_token_encryption_enc_values_supported,omitempty"`
|
||||
UserInfoSigningAlgValues []string `json:"userinfo_signing_alg_values_supported,omitempty"`
|
||||
UserInfoEncryptionAlgValues []string `json:"userinfo_encryption_alg_values_supported,omitempty"`
|
||||
UserInfoEncryptionEncValues []string `json:"userinfo_encryption_enc_values_supported,omitempty"`
|
||||
ReqObjSigningAlgValues []string `json:"request_object_signing_alg_values_supported,omitempty"`
|
||||
ReqObjEncryptionAlgValues []string `json:"request_object_encryption_alg_values_supported,omitempty"`
|
||||
ReqObjEncryptionEncValues []string `json:"request_object_encryption_enc_values_supported,omitempty"`
|
||||
|
||||
TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported,omitempty"`
|
||||
TokenEndpointAuthSigningAlgValuesSupported []string `json:"token_endpoint_auth_signing_alg_values_supported,omitempty"`
|
||||
|
||||
DisplayValuesSupported []string `json:"display_values_supported,omitempty"`
|
||||
ClaimTypesSupported []string `json:"claim_types_supported,omitempty"`
|
||||
ClaimsSupported []string `json:"claims_supported,omitempty"`
|
||||
ServiceDocs string `json:"service_documentation,omitempty"`
|
||||
ClaimsLocalsSupported []string `json:"claims_locales_supported,omitempty"`
|
||||
UILocalsSupported []string `json:"ui_locales_supported,omitempty"`
|
||||
ClaimsParameterSupported bool `json:"claims_parameter_supported,omitempty"`
|
||||
RequestParameterSupported bool `json:"request_parameter_supported,omitempty"`
|
||||
RequestURIParamaterSupported bool `json:"request_uri_parameter_supported,omitempty"`
|
||||
RequireRequestURIRegistration bool `json:"require_request_uri_registration,omitempty"`
|
||||
|
||||
Policy string `json:"op_policy_uri,omitempty"`
|
||||
TermsOfService string `json:"op_tos_uri,omitempty"`
|
||||
}
|
||||
|
||||
func (cfg ProviderConfig) toEncodableStruct() encodableProviderConfig {
|
||||
return encodableProviderConfig{
|
||||
Issuer: uriToString(cfg.Issuer),
|
||||
AuthEndpoint: uriToString(cfg.AuthEndpoint),
|
||||
TokenEndpoint: uriToString(cfg.TokenEndpoint),
|
||||
UserInfoEndpoint: uriToString(cfg.UserInfoEndpoint),
|
||||
KeysEndpoint: uriToString(cfg.KeysEndpoint),
|
||||
RegistrationEndpoint: uriToString(cfg.RegistrationEndpoint),
|
||||
EndSessionEndpoint: uriToString(cfg.EndSessionEndpoint),
|
||||
CheckSessionIFrame: uriToString(cfg.CheckSessionIFrame),
|
||||
ScopesSupported: cfg.ScopesSupported,
|
||||
ResponseTypesSupported: cfg.ResponseTypesSupported,
|
||||
ResponseModesSupported: cfg.ResponseModesSupported,
|
||||
GrantTypesSupported: cfg.GrantTypesSupported,
|
||||
ACRValuesSupported: cfg.ACRValuesSupported,
|
||||
SubjectTypesSupported: cfg.SubjectTypesSupported,
|
||||
IDTokenSigningAlgValues: cfg.IDTokenSigningAlgValues,
|
||||
IDTokenEncryptionAlgValues: cfg.IDTokenEncryptionAlgValues,
|
||||
IDTokenEncryptionEncValues: cfg.IDTokenEncryptionEncValues,
|
||||
UserInfoSigningAlgValues: cfg.UserInfoSigningAlgValues,
|
||||
UserInfoEncryptionAlgValues: cfg.UserInfoEncryptionAlgValues,
|
||||
UserInfoEncryptionEncValues: cfg.UserInfoEncryptionEncValues,
|
||||
ReqObjSigningAlgValues: cfg.ReqObjSigningAlgValues,
|
||||
ReqObjEncryptionAlgValues: cfg.ReqObjEncryptionAlgValues,
|
||||
ReqObjEncryptionEncValues: cfg.ReqObjEncryptionEncValues,
|
||||
TokenEndpointAuthMethodsSupported: cfg.TokenEndpointAuthMethodsSupported,
|
||||
TokenEndpointAuthSigningAlgValuesSupported: cfg.TokenEndpointAuthSigningAlgValuesSupported,
|
||||
DisplayValuesSupported: cfg.DisplayValuesSupported,
|
||||
ClaimTypesSupported: cfg.ClaimTypesSupported,
|
||||
ClaimsSupported: cfg.ClaimsSupported,
|
||||
ServiceDocs: uriToString(cfg.ServiceDocs),
|
||||
ClaimsLocalsSupported: cfg.ClaimsLocalsSupported,
|
||||
UILocalsSupported: cfg.UILocalsSupported,
|
||||
ClaimsParameterSupported: cfg.ClaimsParameterSupported,
|
||||
RequestParameterSupported: cfg.RequestParameterSupported,
|
||||
RequestURIParamaterSupported: cfg.RequestURIParamaterSupported,
|
||||
RequireRequestURIRegistration: cfg.RequireRequestURIRegistration,
|
||||
Policy: uriToString(cfg.Policy),
|
||||
TermsOfService: uriToString(cfg.TermsOfService),
|
||||
}
|
||||
}
|
||||
|
||||
func (e encodableProviderConfig) toStruct() (ProviderConfig, error) {
|
||||
p := stickyErrParser{}
|
||||
conf := ProviderConfig{
|
||||
Issuer: p.parseURI(e.Issuer, "issuer"),
|
||||
AuthEndpoint: p.parseURI(e.AuthEndpoint, "authorization_endpoint"),
|
||||
TokenEndpoint: p.parseURI(e.TokenEndpoint, "token_endpoint"),
|
||||
UserInfoEndpoint: p.parseURI(e.UserInfoEndpoint, "userinfo_endpoint"),
|
||||
KeysEndpoint: p.parseURI(e.KeysEndpoint, "jwks_uri"),
|
||||
RegistrationEndpoint: p.parseURI(e.RegistrationEndpoint, "registration_endpoint"),
|
||||
EndSessionEndpoint: p.parseURI(e.EndSessionEndpoint, "end_session_endpoint"),
|
||||
CheckSessionIFrame: p.parseURI(e.CheckSessionIFrame, "check_session_iframe"),
|
||||
ScopesSupported: e.ScopesSupported,
|
||||
ResponseTypesSupported: e.ResponseTypesSupported,
|
||||
ResponseModesSupported: e.ResponseModesSupported,
|
||||
GrantTypesSupported: e.GrantTypesSupported,
|
||||
ACRValuesSupported: e.ACRValuesSupported,
|
||||
SubjectTypesSupported: e.SubjectTypesSupported,
|
||||
IDTokenSigningAlgValues: e.IDTokenSigningAlgValues,
|
||||
IDTokenEncryptionAlgValues: e.IDTokenEncryptionAlgValues,
|
||||
IDTokenEncryptionEncValues: e.IDTokenEncryptionEncValues,
|
||||
UserInfoSigningAlgValues: e.UserInfoSigningAlgValues,
|
||||
UserInfoEncryptionAlgValues: e.UserInfoEncryptionAlgValues,
|
||||
UserInfoEncryptionEncValues: e.UserInfoEncryptionEncValues,
|
||||
ReqObjSigningAlgValues: e.ReqObjSigningAlgValues,
|
||||
ReqObjEncryptionAlgValues: e.ReqObjEncryptionAlgValues,
|
||||
ReqObjEncryptionEncValues: e.ReqObjEncryptionEncValues,
|
||||
TokenEndpointAuthMethodsSupported: e.TokenEndpointAuthMethodsSupported,
|
||||
TokenEndpointAuthSigningAlgValuesSupported: e.TokenEndpointAuthSigningAlgValuesSupported,
|
||||
DisplayValuesSupported: e.DisplayValuesSupported,
|
||||
ClaimTypesSupported: e.ClaimTypesSupported,
|
||||
ClaimsSupported: e.ClaimsSupported,
|
||||
ServiceDocs: p.parseURI(e.ServiceDocs, "service_documentation"),
|
||||
ClaimsLocalsSupported: e.ClaimsLocalsSupported,
|
||||
UILocalsSupported: e.UILocalsSupported,
|
||||
ClaimsParameterSupported: e.ClaimsParameterSupported,
|
||||
RequestParameterSupported: e.RequestParameterSupported,
|
||||
RequestURIParamaterSupported: e.RequestURIParamaterSupported,
|
||||
RequireRequestURIRegistration: e.RequireRequestURIRegistration,
|
||||
Policy: p.parseURI(e.Policy, "op_policy-uri"),
|
||||
TermsOfService: p.parseURI(e.TermsOfService, "op_tos_uri"),
|
||||
}
|
||||
if p.firstErr != nil {
|
||||
return ProviderConfig{}, p.firstErr
|
||||
}
|
||||
return conf, nil
|
||||
}
|
||||
|
||||
// Empty returns if a ProviderConfig holds no information.
|
||||
//
|
||||
// This case generally indicates a ProviderConfigGetter has experienced an error
|
||||
// and has nothing to report.
|
||||
func (p ProviderConfig) Empty() bool {
|
||||
return p.Issuer == nil
|
||||
}
|
||||
|
||||
func contains(sli []string, ele string) bool {
|
||||
for _, s := range sli {
|
||||
if s == ele {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Valid determines if a ProviderConfig conforms with the OIDC specification.
|
||||
// If Valid returns successfully it guarantees required field are non-nil and
|
||||
// URLs are well formed.
|
||||
//
|
||||
// Valid is called by UnmarshalJSON.
|
||||
//
|
||||
// NOTE(ericchiang): For development purposes Valid does not mandate 'https' for
|
||||
// URLs fields where the OIDC spec requires it. This may change in future releases
|
||||
// of this package. See: https://github.com/coreos/go-oidc/issues/34
|
||||
func (p ProviderConfig) Valid() error {
|
||||
grantTypes := p.GrantTypesSupported
|
||||
if len(grantTypes) == 0 {
|
||||
grantTypes = DefaultGrantTypesSupported
|
||||
}
|
||||
implicitOnly := true
|
||||
for _, grantType := range grantTypes {
|
||||
if grantType != oauth2.GrantTypeImplicit {
|
||||
implicitOnly = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(p.SubjectTypesSupported) == 0 {
|
||||
return errors.New("missing required field subject_types_supported")
|
||||
}
|
||||
if len(p.IDTokenSigningAlgValues) == 0 {
|
||||
return errors.New("missing required field id_token_signing_alg_values_supported")
|
||||
}
|
||||
|
||||
if len(p.ScopesSupported) != 0 && !contains(p.ScopesSupported, "openid") {
|
||||
return errors.New("scoped_supported must be unspecified or include 'openid'")
|
||||
}
|
||||
|
||||
if !contains(p.IDTokenSigningAlgValues, "RS256") {
|
||||
return errors.New("id_token_signing_alg_values_supported must include 'RS256'")
|
||||
}
|
||||
if contains(p.TokenEndpointAuthMethodsSupported, "none") {
|
||||
return errors.New("token_endpoint_auth_signing_alg_values_supported cannot include 'none'")
|
||||
}
|
||||
|
||||
uris := []struct {
|
||||
val *url.URL
|
||||
name string
|
||||
required bool
|
||||
}{
|
||||
{p.Issuer, "issuer", true},
|
||||
{p.AuthEndpoint, "authorization_endpoint", true},
|
||||
{p.TokenEndpoint, "token_endpoint", !implicitOnly},
|
||||
{p.UserInfoEndpoint, "userinfo_endpoint", false},
|
||||
{p.KeysEndpoint, "jwks_uri", true},
|
||||
{p.RegistrationEndpoint, "registration_endpoint", false},
|
||||
{p.EndSessionEndpoint, "end_session_endpoint", false},
|
||||
{p.CheckSessionIFrame, "check_session_iframe", false},
|
||||
{p.ServiceDocs, "service_documentation", false},
|
||||
{p.Policy, "op_policy_uri", false},
|
||||
{p.TermsOfService, "op_tos_uri", false},
|
||||
}
|
||||
|
||||
for _, uri := range uris {
|
||||
if uri.val == nil {
|
||||
if !uri.required {
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("empty value for required uri field %s", uri.name)
|
||||
}
|
||||
if uri.val.Host == "" {
|
||||
return fmt.Errorf("no host for uri field %s", uri.name)
|
||||
}
|
||||
if uri.val.Scheme != "http" && uri.val.Scheme != "https" {
|
||||
return fmt.Errorf("uri field %s schemeis not http or https", uri.name)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Supports determines if provider supports a client given their respective metadata.
|
||||
func (p ProviderConfig) Supports(c ClientMetadata) error {
|
||||
if err := p.Valid(); err != nil {
|
||||
return fmt.Errorf("invalid provider config: %v", err)
|
||||
}
|
||||
if err := c.Valid(); err != nil {
|
||||
return fmt.Errorf("invalid client config: %v", err)
|
||||
}
|
||||
|
||||
// Fill default values for omitted fields
|
||||
c = c.Defaults()
|
||||
p = p.Defaults()
|
||||
|
||||
// Do the supported values list the requested one?
|
||||
supports := []struct {
|
||||
supported []string
|
||||
requested string
|
||||
name string
|
||||
}{
|
||||
{p.IDTokenSigningAlgValues, c.IDTokenResponseOptions.SigningAlg, "id_token_signed_response_alg"},
|
||||
{p.IDTokenEncryptionAlgValues, c.IDTokenResponseOptions.EncryptionAlg, "id_token_encryption_response_alg"},
|
||||
{p.IDTokenEncryptionEncValues, c.IDTokenResponseOptions.EncryptionEnc, "id_token_encryption_response_enc"},
|
||||
{p.UserInfoSigningAlgValues, c.UserInfoResponseOptions.SigningAlg, "userinfo_signed_response_alg"},
|
||||
{p.UserInfoEncryptionAlgValues, c.UserInfoResponseOptions.EncryptionAlg, "userinfo_encryption_response_alg"},
|
||||
{p.UserInfoEncryptionEncValues, c.UserInfoResponseOptions.EncryptionEnc, "userinfo_encryption_response_enc"},
|
||||
{p.ReqObjSigningAlgValues, c.RequestObjectOptions.SigningAlg, "request_object_signing_alg"},
|
||||
{p.ReqObjEncryptionAlgValues, c.RequestObjectOptions.EncryptionAlg, "request_object_encryption_alg"},
|
||||
{p.ReqObjEncryptionEncValues, c.RequestObjectOptions.EncryptionEnc, "request_object_encryption_enc"},
|
||||
}
|
||||
for _, field := range supports {
|
||||
if field.requested == "" {
|
||||
continue
|
||||
}
|
||||
if !contains(field.supported, field.requested) {
|
||||
return fmt.Errorf("provider does not support requested value for field %s", field.name)
|
||||
}
|
||||
}
|
||||
|
||||
stringsEqual := func(s1, s2 string) bool { return s1 == s2 }
|
||||
|
||||
// For lists, are the list of requested values a subset of the supported ones?
|
||||
supportsAll := []struct {
|
||||
supported []string
|
||||
requested []string
|
||||
name string
|
||||
// OAuth2.0 response_type can be space separated lists where order doesn't matter.
|
||||
// For example "id_token token" is the same as "token id_token"
|
||||
// Support a custom compare method.
|
||||
comp func(s1, s2 string) bool
|
||||
}{
|
||||
{p.GrantTypesSupported, c.GrantTypes, "grant_types", stringsEqual},
|
||||
{p.ResponseTypesSupported, c.ResponseTypes, "response_type", oauth2.ResponseTypesEqual},
|
||||
}
|
||||
for _, field := range supportsAll {
|
||||
requestLoop:
|
||||
for _, req := range field.requested {
|
||||
for _, sup := range field.supported {
|
||||
if field.comp(req, sup) {
|
||||
continue requestLoop
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("provider does not support requested value for field %s", field.name)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(ericchiang): Are there more checks we feel comfortable with begin strict about?
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p ProviderConfig) SupportsGrantType(grantType string) bool {
|
||||
var supported []string
|
||||
if len(p.GrantTypesSupported) == 0 {
|
||||
supported = DefaultGrantTypesSupported
|
||||
} else {
|
||||
supported = p.GrantTypesSupported
|
||||
}
|
||||
|
||||
for _, t := range supported {
|
||||
if t == grantType {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ProviderConfigGetter interface {
|
||||
Get() (ProviderConfig, error)
|
||||
}
|
||||
|
||||
type ProviderConfigSetter interface {
|
||||
Set(ProviderConfig) error
|
||||
}
|
||||
|
||||
type ProviderConfigSyncer struct {
|
||||
from ProviderConfigGetter
|
||||
to ProviderConfigSetter
|
||||
clock clockwork.Clock
|
||||
|
||||
initialSyncDone bool
|
||||
initialSyncWait sync.WaitGroup
|
||||
}
|
||||
|
||||
func NewProviderConfigSyncer(from ProviderConfigGetter, to ProviderConfigSetter) *ProviderConfigSyncer {
|
||||
return &ProviderConfigSyncer{
|
||||
from: from,
|
||||
to: to,
|
||||
clock: clockwork.NewRealClock(),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ProviderConfigSyncer) Run() chan struct{} {
|
||||
stop := make(chan struct{})
|
||||
|
||||
var next pcsStepper
|
||||
next = &pcsStepNext{aft: time.Duration(0)}
|
||||
|
||||
s.initialSyncWait.Add(1)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-s.clock.After(next.after()):
|
||||
next = next.step(s.sync)
|
||||
case <-stop:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return stop
|
||||
}
|
||||
|
||||
func (s *ProviderConfigSyncer) WaitUntilInitialSync() {
|
||||
s.initialSyncWait.Wait()
|
||||
}
|
||||
|
||||
func (s *ProviderConfigSyncer) sync() (time.Duration, error) {
|
||||
cfg, err := s.from.Get()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if err = s.to.Set(cfg); err != nil {
|
||||
return 0, fmt.Errorf("error setting provider config: %v", err)
|
||||
}
|
||||
|
||||
if !s.initialSyncDone {
|
||||
s.initialSyncWait.Done()
|
||||
s.initialSyncDone = true
|
||||
}
|
||||
|
||||
return nextSyncAfter(cfg.ExpiresAt, s.clock), nil
|
||||
}
|
||||
|
||||
type pcsStepFunc func() (time.Duration, error)
|
||||
|
||||
type pcsStepper interface {
|
||||
after() time.Duration
|
||||
step(pcsStepFunc) pcsStepper
|
||||
}
|
||||
|
||||
type pcsStepNext struct {
|
||||
aft time.Duration
|
||||
}
|
||||
|
||||
func (n *pcsStepNext) after() time.Duration {
|
||||
return n.aft
|
||||
}
|
||||
|
||||
func (n *pcsStepNext) step(fn pcsStepFunc) (next pcsStepper) {
|
||||
ttl, err := fn()
|
||||
if err == nil {
|
||||
next = &pcsStepNext{aft: ttl}
|
||||
} else {
|
||||
next = &pcsStepRetry{aft: time.Second}
|
||||
log.Printf("go-oidc: provider config sync failed, retrying in %v: %v", next.after(), err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type pcsStepRetry struct {
|
||||
aft time.Duration
|
||||
}
|
||||
|
||||
func (r *pcsStepRetry) after() time.Duration {
|
||||
return r.aft
|
||||
}
|
||||
|
||||
func (r *pcsStepRetry) step(fn pcsStepFunc) (next pcsStepper) {
|
||||
ttl, err := fn()
|
||||
if err == nil {
|
||||
next = &pcsStepNext{aft: ttl}
|
||||
} else {
|
||||
next = &pcsStepRetry{aft: timeutil.ExpBackoff(r.aft, time.Minute)}
|
||||
log.Printf("go-oidc: provider config sync failed, retrying in %v: %v", next.after(), err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func nextSyncAfter(exp time.Time, clock clockwork.Clock) time.Duration {
|
||||
if exp.IsZero() {
|
||||
return MaximumProviderConfigSyncInterval
|
||||
}
|
||||
|
||||
t := exp.Sub(clock.Now()) / 2
|
||||
if t > MaximumProviderConfigSyncInterval {
|
||||
t = MaximumProviderConfigSyncInterval
|
||||
} else if t < minimumProviderConfigSyncInterval {
|
||||
t = minimumProviderConfigSyncInterval
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
type httpProviderConfigGetter struct {
|
||||
hc phttp.Client
|
||||
issuerURL string
|
||||
clock clockwork.Clock
|
||||
}
|
||||
|
||||
func NewHTTPProviderConfigGetter(hc phttp.Client, issuerURL string) *httpProviderConfigGetter {
|
||||
return &httpProviderConfigGetter{
|
||||
hc: hc,
|
||||
issuerURL: issuerURL,
|
||||
clock: clockwork.NewRealClock(),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *httpProviderConfigGetter) Get() (cfg ProviderConfig, err error) {
|
||||
// If the Issuer value contains a path component, any terminating / MUST be removed before
|
||||
// appending /.well-known/openid-configuration.
|
||||
// https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest
|
||||
discoveryURL := strings.TrimSuffix(r.issuerURL, "/") + discoveryConfigPath
|
||||
req, err := http.NewRequest("GET", discoveryURL, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := r.hc.Do(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if err = json.NewDecoder(resp.Body).Decode(&cfg); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var ttl time.Duration
|
||||
var ok bool
|
||||
ttl, ok, err = phttp.Cacheable(resp.Header)
|
||||
if err != nil {
|
||||
return
|
||||
} else if ok {
|
||||
cfg.ExpiresAt = r.clock.Now().UTC().Add(ttl)
|
||||
}
|
||||
|
||||
// The issuer value returned MUST be identical to the Issuer URL that was directly used to retrieve the configuration information.
|
||||
// http://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationValidation
|
||||
if !urlEqual(cfg.Issuer.String(), r.issuerURL) {
|
||||
err = fmt.Errorf(`"issuer" in config (%v) does not match provided issuer URL (%v)`, cfg.Issuer, r.issuerURL)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func FetchProviderConfig(hc phttp.Client, issuerURL string) (ProviderConfig, error) {
|
||||
if hc == nil {
|
||||
hc = http.DefaultClient
|
||||
}
|
||||
|
||||
g := NewHTTPProviderConfigGetter(hc, issuerURL)
|
||||
return g.Get()
|
||||
}
|
||||
|
||||
func WaitForProviderConfig(hc phttp.Client, issuerURL string) (pcfg ProviderConfig) {
|
||||
return waitForProviderConfig(hc, issuerURL, clockwork.NewRealClock())
|
||||
}
|
||||
|
||||
func waitForProviderConfig(hc phttp.Client, issuerURL string, clock clockwork.Clock) (pcfg ProviderConfig) {
|
||||
var sleep time.Duration
|
||||
var err error
|
||||
for {
|
||||
pcfg, err = FetchProviderConfig(hc, issuerURL)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
|
||||
sleep = timeutil.ExpBackoff(sleep, time.Minute)
|
||||
fmt.Printf("Failed fetching provider config, trying again in %v: %v\n", sleep, err)
|
||||
time.Sleep(sleep)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
940
vendor/github.com/coreos/go-oidc/oidc/provider_test.go
generated
vendored
940
vendor/github.com/coreos/go-oidc/oidc/provider_test.go
generated
vendored
|
@ -1,940 +0,0 @@
|
|||
package oidc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/jonboulle/clockwork"
|
||||
"github.com/kylelemons/godebug/diff"
|
||||
"github.com/kylelemons/godebug/pretty"
|
||||
|
||||
"github.com/coreos/go-oidc/jose"
|
||||
"github.com/coreos/go-oidc/oauth2"
|
||||
)
|
||||
|
||||
func TestProviderConfigDefaults(t *testing.T) {
|
||||
var cfg ProviderConfig
|
||||
cfg = cfg.Defaults()
|
||||
tests := []struct {
|
||||
got, want []string
|
||||
name string
|
||||
}{
|
||||
{cfg.GrantTypesSupported, DefaultGrantTypesSupported, "grant types"},
|
||||
{cfg.ResponseModesSupported, DefaultResponseModesSupported, "response modes"},
|
||||
{cfg.ClaimTypesSupported, DefaultClaimTypesSupported, "claim types"},
|
||||
{
|
||||
cfg.TokenEndpointAuthMethodsSupported,
|
||||
DefaultTokenEndpointAuthMethodsSupported,
|
||||
"token endpoint auth methods",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
if diff := pretty.Compare(tt.want, tt.got); diff != "" {
|
||||
t.Errorf("%s: did not match %s", tt.name, diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestProviderConfigUnmarshal(t *testing.T) {
|
||||
|
||||
// helper for quickly creating uris
|
||||
uri := func(path string) *url.URL {
|
||||
return &url.URL{
|
||||
Scheme: "https",
|
||||
Host: "server.example.com",
|
||||
Path: path,
|
||||
}
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
data string
|
||||
want ProviderConfig
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
data: `{
|
||||
"issuer": "https://server.example.com",
|
||||
"authorization_endpoint": "https://server.example.com/connect/authorize",
|
||||
"token_endpoint": "https://server.example.com/connect/token",
|
||||
"token_endpoint_auth_methods_supported": ["client_secret_basic", "private_key_jwt"],
|
||||
"token_endpoint_auth_signing_alg_values_supported": ["RS256", "ES256"],
|
||||
"userinfo_endpoint": "https://server.example.com/connect/userinfo",
|
||||
"jwks_uri": "https://server.example.com/jwks.json",
|
||||
"registration_endpoint": "https://server.example.com/connect/register",
|
||||
"scopes_supported": [
|
||||
"openid", "profile", "email", "address", "phone", "offline_access"
|
||||
],
|
||||
"response_types_supported": [
|
||||
"code", "code id_token", "id_token", "id_token token"
|
||||
],
|
||||
"acr_values_supported": [
|
||||
"urn:mace:incommon:iap:silver", "urn:mace:incommon:iap:bronze"
|
||||
],
|
||||
"subject_types_supported": ["public", "pairwise"],
|
||||
"userinfo_signing_alg_values_supported": ["RS256", "ES256", "HS256"],
|
||||
"userinfo_encryption_alg_values_supported": ["RSA1_5", "A128KW"],
|
||||
"userinfo_encryption_enc_values_supported": ["A128CBC-HS256", "A128GCM"],
|
||||
"id_token_signing_alg_values_supported": ["RS256", "ES256", "HS256"],
|
||||
"id_token_encryption_alg_values_supported": ["RSA1_5", "A128KW"],
|
||||
"id_token_encryption_enc_values_supported": ["A128CBC-HS256", "A128GCM"],
|
||||
"request_object_signing_alg_values_supported": ["none", "RS256", "ES256"],
|
||||
"display_values_supported": ["page", "popup"],
|
||||
"claim_types_supported": ["normal", "distributed"],
|
||||
"claims_supported": [
|
||||
"sub", "iss", "auth_time", "acr", "name", "given_name",
|
||||
"family_name", "nickname", "profile", "picture", "website",
|
||||
"email", "email_verified", "locale", "zoneinfo",
|
||||
"http://example.info/claims/groups"
|
||||
],
|
||||
"claims_parameter_supported": true,
|
||||
"service_documentation": "https://server.example.com/connect/service_documentation.html",
|
||||
"ui_locales_supported": ["en-US", "en-GB", "en-CA", "fr-FR", "fr-CA"]
|
||||
}
|
||||
`,
|
||||
want: ProviderConfig{
|
||||
Issuer: &url.URL{Scheme: "https", Host: "server.example.com"},
|
||||
AuthEndpoint: uri("/connect/authorize"),
|
||||
TokenEndpoint: uri("/connect/token"),
|
||||
TokenEndpointAuthMethodsSupported: []string{
|
||||
oauth2.AuthMethodClientSecretBasic, oauth2.AuthMethodPrivateKeyJWT,
|
||||
},
|
||||
TokenEndpointAuthSigningAlgValuesSupported: []string{
|
||||
jose.AlgRS256, jose.AlgES256,
|
||||
},
|
||||
UserInfoEndpoint: uri("/connect/userinfo"),
|
||||
KeysEndpoint: uri("/jwks.json"),
|
||||
RegistrationEndpoint: uri("/connect/register"),
|
||||
ScopesSupported: []string{
|
||||
"openid", "profile", "email", "address", "phone", "offline_access",
|
||||
},
|
||||
ResponseTypesSupported: []string{
|
||||
oauth2.ResponseTypeCode, oauth2.ResponseTypeCodeIDToken,
|
||||
oauth2.ResponseTypeIDToken, oauth2.ResponseTypeIDTokenToken,
|
||||
},
|
||||
ACRValuesSupported: []string{
|
||||
"urn:mace:incommon:iap:silver", "urn:mace:incommon:iap:bronze",
|
||||
},
|
||||
SubjectTypesSupported: []string{
|
||||
SubjectTypePublic, SubjectTypePairwise,
|
||||
},
|
||||
UserInfoSigningAlgValues: []string{jose.AlgRS256, jose.AlgES256, jose.AlgHS256},
|
||||
UserInfoEncryptionAlgValues: []string{"RSA1_5", "A128KW"},
|
||||
UserInfoEncryptionEncValues: []string{"A128CBC-HS256", "A128GCM"},
|
||||
IDTokenSigningAlgValues: []string{jose.AlgRS256, jose.AlgES256, jose.AlgHS256},
|
||||
IDTokenEncryptionAlgValues: []string{"RSA1_5", "A128KW"},
|
||||
IDTokenEncryptionEncValues: []string{"A128CBC-HS256", "A128GCM"},
|
||||
ReqObjSigningAlgValues: []string{jose.AlgNone, jose.AlgRS256, jose.AlgES256},
|
||||
DisplayValuesSupported: []string{"page", "popup"},
|
||||
ClaimTypesSupported: []string{"normal", "distributed"},
|
||||
ClaimsSupported: []string{
|
||||
"sub", "iss", "auth_time", "acr", "name", "given_name",
|
||||
"family_name", "nickname", "profile", "picture", "website",
|
||||
"email", "email_verified", "locale", "zoneinfo",
|
||||
"http://example.info/claims/groups",
|
||||
},
|
||||
ClaimsParameterSupported: true,
|
||||
ServiceDocs: uri("/connect/service_documentation.html"),
|
||||
UILocalsSupported: []string{"en-US", "en-GB", "en-CA", "fr-FR", "fr-CA"},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// missing a lot of required field
|
||||
data: `{}`,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
data: `{
|
||||
"issuer": "https://server.example.com",
|
||||
"authorization_endpoint": "https://server.example.com/connect/authorize",
|
||||
"token_endpoint": "https://server.example.com/connect/token",
|
||||
"jwks_uri": "https://server.example.com/jwks.json",
|
||||
"response_types_supported": [
|
||||
"code", "code id_token", "id_token", "id_token token"
|
||||
],
|
||||
"subject_types_supported": ["public", "pairwise"],
|
||||
"id_token_signing_alg_values_supported": ["RS256", "ES256", "HS256"]
|
||||
}
|
||||
`,
|
||||
want: ProviderConfig{
|
||||
Issuer: &url.URL{Scheme: "https", Host: "server.example.com"},
|
||||
AuthEndpoint: uri("/connect/authorize"),
|
||||
TokenEndpoint: uri("/connect/token"),
|
||||
KeysEndpoint: uri("/jwks.json"),
|
||||
ResponseTypesSupported: []string{
|
||||
oauth2.ResponseTypeCode, oauth2.ResponseTypeCodeIDToken,
|
||||
oauth2.ResponseTypeIDToken, oauth2.ResponseTypeIDTokenToken,
|
||||
},
|
||||
SubjectTypesSupported: []string{
|
||||
SubjectTypePublic, SubjectTypePairwise,
|
||||
},
|
||||
IDTokenSigningAlgValues: []string{jose.AlgRS256, jose.AlgES256, jose.AlgHS256},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
// invalid scheme 'ftp://'
|
||||
data: `{
|
||||
"issuer": "https://server.example.com",
|
||||
"authorization_endpoint": "https://server.example.com/connect/authorize",
|
||||
"token_endpoint": "https://server.example.com/connect/token",
|
||||
"jwks_uri": "ftp://server.example.com/jwks.json",
|
||||
"response_types_supported": [
|
||||
"code", "code id_token", "id_token", "id_token token"
|
||||
],
|
||||
"subject_types_supported": ["public", "pairwise"],
|
||||
"id_token_signing_alg_values_supported": ["RS256", "ES256", "HS256"]
|
||||
}
|
||||
`,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
var got ProviderConfig
|
||||
if err := json.Unmarshal([]byte(tt.data), &got); err != nil {
|
||||
if !tt.wantErr {
|
||||
t.Errorf("case %d: failed to unmarshal provider config: %v", i, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if tt.wantErr {
|
||||
t.Errorf("case %d: expected error", i)
|
||||
continue
|
||||
}
|
||||
if diff := pretty.Compare(tt.want, got); diff != "" {
|
||||
t.Errorf("case %d: unmarshaled struct did not match expected %s", i, diff)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestProviderConfigMarshal(t *testing.T) {
|
||||
tests := []struct {
|
||||
cfg ProviderConfig
|
||||
want string
|
||||
}{
|
||||
{
|
||||
cfg: ProviderConfig{
|
||||
Issuer: &url.URL{Scheme: "https", Host: "auth.example.com"},
|
||||
AuthEndpoint: &url.URL{
|
||||
Scheme: "https", Host: "auth.example.com", Path: "/auth",
|
||||
},
|
||||
TokenEndpoint: &url.URL{
|
||||
Scheme: "https", Host: "auth.example.com", Path: "/token",
|
||||
},
|
||||
UserInfoEndpoint: &url.URL{
|
||||
Scheme: "https", Host: "auth.example.com", Path: "/userinfo",
|
||||
},
|
||||
KeysEndpoint: &url.URL{
|
||||
Scheme: "https", Host: "auth.example.com", Path: "/jwk",
|
||||
},
|
||||
ResponseTypesSupported: []string{oauth2.ResponseTypeCode},
|
||||
SubjectTypesSupported: []string{SubjectTypePublic},
|
||||
IDTokenSigningAlgValues: []string{jose.AlgRS256},
|
||||
},
|
||||
// spacing must match json.MarshalIndent(cfg, "", "\t")
|
||||
want: `{
|
||||
"issuer": "https://auth.example.com",
|
||||
"authorization_endpoint": "https://auth.example.com/auth",
|
||||
"token_endpoint": "https://auth.example.com/token",
|
||||
"userinfo_endpoint": "https://auth.example.com/userinfo",
|
||||
"jwks_uri": "https://auth.example.com/jwk",
|
||||
"response_types_supported": [
|
||||
"code"
|
||||
],
|
||||
"subject_types_supported": [
|
||||
"public"
|
||||
],
|
||||
"id_token_signing_alg_values_supported": [
|
||||
"RS256"
|
||||
]
|
||||
}`,
|
||||
},
|
||||
{
|
||||
cfg: ProviderConfig{
|
||||
Issuer: &url.URL{Scheme: "https", Host: "auth.example.com"},
|
||||
AuthEndpoint: &url.URL{
|
||||
Scheme: "https", Host: "auth.example.com", Path: "/auth",
|
||||
},
|
||||
TokenEndpoint: &url.URL{
|
||||
Scheme: "https", Host: "auth.example.com", Path: "/token",
|
||||
},
|
||||
UserInfoEndpoint: &url.URL{
|
||||
Scheme: "https", Host: "auth.example.com", Path: "/userinfo",
|
||||
},
|
||||
KeysEndpoint: &url.URL{
|
||||
Scheme: "https", Host: "auth.example.com", Path: "/jwk",
|
||||
},
|
||||
RegistrationEndpoint: &url.URL{
|
||||
Scheme: "https", Host: "auth.example.com", Path: "/register",
|
||||
},
|
||||
ScopesSupported: DefaultScope,
|
||||
ResponseTypesSupported: []string{oauth2.ResponseTypeCode},
|
||||
ResponseModesSupported: DefaultResponseModesSupported,
|
||||
GrantTypesSupported: []string{oauth2.GrantTypeAuthCode},
|
||||
SubjectTypesSupported: []string{SubjectTypePublic},
|
||||
IDTokenSigningAlgValues: []string{jose.AlgRS256},
|
||||
ServiceDocs: &url.URL{Scheme: "https", Host: "example.com", Path: "/docs"},
|
||||
},
|
||||
// spacing must match json.MarshalIndent(cfg, "", "\t")
|
||||
want: `{
|
||||
"issuer": "https://auth.example.com",
|
||||
"authorization_endpoint": "https://auth.example.com/auth",
|
||||
"token_endpoint": "https://auth.example.com/token",
|
||||
"userinfo_endpoint": "https://auth.example.com/userinfo",
|
||||
"jwks_uri": "https://auth.example.com/jwk",
|
||||
"registration_endpoint": "https://auth.example.com/register",
|
||||
"scopes_supported": [
|
||||
"openid",
|
||||
"email",
|
||||
"profile"
|
||||
],
|
||||
"response_types_supported": [
|
||||
"code"
|
||||
],
|
||||
"response_modes_supported": [
|
||||
"query",
|
||||
"fragment"
|
||||
],
|
||||
"grant_types_supported": [
|
||||
"authorization_code"
|
||||
],
|
||||
"subject_types_supported": [
|
||||
"public"
|
||||
],
|
||||
"id_token_signing_alg_values_supported": [
|
||||
"RS256"
|
||||
],
|
||||
"service_documentation": "https://example.com/docs"
|
||||
}`,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
got, err := json.MarshalIndent(&tt.cfg, "", "\t")
|
||||
if err != nil {
|
||||
t.Errorf("case %d: failed to marshal config: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if d := diff.Diff(string(got), string(tt.want)); d != "" {
|
||||
t.Errorf("case %d: expected did not match result: %s", i, d)
|
||||
}
|
||||
|
||||
var cfg ProviderConfig
|
||||
if err := json.Unmarshal(got, &cfg); err != nil {
|
||||
t.Errorf("case %d: could not unmarshal marshal response: %v", i, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if d := pretty.Compare(tt.cfg, cfg); d != "" {
|
||||
t.Errorf("case %d: config did not survive JSON marshaling round trip: %s", i, d)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestProviderConfigSupports(t *testing.T) {
|
||||
tests := []struct {
|
||||
provider ProviderConfig
|
||||
client ClientMetadata
|
||||
fillRequiredProviderFields bool
|
||||
ok bool
|
||||
}{
|
||||
{
|
||||
provider: ProviderConfig{},
|
||||
client: ClientMetadata{
|
||||
RedirectURIs: []url.URL{
|
||||
{Scheme: "https", Host: "example.com", Path: "/callback"},
|
||||
},
|
||||
},
|
||||
fillRequiredProviderFields: true,
|
||||
ok: true,
|
||||
},
|
||||
{
|
||||
// invalid provider config
|
||||
provider: ProviderConfig{},
|
||||
client: ClientMetadata{
|
||||
RedirectURIs: []url.URL{
|
||||
{Scheme: "https", Host: "example.com", Path: "/callback"},
|
||||
},
|
||||
},
|
||||
fillRequiredProviderFields: false,
|
||||
ok: false,
|
||||
},
|
||||
{
|
||||
// invalid client config
|
||||
provider: ProviderConfig{},
|
||||
client: ClientMetadata{},
|
||||
fillRequiredProviderFields: true,
|
||||
ok: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
if tt.fillRequiredProviderFields {
|
||||
tt.provider = fillRequiredProviderFields(tt.provider)
|
||||
}
|
||||
|
||||
err := tt.provider.Supports(tt.client)
|
||||
if err == nil && !tt.ok {
|
||||
t.Errorf("case %d: expected non-nil error", i)
|
||||
}
|
||||
if err != nil && tt.ok {
|
||||
t.Errorf("case %d: supports failed: %v", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newValidProviderConfig() ProviderConfig {
|
||||
var cfg ProviderConfig
|
||||
return fillRequiredProviderFields(cfg)
|
||||
}
|
||||
|
||||
// fill a provider config with enough information to be valid
|
||||
func fillRequiredProviderFields(cfg ProviderConfig) ProviderConfig {
|
||||
if cfg.Issuer == nil {
|
||||
cfg.Issuer = &url.URL{Scheme: "https", Host: "auth.example.com"}
|
||||
}
|
||||
urlPath := func(path string) *url.URL {
|
||||
var u url.URL
|
||||
u = *cfg.Issuer
|
||||
u.Path = path
|
||||
return &u
|
||||
}
|
||||
cfg.AuthEndpoint = urlPath("/auth")
|
||||
cfg.TokenEndpoint = urlPath("/token")
|
||||
cfg.UserInfoEndpoint = urlPath("/userinfo")
|
||||
cfg.KeysEndpoint = urlPath("/jwk")
|
||||
cfg.ResponseTypesSupported = []string{oauth2.ResponseTypeCode}
|
||||
cfg.SubjectTypesSupported = []string{SubjectTypePublic}
|
||||
cfg.IDTokenSigningAlgValues = []string{jose.AlgRS256}
|
||||
return cfg
|
||||
}
|
||||
|
||||
type fakeProviderConfigGetterSetter struct {
|
||||
cfg *ProviderConfig
|
||||
getCount int
|
||||
setCount int
|
||||
}
|
||||
|
||||
func (g *fakeProviderConfigGetterSetter) Get() (ProviderConfig, error) {
|
||||
g.getCount++
|
||||
return *g.cfg, nil
|
||||
}
|
||||
|
||||
func (g *fakeProviderConfigGetterSetter) Set(cfg ProviderConfig) error {
|
||||
g.cfg = &cfg
|
||||
g.setCount++
|
||||
return nil
|
||||
}
|
||||
|
||||
type fakeProviderConfigHandler struct {
|
||||
cfg ProviderConfig
|
||||
maxAge time.Duration
|
||||
}
|
||||
|
||||
func (s *fakeProviderConfigHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
b, _ := json.Marshal(&s.cfg)
|
||||
if s.maxAge.Seconds() >= 0 {
|
||||
w.Header().Set("Cache-Control", fmt.Sprintf("public, max-age=%d", int(s.maxAge.Seconds())))
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(b)
|
||||
}
|
||||
|
||||
func TestProviderConfigRequiredFields(t *testing.T) {
|
||||
// Ensure provider metadata responses have all the required fields.
|
||||
// taken from https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
|
||||
requiredFields := []string{
|
||||
"issuer",
|
||||
"authorization_endpoint",
|
||||
"token_endpoint", // "This is REQUIRED unless only the Implicit Flow is used."
|
||||
"jwks_uri",
|
||||
"response_types_supported",
|
||||
"subject_types_supported",
|
||||
"id_token_signing_alg_values_supported",
|
||||
}
|
||||
|
||||
svr := &fakeProviderConfigHandler{
|
||||
cfg: ProviderConfig{
|
||||
Issuer: &url.URL{Scheme: "http", Host: "example.com"},
|
||||
ExpiresAt: time.Now().Add(time.Minute),
|
||||
},
|
||||
maxAge: time.Minute,
|
||||
}
|
||||
svr.cfg = fillRequiredProviderFields(svr.cfg)
|
||||
s := httptest.NewServer(svr)
|
||||
defer s.Close()
|
||||
|
||||
resp, err := http.Get(s.URL + "/")
|
||||
if err != nil {
|
||||
t.Errorf("get: %v", err)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var data map[string]interface{}
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
t.Errorf("decode: %v", err)
|
||||
return
|
||||
}
|
||||
for _, field := range requiredFields {
|
||||
if _, ok := data[field]; !ok {
|
||||
t.Errorf("provider metadata does not have required field '%s'", field)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type handlerClient struct {
|
||||
Handler http.Handler
|
||||
}
|
||||
|
||||
func (hc *handlerClient) Do(r *http.Request) (*http.Response, error) {
|
||||
w := httptest.NewRecorder()
|
||||
hc.Handler.ServeHTTP(w, r)
|
||||
|
||||
resp := http.Response{
|
||||
StatusCode: w.Code,
|
||||
Header: w.Header(),
|
||||
Body: ioutil.NopCloser(w.Body),
|
||||
}
|
||||
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
func TestHTTPProviderConfigGetter(t *testing.T) {
|
||||
svr := &fakeProviderConfigHandler{}
|
||||
hc := &handlerClient{Handler: svr}
|
||||
fc := clockwork.NewFakeClock()
|
||||
now := fc.Now().UTC()
|
||||
|
||||
tests := []struct {
|
||||
dsc string
|
||||
age time.Duration
|
||||
cfg ProviderConfig
|
||||
ok bool
|
||||
}{
|
||||
// everything is good
|
||||
{
|
||||
dsc: "https://example.com",
|
||||
age: time.Minute,
|
||||
cfg: ProviderConfig{
|
||||
Issuer: &url.URL{Scheme: "https", Host: "example.com"},
|
||||
ExpiresAt: now.Add(time.Minute),
|
||||
},
|
||||
ok: true,
|
||||
},
|
||||
// iss and disco url differ by scheme only (how google works)
|
||||
{
|
||||
dsc: "https://example.com",
|
||||
age: time.Minute,
|
||||
cfg: ProviderConfig{
|
||||
Issuer: &url.URL{Scheme: "https", Host: "example.com"},
|
||||
ExpiresAt: now.Add(time.Minute),
|
||||
},
|
||||
ok: true,
|
||||
},
|
||||
// issuer and discovery URL mismatch
|
||||
{
|
||||
dsc: "https://foo.com",
|
||||
age: time.Minute,
|
||||
cfg: ProviderConfig{
|
||||
Issuer: &url.URL{Scheme: "https", Host: "example.com"},
|
||||
ExpiresAt: now.Add(time.Minute),
|
||||
},
|
||||
ok: false,
|
||||
},
|
||||
// missing cache header results in zero ExpiresAt
|
||||
{
|
||||
dsc: "https://example.com",
|
||||
age: -1,
|
||||
cfg: ProviderConfig{
|
||||
Issuer: &url.URL{Scheme: "https", Host: "example.com"},
|
||||
},
|
||||
ok: true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
tt.cfg = fillRequiredProviderFields(tt.cfg)
|
||||
svr.cfg = tt.cfg
|
||||
svr.maxAge = tt.age
|
||||
getter := NewHTTPProviderConfigGetter(hc, tt.dsc)
|
||||
getter.clock = fc
|
||||
|
||||
got, err := getter.Get()
|
||||
if err != nil {
|
||||
if tt.ok {
|
||||
t.Errorf("test %d: unexpected error: %v", i, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if !tt.ok {
|
||||
t.Errorf("test %d: expected error", i)
|
||||
continue
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(tt.cfg, got) {
|
||||
t.Errorf("test %d: want: %#v, got: %#v", i, tt.cfg, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestProviderConfigSyncerRun(t *testing.T) {
|
||||
c1 := &ProviderConfig{
|
||||
Issuer: &url.URL{Scheme: "https", Host: "example.com"},
|
||||
}
|
||||
c2 := &ProviderConfig{
|
||||
Issuer: &url.URL{Scheme: "https", Host: "example.com"},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
first *ProviderConfig
|
||||
advance time.Duration
|
||||
second *ProviderConfig
|
||||
firstExp time.Duration
|
||||
secondExp time.Duration
|
||||
count int
|
||||
}{
|
||||
// exp is 10m, should have same config after 1s
|
||||
{
|
||||
first: c1,
|
||||
firstExp: time.Duration(10 * time.Minute),
|
||||
advance: time.Minute,
|
||||
second: c1,
|
||||
secondExp: time.Duration(10 * time.Minute),
|
||||
count: 1,
|
||||
},
|
||||
// exp is 10m, should have new config after 10/2 = 5m
|
||||
{
|
||||
first: c1,
|
||||
firstExp: time.Duration(10 * time.Minute),
|
||||
advance: time.Duration(5 * time.Minute),
|
||||
second: c2,
|
||||
secondExp: time.Duration(10 * time.Minute),
|
||||
count: 2,
|
||||
},
|
||||
// exp is 20m, should have new config after 20/2 = 10m
|
||||
{
|
||||
first: c1,
|
||||
firstExp: time.Duration(20 * time.Minute),
|
||||
advance: time.Duration(10 * time.Minute),
|
||||
second: c2,
|
||||
secondExp: time.Duration(30 * time.Minute),
|
||||
count: 2,
|
||||
},
|
||||
}
|
||||
|
||||
assertCfg := func(i int, to *fakeProviderConfigGetterSetter, want ProviderConfig) {
|
||||
got, err := to.Get()
|
||||
if err != nil {
|
||||
t.Fatalf("test %d: unable to get config: %v", i, err)
|
||||
}
|
||||
if !reflect.DeepEqual(want, got) {
|
||||
t.Fatalf("test %d: incorrect state:\nwant=%#v\ngot=%#v", i, want, got)
|
||||
}
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
from := &fakeProviderConfigGetterSetter{}
|
||||
to := &fakeProviderConfigGetterSetter{}
|
||||
|
||||
fc := clockwork.NewFakeClock()
|
||||
now := fc.Now().UTC()
|
||||
syncer := NewProviderConfigSyncer(from, to)
|
||||
syncer.clock = fc
|
||||
|
||||
tt.first.ExpiresAt = now.Add(tt.firstExp)
|
||||
tt.second.ExpiresAt = now.Add(tt.secondExp)
|
||||
if err := from.Set(*tt.first); err != nil {
|
||||
t.Fatalf("test %d: unexpected error: %v", i, err)
|
||||
}
|
||||
|
||||
stop := syncer.Run()
|
||||
defer close(stop)
|
||||
fc.BlockUntil(1)
|
||||
|
||||
// first sync
|
||||
assertCfg(i, to, *tt.first)
|
||||
|
||||
if err := from.Set(*tt.second); err != nil {
|
||||
t.Fatalf("test %d: unexpected error: %v", i, err)
|
||||
}
|
||||
|
||||
fc.Advance(tt.advance)
|
||||
fc.BlockUntil(1)
|
||||
|
||||
// second sync
|
||||
assertCfg(i, to, *tt.second)
|
||||
|
||||
if tt.count != from.getCount {
|
||||
t.Fatalf("test %d: want: %v, got: %v", i, tt.count, from.getCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type staticProviderConfigGetter struct {
|
||||
cfg ProviderConfig
|
||||
err error
|
||||
}
|
||||
|
||||
func (g *staticProviderConfigGetter) Get() (ProviderConfig, error) {
|
||||
return g.cfg, g.err
|
||||
}
|
||||
|
||||
type staticProviderConfigSetter struct {
|
||||
cfg *ProviderConfig
|
||||
err error
|
||||
}
|
||||
|
||||
func (s *staticProviderConfigSetter) Set(cfg ProviderConfig) error {
|
||||
s.cfg = &cfg
|
||||
return s.err
|
||||
}
|
||||
|
||||
func TestProviderConfigSyncerSyncFailure(t *testing.T) {
|
||||
fc := clockwork.NewFakeClock()
|
||||
|
||||
tests := []struct {
|
||||
from *staticProviderConfigGetter
|
||||
to *staticProviderConfigSetter
|
||||
|
||||
// want indicates what ProviderConfig should be passed to Set.
|
||||
// If nil, the Set should not be called.
|
||||
want *ProviderConfig
|
||||
}{
|
||||
// generic Get failure
|
||||
{
|
||||
from: &staticProviderConfigGetter{err: errors.New("fail")},
|
||||
to: &staticProviderConfigSetter{},
|
||||
want: nil,
|
||||
},
|
||||
// generic Set failure
|
||||
{
|
||||
from: &staticProviderConfigGetter{cfg: ProviderConfig{ExpiresAt: fc.Now().Add(time.Minute)}},
|
||||
to: &staticProviderConfigSetter{err: errors.New("fail")},
|
||||
want: &ProviderConfig{ExpiresAt: fc.Now().Add(time.Minute)},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
pcs := &ProviderConfigSyncer{
|
||||
from: tt.from,
|
||||
to: tt.to,
|
||||
clock: fc,
|
||||
}
|
||||
_, err := pcs.sync()
|
||||
if err == nil {
|
||||
t.Errorf("case %d: expected non-nil error", i)
|
||||
}
|
||||
if !reflect.DeepEqual(tt.want, tt.to.cfg) {
|
||||
t.Errorf("case %d: Set mismatch: want=%#v got=%#v", i, tt.want, tt.to.cfg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNextSyncAfter(t *testing.T) {
|
||||
fc := clockwork.NewFakeClock()
|
||||
|
||||
tests := []struct {
|
||||
exp time.Time
|
||||
want time.Duration
|
||||
}{
|
||||
{
|
||||
exp: fc.Now().Add(time.Hour),
|
||||
want: 30 * time.Minute,
|
||||
},
|
||||
// override large values with the maximum
|
||||
{
|
||||
exp: fc.Now().Add(168 * time.Hour), // one week
|
||||
want: 24 * time.Hour,
|
||||
},
|
||||
// override "now" values with the minimum
|
||||
{
|
||||
exp: fc.Now(),
|
||||
want: time.Minute,
|
||||
},
|
||||
// override negative values with the minimum
|
||||
{
|
||||
exp: fc.Now().Add(-1 * time.Minute),
|
||||
want: time.Minute,
|
||||
},
|
||||
// zero-value Time results in maximum sync interval
|
||||
{
|
||||
exp: time.Time{},
|
||||
want: 24 * time.Hour,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
got := nextSyncAfter(tt.exp, fc)
|
||||
if tt.want != got {
|
||||
t.Errorf("case %d: want=%v got=%v", i, tt.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestProviderConfigEmpty(t *testing.T) {
|
||||
cfg := ProviderConfig{}
|
||||
if !cfg.Empty() {
|
||||
t.Fatalf("Empty provider config reports non-empty")
|
||||
}
|
||||
cfg = ProviderConfig{
|
||||
Issuer: &url.URL{Scheme: "https", Host: "example.com"},
|
||||
}
|
||||
if cfg.Empty() {
|
||||
t.Fatalf("Non-empty provider config reports empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPCSStepAfter(t *testing.T) {
|
||||
pass := func() (time.Duration, error) { return 7 * time.Second, nil }
|
||||
fail := func() (time.Duration, error) { return 0, errors.New("fail") }
|
||||
|
||||
tests := []struct {
|
||||
stepper pcsStepper
|
||||
stepFunc pcsStepFunc
|
||||
want pcsStepper
|
||||
}{
|
||||
// good step results in retry at TTL
|
||||
{
|
||||
stepper: &pcsStepNext{},
|
||||
stepFunc: pass,
|
||||
want: &pcsStepNext{aft: 7 * time.Second},
|
||||
},
|
||||
|
||||
// good step after failed step results results in retry at TTL
|
||||
{
|
||||
stepper: &pcsStepRetry{aft: 2 * time.Second},
|
||||
stepFunc: pass,
|
||||
want: &pcsStepNext{aft: 7 * time.Second},
|
||||
},
|
||||
|
||||
// failed step results in a retry in 1s
|
||||
{
|
||||
stepper: &pcsStepNext{},
|
||||
stepFunc: fail,
|
||||
want: &pcsStepRetry{aft: time.Second},
|
||||
},
|
||||
|
||||
// failed retry backs off by a factor of 2
|
||||
{
|
||||
stepper: &pcsStepRetry{aft: time.Second},
|
||||
stepFunc: fail,
|
||||
want: &pcsStepRetry{aft: 2 * time.Second},
|
||||
},
|
||||
|
||||
// failed retry backs off by a factor of 2, up to 1m
|
||||
{
|
||||
stepper: &pcsStepRetry{aft: 32 * time.Second},
|
||||
stepFunc: fail,
|
||||
want: &pcsStepRetry{aft: 60 * time.Second},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
got := tt.stepper.step(tt.stepFunc)
|
||||
if !reflect.DeepEqual(tt.want, got) {
|
||||
t.Errorf("case %d: want=%#v got=%#v", i, tt.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestProviderConfigSupportsGrantType(t *testing.T) {
|
||||
tests := []struct {
|
||||
types []string
|
||||
typ string
|
||||
want bool
|
||||
}{
|
||||
// explicitly supported
|
||||
{
|
||||
types: []string{"foo_type"},
|
||||
typ: "foo_type",
|
||||
want: true,
|
||||
},
|
||||
|
||||
// explicitly unsupported
|
||||
{
|
||||
types: []string{"bar_type"},
|
||||
typ: "foo_type",
|
||||
want: false,
|
||||
},
|
||||
|
||||
// default type explicitly unsupported
|
||||
{
|
||||
types: []string{oauth2.GrantTypeImplicit},
|
||||
typ: oauth2.GrantTypeAuthCode,
|
||||
want: false,
|
||||
},
|
||||
|
||||
// type not found in default set
|
||||
{
|
||||
types: []string{},
|
||||
typ: "foo_type",
|
||||
want: false,
|
||||
},
|
||||
|
||||
// type found in default set
|
||||
{
|
||||
types: []string{},
|
||||
typ: oauth2.GrantTypeAuthCode,
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
cfg := ProviderConfig{
|
||||
GrantTypesSupported: tt.types,
|
||||
}
|
||||
got := cfg.SupportsGrantType(tt.typ)
|
||||
if tt.want != got {
|
||||
t.Errorf("case %d: assert %v supports %v: want=%t got=%t", i, tt.types, tt.typ, tt.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type fakeClient struct {
|
||||
resp *http.Response
|
||||
}
|
||||
|
||||
func (f *fakeClient) Do(req *http.Request) (*http.Response, error) {
|
||||
return f.resp, nil
|
||||
}
|
||||
|
||||
func TestWaitForProviderConfigImmediateSuccess(t *testing.T) {
|
||||
cfg := newValidProviderConfig()
|
||||
b, err := json.Marshal(&cfg)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed marshaling provider config")
|
||||
}
|
||||
|
||||
resp := http.Response{Body: ioutil.NopCloser(bytes.NewBuffer(b))}
|
||||
hc := &fakeClient{&resp}
|
||||
fc := clockwork.NewFakeClock()
|
||||
|
||||
reschan := make(chan ProviderConfig)
|
||||
go func() {
|
||||
reschan <- waitForProviderConfig(hc, cfg.Issuer.String(), fc)
|
||||
}()
|
||||
|
||||
var got ProviderConfig
|
||||
select {
|
||||
case got = <-reschan:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatalf("Did not receive result within 1s")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cfg, got) {
|
||||
t.Fatalf("Received incorrect provider config: want=%#v got=%#v", cfg, got)
|
||||
}
|
||||
}
|
88
vendor/github.com/coreos/go-oidc/oidc/transport.go
generated
vendored
88
vendor/github.com/coreos/go-oidc/oidc/transport.go
generated
vendored
|
@ -1,88 +0,0 @@
|
|||
package oidc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
phttp "github.com/coreos/go-oidc/http"
|
||||
"github.com/coreos/go-oidc/jose"
|
||||
)
|
||||
|
||||
type TokenRefresher interface {
|
||||
// Verify checks if the provided token is currently valid or not.
|
||||
Verify(jose.JWT) error
|
||||
|
||||
// Refresh attempts to authenticate and retrieve a new token.
|
||||
Refresh() (jose.JWT, error)
|
||||
}
|
||||
|
||||
type ClientCredsTokenRefresher struct {
|
||||
Issuer string
|
||||
OIDCClient *Client
|
||||
}
|
||||
|
||||
func (c *ClientCredsTokenRefresher) Verify(jwt jose.JWT) (err error) {
|
||||
_, err = VerifyClientClaims(jwt, c.Issuer)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *ClientCredsTokenRefresher) Refresh() (jwt jose.JWT, err error) {
|
||||
if err = c.OIDCClient.Healthy(); err != nil {
|
||||
err = fmt.Errorf("unable to authenticate, unhealthy OIDC client: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
jwt, err = c.OIDCClient.ClientCredsToken([]string{"openid"})
|
||||
if err != nil {
|
||||
err = fmt.Errorf("unable to verify auth code with issuer: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type AuthenticatedTransport struct {
|
||||
TokenRefresher
|
||||
http.RoundTripper
|
||||
|
||||
mu sync.Mutex
|
||||
jwt jose.JWT
|
||||
}
|
||||
|
||||
func (t *AuthenticatedTransport) verifiedJWT() (jose.JWT, error) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
if t.TokenRefresher.Verify(t.jwt) == nil {
|
||||
return t.jwt, nil
|
||||
}
|
||||
|
||||
jwt, err := t.TokenRefresher.Refresh()
|
||||
if err != nil {
|
||||
return jose.JWT{}, fmt.Errorf("unable to acquire valid JWT: %v", err)
|
||||
}
|
||||
|
||||
t.jwt = jwt
|
||||
return t.jwt, nil
|
||||
}
|
||||
|
||||
// SetJWT sets the JWT held by the Transport.
|
||||
// This is useful for cases in which you want to set an initial JWT.
|
||||
func (t *AuthenticatedTransport) SetJWT(jwt jose.JWT) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
t.jwt = jwt
|
||||
}
|
||||
|
||||
func (t *AuthenticatedTransport) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||
jwt, err := t.verifiedJWT()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := phttp.CopyRequest(r)
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", jwt.Encode()))
|
||||
return t.RoundTripper.RoundTrip(req)
|
||||
}
|
176
vendor/github.com/coreos/go-oidc/oidc/transport_test.go
generated
vendored
176
vendor/github.com/coreos/go-oidc/oidc/transport_test.go
generated
vendored
|
@ -1,176 +0,0 @@
|
|||
package oidc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/go-oidc/jose"
|
||||
)
|
||||
|
||||
type staticTokenRefresher struct {
|
||||
verify func(jose.JWT) error
|
||||
refresh func() (jose.JWT, error)
|
||||
}
|
||||
|
||||
func (s *staticTokenRefresher) Verify(jwt jose.JWT) error {
|
||||
return s.verify(jwt)
|
||||
}
|
||||
|
||||
func (s *staticTokenRefresher) Refresh() (jose.JWT, error) {
|
||||
return s.refresh()
|
||||
}
|
||||
|
||||
func TestAuthenticatedTransportVerifiedJWT(t *testing.T) {
|
||||
tests := []struct {
|
||||
refresher TokenRefresher
|
||||
startJWT jose.JWT
|
||||
wantJWT jose.JWT
|
||||
wantError error
|
||||
}{
|
||||
// verification succeeds, so refresh is not called
|
||||
{
|
||||
refresher: &staticTokenRefresher{
|
||||
verify: func(jose.JWT) error { return nil },
|
||||
refresh: func() (jose.JWT, error) { return jose.JWT{RawPayload: "2"}, nil },
|
||||
},
|
||||
startJWT: jose.JWT{RawPayload: "1"},
|
||||
wantJWT: jose.JWT{RawPayload: "1"},
|
||||
},
|
||||
|
||||
// verification fails, refresh succeeds so cached JWT changes
|
||||
{
|
||||
refresher: &staticTokenRefresher{
|
||||
verify: func(jose.JWT) error { return errors.New("fail!") },
|
||||
refresh: func() (jose.JWT, error) { return jose.JWT{RawPayload: "2"}, nil },
|
||||
},
|
||||
startJWT: jose.JWT{RawPayload: "1"},
|
||||
wantJWT: jose.JWT{RawPayload: "2"},
|
||||
},
|
||||
|
||||
// verification succeeds, so failing refresh isn't attempted
|
||||
{
|
||||
refresher: &staticTokenRefresher{
|
||||
verify: func(jose.JWT) error { return nil },
|
||||
refresh: func() (jose.JWT, error) { return jose.JWT{}, errors.New("fail!") },
|
||||
},
|
||||
startJWT: jose.JWT{RawPayload: "1"},
|
||||
wantJWT: jose.JWT{RawPayload: "1"},
|
||||
},
|
||||
|
||||
// verification fails, but refresh fails, too
|
||||
{
|
||||
refresher: &staticTokenRefresher{
|
||||
verify: func(jose.JWT) error { return errors.New("fail!") },
|
||||
refresh: func() (jose.JWT, error) { return jose.JWT{}, errors.New("fail!") },
|
||||
},
|
||||
startJWT: jose.JWT{RawPayload: "1"},
|
||||
wantJWT: jose.JWT{},
|
||||
wantError: errors.New("unable to acquire valid JWT: fail!"),
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
at := &AuthenticatedTransport{
|
||||
TokenRefresher: tt.refresher,
|
||||
}
|
||||
at.SetJWT(tt.startJWT)
|
||||
|
||||
gotJWT, err := at.verifiedJWT()
|
||||
if !reflect.DeepEqual(tt.wantError, err) {
|
||||
t.Errorf("#%d: unexpected error: want=%#v got=%#v", i, tt.wantError, err)
|
||||
}
|
||||
if !reflect.DeepEqual(tt.wantJWT, gotJWT) {
|
||||
t.Errorf("#%d: incorrect JWT returned from verifiedJWT: want=%#v got=%#v", i, tt.wantJWT, gotJWT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthenticatedTransportJWTCaching(t *testing.T) {
|
||||
at := &AuthenticatedTransport{
|
||||
TokenRefresher: &staticTokenRefresher{
|
||||
verify: func(jose.JWT) error { return errors.New("fail!") },
|
||||
refresh: func() (jose.JWT, error) { return jose.JWT{RawPayload: "2"}, nil },
|
||||
},
|
||||
jwt: jose.JWT{RawPayload: "1"},
|
||||
}
|
||||
|
||||
wantJWT := jose.JWT{RawPayload: "2"}
|
||||
gotJWT, err := at.verifiedJWT()
|
||||
if err != nil {
|
||||
t.Fatalf("got non-nil error: %#v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(wantJWT, gotJWT) {
|
||||
t.Fatalf("incorrect JWT returned from verifiedJWT: want=%#v got=%#v", wantJWT, gotJWT)
|
||||
}
|
||||
|
||||
at.TokenRefresher = &staticTokenRefresher{
|
||||
verify: func(jose.JWT) error { return nil },
|
||||
refresh: func() (jose.JWT, error) { return jose.JWT{RawPayload: "3"}, nil },
|
||||
}
|
||||
|
||||
// the previous JWT should still be cached on the AuthenticatedTransport since
|
||||
// it is still valid, even though there's a new token ready to refresh
|
||||
gotJWT, err = at.verifiedJWT()
|
||||
if err != nil {
|
||||
t.Fatalf("got non-nil error: %#v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(wantJWT, gotJWT) {
|
||||
t.Fatalf("incorrect JWT returned from verifiedJWT: want=%#v got=%#v", wantJWT, gotJWT)
|
||||
}
|
||||
}
|
||||
|
||||
type fakeRoundTripper struct {
|
||||
Request *http.Request
|
||||
resp *http.Response
|
||||
}
|
||||
|
||||
func (r *fakeRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
r.Request = req
|
||||
return r.resp, nil
|
||||
}
|
||||
|
||||
func TestAuthenticatedTransportRoundTrip(t *testing.T) {
|
||||
rr := &fakeRoundTripper{nil, &http.Response{StatusCode: http.StatusOK}}
|
||||
at := &AuthenticatedTransport{
|
||||
TokenRefresher: &staticTokenRefresher{
|
||||
verify: func(jose.JWT) error { return nil },
|
||||
},
|
||||
RoundTripper: rr,
|
||||
jwt: jose.JWT{RawPayload: "1"},
|
||||
}
|
||||
|
||||
req := http.Request{}
|
||||
_, err := at.RoundTrip(&req)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(req, http.Request{}) {
|
||||
t.Errorf("http.Request object was modified")
|
||||
}
|
||||
|
||||
want := []string{"Bearer .1."}
|
||||
got := rr.Request.Header["Authorization"]
|
||||
if !reflect.DeepEqual(want, got) {
|
||||
t.Errorf("incorrect Authorization header: want=%#v got=%#v", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthenticatedTransportRoundTripRefreshFail(t *testing.T) {
|
||||
rr := &fakeRoundTripper{nil, &http.Response{StatusCode: http.StatusOK}}
|
||||
at := &AuthenticatedTransport{
|
||||
TokenRefresher: &staticTokenRefresher{
|
||||
verify: func(jose.JWT) error { return errors.New("fail!") },
|
||||
refresh: func() (jose.JWT, error) { return jose.JWT{}, errors.New("fail!") },
|
||||
},
|
||||
RoundTripper: rr,
|
||||
jwt: jose.JWT{RawPayload: "1"},
|
||||
}
|
||||
|
||||
_, err := at.RoundTrip(&http.Request{})
|
||||
if err == nil {
|
||||
t.Errorf("expected non-nil error")
|
||||
}
|
||||
}
|
109
vendor/github.com/coreos/go-oidc/oidc/util.go
generated
vendored
109
vendor/github.com/coreos/go-oidc/oidc/util.go
generated
vendored
|
@ -1,109 +0,0 @@
|
|||
package oidc
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-oidc/jose"
|
||||
)
|
||||
|
||||
// RequestTokenExtractor funcs extract a raw encoded token from a request.
|
||||
type RequestTokenExtractor func(r *http.Request) (string, error)
|
||||
|
||||
// ExtractBearerToken is a RequestTokenExtractor which extracts a bearer token from a request's
|
||||
// Authorization header.
|
||||
func ExtractBearerToken(r *http.Request) (string, error) {
|
||||
ah := r.Header.Get("Authorization")
|
||||
if ah == "" {
|
||||
return "", errors.New("missing Authorization header")
|
||||
}
|
||||
|
||||
if len(ah) <= 6 || strings.ToUpper(ah[0:6]) != "BEARER" {
|
||||
return "", errors.New("should be a bearer token")
|
||||
}
|
||||
|
||||
val := ah[7:]
|
||||
if len(val) == 0 {
|
||||
return "", errors.New("bearer token is empty")
|
||||
}
|
||||
|
||||
return val, nil
|
||||
}
|
||||
|
||||
// CookieTokenExtractor returns a RequestTokenExtractor which extracts a token from the named cookie in a request.
|
||||
func CookieTokenExtractor(cookieName string) RequestTokenExtractor {
|
||||
return func(r *http.Request) (string, error) {
|
||||
ck, err := r.Cookie(cookieName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("token cookie not found in request: %v", err)
|
||||
}
|
||||
|
||||
if ck.Value == "" {
|
||||
return "", errors.New("token cookie found but is empty")
|
||||
}
|
||||
|
||||
return ck.Value, nil
|
||||
}
|
||||
}
|
||||
|
||||
func NewClaims(iss, sub string, aud interface{}, iat, exp time.Time) jose.Claims {
|
||||
return jose.Claims{
|
||||
// required
|
||||
"iss": iss,
|
||||
"sub": sub,
|
||||
"aud": aud,
|
||||
"iat": iat.Unix(),
|
||||
"exp": exp.Unix(),
|
||||
}
|
||||
}
|
||||
|
||||
func GenClientID(hostport string) (string, error) {
|
||||
b, err := randBytes(32)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var host string
|
||||
if strings.Contains(hostport, ":") {
|
||||
host, _, err = net.SplitHostPort(hostport)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
host = hostport
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s@%s", base64.URLEncoding.EncodeToString(b), host), nil
|
||||
}
|
||||
|
||||
func randBytes(n int) ([]byte, error) {
|
||||
b := make([]byte, n)
|
||||
got, err := rand.Read(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if n != got {
|
||||
return nil, errors.New("unable to generate enough random data")
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// urlEqual checks two urls for equality using only the host and path portions.
|
||||
func urlEqual(url1, url2 string) bool {
|
||||
u1, err := url.Parse(url1)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
u2, err := url.Parse(url2)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return strings.ToLower(u1.Host+u1.Path) == strings.ToLower(u2.Host+u2.Path)
|
||||
}
|
110
vendor/github.com/coreos/go-oidc/oidc/util_test.go
generated
vendored
110
vendor/github.com/coreos/go-oidc/oidc/util_test.go
generated
vendored
|
@ -1,110 +0,0 @@
|
|||
package oidc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-oidc/jose"
|
||||
)
|
||||
|
||||
func TestCookieTokenExtractorInvalid(t *testing.T) {
|
||||
ckName := "tokenCookie"
|
||||
tests := []*http.Cookie{
|
||||
&http.Cookie{},
|
||||
&http.Cookie{Name: ckName},
|
||||
&http.Cookie{Name: ckName, Value: ""},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
r, _ := http.NewRequest("", "", nil)
|
||||
r.AddCookie(tt)
|
||||
_, err := CookieTokenExtractor(ckName)(r)
|
||||
if err == nil {
|
||||
t.Errorf("case %d: want: error for invalid cookie token, got: no error.", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCookieTokenExtractorValid(t *testing.T) {
|
||||
validToken := "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"
|
||||
ckName := "tokenCookie"
|
||||
tests := []*http.Cookie{
|
||||
&http.Cookie{Name: ckName, Value: "some non-empty value"},
|
||||
&http.Cookie{Name: ckName, Value: validToken},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
r, _ := http.NewRequest("", "", nil)
|
||||
r.AddCookie(tt)
|
||||
_, err := CookieTokenExtractor(ckName)(r)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: want: valid cookie with no error, got: %v", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractBearerTokenInvalid(t *testing.T) {
|
||||
tests := []string{"", "x", "Bearer", "xxxxxxx", "Bearer "}
|
||||
|
||||
for i, tt := range tests {
|
||||
r, _ := http.NewRequest("", "", nil)
|
||||
r.Header.Add("Authorization", tt)
|
||||
_, err := ExtractBearerToken(r)
|
||||
if err == nil {
|
||||
t.Errorf("case %d: want: invalid Authorization header, got: valid Authorization header.", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractBearerTokenValid(t *testing.T) {
|
||||
validToken := "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"
|
||||
tests := []string{
|
||||
fmt.Sprintf("Bearer %s", validToken),
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
r, _ := http.NewRequest("", "", nil)
|
||||
r.Header.Add("Authorization", tt)
|
||||
_, err := ExtractBearerToken(r)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: want: valid Authorization header, got: invalid Authorization header: %v.", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewClaims(t *testing.T) {
|
||||
issAt := time.Date(2, time.January, 1, 0, 0, 0, 0, time.UTC)
|
||||
expAt := time.Date(2, time.January, 1, 1, 0, 0, 0, time.UTC)
|
||||
|
||||
want := jose.Claims{
|
||||
"iss": "https://example.com",
|
||||
"sub": "user-123",
|
||||
"aud": "client-abc",
|
||||
"iat": issAt.Unix(),
|
||||
"exp": expAt.Unix(),
|
||||
}
|
||||
|
||||
got := NewClaims("https://example.com", "user-123", "client-abc", issAt, expAt)
|
||||
|
||||
if !reflect.DeepEqual(want, got) {
|
||||
t.Fatalf("want=%#v got=%#v", want, got)
|
||||
}
|
||||
|
||||
want2 := jose.Claims{
|
||||
"iss": "https://example.com",
|
||||
"sub": "user-123",
|
||||
"aud": []string{"client-abc", "client-def"},
|
||||
"iat": issAt.Unix(),
|
||||
"exp": expAt.Unix(),
|
||||
}
|
||||
|
||||
got2 := NewClaims("https://example.com", "user-123", []string{"client-abc", "client-def"}, issAt, expAt)
|
||||
|
||||
if !reflect.DeepEqual(want2, got2) {
|
||||
t.Fatalf("want=%#v got=%#v", want2, got2)
|
||||
}
|
||||
|
||||
}
|
190
vendor/github.com/coreos/go-oidc/oidc/verification.go
generated
vendored
190
vendor/github.com/coreos/go-oidc/oidc/verification.go
generated
vendored
|
@ -1,190 +0,0 @@
|
|||
package oidc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jonboulle/clockwork"
|
||||
|
||||
"github.com/coreos/go-oidc/jose"
|
||||
"github.com/coreos/go-oidc/key"
|
||||
)
|
||||
|
||||
func VerifySignature(jwt jose.JWT, keys []key.PublicKey) (bool, error) {
|
||||
jwtBytes := []byte(jwt.Data())
|
||||
for _, k := range keys {
|
||||
v, err := k.Verifier()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if v.Verify(jwt.Signature, jwtBytes) == nil {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// containsString returns true if the given string(needle) is found
|
||||
// in the string array(haystack).
|
||||
func containsString(needle string, haystack []string) bool {
|
||||
for _, v := range haystack {
|
||||
if v == needle {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Verify claims in accordance with OIDC spec
|
||||
// http://openid.net/specs/openid-connect-basic-1_0.html#IDTokenValidation
|
||||
func VerifyClaims(jwt jose.JWT, issuer, clientID string) error {
|
||||
now := time.Now().UTC()
|
||||
|
||||
claims, err := jwt.Claims()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ident, err := IdentityFromClaims(claims)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ident.ExpiresAt.Before(now) {
|
||||
return errors.New("token is expired")
|
||||
}
|
||||
|
||||
// iss REQUIRED. Issuer Identifier for the Issuer of the response.
|
||||
// The iss value is a case sensitive URL using the https scheme that contains scheme,
|
||||
// host, and optionally, port number and path components and no query or fragment components.
|
||||
if iss, exists := claims["iss"].(string); exists {
|
||||
if !urlEqual(iss, issuer) {
|
||||
return fmt.Errorf("invalid claim value: 'iss'. expected=%s, found=%s.", issuer, iss)
|
||||
}
|
||||
} else {
|
||||
return errors.New("missing claim: 'iss'")
|
||||
}
|
||||
|
||||
// iat REQUIRED. Time at which the JWT was issued.
|
||||
// Its value is a JSON number representing the number of seconds from 1970-01-01T0:0:0Z
|
||||
// as measured in UTC until the date/time.
|
||||
if _, exists := claims["iat"].(float64); !exists {
|
||||
return errors.New("missing claim: 'iat'")
|
||||
}
|
||||
|
||||
// aud REQUIRED. Audience(s) that this ID Token is intended for.
|
||||
// It MUST contain the OAuth 2.0 client_id of the Relying Party as an audience value.
|
||||
// It MAY also contain identifiers for other audiences. In the general case, the aud
|
||||
// value is an array of case sensitive strings. In the common special case when there
|
||||
// is one audience, the aud value MAY be a single case sensitive string.
|
||||
if aud, ok, err := claims.StringClaim("aud"); err == nil && ok {
|
||||
if aud != clientID {
|
||||
return fmt.Errorf("invalid claims, 'aud' claim and 'client_id' do not match, aud=%s, client_id=%s", aud, clientID)
|
||||
}
|
||||
} else if aud, ok, err := claims.StringsClaim("aud"); err == nil && ok {
|
||||
if !containsString(clientID, aud) {
|
||||
return fmt.Errorf("invalid claims, cannot find 'client_id' in 'aud' claim, aud=%v, client_id=%s", aud, clientID)
|
||||
}
|
||||
} else {
|
||||
return errors.New("invalid claim value: 'aud' is required, and should be either string or string array")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VerifyClientClaims verifies all the required claims are valid for a "client credentials" JWT.
|
||||
// Returns the client ID if valid, or an error if invalid.
|
||||
func VerifyClientClaims(jwt jose.JWT, issuer string) (string, error) {
|
||||
claims, err := jwt.Claims()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to parse JWT claims: %v", err)
|
||||
}
|
||||
|
||||
iss, ok, err := claims.StringClaim("iss")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to parse 'iss' claim: %v", err)
|
||||
} else if !ok {
|
||||
return "", errors.New("missing required 'iss' claim")
|
||||
} else if !urlEqual(iss, issuer) {
|
||||
return "", fmt.Errorf("'iss' claim does not match expected issuer, iss=%s", iss)
|
||||
}
|
||||
|
||||
sub, ok, err := claims.StringClaim("sub")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to parse 'sub' claim: %v", err)
|
||||
} else if !ok {
|
||||
return "", errors.New("missing required 'sub' claim")
|
||||
}
|
||||
|
||||
if aud, ok, err := claims.StringClaim("aud"); err == nil && ok {
|
||||
if aud != sub {
|
||||
return "", fmt.Errorf("invalid claims, 'aud' claim and 'sub' claim do not match, aud=%s, sub=%s", aud, sub)
|
||||
}
|
||||
} else if aud, ok, err := claims.StringsClaim("aud"); err == nil && ok {
|
||||
if !containsString(sub, aud) {
|
||||
return "", fmt.Errorf("invalid claims, cannot find 'sud' in 'aud' claim, aud=%v, sub=%s", aud, sub)
|
||||
}
|
||||
} else {
|
||||
return "", errors.New("invalid claim value: 'aud' is required, and should be either string or string array")
|
||||
}
|
||||
|
||||
now := time.Now().UTC()
|
||||
exp, ok, err := claims.TimeClaim("exp")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to parse 'exp' claim: %v", err)
|
||||
} else if !ok {
|
||||
return "", errors.New("missing required 'exp' claim")
|
||||
} else if exp.Before(now) {
|
||||
return "", fmt.Errorf("token already expired at: %v", exp)
|
||||
}
|
||||
|
||||
return sub, nil
|
||||
}
|
||||
|
||||
type JWTVerifier struct {
|
||||
issuer string
|
||||
clientID string
|
||||
syncFunc func() error
|
||||
keysFunc func() []key.PublicKey
|
||||
clock clockwork.Clock
|
||||
}
|
||||
|
||||
func NewJWTVerifier(issuer, clientID string, syncFunc func() error, keysFunc func() []key.PublicKey) JWTVerifier {
|
||||
return JWTVerifier{
|
||||
issuer: issuer,
|
||||
clientID: clientID,
|
||||
syncFunc: syncFunc,
|
||||
keysFunc: keysFunc,
|
||||
clock: clockwork.NewRealClock(),
|
||||
}
|
||||
}
|
||||
|
||||
func (v *JWTVerifier) Verify(jwt jose.JWT) error {
|
||||
// Verify claims before verifying the signature. This is an optimization to throw out
|
||||
// tokens we know are invalid without undergoing an expensive signature check and
|
||||
// possibly a re-sync event.
|
||||
if err := VerifyClaims(jwt, v.issuer, v.clientID); err != nil {
|
||||
return fmt.Errorf("oidc: JWT claims invalid: %v", err)
|
||||
}
|
||||
|
||||
ok, err := VerifySignature(jwt, v.keysFunc())
|
||||
if err != nil {
|
||||
return fmt.Errorf("oidc: JWT signature verification failed: %v", err)
|
||||
} else if ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err = v.syncFunc(); err != nil {
|
||||
return fmt.Errorf("oidc: failed syncing KeySet: %v", err)
|
||||
}
|
||||
|
||||
ok, err = VerifySignature(jwt, v.keysFunc())
|
||||
if err != nil {
|
||||
return fmt.Errorf("oidc: JWT signature verification failed: %v", err)
|
||||
} else if !ok {
|
||||
return errors.New("oidc: unable to verify JWT signature: no matching keys")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
380
vendor/github.com/coreos/go-oidc/oidc/verification_test.go
generated
vendored
380
vendor/github.com/coreos/go-oidc/oidc/verification_test.go
generated
vendored
|
@ -1,380 +0,0 @@
|
|||
package oidc
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-oidc/jose"
|
||||
"github.com/coreos/go-oidc/key"
|
||||
)
|
||||
|
||||
func TestVerifyClientClaims(t *testing.T) {
|
||||
validIss := "https://example.com"
|
||||
validClientID := "valid-client"
|
||||
now := time.Now()
|
||||
tomorrow := now.Add(24 * time.Hour)
|
||||
header := jose.JOSEHeader{
|
||||
jose.HeaderKeyAlgorithm: "test-alg",
|
||||
jose.HeaderKeyID: "1",
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
claims jose.Claims
|
||||
ok bool
|
||||
}{
|
||||
// valid token
|
||||
{
|
||||
claims: jose.Claims{
|
||||
"iss": validIss,
|
||||
"sub": validClientID,
|
||||
"aud": validClientID,
|
||||
"iat": float64(now.Unix()),
|
||||
"exp": float64(tomorrow.Unix()),
|
||||
},
|
||||
ok: true,
|
||||
},
|
||||
// valid token, ('aud' claim is []string)
|
||||
{
|
||||
claims: jose.Claims{
|
||||
"iss": validIss,
|
||||
"sub": validClientID,
|
||||
"aud": []string{"foo", validClientID},
|
||||
"iat": float64(now.Unix()),
|
||||
"exp": float64(tomorrow.Unix()),
|
||||
},
|
||||
ok: true,
|
||||
},
|
||||
// valid token, ('aud' claim is []interface{})
|
||||
{
|
||||
claims: jose.Claims{
|
||||
"iss": validIss,
|
||||
"sub": validClientID,
|
||||
"aud": []interface{}{"foo", validClientID},
|
||||
"iat": float64(now.Unix()),
|
||||
"exp": float64(tomorrow.Unix()),
|
||||
},
|
||||
ok: true,
|
||||
},
|
||||
// missing 'iss' claim
|
||||
{
|
||||
claims: jose.Claims{
|
||||
"sub": validClientID,
|
||||
"aud": validClientID,
|
||||
"iat": float64(now.Unix()),
|
||||
"exp": float64(tomorrow.Unix()),
|
||||
},
|
||||
ok: false,
|
||||
},
|
||||
// invalid 'iss' claim
|
||||
{
|
||||
claims: jose.Claims{
|
||||
"iss": "INVALID",
|
||||
"sub": validClientID,
|
||||
"aud": validClientID,
|
||||
"iat": float64(now.Unix()),
|
||||
"exp": float64(tomorrow.Unix()),
|
||||
},
|
||||
ok: false,
|
||||
},
|
||||
// missing 'sub' claim
|
||||
{
|
||||
claims: jose.Claims{
|
||||
"iss": validIss,
|
||||
"aud": validClientID,
|
||||
"iat": float64(now.Unix()),
|
||||
"exp": float64(tomorrow.Unix()),
|
||||
},
|
||||
ok: false,
|
||||
},
|
||||
// invalid 'sub' claim
|
||||
{
|
||||
claims: jose.Claims{
|
||||
"iss": validIss,
|
||||
"sub": "INVALID",
|
||||
"aud": validClientID,
|
||||
"iat": float64(now.Unix()),
|
||||
"exp": float64(tomorrow.Unix()),
|
||||
},
|
||||
ok: false,
|
||||
},
|
||||
// missing 'aud' claim
|
||||
{
|
||||
claims: jose.Claims{
|
||||
"iss": validIss,
|
||||
"sub": validClientID,
|
||||
"iat": float64(now.Unix()),
|
||||
"exp": float64(tomorrow.Unix()),
|
||||
},
|
||||
ok: false,
|
||||
},
|
||||
// invalid 'aud' claim
|
||||
{
|
||||
claims: jose.Claims{
|
||||
"iss": validIss,
|
||||
"sub": validClientID,
|
||||
"aud": "INVALID",
|
||||
"iat": float64(now.Unix()),
|
||||
"exp": float64(tomorrow.Unix()),
|
||||
},
|
||||
ok: false,
|
||||
},
|
||||
// invalid 'aud' claim
|
||||
{
|
||||
claims: jose.Claims{
|
||||
"iss": validIss,
|
||||
"sub": validClientID,
|
||||
"aud": []string{"INVALID1", "INVALID2"},
|
||||
"iat": float64(now.Unix()),
|
||||
"exp": float64(tomorrow.Unix()),
|
||||
},
|
||||
ok: false,
|
||||
},
|
||||
// invalid 'aud' type
|
||||
{
|
||||
claims: jose.Claims{
|
||||
"iss": validIss,
|
||||
"sub": validClientID,
|
||||
"aud": struct{}{},
|
||||
"iat": float64(now.Unix()),
|
||||
"exp": float64(tomorrow.Unix()),
|
||||
},
|
||||
ok: false,
|
||||
},
|
||||
// expired
|
||||
{
|
||||
claims: jose.Claims{
|
||||
"iss": validIss,
|
||||
"sub": validClientID,
|
||||
"aud": validClientID,
|
||||
"iat": float64(now.Unix()),
|
||||
"exp": float64(now.Unix()),
|
||||
},
|
||||
ok: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
jwt, err := jose.NewJWT(header, tt.claims)
|
||||
if err != nil {
|
||||
t.Fatalf("case %d: Failed to generate JWT, error=%v", i, err)
|
||||
}
|
||||
|
||||
got, err := VerifyClientClaims(jwt, validIss)
|
||||
if tt.ok {
|
||||
if err != nil {
|
||||
t.Errorf("case %d: unexpected error, err=%v", i, err)
|
||||
}
|
||||
if got != validClientID {
|
||||
t.Errorf("case %d: incorrect client ID, want=%s, got=%s", i, validClientID, got)
|
||||
}
|
||||
} else if err == nil {
|
||||
t.Errorf("case %d: expected error but err is nil", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestJWTVerifier(t *testing.T) {
|
||||
iss := "http://example.com"
|
||||
now := time.Now()
|
||||
future12 := now.Add(12 * time.Hour)
|
||||
past36 := now.Add(-36 * time.Hour)
|
||||
past12 := now.Add(-12 * time.Hour)
|
||||
|
||||
priv1, err := key.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to generate private key, error=%v", err)
|
||||
}
|
||||
pk1 := *key.NewPublicKey(priv1.JWK())
|
||||
|
||||
priv2, err := key.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to generate private key, error=%v", err)
|
||||
}
|
||||
pk2 := *key.NewPublicKey(priv2.JWK())
|
||||
|
||||
newJWT := func(issuer, subject string, aud interface{}, issuedAt, exp time.Time, signer jose.Signer) jose.JWT {
|
||||
jwt, err := jose.NewSignedJWT(NewClaims(issuer, subject, aud, issuedAt, exp), signer)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return *jwt
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
verifier JWTVerifier
|
||||
jwt jose.JWT
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "JWT signed with available key",
|
||||
verifier: JWTVerifier{
|
||||
issuer: "example.com",
|
||||
clientID: "XXX",
|
||||
syncFunc: func() error { return nil },
|
||||
keysFunc: func() []key.PublicKey {
|
||||
return []key.PublicKey{pk1}
|
||||
},
|
||||
},
|
||||
jwt: newJWT(iss, "XXX", "XXX", past12, future12, priv1.Signer()),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "JWT signed with available key, with bad claims",
|
||||
verifier: JWTVerifier{
|
||||
issuer: "example.com",
|
||||
clientID: "XXX",
|
||||
syncFunc: func() error { return nil },
|
||||
keysFunc: func() []key.PublicKey {
|
||||
return []key.PublicKey{pk1}
|
||||
},
|
||||
},
|
||||
jwt: newJWT(iss, "XXX", "YYY", past12, future12, priv1.Signer()),
|
||||
wantErr: true,
|
||||
},
|
||||
|
||||
{
|
||||
name: "JWT signed with available key",
|
||||
verifier: JWTVerifier{
|
||||
issuer: "example.com",
|
||||
clientID: "XXX",
|
||||
syncFunc: func() error { return nil },
|
||||
keysFunc: func() []key.PublicKey {
|
||||
return []key.PublicKey{pk1}
|
||||
},
|
||||
},
|
||||
jwt: newJWT(iss, "XXX", []string{"YYY", "ZZZ"}, past12, future12, priv1.Signer()),
|
||||
wantErr: true,
|
||||
},
|
||||
|
||||
{
|
||||
name: "expired JWT signed with available key",
|
||||
verifier: JWTVerifier{
|
||||
issuer: "example.com",
|
||||
clientID: "XXX",
|
||||
syncFunc: func() error { return nil },
|
||||
keysFunc: func() []key.PublicKey {
|
||||
return []key.PublicKey{pk1}
|
||||
},
|
||||
},
|
||||
jwt: newJWT(iss, "XXX", "XXX", past36, past12, priv1.Signer()),
|
||||
wantErr: true,
|
||||
},
|
||||
|
||||
{
|
||||
name: "JWT signed with unrecognized key, verifiable after sync",
|
||||
verifier: JWTVerifier{
|
||||
issuer: "example.com",
|
||||
clientID: "XXX",
|
||||
syncFunc: func() error { return nil },
|
||||
keysFunc: func() func() []key.PublicKey {
|
||||
var i int
|
||||
return func() []key.PublicKey {
|
||||
defer func() { i++ }()
|
||||
return [][]key.PublicKey{
|
||||
[]key.PublicKey{pk1},
|
||||
[]key.PublicKey{pk2},
|
||||
}[i]
|
||||
}
|
||||
}(),
|
||||
},
|
||||
jwt: newJWT(iss, "XXX", "XXX", past36, future12, priv2.Signer()),
|
||||
wantErr: false,
|
||||
},
|
||||
|
||||
{
|
||||
name: "JWT signed with unrecognized key, not verifiable after sync",
|
||||
verifier: JWTVerifier{
|
||||
issuer: "example.com",
|
||||
clientID: "XXX",
|
||||
syncFunc: func() error { return nil },
|
||||
keysFunc: func() []key.PublicKey {
|
||||
return []key.PublicKey{pk1}
|
||||
},
|
||||
},
|
||||
jwt: newJWT(iss, "XXX", "XXX", past12, future12, priv2.Signer()),
|
||||
wantErr: true,
|
||||
},
|
||||
|
||||
{
|
||||
name: "verifier gets no keys from keysFunc, still not verifiable after sync",
|
||||
verifier: JWTVerifier{
|
||||
issuer: "example.com",
|
||||
clientID: "XXX",
|
||||
syncFunc: func() error { return nil },
|
||||
keysFunc: func() []key.PublicKey {
|
||||
return []key.PublicKey{}
|
||||
},
|
||||
},
|
||||
jwt: newJWT(iss, "XXX", "XXX", past12, future12, priv1.Signer()),
|
||||
wantErr: true,
|
||||
},
|
||||
|
||||
{
|
||||
name: "verifier gets no keys from keysFunc, verifiable after sync",
|
||||
verifier: JWTVerifier{
|
||||
issuer: "example.com",
|
||||
clientID: "XXX",
|
||||
syncFunc: func() error { return nil },
|
||||
keysFunc: func() func() []key.PublicKey {
|
||||
var i int
|
||||
return func() []key.PublicKey {
|
||||
defer func() { i++ }()
|
||||
return [][]key.PublicKey{
|
||||
[]key.PublicKey{},
|
||||
[]key.PublicKey{pk2},
|
||||
}[i]
|
||||
}
|
||||
}(),
|
||||
},
|
||||
jwt: newJWT(iss, "XXX", "XXX", past12, future12, priv2.Signer()),
|
||||
wantErr: false,
|
||||
},
|
||||
|
||||
{
|
||||
name: "JWT signed with available key, 'aud' is a string array",
|
||||
verifier: JWTVerifier{
|
||||
issuer: "example.com",
|
||||
clientID: "XXX",
|
||||
syncFunc: func() error { return nil },
|
||||
keysFunc: func() []key.PublicKey {
|
||||
return []key.PublicKey{pk1}
|
||||
},
|
||||
},
|
||||
jwt: newJWT(iss, "XXX", []string{"ZZZ", "XXX"}, past12, future12, priv1.Signer()),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "invalid issuer claim shouldn't trigger sync",
|
||||
verifier: JWTVerifier{
|
||||
issuer: "example.com",
|
||||
clientID: "XXX",
|
||||
syncFunc: func() error {
|
||||
t.Errorf("invalid issuer claim shouldn't trigger a sync")
|
||||
return nil
|
||||
},
|
||||
keysFunc: func() func() []key.PublicKey {
|
||||
var i int
|
||||
return func() []key.PublicKey {
|
||||
defer func() { i++ }()
|
||||
return [][]key.PublicKey{
|
||||
[]key.PublicKey{},
|
||||
[]key.PublicKey{pk2},
|
||||
}[i]
|
||||
}
|
||||
}(),
|
||||
},
|
||||
jwt: newJWT("invalid-issuer", "XXX", []string{"ZZZ", "XXX"}, past12, future12, priv2.Signer()),
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
err := tt.verifier.Verify(tt.jwt)
|
||||
if tt.wantErr && (err == nil) {
|
||||
t.Errorf("case %q: wanted non-nil error", tt.name)
|
||||
} else if !tt.wantErr && (err != nil) {
|
||||
t.Errorf("case %q: wanted nil error, got %v", tt.name, err)
|
||||
}
|
||||
}
|
||||
}
|
15
vendor/github.com/golang/protobuf/.gitignore
generated
vendored
15
vendor/github.com/golang/protobuf/.gitignore
generated
vendored
|
@ -1,15 +0,0 @@
|
|||
.DS_Store
|
||||
*.[568ao]
|
||||
*.ao
|
||||
*.so
|
||||
*.pyc
|
||||
._*
|
||||
.nfs.*
|
||||
[568a].out
|
||||
*~
|
||||
*.orig
|
||||
core
|
||||
_obj
|
||||
_test
|
||||
_testmain.go
|
||||
protoc-gen-go/testdata/multi/*.pb.go
|
3
vendor/github.com/golang/protobuf/AUTHORS
generated
vendored
3
vendor/github.com/golang/protobuf/AUTHORS
generated
vendored
|
@ -1,3 +0,0 @@
|
|||
# This source code refers to The Go Authors for copyright purposes.
|
||||
# The master list of authors is in the main Go distribution,
|
||||
# visible at http://tip.golang.org/AUTHORS.
|
3
vendor/github.com/golang/protobuf/CONTRIBUTORS
generated
vendored
3
vendor/github.com/golang/protobuf/CONTRIBUTORS
generated
vendored
|
@ -1,3 +0,0 @@
|
|||
# This source code was written by the Go contributors.
|
||||
# The master list of contributors is in the main Go distribution,
|
||||
# visible at http://tip.golang.org/CONTRIBUTORS.
|
40
vendor/github.com/golang/protobuf/Make.protobuf
generated
vendored
40
vendor/github.com/golang/protobuf/Make.protobuf
generated
vendored
|
@ -1,40 +0,0 @@
|
|||
# Go support for Protocol Buffers - Google's data interchange format
|
||||
#
|
||||
# Copyright 2010 The Go Authors. All rights reserved.
|
||||
# https://github.com/golang/protobuf
|
||||
#
|
||||
# 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 Google 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.
|
||||
|
||||
# Includable Makefile to add a rule for generating .pb.go files from .proto files
|
||||
# (Google protocol buffer descriptions).
|
||||
# Typical use if myproto.proto is a file in package mypackage in this directory:
|
||||
#
|
||||
# include $(GOROOT)/src/pkg/github.com/golang/protobuf/Make.protobuf
|
||||
|
||||
%.pb.go: %.proto
|
||||
protoc --go_out=. $<
|
||||
|
54
vendor/github.com/golang/protobuf/Makefile
generated
vendored
54
vendor/github.com/golang/protobuf/Makefile
generated
vendored
|
@ -1,54 +0,0 @@
|
|||
# Go support for Protocol Buffers - Google's data interchange format
|
||||
#
|
||||
# Copyright 2010 The Go Authors. All rights reserved.
|
||||
# https://github.com/golang/protobuf
|
||||
#
|
||||
# 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 Google 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.
|
||||
|
||||
|
||||
all: install
|
||||
|
||||
install:
|
||||
go install ./proto ./jsonpb ./ptypes
|
||||
go install ./protoc-gen-go
|
||||
|
||||
test:
|
||||
go test ./proto ./jsonpb ./ptypes
|
||||
make -C protoc-gen-go/testdata test
|
||||
|
||||
clean:
|
||||
go clean ./...
|
||||
|
||||
nuke:
|
||||
go clean -i ./...
|
||||
|
||||
regenerate:
|
||||
make -C protoc-gen-go/descriptor regenerate
|
||||
make -C protoc-gen-go/plugin regenerate
|
||||
make -C protoc-gen-go/testdata regenerate
|
||||
make -C proto/testdata regenerate
|
||||
make -C jsonpb/jsonpb_test_proto regenerate
|
199
vendor/github.com/golang/protobuf/README.md
generated
vendored
199
vendor/github.com/golang/protobuf/README.md
generated
vendored
|
@ -1,199 +0,0 @@
|
|||
# Go support for Protocol Buffers
|
||||
|
||||
Google's data interchange format.
|
||||
Copyright 2010 The Go Authors.
|
||||
https://github.com/golang/protobuf
|
||||
|
||||
This package and the code it generates requires at least Go 1.4.
|
||||
|
||||
This software implements Go bindings for protocol buffers. For
|
||||
information about protocol buffers themselves, see
|
||||
https://developers.google.com/protocol-buffers/
|
||||
|
||||
## Installation ##
|
||||
|
||||
To use this software, you must:
|
||||
- Install the standard C++ implementation of protocol buffers from
|
||||
https://developers.google.com/protocol-buffers/
|
||||
- Of course, install the Go compiler and tools from
|
||||
https://golang.org/
|
||||
See
|
||||
https://golang.org/doc/install
|
||||
for details or, if you are using gccgo, follow the instructions at
|
||||
https://golang.org/doc/install/gccgo
|
||||
- Grab the code from the repository and install the proto package.
|
||||
The simplest way is to run `go get -u github.com/golang/protobuf/{proto,protoc-gen-go}`.
|
||||
The compiler plugin, protoc-gen-go, will be installed in $GOBIN,
|
||||
defaulting to $GOPATH/bin. It must be in your $PATH for the protocol
|
||||
compiler, protoc, to find it.
|
||||
|
||||
This software has two parts: a 'protocol compiler plugin' that
|
||||
generates Go source files that, once compiled, can access and manage
|
||||
protocol buffers; and a library that implements run-time support for
|
||||
encoding (marshaling), decoding (unmarshaling), and accessing protocol
|
||||
buffers.
|
||||
|
||||
There is support for gRPC in Go using protocol buffers.
|
||||
See the note at the bottom of this file for details.
|
||||
|
||||
There are no insertion points in the plugin.
|
||||
|
||||
|
||||
## Using protocol buffers with Go ##
|
||||
|
||||
Once the software is installed, there are two steps to using it.
|
||||
First you must compile the protocol buffer definitions and then import
|
||||
them, with the support library, into your program.
|
||||
|
||||
To compile the protocol buffer definition, run protoc with the --go_out
|
||||
parameter set to the directory you want to output the Go code to.
|
||||
|
||||
protoc --go_out=. *.proto
|
||||
|
||||
The generated files will be suffixed .pb.go. See the Test code below
|
||||
for an example using such a file.
|
||||
|
||||
|
||||
The package comment for the proto library contains text describing
|
||||
the interface provided in Go for protocol buffers. Here is an edited
|
||||
version.
|
||||
|
||||
==========
|
||||
|
||||
The proto package converts data structures to and from the
|
||||
wire format of protocol buffers. It works in concert with the
|
||||
Go source code generated for .proto files by the protocol compiler.
|
||||
|
||||
A summary of the properties of the protocol buffer interface
|
||||
for a protocol buffer variable v:
|
||||
|
||||
- Names are turned from camel_case to CamelCase for export.
|
||||
- There are no methods on v to set fields; just treat
|
||||
them as structure fields.
|
||||
- There are getters that return a field's value if set,
|
||||
and return the field's default value if unset.
|
||||
The getters work even if the receiver is a nil message.
|
||||
- The zero value for a struct is its correct initialization state.
|
||||
All desired fields must be set before marshaling.
|
||||
- A Reset() method will restore a protobuf struct to its zero state.
|
||||
- Non-repeated fields are pointers to the values; nil means unset.
|
||||
That is, optional or required field int32 f becomes F *int32.
|
||||
- Repeated fields are slices.
|
||||
- Helper functions are available to aid the setting of fields.
|
||||
Helpers for getting values are superseded by the
|
||||
GetFoo methods and their use is deprecated.
|
||||
msg.Foo = proto.String("hello") // set field
|
||||
- Constants are defined to hold the default values of all fields that
|
||||
have them. They have the form Default_StructName_FieldName.
|
||||
Because the getter methods handle defaulted values,
|
||||
direct use of these constants should be rare.
|
||||
- Enums are given type names and maps from names to values.
|
||||
Enum values are prefixed with the enum's type name. Enum types have
|
||||
a String method, and a Enum method to assist in message construction.
|
||||
- Nested groups and enums have type names prefixed with the name of
|
||||
the surrounding message type.
|
||||
- Extensions are given descriptor names that start with E_,
|
||||
followed by an underscore-delimited list of the nested messages
|
||||
that contain it (if any) followed by the CamelCased name of the
|
||||
extension field itself. HasExtension, ClearExtension, GetExtension
|
||||
and SetExtension are functions for manipulating extensions.
|
||||
- Oneof field sets are given a single field in their message,
|
||||
with distinguished wrapper types for each possible field value.
|
||||
- Marshal and Unmarshal are functions to encode and decode the wire format.
|
||||
|
||||
When the .proto file specifies `syntax="proto3"`, there are some differences:
|
||||
|
||||
- Non-repeated fields of non-message type are values instead of pointers.
|
||||
- Getters are only generated for message and oneof fields.
|
||||
- Enum types do not get an Enum method.
|
||||
|
||||
Consider file test.proto, containing
|
||||
|
||||
```proto
|
||||
package example;
|
||||
|
||||
enum FOO { X = 17; };
|
||||
|
||||
message Test {
|
||||
required string label = 1;
|
||||
optional int32 type = 2 [default=77];
|
||||
repeated int64 reps = 3;
|
||||
optional group OptionalGroup = 4 {
|
||||
required string RequiredField = 5;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To create and play with a Test object from the example package,
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"path/to/example"
|
||||
)
|
||||
|
||||
func main() {
|
||||
test := &example.Test {
|
||||
Label: proto.String("hello"),
|
||||
Type: proto.Int32(17),
|
||||
Reps: []int64{1, 2, 3},
|
||||
Optionalgroup: &example.Test_OptionalGroup {
|
||||
RequiredField: proto.String("good bye"),
|
||||
},
|
||||
}
|
||||
data, err := proto.Marshal(test)
|
||||
if err != nil {
|
||||
log.Fatal("marshaling error: ", err)
|
||||
}
|
||||
newTest := &example.Test{}
|
||||
err = proto.Unmarshal(data, newTest)
|
||||
if err != nil {
|
||||
log.Fatal("unmarshaling error: ", err)
|
||||
}
|
||||
// Now test and newTest contain the same data.
|
||||
if test.GetLabel() != newTest.GetLabel() {
|
||||
log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
|
||||
}
|
||||
// etc.
|
||||
}
|
||||
```
|
||||
|
||||
## Parameters ##
|
||||
|
||||
To pass extra parameters to the plugin, use a comma-separated
|
||||
parameter list separated from the output directory by a colon:
|
||||
|
||||
|
||||
protoc --go_out=plugins=grpc,import_path=mypackage:. *.proto
|
||||
|
||||
|
||||
- `import_prefix=xxx` - a prefix that is added onto the beginning of
|
||||
all imports. Useful for things like generating protos in a
|
||||
subdirectory, or regenerating vendored protobufs in-place.
|
||||
- `import_path=foo/bar` - used as the package if no input files
|
||||
declare `go_package`. If it contains slashes, everything up to the
|
||||
rightmost slash is ignored.
|
||||
- `plugins=plugin1+plugin2` - specifies the list of sub-plugins to
|
||||
load. The only plugin in this repo is `grpc`.
|
||||
- `Mfoo/bar.proto=quux/shme` - declares that foo/bar.proto is
|
||||
associated with Go package quux/shme. This is subject to the
|
||||
import_prefix parameter.
|
||||
|
||||
## gRPC Support ##
|
||||
|
||||
If a proto file specifies RPC services, protoc-gen-go can be instructed to
|
||||
generate code compatible with gRPC (http://www.grpc.io/). To do this, pass
|
||||
the `plugins` parameter to protoc-gen-go; the usual way is to insert it into
|
||||
the --go_out argument to protoc:
|
||||
|
||||
protoc --go_out=plugins=grpc:. *.proto
|
||||
|
||||
## Plugins ##
|
||||
|
||||
The `protoc-gen-go/generator` package exposes a plugin interface,
|
||||
which is used by the gRPC code generation. This interface is not
|
||||
supported and is subject to incompatible changes without notice.
|
832
vendor/github.com/golang/protobuf/jsonpb/jsonpb.go
generated
vendored
832
vendor/github.com/golang/protobuf/jsonpb/jsonpb.go
generated
vendored
|
@ -1,832 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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 Google 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.
|
||||
|
||||
/*
|
||||
Package jsonpb provides marshaling and unmarshaling between protocol buffers and JSON.
|
||||
It follows the specification at https://developers.google.com/protocol-buffers/docs/proto3#json.
|
||||
|
||||
This package produces a different output than the standard "encoding/json" package,
|
||||
which does not operate correctly on protocol buffers.
|
||||
*/
|
||||
package jsonpb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
// Marshaler is a configurable object for converting between
|
||||
// protocol buffer objects and a JSON representation for them.
|
||||
type Marshaler struct {
|
||||
// Whether to render enum values as integers, as opposed to string values.
|
||||
EnumsAsInts bool
|
||||
|
||||
// Whether to render fields with zero values.
|
||||
EmitDefaults bool
|
||||
|
||||
// A string to indent each level by. The presence of this field will
|
||||
// also cause a space to appear between the field separator and
|
||||
// value, and for newlines to be appear between fields and array
|
||||
// elements.
|
||||
Indent string
|
||||
|
||||
// Whether to use the original (.proto) name for fields.
|
||||
OrigName bool
|
||||
}
|
||||
|
||||
// Marshal marshals a protocol buffer into JSON.
|
||||
func (m *Marshaler) Marshal(out io.Writer, pb proto.Message) error {
|
||||
writer := &errWriter{writer: out}
|
||||
return m.marshalObject(writer, pb, "", "")
|
||||
}
|
||||
|
||||
// MarshalToString converts a protocol buffer object to JSON string.
|
||||
func (m *Marshaler) MarshalToString(pb proto.Message) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
if err := m.Marshal(&buf, pb); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
type int32Slice []int32
|
||||
|
||||
// For sorting extensions ids to ensure stable output.
|
||||
func (s int32Slice) Len() int { return len(s) }
|
||||
func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
|
||||
func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
type wkt interface {
|
||||
XXX_WellKnownType() string
|
||||
}
|
||||
|
||||
// marshalObject writes a struct to the Writer.
|
||||
func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeURL string) error {
|
||||
s := reflect.ValueOf(v).Elem()
|
||||
|
||||
// Handle well-known types.
|
||||
if wkt, ok := v.(wkt); ok {
|
||||
switch wkt.XXX_WellKnownType() {
|
||||
case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value",
|
||||
"Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue":
|
||||
// "Wrappers use the same representation in JSON
|
||||
// as the wrapped primitive type, ..."
|
||||
sprop := proto.GetProperties(s.Type())
|
||||
return m.marshalValue(out, sprop.Prop[0], s.Field(0), indent)
|
||||
case "Any":
|
||||
// Any is a bit more involved.
|
||||
return m.marshalAny(out, v, indent)
|
||||
case "Duration":
|
||||
// "Generated output always contains 3, 6, or 9 fractional digits,
|
||||
// depending on required precision."
|
||||
s, ns := s.Field(0).Int(), s.Field(1).Int()
|
||||
d := time.Duration(s)*time.Second + time.Duration(ns)*time.Nanosecond
|
||||
x := fmt.Sprintf("%.9f", d.Seconds())
|
||||
x = strings.TrimSuffix(x, "000")
|
||||
x = strings.TrimSuffix(x, "000")
|
||||
out.write(`"`)
|
||||
out.write(x)
|
||||
out.write(`s"`)
|
||||
return out.err
|
||||
case "Struct":
|
||||
// Let marshalValue handle the `fields` map.
|
||||
// TODO: pass the correct Properties if needed.
|
||||
return m.marshalValue(out, &proto.Properties{}, s.Field(0), indent)
|
||||
case "Timestamp":
|
||||
// "RFC 3339, where generated output will always be Z-normalized
|
||||
// and uses 3, 6 or 9 fractional digits."
|
||||
s, ns := s.Field(0).Int(), s.Field(1).Int()
|
||||
t := time.Unix(s, ns).UTC()
|
||||
// time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits).
|
||||
x := t.Format("2006-01-02T15:04:05.000000000")
|
||||
x = strings.TrimSuffix(x, "000")
|
||||
x = strings.TrimSuffix(x, "000")
|
||||
out.write(`"`)
|
||||
out.write(x)
|
||||
out.write(`Z"`)
|
||||
return out.err
|
||||
case "Value":
|
||||
// Value has a single oneof.
|
||||
kind := s.Field(0)
|
||||
if kind.IsNil() {
|
||||
// "absence of any variant indicates an error"
|
||||
return errors.New("nil Value")
|
||||
}
|
||||
// oneof -> *T -> T -> T.F
|
||||
x := kind.Elem().Elem().Field(0)
|
||||
// TODO: pass the correct Properties if needed.
|
||||
return m.marshalValue(out, &proto.Properties{}, x, indent)
|
||||
}
|
||||
}
|
||||
|
||||
out.write("{")
|
||||
if m.Indent != "" {
|
||||
out.write("\n")
|
||||
}
|
||||
|
||||
firstField := true
|
||||
|
||||
if typeURL != "" {
|
||||
if err := m.marshalTypeURL(out, indent, typeURL); err != nil {
|
||||
return err
|
||||
}
|
||||
firstField = false
|
||||
}
|
||||
|
||||
for i := 0; i < s.NumField(); i++ {
|
||||
value := s.Field(i)
|
||||
valueField := s.Type().Field(i)
|
||||
if strings.HasPrefix(valueField.Name, "XXX_") {
|
||||
continue
|
||||
}
|
||||
|
||||
// IsNil will panic on most value kinds.
|
||||
switch value.Kind() {
|
||||
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
|
||||
if value.IsNil() {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if !m.EmitDefaults {
|
||||
switch value.Kind() {
|
||||
case reflect.Bool:
|
||||
if !value.Bool() {
|
||||
continue
|
||||
}
|
||||
case reflect.Int32, reflect.Int64:
|
||||
if value.Int() == 0 {
|
||||
continue
|
||||
}
|
||||
case reflect.Uint32, reflect.Uint64:
|
||||
if value.Uint() == 0 {
|
||||
continue
|
||||
}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
if value.Float() == 0 {
|
||||
continue
|
||||
}
|
||||
case reflect.String:
|
||||
if value.Len() == 0 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Oneof fields need special handling.
|
||||
if valueField.Tag.Get("protobuf_oneof") != "" {
|
||||
// value is an interface containing &T{real_value}.
|
||||
sv := value.Elem().Elem() // interface -> *T -> T
|
||||
value = sv.Field(0)
|
||||
valueField = sv.Type().Field(0)
|
||||
}
|
||||
prop := jsonProperties(valueField, m.OrigName)
|
||||
if !firstField {
|
||||
m.writeSep(out)
|
||||
}
|
||||
if err := m.marshalField(out, prop, value, indent); err != nil {
|
||||
return err
|
||||
}
|
||||
firstField = false
|
||||
}
|
||||
|
||||
// Handle proto2 extensions.
|
||||
if ep, ok := v.(proto.Message); ok {
|
||||
extensions := proto.RegisteredExtensions(v)
|
||||
// Sort extensions for stable output.
|
||||
ids := make([]int32, 0, len(extensions))
|
||||
for id, desc := range extensions {
|
||||
if !proto.HasExtension(ep, desc) {
|
||||
continue
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
sort.Sort(int32Slice(ids))
|
||||
for _, id := range ids {
|
||||
desc := extensions[id]
|
||||
if desc == nil {
|
||||
// unknown extension
|
||||
continue
|
||||
}
|
||||
ext, extErr := proto.GetExtension(ep, desc)
|
||||
if extErr != nil {
|
||||
return extErr
|
||||
}
|
||||
value := reflect.ValueOf(ext)
|
||||
var prop proto.Properties
|
||||
prop.Parse(desc.Tag)
|
||||
prop.JSONName = fmt.Sprintf("[%s]", desc.Name)
|
||||
if !firstField {
|
||||
m.writeSep(out)
|
||||
}
|
||||
if err := m.marshalField(out, &prop, value, indent); err != nil {
|
||||
return err
|
||||
}
|
||||
firstField = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if m.Indent != "" {
|
||||
out.write("\n")
|
||||
out.write(indent)
|
||||
}
|
||||
out.write("}")
|
||||
return out.err
|
||||
}
|
||||
|
||||
func (m *Marshaler) writeSep(out *errWriter) {
|
||||
if m.Indent != "" {
|
||||
out.write(",\n")
|
||||
} else {
|
||||
out.write(",")
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Marshaler) marshalAny(out *errWriter, any proto.Message, indent string) error {
|
||||
// "If the Any contains a value that has a special JSON mapping,
|
||||
// it will be converted as follows: {"@type": xxx, "value": yyy}.
|
||||
// Otherwise, the value will be converted into a JSON object,
|
||||
// and the "@type" field will be inserted to indicate the actual data type."
|
||||
v := reflect.ValueOf(any).Elem()
|
||||
turl := v.Field(0).String()
|
||||
val := v.Field(1).Bytes()
|
||||
|
||||
// Only the part of type_url after the last slash is relevant.
|
||||
mname := turl
|
||||
if slash := strings.LastIndex(mname, "/"); slash >= 0 {
|
||||
mname = mname[slash+1:]
|
||||
}
|
||||
mt := proto.MessageType(mname)
|
||||
if mt == nil {
|
||||
return fmt.Errorf("unknown message type %q", mname)
|
||||
}
|
||||
msg := reflect.New(mt.Elem()).Interface().(proto.Message)
|
||||
if err := proto.Unmarshal(val, msg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, ok := msg.(wkt); ok {
|
||||
out.write("{")
|
||||
if m.Indent != "" {
|
||||
out.write("\n")
|
||||
}
|
||||
if err := m.marshalTypeURL(out, indent, turl); err != nil {
|
||||
return err
|
||||
}
|
||||
m.writeSep(out)
|
||||
if m.Indent != "" {
|
||||
out.write(indent)
|
||||
out.write(m.Indent)
|
||||
out.write(`"value": `)
|
||||
} else {
|
||||
out.write(`"value":`)
|
||||
}
|
||||
if err := m.marshalObject(out, msg, indent+m.Indent, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
if m.Indent != "" {
|
||||
out.write("\n")
|
||||
out.write(indent)
|
||||
}
|
||||
out.write("}")
|
||||
return out.err
|
||||
}
|
||||
|
||||
return m.marshalObject(out, msg, indent, turl)
|
||||
}
|
||||
|
||||
func (m *Marshaler) marshalTypeURL(out *errWriter, indent, typeURL string) error {
|
||||
if m.Indent != "" {
|
||||
out.write(indent)
|
||||
out.write(m.Indent)
|
||||
}
|
||||
out.write(`"@type":`)
|
||||
if m.Indent != "" {
|
||||
out.write(" ")
|
||||
}
|
||||
b, err := json.Marshal(typeURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out.write(string(b))
|
||||
return out.err
|
||||
}
|
||||
|
||||
// marshalField writes field description and value to the Writer.
|
||||
func (m *Marshaler) marshalField(out *errWriter, prop *proto.Properties, v reflect.Value, indent string) error {
|
||||
if m.Indent != "" {
|
||||
out.write(indent)
|
||||
out.write(m.Indent)
|
||||
}
|
||||
out.write(`"`)
|
||||
out.write(prop.JSONName)
|
||||
out.write(`":`)
|
||||
if m.Indent != "" {
|
||||
out.write(" ")
|
||||
}
|
||||
if err := m.marshalValue(out, prop, v, indent); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// marshalValue writes the value to the Writer.
|
||||
func (m *Marshaler) marshalValue(out *errWriter, prop *proto.Properties, v reflect.Value, indent string) error {
|
||||
|
||||
var err error
|
||||
v = reflect.Indirect(v)
|
||||
|
||||
// Handle repeated elements.
|
||||
if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 {
|
||||
out.write("[")
|
||||
comma := ""
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
sliceVal := v.Index(i)
|
||||
out.write(comma)
|
||||
if m.Indent != "" {
|
||||
out.write("\n")
|
||||
out.write(indent)
|
||||
out.write(m.Indent)
|
||||
out.write(m.Indent)
|
||||
}
|
||||
if err := m.marshalValue(out, prop, sliceVal, indent+m.Indent); err != nil {
|
||||
return err
|
||||
}
|
||||
comma = ","
|
||||
}
|
||||
if m.Indent != "" {
|
||||
out.write("\n")
|
||||
out.write(indent)
|
||||
out.write(m.Indent)
|
||||
}
|
||||
out.write("]")
|
||||
return out.err
|
||||
}
|
||||
|
||||
// Handle well-known types.
|
||||
// Most are handled up in marshalObject (because 99% are messages).
|
||||
type wkt interface {
|
||||
XXX_WellKnownType() string
|
||||
}
|
||||
if wkt, ok := v.Interface().(wkt); ok {
|
||||
switch wkt.XXX_WellKnownType() {
|
||||
case "NullValue":
|
||||
out.write("null")
|
||||
return out.err
|
||||
}
|
||||
}
|
||||
|
||||
// Handle enumerations.
|
||||
if !m.EnumsAsInts && prop.Enum != "" {
|
||||
// Unknown enum values will are stringified by the proto library as their
|
||||
// value. Such values should _not_ be quoted or they will be interpreted
|
||||
// as an enum string instead of their value.
|
||||
enumStr := v.Interface().(fmt.Stringer).String()
|
||||
var valStr string
|
||||
if v.Kind() == reflect.Ptr {
|
||||
valStr = strconv.Itoa(int(v.Elem().Int()))
|
||||
} else {
|
||||
valStr = strconv.Itoa(int(v.Int()))
|
||||
}
|
||||
isKnownEnum := enumStr != valStr
|
||||
if isKnownEnum {
|
||||
out.write(`"`)
|
||||
}
|
||||
out.write(enumStr)
|
||||
if isKnownEnum {
|
||||
out.write(`"`)
|
||||
}
|
||||
return out.err
|
||||
}
|
||||
|
||||
// Handle nested messages.
|
||||
if v.Kind() == reflect.Struct {
|
||||
return m.marshalObject(out, v.Addr().Interface().(proto.Message), indent+m.Indent, "")
|
||||
}
|
||||
|
||||
// Handle maps.
|
||||
// Since Go randomizes map iteration, we sort keys for stable output.
|
||||
if v.Kind() == reflect.Map {
|
||||
out.write(`{`)
|
||||
keys := v.MapKeys()
|
||||
sort.Sort(mapKeys(keys))
|
||||
for i, k := range keys {
|
||||
if i > 0 {
|
||||
out.write(`,`)
|
||||
}
|
||||
if m.Indent != "" {
|
||||
out.write("\n")
|
||||
out.write(indent)
|
||||
out.write(m.Indent)
|
||||
out.write(m.Indent)
|
||||
}
|
||||
|
||||
b, err := json.Marshal(k.Interface())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s := string(b)
|
||||
|
||||
// If the JSON is not a string value, encode it again to make it one.
|
||||
if !strings.HasPrefix(s, `"`) {
|
||||
b, err := json.Marshal(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s = string(b)
|
||||
}
|
||||
|
||||
out.write(s)
|
||||
out.write(`:`)
|
||||
if m.Indent != "" {
|
||||
out.write(` `)
|
||||
}
|
||||
|
||||
if err := m.marshalValue(out, prop, v.MapIndex(k), indent+m.Indent); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if m.Indent != "" {
|
||||
out.write("\n")
|
||||
out.write(indent)
|
||||
out.write(m.Indent)
|
||||
}
|
||||
out.write(`}`)
|
||||
return out.err
|
||||
}
|
||||
|
||||
// Default handling defers to the encoding/json library.
|
||||
b, err := json.Marshal(v.Interface())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
needToQuote := string(b[0]) != `"` && (v.Kind() == reflect.Int64 || v.Kind() == reflect.Uint64)
|
||||
if needToQuote {
|
||||
out.write(`"`)
|
||||
}
|
||||
out.write(string(b))
|
||||
if needToQuote {
|
||||
out.write(`"`)
|
||||
}
|
||||
return out.err
|
||||
}
|
||||
|
||||
// Unmarshaler is a configurable object for converting from a JSON
|
||||
// representation to a protocol buffer object.
|
||||
type Unmarshaler struct {
|
||||
// Whether to allow messages to contain unknown fields, as opposed to
|
||||
// failing to unmarshal.
|
||||
AllowUnknownFields bool
|
||||
}
|
||||
|
||||
// UnmarshalNext unmarshals the next protocol buffer from a JSON object stream.
|
||||
// This function is lenient and will decode any options permutations of the
|
||||
// related Marshaler.
|
||||
func (u *Unmarshaler) UnmarshalNext(dec *json.Decoder, pb proto.Message) error {
|
||||
inputValue := json.RawMessage{}
|
||||
if err := dec.Decode(&inputValue); err != nil {
|
||||
return err
|
||||
}
|
||||
return u.unmarshalValue(reflect.ValueOf(pb).Elem(), inputValue, nil)
|
||||
}
|
||||
|
||||
// Unmarshal unmarshals a JSON object stream into a protocol
|
||||
// buffer. This function is lenient and will decode any options
|
||||
// permutations of the related Marshaler.
|
||||
func (u *Unmarshaler) Unmarshal(r io.Reader, pb proto.Message) error {
|
||||
dec := json.NewDecoder(r)
|
||||
return u.UnmarshalNext(dec, pb)
|
||||
}
|
||||
|
||||
// UnmarshalNext unmarshals the next protocol buffer from a JSON object stream.
|
||||
// This function is lenient and will decode any options permutations of the
|
||||
// related Marshaler.
|
||||
func UnmarshalNext(dec *json.Decoder, pb proto.Message) error {
|
||||
return new(Unmarshaler).UnmarshalNext(dec, pb)
|
||||
}
|
||||
|
||||
// Unmarshal unmarshals a JSON object stream into a protocol
|
||||
// buffer. This function is lenient and will decode any options
|
||||
// permutations of the related Marshaler.
|
||||
func Unmarshal(r io.Reader, pb proto.Message) error {
|
||||
return new(Unmarshaler).Unmarshal(r, pb)
|
||||
}
|
||||
|
||||
// UnmarshalString will populate the fields of a protocol buffer based
|
||||
// on a JSON string. This function is lenient and will decode any options
|
||||
// permutations of the related Marshaler.
|
||||
func UnmarshalString(str string, pb proto.Message) error {
|
||||
return new(Unmarshaler).Unmarshal(strings.NewReader(str), pb)
|
||||
}
|
||||
|
||||
// unmarshalValue converts/copies a value into the target.
|
||||
// prop may be nil.
|
||||
func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMessage, prop *proto.Properties) error {
|
||||
targetType := target.Type()
|
||||
|
||||
// Allocate memory for pointer fields.
|
||||
if targetType.Kind() == reflect.Ptr {
|
||||
target.Set(reflect.New(targetType.Elem()))
|
||||
return u.unmarshalValue(target.Elem(), inputValue, prop)
|
||||
}
|
||||
|
||||
// Handle well-known types.
|
||||
type wkt interface {
|
||||
XXX_WellKnownType() string
|
||||
}
|
||||
if wkt, ok := target.Addr().Interface().(wkt); ok {
|
||||
switch wkt.XXX_WellKnownType() {
|
||||
case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value",
|
||||
"Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue":
|
||||
// "Wrappers use the same representation in JSON
|
||||
// as the wrapped primitive type, except that null is allowed."
|
||||
// encoding/json will turn JSON `null` into Go `nil`,
|
||||
// so we don't have to do any extra work.
|
||||
return u.unmarshalValue(target.Field(0), inputValue, prop)
|
||||
case "Any":
|
||||
return fmt.Errorf("unmarshaling Any not supported yet")
|
||||
case "Duration":
|
||||
unq, err := strconv.Unquote(string(inputValue))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d, err := time.ParseDuration(unq)
|
||||
if err != nil {
|
||||
return fmt.Errorf("bad Duration: %v", err)
|
||||
}
|
||||
ns := d.Nanoseconds()
|
||||
s := ns / 1e9
|
||||
ns %= 1e9
|
||||
target.Field(0).SetInt(s)
|
||||
target.Field(1).SetInt(ns)
|
||||
return nil
|
||||
case "Timestamp":
|
||||
unq, err := strconv.Unquote(string(inputValue))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t, err := time.Parse(time.RFC3339Nano, unq)
|
||||
if err != nil {
|
||||
return fmt.Errorf("bad Timestamp: %v", err)
|
||||
}
|
||||
ns := t.UnixNano()
|
||||
s := ns / 1e9
|
||||
ns %= 1e9
|
||||
target.Field(0).SetInt(s)
|
||||
target.Field(1).SetInt(ns)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Handle enums, which have an underlying type of int32,
|
||||
// and may appear as strings.
|
||||
// The case of an enum appearing as a number is handled
|
||||
// at the bottom of this function.
|
||||
if inputValue[0] == '"' && prop != nil && prop.Enum != "" {
|
||||
vmap := proto.EnumValueMap(prop.Enum)
|
||||
// Don't need to do unquoting; valid enum names
|
||||
// are from a limited character set.
|
||||
s := inputValue[1 : len(inputValue)-1]
|
||||
n, ok := vmap[string(s)]
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown value %q for enum %s", s, prop.Enum)
|
||||
}
|
||||
if target.Kind() == reflect.Ptr { // proto2
|
||||
target.Set(reflect.New(targetType.Elem()))
|
||||
target = target.Elem()
|
||||
}
|
||||
target.SetInt(int64(n))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Handle nested messages.
|
||||
if targetType.Kind() == reflect.Struct {
|
||||
var jsonFields map[string]json.RawMessage
|
||||
if err := json.Unmarshal(inputValue, &jsonFields); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
consumeField := func(prop *proto.Properties) (json.RawMessage, bool) {
|
||||
// Be liberal in what names we accept; both orig_name and camelName are okay.
|
||||
fieldNames := acceptedJSONFieldNames(prop)
|
||||
|
||||
vOrig, okOrig := jsonFields[fieldNames.orig]
|
||||
vCamel, okCamel := jsonFields[fieldNames.camel]
|
||||
if !okOrig && !okCamel {
|
||||
return nil, false
|
||||
}
|
||||
// If, for some reason, both are present in the data, favour the camelName.
|
||||
var raw json.RawMessage
|
||||
if okOrig {
|
||||
raw = vOrig
|
||||
delete(jsonFields, fieldNames.orig)
|
||||
}
|
||||
if okCamel {
|
||||
raw = vCamel
|
||||
delete(jsonFields, fieldNames.camel)
|
||||
}
|
||||
return raw, true
|
||||
}
|
||||
|
||||
sprops := proto.GetProperties(targetType)
|
||||
for i := 0; i < target.NumField(); i++ {
|
||||
ft := target.Type().Field(i)
|
||||
if strings.HasPrefix(ft.Name, "XXX_") {
|
||||
continue
|
||||
}
|
||||
|
||||
valueForField, ok := consumeField(sprops.Prop[i])
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := u.unmarshalValue(target.Field(i), valueForField, sprops.Prop[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Check for any oneof fields.
|
||||
if len(jsonFields) > 0 {
|
||||
for _, oop := range sprops.OneofTypes {
|
||||
raw, ok := consumeField(oop.Prop)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
nv := reflect.New(oop.Type.Elem())
|
||||
target.Field(oop.Field).Set(nv)
|
||||
if err := u.unmarshalValue(nv.Elem().Field(0), raw, oop.Prop); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if !u.AllowUnknownFields && len(jsonFields) > 0 {
|
||||
// Pick any field to be the scapegoat.
|
||||
var f string
|
||||
for fname := range jsonFields {
|
||||
f = fname
|
||||
break
|
||||
}
|
||||
return fmt.Errorf("unknown field %q in %v", f, targetType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Handle arrays (which aren't encoded bytes)
|
||||
if targetType.Kind() == reflect.Slice && targetType.Elem().Kind() != reflect.Uint8 {
|
||||
var slc []json.RawMessage
|
||||
if err := json.Unmarshal(inputValue, &slc); err != nil {
|
||||
return err
|
||||
}
|
||||
len := len(slc)
|
||||
target.Set(reflect.MakeSlice(targetType, len, len))
|
||||
for i := 0; i < len; i++ {
|
||||
if err := u.unmarshalValue(target.Index(i), slc[i], prop); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Handle maps (whose keys are always strings)
|
||||
if targetType.Kind() == reflect.Map {
|
||||
var mp map[string]json.RawMessage
|
||||
if err := json.Unmarshal(inputValue, &mp); err != nil {
|
||||
return err
|
||||
}
|
||||
target.Set(reflect.MakeMap(targetType))
|
||||
var keyprop, valprop *proto.Properties
|
||||
if prop != nil {
|
||||
// These could still be nil if the protobuf metadata is broken somehow.
|
||||
// TODO: This won't work because the fields are unexported.
|
||||
// We should probably just reparse them.
|
||||
//keyprop, valprop = prop.mkeyprop, prop.mvalprop
|
||||
}
|
||||
for ks, raw := range mp {
|
||||
// Unmarshal map key. The core json library already decoded the key into a
|
||||
// string, so we handle that specially. Other types were quoted post-serialization.
|
||||
var k reflect.Value
|
||||
if targetType.Key().Kind() == reflect.String {
|
||||
k = reflect.ValueOf(ks)
|
||||
} else {
|
||||
k = reflect.New(targetType.Key()).Elem()
|
||||
if err := u.unmarshalValue(k, json.RawMessage(ks), keyprop); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Unmarshal map value.
|
||||
v := reflect.New(targetType.Elem()).Elem()
|
||||
if err := u.unmarshalValue(v, raw, valprop); err != nil {
|
||||
return err
|
||||
}
|
||||
target.SetMapIndex(k, v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 64-bit integers can be encoded as strings. In this case we drop
|
||||
// the quotes and proceed as normal.
|
||||
isNum := targetType.Kind() == reflect.Int64 || targetType.Kind() == reflect.Uint64
|
||||
if isNum && strings.HasPrefix(string(inputValue), `"`) {
|
||||
inputValue = inputValue[1 : len(inputValue)-1]
|
||||
}
|
||||
|
||||
// Use the encoding/json for parsing other value types.
|
||||
return json.Unmarshal(inputValue, target.Addr().Interface())
|
||||
}
|
||||
|
||||
// jsonProperties returns parsed proto.Properties for the field and corrects JSONName attribute.
|
||||
func jsonProperties(f reflect.StructField, origName bool) *proto.Properties {
|
||||
var prop proto.Properties
|
||||
prop.Init(f.Type, f.Name, f.Tag.Get("protobuf"), &f)
|
||||
if origName || prop.JSONName == "" {
|
||||
prop.JSONName = prop.OrigName
|
||||
}
|
||||
return &prop
|
||||
}
|
||||
|
||||
type fieldNames struct {
|
||||
orig, camel string
|
||||
}
|
||||
|
||||
func acceptedJSONFieldNames(prop *proto.Properties) fieldNames {
|
||||
opts := fieldNames{orig: prop.OrigName, camel: prop.OrigName}
|
||||
if prop.JSONName != "" {
|
||||
opts.camel = prop.JSONName
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
// Writer wrapper inspired by https://blog.golang.org/errors-are-values
|
||||
type errWriter struct {
|
||||
writer io.Writer
|
||||
err error
|
||||
}
|
||||
|
||||
func (w *errWriter) write(str string) {
|
||||
if w.err != nil {
|
||||
return
|
||||
}
|
||||
_, w.err = w.writer.Write([]byte(str))
|
||||
}
|
||||
|
||||
// Map fields may have key types of non-float scalars, strings and enums.
|
||||
// The easiest way to sort them in some deterministic order is to use fmt.
|
||||
// If this turns out to be inefficient we can always consider other options,
|
||||
// such as doing a Schwartzian transform.
|
||||
//
|
||||
// Numeric keys are sorted in numeric order per
|
||||
// https://developers.google.com/protocol-buffers/docs/proto#maps.
|
||||
type mapKeys []reflect.Value
|
||||
|
||||
func (s mapKeys) Len() int { return len(s) }
|
||||
func (s mapKeys) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
func (s mapKeys) Less(i, j int) bool {
|
||||
if k := s[i].Kind(); k == s[j].Kind() {
|
||||
switch k {
|
||||
case reflect.Int32, reflect.Int64:
|
||||
return s[i].Int() < s[j].Int()
|
||||
case reflect.Uint32, reflect.Uint64:
|
||||
return s[i].Uint() < s[j].Uint()
|
||||
}
|
||||
}
|
||||
return fmt.Sprint(s[i].Interface()) < fmt.Sprint(s[j].Interface())
|
||||
}
|
557
vendor/github.com/golang/protobuf/jsonpb/jsonpb_test.go
generated
vendored
557
vendor/github.com/golang/protobuf/jsonpb/jsonpb_test.go
generated
vendored
|
@ -1,557 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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 Google 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.
|
||||
|
||||
package jsonpb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
pb "github.com/golang/protobuf/jsonpb/jsonpb_test_proto"
|
||||
proto3pb "github.com/golang/protobuf/proto/proto3_proto"
|
||||
anypb "github.com/golang/protobuf/ptypes/any"
|
||||
durpb "github.com/golang/protobuf/ptypes/duration"
|
||||
stpb "github.com/golang/protobuf/ptypes/struct"
|
||||
tspb "github.com/golang/protobuf/ptypes/timestamp"
|
||||
wpb "github.com/golang/protobuf/ptypes/wrappers"
|
||||
)
|
||||
|
||||
var (
|
||||
marshaler = Marshaler{}
|
||||
|
||||
marshalerAllOptions = Marshaler{
|
||||
Indent: " ",
|
||||
}
|
||||
|
||||
simpleObject = &pb.Simple{
|
||||
OInt32: proto.Int32(-32),
|
||||
OInt64: proto.Int64(-6400000000),
|
||||
OUint32: proto.Uint32(32),
|
||||
OUint64: proto.Uint64(6400000000),
|
||||
OSint32: proto.Int32(-13),
|
||||
OSint64: proto.Int64(-2600000000),
|
||||
OFloat: proto.Float32(3.14),
|
||||
ODouble: proto.Float64(6.02214179e23),
|
||||
OBool: proto.Bool(true),
|
||||
OString: proto.String("hello \"there\""),
|
||||
OBytes: []byte("beep boop"),
|
||||
}
|
||||
|
||||
simpleObjectJSON = `{` +
|
||||
`"oBool":true,` +
|
||||
`"oInt32":-32,` +
|
||||
`"oInt64":"-6400000000",` +
|
||||
`"oUint32":32,` +
|
||||
`"oUint64":"6400000000",` +
|
||||
`"oSint32":-13,` +
|
||||
`"oSint64":"-2600000000",` +
|
||||
`"oFloat":3.14,` +
|
||||
`"oDouble":6.02214179e+23,` +
|
||||
`"oString":"hello \"there\"",` +
|
||||
`"oBytes":"YmVlcCBib29w"` +
|
||||
`}`
|
||||
|
||||
simpleObjectPrettyJSON = `{
|
||||
"oBool": true,
|
||||
"oInt32": -32,
|
||||
"oInt64": "-6400000000",
|
||||
"oUint32": 32,
|
||||
"oUint64": "6400000000",
|
||||
"oSint32": -13,
|
||||
"oSint64": "-2600000000",
|
||||
"oFloat": 3.14,
|
||||
"oDouble": 6.02214179e+23,
|
||||
"oString": "hello \"there\"",
|
||||
"oBytes": "YmVlcCBib29w"
|
||||
}`
|
||||
|
||||
repeatsObject = &pb.Repeats{
|
||||
RBool: []bool{true, false, true},
|
||||
RInt32: []int32{-3, -4, -5},
|
||||
RInt64: []int64{-123456789, -987654321},
|
||||
RUint32: []uint32{1, 2, 3},
|
||||
RUint64: []uint64{6789012345, 3456789012},
|
||||
RSint32: []int32{-1, -2, -3},
|
||||
RSint64: []int64{-6789012345, -3456789012},
|
||||
RFloat: []float32{3.14, 6.28},
|
||||
RDouble: []float64{299792458, 6.62606957e-34},
|
||||
RString: []string{"happy", "days"},
|
||||
RBytes: [][]byte{[]byte("skittles"), []byte("m&m's")},
|
||||
}
|
||||
|
||||
repeatsObjectJSON = `{` +
|
||||
`"rBool":[true,false,true],` +
|
||||
`"rInt32":[-3,-4,-5],` +
|
||||
`"rInt64":["-123456789","-987654321"],` +
|
||||
`"rUint32":[1,2,3],` +
|
||||
`"rUint64":["6789012345","3456789012"],` +
|
||||
`"rSint32":[-1,-2,-3],` +
|
||||
`"rSint64":["-6789012345","-3456789012"],` +
|
||||
`"rFloat":[3.14,6.28],` +
|
||||
`"rDouble":[2.99792458e+08,6.62606957e-34],` +
|
||||
`"rString":["happy","days"],` +
|
||||
`"rBytes":["c2tpdHRsZXM=","bSZtJ3M="]` +
|
||||
`}`
|
||||
|
||||
repeatsObjectPrettyJSON = `{
|
||||
"rBool": [
|
||||
true,
|
||||
false,
|
||||
true
|
||||
],
|
||||
"rInt32": [
|
||||
-3,
|
||||
-4,
|
||||
-5
|
||||
],
|
||||
"rInt64": [
|
||||
"-123456789",
|
||||
"-987654321"
|
||||
],
|
||||
"rUint32": [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
],
|
||||
"rUint64": [
|
||||
"6789012345",
|
||||
"3456789012"
|
||||
],
|
||||
"rSint32": [
|
||||
-1,
|
||||
-2,
|
||||
-3
|
||||
],
|
||||
"rSint64": [
|
||||
"-6789012345",
|
||||
"-3456789012"
|
||||
],
|
||||
"rFloat": [
|
||||
3.14,
|
||||
6.28
|
||||
],
|
||||
"rDouble": [
|
||||
2.99792458e+08,
|
||||
6.62606957e-34
|
||||
],
|
||||
"rString": [
|
||||
"happy",
|
||||
"days"
|
||||
],
|
||||
"rBytes": [
|
||||
"c2tpdHRsZXM=",
|
||||
"bSZtJ3M="
|
||||
]
|
||||
}`
|
||||
|
||||
innerSimple = &pb.Simple{OInt32: proto.Int32(-32)}
|
||||
innerSimple2 = &pb.Simple{OInt64: proto.Int64(25)}
|
||||
innerRepeats = &pb.Repeats{RString: []string{"roses", "red"}}
|
||||
innerRepeats2 = &pb.Repeats{RString: []string{"violets", "blue"}}
|
||||
complexObject = &pb.Widget{
|
||||
Color: pb.Widget_GREEN.Enum(),
|
||||
RColor: []pb.Widget_Color{pb.Widget_RED, pb.Widget_GREEN, pb.Widget_BLUE},
|
||||
Simple: innerSimple,
|
||||
RSimple: []*pb.Simple{innerSimple, innerSimple2},
|
||||
Repeats: innerRepeats,
|
||||
RRepeats: []*pb.Repeats{innerRepeats, innerRepeats2},
|
||||
}
|
||||
|
||||
complexObjectJSON = `{"color":"GREEN",` +
|
||||
`"rColor":["RED","GREEN","BLUE"],` +
|
||||
`"simple":{"oInt32":-32},` +
|
||||
`"rSimple":[{"oInt32":-32},{"oInt64":"25"}],` +
|
||||
`"repeats":{"rString":["roses","red"]},` +
|
||||
`"rRepeats":[{"rString":["roses","red"]},{"rString":["violets","blue"]}]` +
|
||||
`}`
|
||||
|
||||
complexObjectPrettyJSON = `{
|
||||
"color": "GREEN",
|
||||
"rColor": [
|
||||
"RED",
|
||||
"GREEN",
|
||||
"BLUE"
|
||||
],
|
||||
"simple": {
|
||||
"oInt32": -32
|
||||
},
|
||||
"rSimple": [
|
||||
{
|
||||
"oInt32": -32
|
||||
},
|
||||
{
|
||||
"oInt64": "25"
|
||||
}
|
||||
],
|
||||
"repeats": {
|
||||
"rString": [
|
||||
"roses",
|
||||
"red"
|
||||
]
|
||||
},
|
||||
"rRepeats": [
|
||||
{
|
||||
"rString": [
|
||||
"roses",
|
||||
"red"
|
||||
]
|
||||
},
|
||||
{
|
||||
"rString": [
|
||||
"violets",
|
||||
"blue"
|
||||
]
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
colorPrettyJSON = `{
|
||||
"color": 2
|
||||
}`
|
||||
|
||||
colorListPrettyJSON = `{
|
||||
"color": 1000,
|
||||
"rColor": [
|
||||
"RED"
|
||||
]
|
||||
}`
|
||||
|
||||
nummyPrettyJSON = `{
|
||||
"nummy": {
|
||||
"1": 2,
|
||||
"3": 4
|
||||
}
|
||||
}`
|
||||
|
||||
objjyPrettyJSON = `{
|
||||
"objjy": {
|
||||
"1": {
|
||||
"dub": 1
|
||||
}
|
||||
}
|
||||
}`
|
||||
realNumber = &pb.Real{Value: proto.Float64(3.14159265359)}
|
||||
realNumberName = "Pi"
|
||||
complexNumber = &pb.Complex{Imaginary: proto.Float64(0.5772156649)}
|
||||
realNumberJSON = `{` +
|
||||
`"value":3.14159265359,` +
|
||||
`"[jsonpb.Complex.real_extension]":{"imaginary":0.5772156649},` +
|
||||
`"[jsonpb.name]":"Pi"` +
|
||||
`}`
|
||||
|
||||
anySimple = &pb.KnownTypes{
|
||||
An: &anypb.Any{
|
||||
TypeUrl: "something.example.com/jsonpb.Simple",
|
||||
Value: []byte{
|
||||
// &pb.Simple{OBool:true}
|
||||
1 << 3, 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
anySimpleJSON = `{"an":{"@type":"something.example.com/jsonpb.Simple","oBool":true}}`
|
||||
anySimplePrettyJSON = `{
|
||||
"an": {
|
||||
"@type": "something.example.com/jsonpb.Simple",
|
||||
"oBool": true
|
||||
}
|
||||
}`
|
||||
|
||||
anyWellKnown = &pb.KnownTypes{
|
||||
An: &anypb.Any{
|
||||
TypeUrl: "type.googleapis.com/google.protobuf.Duration",
|
||||
Value: []byte{
|
||||
// &durpb.Duration{Seconds: 1, Nanos: 212000000 }
|
||||
1 << 3, 1, // seconds
|
||||
2 << 3, 0x80, 0xba, 0x8b, 0x65, // nanos
|
||||
},
|
||||
},
|
||||
}
|
||||
anyWellKnownJSON = `{"an":{"@type":"type.googleapis.com/google.protobuf.Duration","value":"1.212s"}}`
|
||||
anyWellKnownPrettyJSON = `{
|
||||
"an": {
|
||||
"@type": "type.googleapis.com/google.protobuf.Duration",
|
||||
"value": "1.212s"
|
||||
}
|
||||
}`
|
||||
)
|
||||
|
||||
func init() {
|
||||
if err := proto.SetExtension(realNumber, pb.E_Name, &realNumberName); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := proto.SetExtension(realNumber, pb.E_Complex_RealExtension, complexNumber); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
var marshalingTests = []struct {
|
||||
desc string
|
||||
marshaler Marshaler
|
||||
pb proto.Message
|
||||
json string
|
||||
}{
|
||||
{"simple flat object", marshaler, simpleObject, simpleObjectJSON},
|
||||
{"simple pretty object", marshalerAllOptions, simpleObject, simpleObjectPrettyJSON},
|
||||
{"repeated fields flat object", marshaler, repeatsObject, repeatsObjectJSON},
|
||||
{"repeated fields pretty object", marshalerAllOptions, repeatsObject, repeatsObjectPrettyJSON},
|
||||
{"nested message/enum flat object", marshaler, complexObject, complexObjectJSON},
|
||||
{"nested message/enum pretty object", marshalerAllOptions, complexObject, complexObjectPrettyJSON},
|
||||
{"enum-string flat object", Marshaler{},
|
||||
&pb.Widget{Color: pb.Widget_BLUE.Enum()}, `{"color":"BLUE"}`},
|
||||
{"enum-value pretty object", Marshaler{EnumsAsInts: true, Indent: " "},
|
||||
&pb.Widget{Color: pb.Widget_BLUE.Enum()}, colorPrettyJSON},
|
||||
{"unknown enum value object", marshalerAllOptions,
|
||||
&pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}, colorListPrettyJSON},
|
||||
{"repeated proto3 enum", Marshaler{},
|
||||
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
|
||||
proto3pb.Message_PUNS,
|
||||
proto3pb.Message_SLAPSTICK,
|
||||
}},
|
||||
`{"rFunny":["PUNS","SLAPSTICK"]}`},
|
||||
{"repeated proto3 enum as int", Marshaler{EnumsAsInts: true},
|
||||
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
|
||||
proto3pb.Message_PUNS,
|
||||
proto3pb.Message_SLAPSTICK,
|
||||
}},
|
||||
`{"rFunny":[1,2]}`},
|
||||
{"empty value", marshaler, &pb.Simple3{}, `{}`},
|
||||
{"empty value emitted", Marshaler{EmitDefaults: true}, &pb.Simple3{}, `{"dub":0}`},
|
||||
{"map<int64, int32>", marshaler, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}, `{"nummy":{"1":2,"3":4}}`},
|
||||
{"map<int64, int32>", marshalerAllOptions, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}, nummyPrettyJSON},
|
||||
{"map<string, string>", marshaler,
|
||||
&pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}},
|
||||
`{"strry":{"\"one\"":"two","three":"four"}}`},
|
||||
{"map<int32, Object>", marshaler,
|
||||
&pb.Mappy{Objjy: map[int32]*pb.Simple3{1: &pb.Simple3{Dub: 1}}}, `{"objjy":{"1":{"dub":1}}}`},
|
||||
{"map<int32, Object>", marshalerAllOptions,
|
||||
&pb.Mappy{Objjy: map[int32]*pb.Simple3{1: &pb.Simple3{Dub: 1}}}, objjyPrettyJSON},
|
||||
{"map<int64, string>", marshaler, &pb.Mappy{Buggy: map[int64]string{1234: "yup"}},
|
||||
`{"buggy":{"1234":"yup"}}`},
|
||||
{"map<bool, bool>", marshaler, &pb.Mappy{Booly: map[bool]bool{false: true}}, `{"booly":{"false":true}}`},
|
||||
// TODO: This is broken.
|
||||
//{"map<string, enum>", marshaler, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}, `{"enumy":{"XIV":"ROMAN"}`},
|
||||
{"map<string, enum as int>", Marshaler{EnumsAsInts: true}, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}, `{"enumy":{"XIV":2}}`},
|
||||
{"map<int32, bool>", marshaler, &pb.Mappy{S32Booly: map[int32]bool{1: true, 3: false, 10: true, 12: false}}, `{"s32booly":{"1":true,"3":false,"10":true,"12":false}}`},
|
||||
{"map<int64, bool>", marshaler, &pb.Mappy{S64Booly: map[int64]bool{1: true, 3: false, 10: true, 12: false}}, `{"s64booly":{"1":true,"3":false,"10":true,"12":false}}`},
|
||||
{"map<uint32, bool>", marshaler, &pb.Mappy{U32Booly: map[uint32]bool{1: true, 3: false, 10: true, 12: false}}, `{"u32booly":{"1":true,"3":false,"10":true,"12":false}}`},
|
||||
{"map<uint64, bool>", marshaler, &pb.Mappy{U64Booly: map[uint64]bool{1: true, 3: false, 10: true, 12: false}}, `{"u64booly":{"1":true,"3":false,"10":true,"12":false}}`},
|
||||
{"proto2 map<int64, string>", marshaler, &pb.Maps{MInt64Str: map[int64]string{213: "cat"}},
|
||||
`{"mInt64Str":{"213":"cat"}}`},
|
||||
{"proto2 map<bool, Object>", marshaler,
|
||||
&pb.Maps{MBoolSimple: map[bool]*pb.Simple{true: &pb.Simple{OInt32: proto.Int32(1)}}},
|
||||
`{"mBoolSimple":{"true":{"oInt32":1}}}`},
|
||||
{"oneof, not set", marshaler, &pb.MsgWithOneof{}, `{}`},
|
||||
{"oneof, set", marshaler, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Title{"Grand Poobah"}}, `{"title":"Grand Poobah"}`},
|
||||
{"force orig_name", Marshaler{OrigName: true}, &pb.Simple{OInt32: proto.Int32(4)},
|
||||
`{"o_int32":4}`},
|
||||
{"proto2 extension", marshaler, realNumber, realNumberJSON},
|
||||
{"Any with message", marshaler, anySimple, anySimpleJSON},
|
||||
{"Any with message and indent", marshalerAllOptions, anySimple, anySimplePrettyJSON},
|
||||
{"Any with WKT", marshaler, anyWellKnown, anyWellKnownJSON},
|
||||
{"Any with WKT and indent", marshalerAllOptions, anyWellKnown, anyWellKnownPrettyJSON},
|
||||
{"Duration", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}, `{"dur":"3.000s"}`},
|
||||
{"Struct", marshaler, &pb.KnownTypes{St: &stpb.Struct{
|
||||
Fields: map[string]*stpb.Value{
|
||||
"one": &stpb.Value{Kind: &stpb.Value_StringValue{"loneliest number"}},
|
||||
"two": &stpb.Value{Kind: &stpb.Value_NullValue{stpb.NullValue_NULL_VALUE}},
|
||||
},
|
||||
}}, `{"st":{"one":"loneliest number","two":null}}`},
|
||||
{"Timestamp", marshaler, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}, `{"ts":"2014-05-13T16:53:20.021Z"}`},
|
||||
|
||||
{"DoubleValue", marshaler, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}, `{"dbl":1.2}`},
|
||||
{"FloatValue", marshaler, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}, `{"flt":1.2}`},
|
||||
{"Int64Value", marshaler, &pb.KnownTypes{I64: &wpb.Int64Value{Value: -3}}, `{"i64":"-3"}`},
|
||||
{"UInt64Value", marshaler, &pb.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}, `{"u64":"3"}`},
|
||||
{"Int32Value", marshaler, &pb.KnownTypes{I32: &wpb.Int32Value{Value: -4}}, `{"i32":-4}`},
|
||||
{"UInt32Value", marshaler, &pb.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}, `{"u32":4}`},
|
||||
{"BoolValue", marshaler, &pb.KnownTypes{Bool: &wpb.BoolValue{Value: true}}, `{"bool":true}`},
|
||||
{"StringValue", marshaler, &pb.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}, `{"str":"plush"}`},
|
||||
{"BytesValue", marshaler, &pb.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}, `{"bytes":"d293"}`},
|
||||
}
|
||||
|
||||
func TestMarshaling(t *testing.T) {
|
||||
for _, tt := range marshalingTests {
|
||||
json, err := tt.marshaler.MarshalToString(tt.pb)
|
||||
if err != nil {
|
||||
t.Errorf("%s: marshaling error: %v", tt.desc, err)
|
||||
} else if tt.json != json {
|
||||
t.Errorf("%s: got [%v] want [%v]", tt.desc, json, tt.json)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var unmarshalingTests = []struct {
|
||||
desc string
|
||||
unmarshaler Unmarshaler
|
||||
json string
|
||||
pb proto.Message
|
||||
}{
|
||||
{"simple flat object", Unmarshaler{}, simpleObjectJSON, simpleObject},
|
||||
{"simple pretty object", Unmarshaler{}, simpleObjectPrettyJSON, simpleObject},
|
||||
{"repeated fields flat object", Unmarshaler{}, repeatsObjectJSON, repeatsObject},
|
||||
{"repeated fields pretty object", Unmarshaler{}, repeatsObjectPrettyJSON, repeatsObject},
|
||||
{"nested message/enum flat object", Unmarshaler{}, complexObjectJSON, complexObject},
|
||||
{"nested message/enum pretty object", Unmarshaler{}, complexObjectPrettyJSON, complexObject},
|
||||
{"enum-string object", Unmarshaler{}, `{"color":"BLUE"}`, &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
|
||||
{"enum-value object", Unmarshaler{}, "{\n \"color\": 2\n}", &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
|
||||
{"unknown field with allowed option", Unmarshaler{AllowUnknownFields: true}, `{"unknown": "foo"}`, new(pb.Simple)},
|
||||
{"proto3 enum string", Unmarshaler{}, `{"hilarity":"PUNS"}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
|
||||
{"proto3 enum value", Unmarshaler{}, `{"hilarity":1}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
|
||||
{"unknown enum value object",
|
||||
Unmarshaler{},
|
||||
"{\n \"color\": 1000,\n \"r_color\": [\n \"RED\"\n ]\n}",
|
||||
&pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}},
|
||||
{"repeated proto3 enum", Unmarshaler{}, `{"rFunny":["PUNS","SLAPSTICK"]}`,
|
||||
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
|
||||
proto3pb.Message_PUNS,
|
||||
proto3pb.Message_SLAPSTICK,
|
||||
}}},
|
||||
{"repeated proto3 enum as int", Unmarshaler{}, `{"rFunny":[1,2]}`,
|
||||
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
|
||||
proto3pb.Message_PUNS,
|
||||
proto3pb.Message_SLAPSTICK,
|
||||
}}},
|
||||
{"repeated proto3 enum as mix of strings and ints", Unmarshaler{}, `{"rFunny":["PUNS",2]}`,
|
||||
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
|
||||
proto3pb.Message_PUNS,
|
||||
proto3pb.Message_SLAPSTICK,
|
||||
}}},
|
||||
{"unquoted int64 object", Unmarshaler{}, `{"oInt64":-314}`, &pb.Simple{OInt64: proto.Int64(-314)}},
|
||||
{"unquoted uint64 object", Unmarshaler{}, `{"oUint64":123}`, &pb.Simple{OUint64: proto.Uint64(123)}},
|
||||
{"map<int64, int32>", Unmarshaler{}, `{"nummy":{"1":2,"3":4}}`, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}},
|
||||
{"map<string, string>", Unmarshaler{}, `{"strry":{"\"one\"":"two","three":"four"}}`, &pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}}},
|
||||
{"map<int32, Object>", Unmarshaler{}, `{"objjy":{"1":{"dub":1}}}`, &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: &pb.Simple3{Dub: 1}}}},
|
||||
// TODO: This is broken.
|
||||
//{"map<string, enum>", Unmarshaler{}, `{"enumy":{"XIV":"ROMAN"}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
|
||||
{"map<string, enum as int>", Unmarshaler{}, `{"enumy":{"XIV":2}}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
|
||||
{"oneof", Unmarshaler{}, `{"salary":31000}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Salary{31000}}},
|
||||
{"oneof spec name", Unmarshaler{}, `{"country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}},
|
||||
{"oneof orig_name", Unmarshaler{}, `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}},
|
||||
{"orig_name input", Unmarshaler{}, `{"o_bool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
|
||||
{"camelName input", Unmarshaler{}, `{"oBool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
|
||||
|
||||
{"Duration", Unmarshaler{}, `{"dur":"3.000s"}`, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}},
|
||||
{"Timestamp", Unmarshaler{}, `{"ts":"2014-05-13T16:53:20.021Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}},
|
||||
|
||||
{"DoubleValue", Unmarshaler{}, `{"dbl":1.2}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}},
|
||||
{"FloatValue", Unmarshaler{}, `{"flt":1.2}`, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}},
|
||||
{"Int64Value", Unmarshaler{}, `{"i64":"-3"}`, &pb.KnownTypes{I64: &wpb.Int64Value{Value: -3}}},
|
||||
{"UInt64Value", Unmarshaler{}, `{"u64":"3"}`, &pb.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}},
|
||||
{"Int32Value", Unmarshaler{}, `{"i32":-4}`, &pb.KnownTypes{I32: &wpb.Int32Value{Value: -4}}},
|
||||
{"UInt32Value", Unmarshaler{}, `{"u32":4}`, &pb.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}},
|
||||
{"BoolValue", Unmarshaler{}, `{"bool":true}`, &pb.KnownTypes{Bool: &wpb.BoolValue{Value: true}}},
|
||||
{"StringValue", Unmarshaler{}, `{"str":"plush"}`, &pb.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}},
|
||||
{"BytesValue", Unmarshaler{}, `{"bytes":"d293"}`, &pb.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}},
|
||||
// `null` is also a permissible value. Let's just test one.
|
||||
{"null DoubleValue", Unmarshaler{}, `{"dbl":null}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{}}},
|
||||
}
|
||||
|
||||
func TestUnmarshaling(t *testing.T) {
|
||||
for _, tt := range unmarshalingTests {
|
||||
// Make a new instance of the type of our expected object.
|
||||
p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message)
|
||||
|
||||
err := tt.unmarshaler.Unmarshal(strings.NewReader(tt.json), p)
|
||||
if err != nil {
|
||||
t.Errorf("%s: %v", tt.desc, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// For easier diffs, compare text strings of the protos.
|
||||
exp := proto.MarshalTextString(tt.pb)
|
||||
act := proto.MarshalTextString(p)
|
||||
if string(exp) != string(act) {
|
||||
t.Errorf("%s: got [%s] want [%s]", tt.desc, act, exp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalNext(t *testing.T) {
|
||||
// We only need to check against a few, not all of them.
|
||||
tests := unmarshalingTests[:5]
|
||||
|
||||
// Create a buffer with many concatenated JSON objects.
|
||||
var b bytes.Buffer
|
||||
for _, tt := range tests {
|
||||
b.WriteString(tt.json)
|
||||
}
|
||||
|
||||
dec := json.NewDecoder(&b)
|
||||
for _, tt := range tests {
|
||||
// Make a new instance of the type of our expected object.
|
||||
p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message)
|
||||
|
||||
err := tt.unmarshaler.UnmarshalNext(dec, p)
|
||||
if err != nil {
|
||||
t.Errorf("%s: %v", tt.desc, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// For easier diffs, compare text strings of the protos.
|
||||
exp := proto.MarshalTextString(tt.pb)
|
||||
act := proto.MarshalTextString(p)
|
||||
if string(exp) != string(act) {
|
||||
t.Errorf("%s: got [%s] want [%s]", tt.desc, act, exp)
|
||||
}
|
||||
}
|
||||
|
||||
p := &pb.Simple{}
|
||||
err := new(Unmarshaler).UnmarshalNext(dec, p)
|
||||
if err != io.EOF {
|
||||
t.Errorf("eof: got %v, expected io.EOF", err)
|
||||
}
|
||||
}
|
||||
|
||||
var unmarshalingShouldError = []struct {
|
||||
desc string
|
||||
in string
|
||||
pb proto.Message
|
||||
}{
|
||||
{"a value", "666", new(pb.Simple)},
|
||||
{"gibberish", "{adskja123;l23=-=", new(pb.Simple)},
|
||||
{"unknown field", `{"unknown": "foo"}`, new(pb.Simple)},
|
||||
{"unknown enum name", `{"hilarity":"DAVE"}`, new(proto3pb.Message)},
|
||||
}
|
||||
|
||||
func TestUnmarshalingBadInput(t *testing.T) {
|
||||
for _, tt := range unmarshalingShouldError {
|
||||
err := UnmarshalString(tt.in, tt.pb)
|
||||
if err == nil {
|
||||
t.Errorf("an error was expected when parsing %q instead of an object", tt.desc)
|
||||
}
|
||||
}
|
||||
}
|
33
vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/Makefile
generated
vendored
33
vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/Makefile
generated
vendored
|
@ -1,33 +0,0 @@
|
|||
# Go support for Protocol Buffers - Google's data interchange format
|
||||
#
|
||||
# Copyright 2015 The Go Authors. All rights reserved.
|
||||
# https://github.com/golang/protobuf
|
||||
#
|
||||
# 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 Google 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.
|
||||
|
||||
regenerate:
|
||||
protoc --go_out=Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any,Mgoogle/protobuf/duration.proto=github.com/golang/protobuf/ptypes/duration,Mgoogle/protobuf/struct.proto=github.com/golang/protobuf/ptypes/struct,Mgoogle/protobuf/timestamp.proto=github.com/golang/protobuf/ptypes/timestamp,Mgoogle/protobuf/wrappers.proto=github.com/golang/protobuf/ptypes/wrappers:. *.proto
|
200
vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/more_test_objects.pb.go
generated
vendored
200
vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/more_test_objects.pb.go
generated
vendored
|
@ -1,200 +0,0 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// source: more_test_objects.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package jsonpb is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
more_test_objects.proto
|
||||
test_objects.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Simple3
|
||||
Mappy
|
||||
Simple
|
||||
Repeats
|
||||
Widget
|
||||
Maps
|
||||
MsgWithOneof
|
||||
Real
|
||||
Complex
|
||||
KnownTypes
|
||||
*/
|
||||
package jsonpb
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type Numeral int32
|
||||
|
||||
const (
|
||||
Numeral_UNKNOWN Numeral = 0
|
||||
Numeral_ARABIC Numeral = 1
|
||||
Numeral_ROMAN Numeral = 2
|
||||
)
|
||||
|
||||
var Numeral_name = map[int32]string{
|
||||
0: "UNKNOWN",
|
||||
1: "ARABIC",
|
||||
2: "ROMAN",
|
||||
}
|
||||
var Numeral_value = map[string]int32{
|
||||
"UNKNOWN": 0,
|
||||
"ARABIC": 1,
|
||||
"ROMAN": 2,
|
||||
}
|
||||
|
||||
func (x Numeral) String() string {
|
||||
return proto.EnumName(Numeral_name, int32(x))
|
||||
}
|
||||
func (Numeral) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
type Simple3 struct {
|
||||
Dub float64 `protobuf:"fixed64,1,opt,name=dub" json:"dub,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Simple3) Reset() { *m = Simple3{} }
|
||||
func (m *Simple3) String() string { return proto.CompactTextString(m) }
|
||||
func (*Simple3) ProtoMessage() {}
|
||||
func (*Simple3) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
type Mappy struct {
|
||||
Nummy map[int64]int32 `protobuf:"bytes,1,rep,name=nummy" json:"nummy,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"`
|
||||
Strry map[string]string `protobuf:"bytes,2,rep,name=strry" json:"strry,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
Objjy map[int32]*Simple3 `protobuf:"bytes,3,rep,name=objjy" json:"objjy,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
Buggy map[int64]string `protobuf:"bytes,4,rep,name=buggy" json:"buggy,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
Booly map[bool]bool `protobuf:"bytes,5,rep,name=booly" json:"booly,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"`
|
||||
Enumy map[string]Numeral `protobuf:"bytes,6,rep,name=enumy" json:"enumy,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"varint,2,opt,name=value,enum=jsonpb.Numeral"`
|
||||
S32Booly map[int32]bool `protobuf:"bytes,7,rep,name=s32booly" json:"s32booly,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"`
|
||||
S64Booly map[int64]bool `protobuf:"bytes,8,rep,name=s64booly" json:"s64booly,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"`
|
||||
U32Booly map[uint32]bool `protobuf:"bytes,9,rep,name=u32booly" json:"u32booly,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"`
|
||||
U64Booly map[uint64]bool `protobuf:"bytes,10,rep,name=u64booly" json:"u64booly,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"`
|
||||
}
|
||||
|
||||
func (m *Mappy) Reset() { *m = Mappy{} }
|
||||
func (m *Mappy) String() string { return proto.CompactTextString(m) }
|
||||
func (*Mappy) ProtoMessage() {}
|
||||
func (*Mappy) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *Mappy) GetNummy() map[int64]int32 {
|
||||
if m != nil {
|
||||
return m.Nummy
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Mappy) GetStrry() map[string]string {
|
||||
if m != nil {
|
||||
return m.Strry
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Mappy) GetObjjy() map[int32]*Simple3 {
|
||||
if m != nil {
|
||||
return m.Objjy
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Mappy) GetBuggy() map[int64]string {
|
||||
if m != nil {
|
||||
return m.Buggy
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Mappy) GetBooly() map[bool]bool {
|
||||
if m != nil {
|
||||
return m.Booly
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Mappy) GetEnumy() map[string]Numeral {
|
||||
if m != nil {
|
||||
return m.Enumy
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Mappy) GetS32Booly() map[int32]bool {
|
||||
if m != nil {
|
||||
return m.S32Booly
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Mappy) GetS64Booly() map[int64]bool {
|
||||
if m != nil {
|
||||
return m.S64Booly
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Mappy) GetU32Booly() map[uint32]bool {
|
||||
if m != nil {
|
||||
return m.U32Booly
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Mappy) GetU64Booly() map[uint64]bool {
|
||||
if m != nil {
|
||||
return m.U64Booly
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Simple3)(nil), "jsonpb.Simple3")
|
||||
proto.RegisterType((*Mappy)(nil), "jsonpb.Mappy")
|
||||
proto.RegisterEnum("jsonpb.Numeral", Numeral_name, Numeral_value)
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("more_test_objects.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 442 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x94, 0xcf, 0xab, 0xd3, 0x40,
|
||||
0x10, 0xc7, 0x4d, 0xf3, 0xf2, 0x6b, 0xca, 0xd3, 0xb0, 0x08, 0x06, 0xdf, 0x45, 0x1e, 0x08, 0x45,
|
||||
0x30, 0x87, 0x56, 0xf4, 0xa1, 0xa7, 0x56, 0x7a, 0x28, 0xd2, 0x14, 0x52, 0x8a, 0xc7, 0xd2, 0xe8,
|
||||
0x52, 0xac, 0x49, 0x13, 0xf2, 0x43, 0xd8, 0x3f, 0x5e, 0x30, 0xb3, 0xd9, 0x34, 0x9b, 0xb0, 0xa5,
|
||||
0xde, 0x36, 0x7c, 0x3f, 0x9f, 0xce, 0xec, 0xce, 0x50, 0x78, 0x95, 0xa4, 0x39, 0xdd, 0x97, 0xb4,
|
||||
0x28, 0xf7, 0x69, 0x74, 0xa2, 0x3f, 0xca, 0xc2, 0xcf, 0xf2, 0xb4, 0x4c, 0x89, 0x79, 0x2a, 0xd2,
|
||||
0x73, 0x16, 0x3d, 0x3e, 0x80, 0xb5, 0xfd, 0x95, 0x64, 0x31, 0x9d, 0x11, 0x17, 0xf4, 0x9f, 0x55,
|
||||
0xe4, 0x69, 0x6f, 0xb4, 0x89, 0x16, 0xe2, 0xf1, 0xf1, 0xaf, 0x0d, 0xc6, 0xfa, 0x90, 0x65, 0x8c,
|
||||
0xf8, 0x60, 0x9c, 0xab, 0x24, 0x61, 0x75, 0xaa, 0x4f, 0xc6, 0x53, 0xcf, 0x6f, 0x74, 0x9f, 0xa7,
|
||||
0x7e, 0x80, 0xd1, 0xf2, 0x5c, 0xe6, 0x2c, 0x6c, 0x30, 0xe4, 0x8b, 0x32, 0xcf, 0x99, 0x37, 0x52,
|
||||
0xf1, 0x5b, 0x8c, 0x04, 0xcf, 0x31, 0xe4, 0xeb, 0xfe, 0x4e, 0xcc, 0xd3, 0x55, 0xfc, 0x06, 0x23,
|
||||
0xc1, 0x73, 0x0c, 0xf9, 0xa8, 0x3a, 0x1e, 0x99, 0x77, 0xa7, 0xe2, 0x17, 0x18, 0x09, 0x9e, 0x63,
|
||||
0x9c, 0x4f, 0xd3, 0x98, 0x79, 0x86, 0x92, 0xc7, 0xa8, 0xe5, 0xf1, 0x8c, 0x3c, 0xad, 0x6f, 0xc2,
|
||||
0x3c, 0x53, 0xc5, 0x2f, 0x31, 0x12, 0x3c, 0xc7, 0xc8, 0x27, 0xb0, 0x8b, 0xd9, 0xb4, 0x29, 0x61,
|
||||
0x71, 0xe5, 0x61, 0x70, 0x65, 0x91, 0x36, 0xd6, 0x05, 0xe6, 0xe2, 0xc7, 0x0f, 0x8d, 0x68, 0x2b,
|
||||
0x45, 0x91, 0xb6, 0xa2, 0xf8, 0x44, 0xb1, 0x6a, 0x2b, 0x3a, 0x2a, 0x71, 0xd7, 0xaf, 0x58, 0x49,
|
||||
0x15, 0xab, 0xb6, 0x22, 0x28, 0xc5, 0x7e, 0xc5, 0x16, 0x7e, 0xfd, 0x04, 0xd0, 0x0d, 0x1a, 0xb7,
|
||||
0xe5, 0x37, 0x65, 0x7c, 0x5b, 0xf4, 0x10, 0x8f, 0xe4, 0x25, 0x18, 0x7f, 0x0e, 0x71, 0x45, 0xeb,
|
||||
0x99, 0x6b, 0x13, 0x23, 0x6c, 0x3e, 0x3e, 0x8f, 0x9e, 0x34, 0x34, 0xbb, 0x91, 0xcb, 0xa6, 0xa3,
|
||||
0x30, 0x1d, 0xd9, 0x5c, 0x01, 0x74, 0xc3, 0x97, 0x4d, 0xa3, 0x31, 0xdf, 0xca, 0xe6, 0x78, 0xfa,
|
||||
0xa2, 0xbd, 0x89, 0xd8, 0xe9, 0x41, 0x13, 0xdd, 0x5e, 0xdc, 0x6a, 0xdf, 0x19, 0x9a, 0x97, 0x07,
|
||||
0x91, 0x4d, 0x5b, 0x61, 0xda, 0x83, 0xf6, 0xbb, 0x5d, 0x51, 0x5c, 0xbc, 0xd7, 0xfe, 0xf3, 0xae,
|
||||
0xfd, 0xfa, 0x9d, 0x69, 0x7e, 0x88, 0xe5, 0x9f, 0xfa, 0x02, 0xf7, 0xbd, 0x1d, 0x52, 0x3c, 0xc6,
|
||||
0xf5, 0x3e, 0x50, 0x96, 0xa7, 0x7a, 0xeb, 0xfa, 0x43, 0x79, 0x77, 0xad, 0xf2, 0xfd, 0xff, 0xc8,
|
||||
0xd7, 0x2a, 0xdf, 0xdd, 0x90, 0xdf, 0xbd, 0x07, 0x4b, 0xbc, 0x04, 0x19, 0x83, 0xb5, 0x0b, 0xbe,
|
||||
0x05, 0x9b, 0xef, 0x81, 0xfb, 0x8c, 0x00, 0x98, 0xf3, 0x70, 0xbe, 0x58, 0x7d, 0x75, 0x35, 0xe2,
|
||||
0x80, 0x11, 0x6e, 0xd6, 0xf3, 0xc0, 0x1d, 0x45, 0x26, 0xff, 0x6b, 0x9b, 0xfd, 0x0b, 0x00, 0x00,
|
||||
0xff, 0xff, 0xa2, 0x4b, 0xe1, 0x77, 0xf5, 0x04, 0x00, 0x00,
|
||||
}
|
57
vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/more_test_objects.proto
generated
vendored
57
vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/more_test_objects.proto
generated
vendored
|
@ -1,57 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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 Google 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.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package jsonpb;
|
||||
|
||||
message Simple3 {
|
||||
double dub = 1;
|
||||
}
|
||||
|
||||
enum Numeral {
|
||||
UNKNOWN = 0;
|
||||
ARABIC = 1;
|
||||
ROMAN = 2;
|
||||
}
|
||||
|
||||
message Mappy {
|
||||
map<int64, int32> nummy = 1;
|
||||
map<string, string> strry = 2;
|
||||
map<int32, Simple3> objjy = 3;
|
||||
map<int64, string> buggy = 4;
|
||||
map<bool, bool> booly = 5;
|
||||
map<string, Numeral> enumy = 6;
|
||||
map<int32, bool> s32booly = 7;
|
||||
map<int64, bool> s64booly = 8;
|
||||
map<uint32, bool> u32booly = 9;
|
||||
map<uint64, bool> u64booly = 10;
|
||||
}
|
739
vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/test_objects.pb.go
generated
vendored
739
vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/test_objects.pb.go
generated
vendored
|
@ -1,739 +0,0 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// source: test_objects.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
package jsonpb
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import google_protobuf "github.com/golang/protobuf/ptypes/any"
|
||||
import google_protobuf1 "github.com/golang/protobuf/ptypes/duration"
|
||||
import google_protobuf2 "github.com/golang/protobuf/ptypes/struct"
|
||||
import google_protobuf3 "github.com/golang/protobuf/ptypes/timestamp"
|
||||
import google_protobuf4 "github.com/golang/protobuf/ptypes/wrappers"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
type Widget_Color int32
|
||||
|
||||
const (
|
||||
Widget_RED Widget_Color = 0
|
||||
Widget_GREEN Widget_Color = 1
|
||||
Widget_BLUE Widget_Color = 2
|
||||
)
|
||||
|
||||
var Widget_Color_name = map[int32]string{
|
||||
0: "RED",
|
||||
1: "GREEN",
|
||||
2: "BLUE",
|
||||
}
|
||||
var Widget_Color_value = map[string]int32{
|
||||
"RED": 0,
|
||||
"GREEN": 1,
|
||||
"BLUE": 2,
|
||||
}
|
||||
|
||||
func (x Widget_Color) Enum() *Widget_Color {
|
||||
p := new(Widget_Color)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
func (x Widget_Color) String() string {
|
||||
return proto.EnumName(Widget_Color_name, int32(x))
|
||||
}
|
||||
func (x *Widget_Color) UnmarshalJSON(data []byte) error {
|
||||
value, err := proto.UnmarshalJSONEnum(Widget_Color_value, data, "Widget_Color")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*x = Widget_Color(value)
|
||||
return nil
|
||||
}
|
||||
func (Widget_Color) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{2, 0} }
|
||||
|
||||
// Test message for holding primitive types.
|
||||
type Simple struct {
|
||||
OBool *bool `protobuf:"varint,1,opt,name=o_bool,json=oBool" json:"o_bool,omitempty"`
|
||||
OInt32 *int32 `protobuf:"varint,2,opt,name=o_int32,json=oInt32" json:"o_int32,omitempty"`
|
||||
OInt64 *int64 `protobuf:"varint,3,opt,name=o_int64,json=oInt64" json:"o_int64,omitempty"`
|
||||
OUint32 *uint32 `protobuf:"varint,4,opt,name=o_uint32,json=oUint32" json:"o_uint32,omitempty"`
|
||||
OUint64 *uint64 `protobuf:"varint,5,opt,name=o_uint64,json=oUint64" json:"o_uint64,omitempty"`
|
||||
OSint32 *int32 `protobuf:"zigzag32,6,opt,name=o_sint32,json=oSint32" json:"o_sint32,omitempty"`
|
||||
OSint64 *int64 `protobuf:"zigzag64,7,opt,name=o_sint64,json=oSint64" json:"o_sint64,omitempty"`
|
||||
OFloat *float32 `protobuf:"fixed32,8,opt,name=o_float,json=oFloat" json:"o_float,omitempty"`
|
||||
ODouble *float64 `protobuf:"fixed64,9,opt,name=o_double,json=oDouble" json:"o_double,omitempty"`
|
||||
OString *string `protobuf:"bytes,10,opt,name=o_string,json=oString" json:"o_string,omitempty"`
|
||||
OBytes []byte `protobuf:"bytes,11,opt,name=o_bytes,json=oBytes" json:"o_bytes,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Simple) Reset() { *m = Simple{} }
|
||||
func (m *Simple) String() string { return proto.CompactTextString(m) }
|
||||
func (*Simple) ProtoMessage() {}
|
||||
func (*Simple) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
|
||||
|
||||
func (m *Simple) GetOBool() bool {
|
||||
if m != nil && m.OBool != nil {
|
||||
return *m.OBool
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *Simple) GetOInt32() int32 {
|
||||
if m != nil && m.OInt32 != nil {
|
||||
return *m.OInt32
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Simple) GetOInt64() int64 {
|
||||
if m != nil && m.OInt64 != nil {
|
||||
return *m.OInt64
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Simple) GetOUint32() uint32 {
|
||||
if m != nil && m.OUint32 != nil {
|
||||
return *m.OUint32
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Simple) GetOUint64() uint64 {
|
||||
if m != nil && m.OUint64 != nil {
|
||||
return *m.OUint64
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Simple) GetOSint32() int32 {
|
||||
if m != nil && m.OSint32 != nil {
|
||||
return *m.OSint32
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Simple) GetOSint64() int64 {
|
||||
if m != nil && m.OSint64 != nil {
|
||||
return *m.OSint64
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Simple) GetOFloat() float32 {
|
||||
if m != nil && m.OFloat != nil {
|
||||
return *m.OFloat
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Simple) GetODouble() float64 {
|
||||
if m != nil && m.ODouble != nil {
|
||||
return *m.ODouble
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Simple) GetOString() string {
|
||||
if m != nil && m.OString != nil {
|
||||
return *m.OString
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Simple) GetOBytes() []byte {
|
||||
if m != nil {
|
||||
return m.OBytes
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Test message for holding repeated primitives.
|
||||
type Repeats struct {
|
||||
RBool []bool `protobuf:"varint,1,rep,name=r_bool,json=rBool" json:"r_bool,omitempty"`
|
||||
RInt32 []int32 `protobuf:"varint,2,rep,name=r_int32,json=rInt32" json:"r_int32,omitempty"`
|
||||
RInt64 []int64 `protobuf:"varint,3,rep,name=r_int64,json=rInt64" json:"r_int64,omitempty"`
|
||||
RUint32 []uint32 `protobuf:"varint,4,rep,name=r_uint32,json=rUint32" json:"r_uint32,omitempty"`
|
||||
RUint64 []uint64 `protobuf:"varint,5,rep,name=r_uint64,json=rUint64" json:"r_uint64,omitempty"`
|
||||
RSint32 []int32 `protobuf:"zigzag32,6,rep,name=r_sint32,json=rSint32" json:"r_sint32,omitempty"`
|
||||
RSint64 []int64 `protobuf:"zigzag64,7,rep,name=r_sint64,json=rSint64" json:"r_sint64,omitempty"`
|
||||
RFloat []float32 `protobuf:"fixed32,8,rep,name=r_float,json=rFloat" json:"r_float,omitempty"`
|
||||
RDouble []float64 `protobuf:"fixed64,9,rep,name=r_double,json=rDouble" json:"r_double,omitempty"`
|
||||
RString []string `protobuf:"bytes,10,rep,name=r_string,json=rString" json:"r_string,omitempty"`
|
||||
RBytes [][]byte `protobuf:"bytes,11,rep,name=r_bytes,json=rBytes" json:"r_bytes,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Repeats) Reset() { *m = Repeats{} }
|
||||
func (m *Repeats) String() string { return proto.CompactTextString(m) }
|
||||
func (*Repeats) ProtoMessage() {}
|
||||
func (*Repeats) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} }
|
||||
|
||||
func (m *Repeats) GetRBool() []bool {
|
||||
if m != nil {
|
||||
return m.RBool
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Repeats) GetRInt32() []int32 {
|
||||
if m != nil {
|
||||
return m.RInt32
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Repeats) GetRInt64() []int64 {
|
||||
if m != nil {
|
||||
return m.RInt64
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Repeats) GetRUint32() []uint32 {
|
||||
if m != nil {
|
||||
return m.RUint32
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Repeats) GetRUint64() []uint64 {
|
||||
if m != nil {
|
||||
return m.RUint64
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Repeats) GetRSint32() []int32 {
|
||||
if m != nil {
|
||||
return m.RSint32
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Repeats) GetRSint64() []int64 {
|
||||
if m != nil {
|
||||
return m.RSint64
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Repeats) GetRFloat() []float32 {
|
||||
if m != nil {
|
||||
return m.RFloat
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Repeats) GetRDouble() []float64 {
|
||||
if m != nil {
|
||||
return m.RDouble
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Repeats) GetRString() []string {
|
||||
if m != nil {
|
||||
return m.RString
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Repeats) GetRBytes() [][]byte {
|
||||
if m != nil {
|
||||
return m.RBytes
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Test message for holding enums and nested messages.
|
||||
type Widget struct {
|
||||
Color *Widget_Color `protobuf:"varint,1,opt,name=color,enum=jsonpb.Widget_Color" json:"color,omitempty"`
|
||||
RColor []Widget_Color `protobuf:"varint,2,rep,name=r_color,json=rColor,enum=jsonpb.Widget_Color" json:"r_color,omitempty"`
|
||||
Simple *Simple `protobuf:"bytes,10,opt,name=simple" json:"simple,omitempty"`
|
||||
RSimple []*Simple `protobuf:"bytes,11,rep,name=r_simple,json=rSimple" json:"r_simple,omitempty"`
|
||||
Repeats *Repeats `protobuf:"bytes,20,opt,name=repeats" json:"repeats,omitempty"`
|
||||
RRepeats []*Repeats `protobuf:"bytes,21,rep,name=r_repeats,json=rRepeats" json:"r_repeats,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Widget) Reset() { *m = Widget{} }
|
||||
func (m *Widget) String() string { return proto.CompactTextString(m) }
|
||||
func (*Widget) ProtoMessage() {}
|
||||
func (*Widget) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} }
|
||||
|
||||
func (m *Widget) GetColor() Widget_Color {
|
||||
if m != nil && m.Color != nil {
|
||||
return *m.Color
|
||||
}
|
||||
return Widget_RED
|
||||
}
|
||||
|
||||
func (m *Widget) GetRColor() []Widget_Color {
|
||||
if m != nil {
|
||||
return m.RColor
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Widget) GetSimple() *Simple {
|
||||
if m != nil {
|
||||
return m.Simple
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Widget) GetRSimple() []*Simple {
|
||||
if m != nil {
|
||||
return m.RSimple
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Widget) GetRepeats() *Repeats {
|
||||
if m != nil {
|
||||
return m.Repeats
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Widget) GetRRepeats() []*Repeats {
|
||||
if m != nil {
|
||||
return m.RRepeats
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Maps struct {
|
||||
MInt64Str map[int64]string `protobuf:"bytes,1,rep,name=m_int64_str,json=mInt64Str" json:"m_int64_str,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
MBoolSimple map[bool]*Simple `protobuf:"bytes,2,rep,name=m_bool_simple,json=mBoolSimple" json:"m_bool_simple,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Maps) Reset() { *m = Maps{} }
|
||||
func (m *Maps) String() string { return proto.CompactTextString(m) }
|
||||
func (*Maps) ProtoMessage() {}
|
||||
func (*Maps) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} }
|
||||
|
||||
func (m *Maps) GetMInt64Str() map[int64]string {
|
||||
if m != nil {
|
||||
return m.MInt64Str
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Maps) GetMBoolSimple() map[bool]*Simple {
|
||||
if m != nil {
|
||||
return m.MBoolSimple
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type MsgWithOneof struct {
|
||||
// Types that are valid to be assigned to Union:
|
||||
// *MsgWithOneof_Title
|
||||
// *MsgWithOneof_Salary
|
||||
// *MsgWithOneof_Country
|
||||
Union isMsgWithOneof_Union `protobuf_oneof:"union"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *MsgWithOneof) Reset() { *m = MsgWithOneof{} }
|
||||
func (m *MsgWithOneof) String() string { return proto.CompactTextString(m) }
|
||||
func (*MsgWithOneof) ProtoMessage() {}
|
||||
func (*MsgWithOneof) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} }
|
||||
|
||||
type isMsgWithOneof_Union interface {
|
||||
isMsgWithOneof_Union()
|
||||
}
|
||||
|
||||
type MsgWithOneof_Title struct {
|
||||
Title string `protobuf:"bytes,1,opt,name=title,oneof"`
|
||||
}
|
||||
type MsgWithOneof_Salary struct {
|
||||
Salary int64 `protobuf:"varint,2,opt,name=salary,oneof"`
|
||||
}
|
||||
type MsgWithOneof_Country struct {
|
||||
Country string `protobuf:"bytes,3,opt,name=Country,json=country,oneof"`
|
||||
}
|
||||
|
||||
func (*MsgWithOneof_Title) isMsgWithOneof_Union() {}
|
||||
func (*MsgWithOneof_Salary) isMsgWithOneof_Union() {}
|
||||
func (*MsgWithOneof_Country) isMsgWithOneof_Union() {}
|
||||
|
||||
func (m *MsgWithOneof) GetUnion() isMsgWithOneof_Union {
|
||||
if m != nil {
|
||||
return m.Union
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MsgWithOneof) GetTitle() string {
|
||||
if x, ok := m.GetUnion().(*MsgWithOneof_Title); ok {
|
||||
return x.Title
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *MsgWithOneof) GetSalary() int64 {
|
||||
if x, ok := m.GetUnion().(*MsgWithOneof_Salary); ok {
|
||||
return x.Salary
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *MsgWithOneof) GetCountry() string {
|
||||
if x, ok := m.GetUnion().(*MsgWithOneof_Country); ok {
|
||||
return x.Country
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// XXX_OneofFuncs is for the internal use of the proto package.
|
||||
func (*MsgWithOneof) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
|
||||
return _MsgWithOneof_OneofMarshaler, _MsgWithOneof_OneofUnmarshaler, _MsgWithOneof_OneofSizer, []interface{}{
|
||||
(*MsgWithOneof_Title)(nil),
|
||||
(*MsgWithOneof_Salary)(nil),
|
||||
(*MsgWithOneof_Country)(nil),
|
||||
}
|
||||
}
|
||||
|
||||
func _MsgWithOneof_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
|
||||
m := msg.(*MsgWithOneof)
|
||||
// union
|
||||
switch x := m.Union.(type) {
|
||||
case *MsgWithOneof_Title:
|
||||
b.EncodeVarint(1<<3 | proto.WireBytes)
|
||||
b.EncodeStringBytes(x.Title)
|
||||
case *MsgWithOneof_Salary:
|
||||
b.EncodeVarint(2<<3 | proto.WireVarint)
|
||||
b.EncodeVarint(uint64(x.Salary))
|
||||
case *MsgWithOneof_Country:
|
||||
b.EncodeVarint(3<<3 | proto.WireBytes)
|
||||
b.EncodeStringBytes(x.Country)
|
||||
case nil:
|
||||
default:
|
||||
return fmt.Errorf("MsgWithOneof.Union has unexpected type %T", x)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func _MsgWithOneof_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
|
||||
m := msg.(*MsgWithOneof)
|
||||
switch tag {
|
||||
case 1: // union.title
|
||||
if wire != proto.WireBytes {
|
||||
return true, proto.ErrInternalBadWireType
|
||||
}
|
||||
x, err := b.DecodeStringBytes()
|
||||
m.Union = &MsgWithOneof_Title{x}
|
||||
return true, err
|
||||
case 2: // union.salary
|
||||
if wire != proto.WireVarint {
|
||||
return true, proto.ErrInternalBadWireType
|
||||
}
|
||||
x, err := b.DecodeVarint()
|
||||
m.Union = &MsgWithOneof_Salary{int64(x)}
|
||||
return true, err
|
||||
case 3: // union.Country
|
||||
if wire != proto.WireBytes {
|
||||
return true, proto.ErrInternalBadWireType
|
||||
}
|
||||
x, err := b.DecodeStringBytes()
|
||||
m.Union = &MsgWithOneof_Country{x}
|
||||
return true, err
|
||||
default:
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
func _MsgWithOneof_OneofSizer(msg proto.Message) (n int) {
|
||||
m := msg.(*MsgWithOneof)
|
||||
// union
|
||||
switch x := m.Union.(type) {
|
||||
case *MsgWithOneof_Title:
|
||||
n += proto.SizeVarint(1<<3 | proto.WireBytes)
|
||||
n += proto.SizeVarint(uint64(len(x.Title)))
|
||||
n += len(x.Title)
|
||||
case *MsgWithOneof_Salary:
|
||||
n += proto.SizeVarint(2<<3 | proto.WireVarint)
|
||||
n += proto.SizeVarint(uint64(x.Salary))
|
||||
case *MsgWithOneof_Country:
|
||||
n += proto.SizeVarint(3<<3 | proto.WireBytes)
|
||||
n += proto.SizeVarint(uint64(len(x.Country)))
|
||||
n += len(x.Country)
|
||||
case nil:
|
||||
default:
|
||||
panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
type Real struct {
|
||||
Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"`
|
||||
proto.XXX_InternalExtensions `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Real) Reset() { *m = Real{} }
|
||||
func (m *Real) String() string { return proto.CompactTextString(m) }
|
||||
func (*Real) ProtoMessage() {}
|
||||
func (*Real) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{5} }
|
||||
|
||||
var extRange_Real = []proto.ExtensionRange{
|
||||
{100, 536870911},
|
||||
}
|
||||
|
||||
func (*Real) ExtensionRangeArray() []proto.ExtensionRange {
|
||||
return extRange_Real
|
||||
}
|
||||
|
||||
func (m *Real) GetValue() float64 {
|
||||
if m != nil && m.Value != nil {
|
||||
return *m.Value
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Complex struct {
|
||||
Imaginary *float64 `protobuf:"fixed64,1,opt,name=imaginary" json:"imaginary,omitempty"`
|
||||
proto.XXX_InternalExtensions `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Complex) Reset() { *m = Complex{} }
|
||||
func (m *Complex) String() string { return proto.CompactTextString(m) }
|
||||
func (*Complex) ProtoMessage() {}
|
||||
func (*Complex) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{6} }
|
||||
|
||||
var extRange_Complex = []proto.ExtensionRange{
|
||||
{100, 536870911},
|
||||
}
|
||||
|
||||
func (*Complex) ExtensionRangeArray() []proto.ExtensionRange {
|
||||
return extRange_Complex
|
||||
}
|
||||
|
||||
func (m *Complex) GetImaginary() float64 {
|
||||
if m != nil && m.Imaginary != nil {
|
||||
return *m.Imaginary
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var E_Complex_RealExtension = &proto.ExtensionDesc{
|
||||
ExtendedType: (*Real)(nil),
|
||||
ExtensionType: (*Complex)(nil),
|
||||
Field: 123,
|
||||
Name: "jsonpb.Complex.real_extension",
|
||||
Tag: "bytes,123,opt,name=real_extension,json=realExtension",
|
||||
}
|
||||
|
||||
type KnownTypes struct {
|
||||
An *google_protobuf.Any `protobuf:"bytes,14,opt,name=an" json:"an,omitempty"`
|
||||
Dur *google_protobuf1.Duration `protobuf:"bytes,1,opt,name=dur" json:"dur,omitempty"`
|
||||
St *google_protobuf2.Struct `protobuf:"bytes,12,opt,name=st" json:"st,omitempty"`
|
||||
Ts *google_protobuf3.Timestamp `protobuf:"bytes,2,opt,name=ts" json:"ts,omitempty"`
|
||||
Dbl *google_protobuf4.DoubleValue `protobuf:"bytes,3,opt,name=dbl" json:"dbl,omitempty"`
|
||||
Flt *google_protobuf4.FloatValue `protobuf:"bytes,4,opt,name=flt" json:"flt,omitempty"`
|
||||
I64 *google_protobuf4.Int64Value `protobuf:"bytes,5,opt,name=i64" json:"i64,omitempty"`
|
||||
U64 *google_protobuf4.UInt64Value `protobuf:"bytes,6,opt,name=u64" json:"u64,omitempty"`
|
||||
I32 *google_protobuf4.Int32Value `protobuf:"bytes,7,opt,name=i32" json:"i32,omitempty"`
|
||||
U32 *google_protobuf4.UInt32Value `protobuf:"bytes,8,opt,name=u32" json:"u32,omitempty"`
|
||||
Bool *google_protobuf4.BoolValue `protobuf:"bytes,9,opt,name=bool" json:"bool,omitempty"`
|
||||
Str *google_protobuf4.StringValue `protobuf:"bytes,10,opt,name=str" json:"str,omitempty"`
|
||||
Bytes *google_protobuf4.BytesValue `protobuf:"bytes,11,opt,name=bytes" json:"bytes,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *KnownTypes) Reset() { *m = KnownTypes{} }
|
||||
func (m *KnownTypes) String() string { return proto.CompactTextString(m) }
|
||||
func (*KnownTypes) ProtoMessage() {}
|
||||
func (*KnownTypes) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{7} }
|
||||
|
||||
func (m *KnownTypes) GetAn() *google_protobuf.Any {
|
||||
if m != nil {
|
||||
return m.An
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetDur() *google_protobuf1.Duration {
|
||||
if m != nil {
|
||||
return m.Dur
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetSt() *google_protobuf2.Struct {
|
||||
if m != nil {
|
||||
return m.St
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetTs() *google_protobuf3.Timestamp {
|
||||
if m != nil {
|
||||
return m.Ts
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetDbl() *google_protobuf4.DoubleValue {
|
||||
if m != nil {
|
||||
return m.Dbl
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetFlt() *google_protobuf4.FloatValue {
|
||||
if m != nil {
|
||||
return m.Flt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetI64() *google_protobuf4.Int64Value {
|
||||
if m != nil {
|
||||
return m.I64
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetU64() *google_protobuf4.UInt64Value {
|
||||
if m != nil {
|
||||
return m.U64
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetI32() *google_protobuf4.Int32Value {
|
||||
if m != nil {
|
||||
return m.I32
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetU32() *google_protobuf4.UInt32Value {
|
||||
if m != nil {
|
||||
return m.U32
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetBool() *google_protobuf4.BoolValue {
|
||||
if m != nil {
|
||||
return m.Bool
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetStr() *google_protobuf4.StringValue {
|
||||
if m != nil {
|
||||
return m.Str
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *KnownTypes) GetBytes() *google_protobuf4.BytesValue {
|
||||
if m != nil {
|
||||
return m.Bytes
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var E_Name = &proto.ExtensionDesc{
|
||||
ExtendedType: (*Real)(nil),
|
||||
ExtensionType: (*string)(nil),
|
||||
Field: 124,
|
||||
Name: "jsonpb.name",
|
||||
Tag: "bytes,124,opt,name=name",
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Simple)(nil), "jsonpb.Simple")
|
||||
proto.RegisterType((*Repeats)(nil), "jsonpb.Repeats")
|
||||
proto.RegisterType((*Widget)(nil), "jsonpb.Widget")
|
||||
proto.RegisterType((*Maps)(nil), "jsonpb.Maps")
|
||||
proto.RegisterType((*MsgWithOneof)(nil), "jsonpb.MsgWithOneof")
|
||||
proto.RegisterType((*Real)(nil), "jsonpb.Real")
|
||||
proto.RegisterType((*Complex)(nil), "jsonpb.Complex")
|
||||
proto.RegisterType((*KnownTypes)(nil), "jsonpb.KnownTypes")
|
||||
proto.RegisterEnum("jsonpb.Widget_Color", Widget_Color_name, Widget_Color_value)
|
||||
proto.RegisterExtension(E_Complex_RealExtension)
|
||||
proto.RegisterExtension(E_Name)
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("test_objects.proto", fileDescriptor1) }
|
||||
|
||||
var fileDescriptor1 = []byte{
|
||||
// 1006 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x7c, 0x55, 0xdd, 0x72, 0xdb, 0x44,
|
||||
0x14, 0xae, 0xb5, 0x96, 0x65, 0xaf, 0x53, 0x63, 0x76, 0x52, 0xaa, 0x98, 0x00, 0x1d, 0x0f, 0x14,
|
||||
0x28, 0xe0, 0x0e, 0x6e, 0xa7, 0xc3, 0x14, 0x6e, 0x9a, 0xc6, 0xfc, 0x0c, 0xa4, 0xcc, 0x6c, 0x1a,
|
||||
0x7a, 0xe9, 0x91, 0x13, 0xc5, 0xa8, 0xc8, 0x5a, 0xcf, 0x6a, 0x45, 0xea, 0x81, 0x0b, 0x1e, 0x82,
|
||||
0x57, 0x80, 0x47, 0xe0, 0x89, 0x78, 0x10, 0xce, 0x39, 0x2b, 0x69, 0x1d, 0xbb, 0xa6, 0x37, 0xcd,
|
||||
0xd1, 0xf7, 0xe3, 0xa3, 0x6f, 0x8f, 0xce, 0x72, 0x61, 0xe2, 0xdc, 0x4c, 0xd5, 0xec, 0x65, 0x7c,
|
||||
0x6e, 0xf2, 0xd1, 0x52, 0x2b, 0xa3, 0x44, 0xeb, 0x65, 0xae, 0xb2, 0xe5, 0x6c, 0x70, 0x30, 0x57,
|
||||
0x6a, 0x9e, 0xc6, 0xf7, 0xe9, 0xe9, 0xac, 0xb8, 0xbc, 0x1f, 0x65, 0x2b, 0x4b, 0x19, 0xbc, 0xbb,
|
||||
0x09, 0x5d, 0x14, 0x3a, 0x32, 0x89, 0xca, 0x4a, 0xfc, 0x70, 0x13, 0xcf, 0x8d, 0x2e, 0xce, 0x4d,
|
||||
0x89, 0xbe, 0xb7, 0x89, 0x9a, 0x64, 0x01, 0x6d, 0x44, 0x8b, 0xe5, 0x2e, 0xfb, 0x2b, 0x1d, 0x2d,
|
||||
0x97, 0xb1, 0x2e, 0x3b, 0x1c, 0xfe, 0xe5, 0xf1, 0xd6, 0x69, 0xb2, 0x58, 0xa6, 0xb1, 0xb8, 0xc5,
|
||||
0x5b, 0x6a, 0x3a, 0x53, 0x2a, 0x0d, 0x1b, 0x77, 0x1a, 0x1f, 0xb5, 0xa5, 0xaf, 0x8e, 0xa0, 0x10,
|
||||
0xb7, 0x79, 0xa0, 0xa6, 0x49, 0x66, 0x1e, 0x8c, 0x43, 0x0f, 0x9e, 0xfb, 0xb2, 0xa5, 0xbe, 0xc3,
|
||||
0xaa, 0x06, 0x1e, 0x3d, 0x0c, 0x19, 0x00, 0xcc, 0x02, 0x8f, 0x1e, 0x8a, 0x03, 0xde, 0x56, 0xd3,
|
||||
0xc2, 0x4a, 0x9a, 0x80, 0xdc, 0x94, 0x81, 0x3a, 0xa3, 0xd2, 0x41, 0x20, 0xf2, 0x01, 0x6a, 0x96,
|
||||
0x50, 0xa5, 0xca, 0xad, 0xaa, 0x05, 0xd0, 0x9b, 0x00, 0x9d, 0xae, 0xa9, 0x72, 0xab, 0x0a, 0x00,
|
||||
0x12, 0x25, 0x04, 0x2a, 0x6a, 0xe2, 0x32, 0x55, 0x91, 0x09, 0xdb, 0x80, 0x78, 0xd0, 0xc4, 0xd7,
|
||||
0x58, 0x59, 0xcd, 0x85, 0x2a, 0x66, 0x69, 0x1c, 0x76, 0x00, 0x69, 0x80, 0xe6, 0x98, 0xca, 0xd2,
|
||||
0xce, 0xe8, 0x24, 0x9b, 0x87, 0x1c, 0xa0, 0x0e, 0xda, 0x51, 0x69, 0xed, 0x66, 0x2b, 0x38, 0xca,
|
||||
0xb0, 0x0b, 0xc8, 0x1e, 0xd8, 0x1d, 0x61, 0x35, 0xfc, 0xdb, 0xe3, 0x81, 0x8c, 0x97, 0x71, 0x64,
|
||||
0x72, 0x0c, 0x4a, 0x57, 0x41, 0x31, 0x0c, 0x4a, 0x57, 0x41, 0xe9, 0x3a, 0x28, 0x86, 0x41, 0xe9,
|
||||
0x3a, 0x28, 0x5d, 0x07, 0xc5, 0x30, 0x28, 0x5d, 0x07, 0xa5, 0x5d, 0x50, 0x0c, 0x83, 0xd2, 0x2e,
|
||||
0x28, 0xed, 0x82, 0x62, 0x18, 0x94, 0x76, 0x41, 0x69, 0x17, 0x14, 0xc3, 0xa0, 0xf4, 0xe9, 0x9a,
|
||||
0xaa, 0x0e, 0x8a, 0x61, 0x50, 0xda, 0x05, 0xa5, 0xeb, 0xa0, 0x18, 0x06, 0xa5, 0xeb, 0xa0, 0xb4,
|
||||
0x0b, 0x8a, 0x61, 0x50, 0xda, 0x05, 0xa5, 0x5d, 0x50, 0x0c, 0x83, 0xd2, 0x2e, 0x28, 0x5d, 0x07,
|
||||
0xc5, 0x30, 0x28, 0x6d, 0x83, 0xfa, 0x07, 0x06, 0xea, 0x45, 0x72, 0x31, 0x8f, 0x8d, 0xb8, 0xc7,
|
||||
0xfd, 0x73, 0x95, 0x2a, 0x4d, 0xf3, 0xd4, 0x1b, 0xef, 0x8f, 0xec, 0xd7, 0x30, 0xb2, 0xf0, 0xe8,
|
||||
0x29, 0x62, 0xd2, 0x52, 0xc4, 0x67, 0xe8, 0x67, 0xd9, 0x18, 0xde, 0x2e, 0x76, 0x4b, 0xd3, 0xff,
|
||||
0xe2, 0x2e, 0x6f, 0xe5, 0x34, 0xb5, 0x74, 0x80, 0xdd, 0x71, 0xaf, 0x62, 0xdb, 0x59, 0x96, 0x25,
|
||||
0x2a, 0x3e, 0xb6, 0x81, 0x10, 0x13, 0xfb, 0xdc, 0x66, 0x62, 0x40, 0x25, 0x35, 0xd0, 0xf6, 0x80,
|
||||
0xc3, 0x7d, 0xf2, 0x7c, 0xa3, 0x62, 0x96, 0xe7, 0x2e, 0x2b, 0x5c, 0x7c, 0xca, 0x3b, 0x7a, 0x5a,
|
||||
0x91, 0x6f, 0x91, 0xed, 0x16, 0xb9, 0xad, 0xcb, 0xbf, 0x86, 0x1f, 0x70, 0xdf, 0x36, 0x1d, 0x70,
|
||||
0x26, 0x27, 0xc7, 0xfd, 0x1b, 0xa2, 0xc3, 0xfd, 0x6f, 0xe4, 0x64, 0xf2, 0xac, 0xdf, 0x10, 0x6d,
|
||||
0xde, 0x3c, 0xfa, 0xe1, 0x6c, 0xd2, 0xf7, 0x86, 0x7f, 0x7a, 0xbc, 0x79, 0x12, 0x2d, 0x73, 0xf1,
|
||||
0x25, 0xef, 0x2e, 0xec, 0xb8, 0x60, 0xf6, 0x34, 0x63, 0xdd, 0xf1, 0xdb, 0x95, 0x3f, 0x52, 0x46,
|
||||
0x27, 0x34, 0x3f, 0x70, 0x14, 0x93, 0xcc, 0xe8, 0x95, 0xec, 0x2c, 0xaa, 0x5a, 0x3c, 0xe1, 0x37,
|
||||
0x17, 0x34, 0x9b, 0xd5, 0x5b, 0x7b, 0x24, 0x7f, 0xe7, 0xba, 0x1c, 0xe7, 0xd5, 0xbe, 0xb6, 0x35,
|
||||
0xe8, 0x2e, 0xdc, 0x93, 0xc1, 0x57, 0xbc, 0x77, 0xdd, 0x5f, 0xf4, 0x39, 0xfb, 0x25, 0x5e, 0xd1,
|
||||
0x31, 0x32, 0x89, 0x7f, 0x8a, 0x7d, 0xee, 0xff, 0x1a, 0xa5, 0x45, 0x4c, 0x2b, 0xa1, 0x23, 0x6d,
|
||||
0xf1, 0xd8, 0xfb, 0xa2, 0x31, 0x78, 0xc6, 0xfb, 0x9b, 0xf6, 0xeb, 0xfa, 0xb6, 0xd5, 0xbf, 0xbf,
|
||||
0xae, 0xdf, 0x3e, 0x14, 0xe7, 0x37, 0x8c, 0xf9, 0xde, 0x49, 0x3e, 0x7f, 0x91, 0x98, 0x9f, 0x7f,
|
||||
0xcc, 0x62, 0x75, 0x29, 0xde, 0xe2, 0xbe, 0x49, 0x0c, 0xbc, 0x18, 0xba, 0x75, 0xbe, 0xbd, 0x21,
|
||||
0x6d, 0x29, 0x42, 0x98, 0x88, 0x28, 0x8d, 0xf4, 0x8a, 0x2c, 0x19, 0x00, 0x65, 0x2d, 0x06, 0x3c,
|
||||
0x78, 0xaa, 0x0a, 0x6c, 0x84, 0xf6, 0x14, 0x6a, 0x82, 0x73, 0xfb, 0xe0, 0x28, 0xe0, 0x7e, 0x91,
|
||||
0xc1, 0xb2, 0x1d, 0xde, 0xe5, 0x4d, 0x19, 0x47, 0xa9, 0x7b, 0xb1, 0x06, 0xed, 0x0c, 0x5b, 0xdc,
|
||||
0x6b, 0xb7, 0x2f, 0xfa, 0x7f, 0xc0, 0x3f, 0x6f, 0x78, 0x85, 0x66, 0xd8, 0xe3, 0x2b, 0x71, 0xc8,
|
||||
0x3b, 0xc9, 0x22, 0x9a, 0x27, 0x19, 0xfe, 0xa8, 0xa5, 0xbb, 0x07, 0x4e, 0x32, 0x3e, 0xe6, 0x3d,
|
||||
0x0d, 0xd6, 0xd3, 0xf8, 0x95, 0x89, 0xb3, 0x1c, 0x7e, 0x4c, 0xec, 0xb9, 0x61, 0x89, 0xd2, 0xf0,
|
||||
0xb7, 0xeb, 0xd3, 0x56, 0xda, 0xcb, 0x9b, 0x28, 0x9a, 0x54, 0x9a, 0xe1, 0xbf, 0x4d, 0xce, 0xbf,
|
||||
0xcf, 0xd4, 0x55, 0xf6, 0x7c, 0xb5, 0x8c, 0x73, 0x08, 0xd0, 0x8b, 0xb2, 0xb0, 0x47, 0xd2, 0xfd,
|
||||
0x91, 0x5d, 0xf2, 0xa3, 0x6a, 0xc9, 0x8f, 0x9e, 0x64, 0x2b, 0x09, 0xb8, 0xf8, 0x84, 0x33, 0xb8,
|
||||
0x4e, 0xa8, 0xb9, 0xee, 0xf8, 0x60, 0x8b, 0x76, 0x5c, 0x5e, 0x35, 0x12, 0x59, 0xe2, 0x43, 0xee,
|
||||
0xe5, 0x26, 0xdc, 0x23, 0xee, 0xed, 0x2d, 0xee, 0x29, 0x5d, 0x3b, 0x12, 0x28, 0xf0, 0x5d, 0x7b,
|
||||
0x30, 0xf7, 0xf6, 0xe4, 0x06, 0x5b, 0xc4, 0xe7, 0xd5, 0x0d, 0x24, 0x81, 0x25, 0x46, 0xd0, 0xc1,
|
||||
0x2c, 0xa5, 0xe0, 0xbb, 0xe3, 0xc3, 0xed, 0x0e, 0x68, 0xd1, 0xfc, 0x84, 0x21, 0x4b, 0x24, 0xc2,
|
||||
0x1e, 0x60, 0x97, 0xa9, 0xa1, 0x6b, 0x03, 0x87, 0x7e, 0x93, 0x4f, 0x2b, 0xab, 0xa4, 0x03, 0x0f,
|
||||
0xe9, 0x49, 0x79, 0x95, 0xbc, 0x8e, 0x4e, 0x63, 0x5c, 0xd2, 0x81, 0x87, 0xdd, 0x14, 0x40, 0x6f,
|
||||
0xed, 0xe8, 0xe6, 0x6c, 0x9d, 0x0f, 0x44, 0xb2, 0x87, 0x2d, 0x1b, 0xec, 0xb6, 0x7f, 0x30, 0xae,
|
||||
0xec, 0x61, 0xfd, 0xa2, 0x3d, 0xd0, 0xdb, 0xff, 0x63, 0x5f, 0xf3, 0x0b, 0xe2, 0x37, 0xe9, 0x1a,
|
||||
0xe9, 0xec, 0x88, 0x12, 0xbf, 0x23, 0x4b, 0x27, 0x1e, 0xfa, 0xe3, 0x46, 0xe0, 0x3b, 0xfc, 0xed,
|
||||
0x6a, 0x2e, 0xfd, 0x81, 0x28, 0x3e, 0xe7, 0xbe, 0xbb, 0xcb, 0x5e, 0xf7, 0x02, 0xb4, 0xb2, 0xad,
|
||||
0xc0, 0x32, 0x1f, 0xdf, 0xe1, 0xcd, 0x2c, 0x5a, 0xc4, 0x1b, 0x23, 0xfa, 0x3b, 0x7d, 0xe5, 0x84,
|
||||
0xfc, 0x17, 0x00, 0x00, 0xff, 0xff, 0xca, 0xa2, 0x76, 0x34, 0xe8, 0x08, 0x00, 0x00,
|
||||
}
|
134
vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/test_objects.proto
generated
vendored
134
vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/test_objects.proto
generated
vendored
|
@ -1,134 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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 Google 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.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
import "google/protobuf/struct.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/protobuf/wrappers.proto";
|
||||
|
||||
package jsonpb;
|
||||
|
||||
// Test message for holding primitive types.
|
||||
message Simple {
|
||||
optional bool o_bool = 1;
|
||||
optional int32 o_int32 = 2;
|
||||
optional int64 o_int64 = 3;
|
||||
optional uint32 o_uint32 = 4;
|
||||
optional uint64 o_uint64 = 5;
|
||||
optional sint32 o_sint32 = 6;
|
||||
optional sint64 o_sint64 = 7;
|
||||
optional float o_float = 8;
|
||||
optional double o_double = 9;
|
||||
optional string o_string = 10;
|
||||
optional bytes o_bytes = 11;
|
||||
}
|
||||
|
||||
// Test message for holding repeated primitives.
|
||||
message Repeats {
|
||||
repeated bool r_bool = 1;
|
||||
repeated int32 r_int32 = 2;
|
||||
repeated int64 r_int64 = 3;
|
||||
repeated uint32 r_uint32 = 4;
|
||||
repeated uint64 r_uint64 = 5;
|
||||
repeated sint32 r_sint32 = 6;
|
||||
repeated sint64 r_sint64 = 7;
|
||||
repeated float r_float = 8;
|
||||
repeated double r_double = 9;
|
||||
repeated string r_string = 10;
|
||||
repeated bytes r_bytes = 11;
|
||||
}
|
||||
|
||||
// Test message for holding enums and nested messages.
|
||||
message Widget {
|
||||
enum Color {
|
||||
RED = 0;
|
||||
GREEN = 1;
|
||||
BLUE = 2;
|
||||
};
|
||||
optional Color color = 1;
|
||||
repeated Color r_color = 2;
|
||||
|
||||
optional Simple simple = 10;
|
||||
repeated Simple r_simple = 11;
|
||||
|
||||
optional Repeats repeats = 20;
|
||||
repeated Repeats r_repeats = 21;
|
||||
}
|
||||
|
||||
message Maps {
|
||||
map<int64, string> m_int64_str = 1;
|
||||
map<bool, Simple> m_bool_simple = 2;
|
||||
}
|
||||
|
||||
message MsgWithOneof {
|
||||
oneof union {
|
||||
string title = 1;
|
||||
int64 salary = 2;
|
||||
string Country = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message Real {
|
||||
optional double value = 1;
|
||||
extensions 100 to max;
|
||||
}
|
||||
|
||||
extend Real {
|
||||
optional string name = 124;
|
||||
}
|
||||
|
||||
message Complex {
|
||||
extend Real {
|
||||
optional Complex real_extension = 123;
|
||||
}
|
||||
optional double imaginary = 1;
|
||||
extensions 100 to max;
|
||||
}
|
||||
|
||||
message KnownTypes {
|
||||
optional google.protobuf.Any an = 14;
|
||||
optional google.protobuf.Duration dur = 1;
|
||||
optional google.protobuf.Struct st = 12;
|
||||
optional google.protobuf.Timestamp ts = 2;
|
||||
|
||||
optional google.protobuf.DoubleValue dbl = 3;
|
||||
optional google.protobuf.FloatValue flt = 4;
|
||||
optional google.protobuf.Int64Value i64 = 5;
|
||||
optional google.protobuf.UInt64Value u64 = 6;
|
||||
optional google.protobuf.Int32Value i32 = 7;
|
||||
optional google.protobuf.UInt32Value u32 = 8;
|
||||
optional google.protobuf.BoolValue bool = 9;
|
||||
optional google.protobuf.StringValue str = 10;
|
||||
optional google.protobuf.BytesValue bytes = 11;
|
||||
}
|
199
vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go
generated
vendored
199
vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go
generated
vendored
|
@ -1,199 +0,0 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// source: proto3_proto/proto3.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package proto3_proto is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
proto3_proto/proto3.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Message
|
||||
Nested
|
||||
MessageWithMap
|
||||
*/
|
||||
package proto3_proto
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import google_protobuf "github.com/golang/protobuf/ptypes/any"
|
||||
import testdata "github.com/golang/protobuf/proto/testdata"
|
||||
|
||||
// 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.
|
||||
const _ = proto.ProtoPackageIsVersion1
|
||||
|
||||
type Message_Humour int32
|
||||
|
||||
const (
|
||||
Message_UNKNOWN Message_Humour = 0
|
||||
Message_PUNS Message_Humour = 1
|
||||
Message_SLAPSTICK Message_Humour = 2
|
||||
Message_BILL_BAILEY Message_Humour = 3
|
||||
)
|
||||
|
||||
var Message_Humour_name = map[int32]string{
|
||||
0: "UNKNOWN",
|
||||
1: "PUNS",
|
||||
2: "SLAPSTICK",
|
||||
3: "BILL_BAILEY",
|
||||
}
|
||||
var Message_Humour_value = map[string]int32{
|
||||
"UNKNOWN": 0,
|
||||
"PUNS": 1,
|
||||
"SLAPSTICK": 2,
|
||||
"BILL_BAILEY": 3,
|
||||
}
|
||||
|
||||
func (x Message_Humour) String() string {
|
||||
return proto.EnumName(Message_Humour_name, int32(x))
|
||||
}
|
||||
func (Message_Humour) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} }
|
||||
|
||||
type Message struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
Hilarity Message_Humour `protobuf:"varint,2,opt,name=hilarity,enum=proto3_proto.Message_Humour" json:"hilarity,omitempty"`
|
||||
HeightInCm uint32 `protobuf:"varint,3,opt,name=height_in_cm,json=heightInCm" json:"height_in_cm,omitempty"`
|
||||
Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
|
||||
ResultCount int64 `protobuf:"varint,7,opt,name=result_count,json=resultCount" json:"result_count,omitempty"`
|
||||
TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman,json=trueScotsman" json:"true_scotsman,omitempty"`
|
||||
Score float32 `protobuf:"fixed32,9,opt,name=score" json:"score,omitempty"`
|
||||
Key []uint64 `protobuf:"varint,5,rep,name=key" json:"key,omitempty"`
|
||||
Nested *Nested `protobuf:"bytes,6,opt,name=nested" json:"nested,omitempty"`
|
||||
RFunny []Message_Humour `protobuf:"varint,16,rep,name=r_funny,json=rFunny,enum=proto3_proto.Message_Humour" json:"r_funny,omitempty"`
|
||||
Terrain map[string]*Nested `protobuf:"bytes,10,rep,name=terrain" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
Proto2Field *testdata.SubDefaults `protobuf:"bytes,11,opt,name=proto2_field,json=proto2Field" json:"proto2_field,omitempty"`
|
||||
Proto2Value map[string]*testdata.SubDefaults `protobuf:"bytes,13,rep,name=proto2_value,json=proto2Value" json:"proto2_value,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
Anything *google_protobuf.Any `protobuf:"bytes,14,opt,name=anything" json:"anything,omitempty"`
|
||||
ManyThings []*google_protobuf.Any `protobuf:"bytes,15,rep,name=many_things,json=manyThings" json:"many_things,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Message) Reset() { *m = Message{} }
|
||||
func (m *Message) String() string { return proto.CompactTextString(m) }
|
||||
func (*Message) ProtoMessage() {}
|
||||
func (*Message) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func (m *Message) GetNested() *Nested {
|
||||
if m != nil {
|
||||
return m.Nested
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetTerrain() map[string]*Nested {
|
||||
if m != nil {
|
||||
return m.Terrain
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetProto2Field() *testdata.SubDefaults {
|
||||
if m != nil {
|
||||
return m.Proto2Field
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetProto2Value() map[string]*testdata.SubDefaults {
|
||||
if m != nil {
|
||||
return m.Proto2Value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetAnything() *google_protobuf.Any {
|
||||
if m != nil {
|
||||
return m.Anything
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Message) GetManyThings() []*google_protobuf.Any {
|
||||
if m != nil {
|
||||
return m.ManyThings
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Nested struct {
|
||||
Bunny string `protobuf:"bytes,1,opt,name=bunny" json:"bunny,omitempty"`
|
||||
Cute bool `protobuf:"varint,2,opt,name=cute" json:"cute,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Nested) Reset() { *m = Nested{} }
|
||||
func (m *Nested) String() string { return proto.CompactTextString(m) }
|
||||
func (*Nested) ProtoMessage() {}
|
||||
func (*Nested) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
type MessageWithMap struct {
|
||||
ByteMapping map[bool][]byte `protobuf:"bytes,1,rep,name=byte_mapping,json=byteMapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
}
|
||||
|
||||
func (m *MessageWithMap) Reset() { *m = MessageWithMap{} }
|
||||
func (m *MessageWithMap) String() string { return proto.CompactTextString(m) }
|
||||
func (*MessageWithMap) ProtoMessage() {}
|
||||
func (*MessageWithMap) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
|
||||
func (m *MessageWithMap) GetByteMapping() map[bool][]byte {
|
||||
if m != nil {
|
||||
return m.ByteMapping
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Message)(nil), "proto3_proto.Message")
|
||||
proto.RegisterType((*Nested)(nil), "proto3_proto.Nested")
|
||||
proto.RegisterType((*MessageWithMap)(nil), "proto3_proto.MessageWithMap")
|
||||
proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value)
|
||||
}
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 621 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x53, 0x5b, 0x6f, 0xd3, 0x4c,
|
||||
0x10, 0xfd, 0x72, 0xa9, 0xe3, 0x8e, 0x9d, 0xd6, 0xda, 0xaf, 0x48, 0xdb, 0x88, 0x87, 0x12, 0x24,
|
||||
0x54, 0x71, 0x71, 0x51, 0x10, 0x52, 0x85, 0x10, 0xa8, 0x2d, 0xad, 0x88, 0x9a, 0x86, 0x68, 0xd3,
|
||||
0x52, 0xf1, 0x64, 0xad, 0xd3, 0x4d, 0x62, 0x11, 0xaf, 0x23, 0x7b, 0x8d, 0xe4, 0xbf, 0xc3, 0xaf,
|
||||
0xe4, 0x91, 0xbd, 0x38, 0xad, 0x5b, 0x05, 0x78, 0xf2, 0xee, 0xcc, 0x39, 0x33, 0xb3, 0xe7, 0x8c,
|
||||
0x61, 0x77, 0x99, 0x26, 0x22, 0x79, 0x13, 0xe8, 0xcf, 0x81, 0xb9, 0xf8, 0xfa, 0x83, 0xdc, 0x6a,
|
||||
0xaa, 0xb3, 0x3b, 0x4b, 0x92, 0xd9, 0x82, 0x19, 0x48, 0x98, 0x4f, 0x0f, 0x28, 0x2f, 0x0c, 0xb0,
|
||||
0xf3, 0xbf, 0x60, 0x99, 0xb8, 0xa1, 0x82, 0x1e, 0xa8, 0x83, 0x09, 0x76, 0x7f, 0x59, 0xd0, 0xba,
|
||||
0x60, 0x59, 0x46, 0x67, 0x0c, 0x21, 0x68, 0x72, 0x1a, 0x33, 0x5c, 0xdb, 0xab, 0xed, 0x6f, 0x12,
|
||||
0x7d, 0x46, 0x87, 0x60, 0xcf, 0xa3, 0x05, 0x4d, 0x23, 0x51, 0xe0, 0xba, 0x8c, 0x6f, 0xf5, 0x1e,
|
||||
0xfb, 0xd5, 0x86, 0x7e, 0x49, 0xf6, 0x3f, 0xe7, 0x71, 0x92, 0xa7, 0xe4, 0x16, 0x8d, 0xf6, 0xc0,
|
||||
0x9d, 0xb3, 0x68, 0x36, 0x17, 0x41, 0xc4, 0x83, 0x49, 0x8c, 0x1b, 0x92, 0xdd, 0x26, 0x60, 0x62,
|
||||
0x7d, 0x7e, 0x12, 0xab, 0x7e, 0x6a, 0x1c, 0xdc, 0x94, 0x19, 0x97, 0xe8, 0x33, 0x7a, 0x02, 0x6e,
|
||||
0xca, 0xb2, 0x7c, 0x21, 0x82, 0x49, 0x92, 0x73, 0x81, 0x5b, 0x32, 0xd7, 0x20, 0x8e, 0x89, 0x9d,
|
||||
0xa8, 0x10, 0x7a, 0x0a, 0x6d, 0x91, 0xe6, 0x2c, 0xc8, 0x26, 0x89, 0xc8, 0x62, 0xca, 0xb1, 0x2d,
|
||||
0x31, 0x36, 0x71, 0x55, 0x70, 0x5c, 0xc6, 0xd0, 0x0e, 0x6c, 0xc8, 0x7c, 0xca, 0xf0, 0xa6, 0x4c,
|
||||
0xd6, 0x89, 0xb9, 0x20, 0x0f, 0x1a, 0xdf, 0x59, 0x81, 0x37, 0xf6, 0x1a, 0xfb, 0x4d, 0xa2, 0x8e,
|
||||
0xe8, 0x25, 0x58, 0x5c, 0xaa, 0xc1, 0x6e, 0xb0, 0x25, 0x81, 0x4e, 0x6f, 0xe7, 0xfe, 0xeb, 0x86,
|
||||
0x3a, 0x47, 0x4a, 0x0c, 0x7a, 0x0b, 0xad, 0x34, 0x98, 0xe6, 0x9c, 0x17, 0xd8, 0x93, 0x35, 0xfe,
|
||||
0x25, 0x86, 0x95, 0x9e, 0x29, 0x2c, 0x7a, 0x0f, 0x2d, 0xc1, 0xd2, 0x94, 0x46, 0x1c, 0x83, 0xa4,
|
||||
0x39, 0xbd, 0xee, 0x7a, 0xda, 0xa5, 0x01, 0x9d, 0x72, 0x91, 0x16, 0x64, 0x45, 0x91, 0x16, 0x18,
|
||||
0x8b, 0x7b, 0xc1, 0x34, 0x62, 0x8b, 0x1b, 0xec, 0xe8, 0x41, 0x1f, 0xf9, 0x2b, 0x3b, 0xfd, 0x71,
|
||||
0x1e, 0x7e, 0x62, 0x53, 0x2a, 0x05, 0xca, 0x88, 0x63, 0xa0, 0x67, 0x0a, 0x89, 0xfa, 0xb7, 0xcc,
|
||||
0x1f, 0x74, 0x91, 0x33, 0xdc, 0xd6, 0xcd, 0x9f, 0xad, 0x6f, 0x3e, 0xd2, 0xc8, 0xaf, 0x0a, 0x68,
|
||||
0x06, 0x28, 0x4b, 0xe9, 0x08, 0x7a, 0x0d, 0xb6, 0xdc, 0x24, 0x31, 0x8f, 0xf8, 0x0c, 0x6f, 0x95,
|
||||
0x4a, 0x99, 0x55, 0xf3, 0x57, 0xab, 0xe6, 0x1f, 0xf1, 0x82, 0xdc, 0xa2, 0xa4, 0x56, 0x8e, 0x34,
|
||||
0xa2, 0x08, 0xf4, 0x2d, 0xc3, 0xdb, 0xba, 0xf7, 0x7a, 0x12, 0x28, 0xe0, 0xa5, 0xc6, 0x75, 0x46,
|
||||
0xe0, 0x56, 0x65, 0x58, 0x59, 0x66, 0x76, 0x52, 0x5b, 0xf6, 0x1c, 0x36, 0xcc, 0x73, 0xea, 0x7f,
|
||||
0x71, 0xcc, 0x40, 0xde, 0xd5, 0x0f, 0x6b, 0x9d, 0x2b, 0xf0, 0x1e, 0xbe, 0x6d, 0x4d, 0xd5, 0x17,
|
||||
0xf7, 0xab, 0xfe, 0x41, 0xde, 0xbb, 0xb2, 0xdd, 0x8f, 0x60, 0x19, 0x9b, 0x91, 0x03, 0xad, 0xab,
|
||||
0xe1, 0xf9, 0xf0, 0xcb, 0xf5, 0xd0, 0xfb, 0x0f, 0xd9, 0xd0, 0x1c, 0x5d, 0x0d, 0xc7, 0x5e, 0x0d,
|
||||
0xb5, 0x61, 0x73, 0x3c, 0x38, 0x1a, 0x8d, 0x2f, 0xfb, 0x27, 0xe7, 0x5e, 0x1d, 0x6d, 0x83, 0x73,
|
||||
0xdc, 0x1f, 0x0c, 0x82, 0xe3, 0xa3, 0xfe, 0xe0, 0xf4, 0x9b, 0xd7, 0xe8, 0xf6, 0xc0, 0x32, 0xc3,
|
||||
0xaa, 0x65, 0x0d, 0xf5, 0x52, 0x99, 0x79, 0xcc, 0x45, 0xfd, 0x1e, 0x93, 0x5c, 0x98, 0x81, 0x6c,
|
||||
0xa2, 0xcf, 0xdd, 0x9f, 0x35, 0xd8, 0x2a, 0x0d, 0xbb, 0x8e, 0xc4, 0xfc, 0x82, 0x2e, 0x91, 0x14,
|
||||
0x2c, 0x2c, 0x04, 0x0b, 0x62, 0xba, 0x5c, 0x2a, 0x77, 0x6a, 0x5a, 0xe8, 0x57, 0x6b, 0x4d, 0x2e,
|
||||
0x39, 0xfe, 0xb1, 0x24, 0x5c, 0x18, 0x7c, 0xe9, 0x75, 0x78, 0x17, 0xe9, 0x7c, 0x00, 0xef, 0x21,
|
||||
0xa0, 0x2a, 0x98, 0x6d, 0x04, 0xdb, 0xa9, 0x0a, 0xe6, 0x56, 0x94, 0x09, 0x2d, 0xd3, 0xfa, 0x77,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0xc9, 0x75, 0x36, 0xb5, 0x04, 0x00, 0x00,
|
||||
}
|
74
vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.proto
generated
vendored
74
vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.proto
generated
vendored
|
@ -1,74 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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 Google 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.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "testdata/test.proto";
|
||||
|
||||
package proto3_proto;
|
||||
|
||||
message Message {
|
||||
enum Humour {
|
||||
UNKNOWN = 0;
|
||||
PUNS = 1;
|
||||
SLAPSTICK = 2;
|
||||
BILL_BAILEY = 3;
|
||||
}
|
||||
|
||||
string name = 1;
|
||||
Humour hilarity = 2;
|
||||
uint32 height_in_cm = 3;
|
||||
bytes data = 4;
|
||||
int64 result_count = 7;
|
||||
bool true_scotsman = 8;
|
||||
float score = 9;
|
||||
|
||||
repeated uint64 key = 5;
|
||||
Nested nested = 6;
|
||||
repeated Humour r_funny = 16;
|
||||
|
||||
map<string, Nested> terrain = 10;
|
||||
testdata.SubDefaults proto2_field = 11;
|
||||
map<string, testdata.SubDefaults> proto2_value = 13;
|
||||
|
||||
google.protobuf.Any anything = 14;
|
||||
repeated google.protobuf.Any many_things = 15;
|
||||
}
|
||||
|
||||
message Nested {
|
||||
string bunny = 1;
|
||||
bool cute = 2;
|
||||
}
|
||||
|
||||
message MessageWithMap {
|
||||
map<bool, bytes> byte_mapping = 1;
|
||||
}
|
50
vendor/github.com/golang/protobuf/proto/testdata/Makefile
generated
vendored
50
vendor/github.com/golang/protobuf/proto/testdata/Makefile
generated
vendored
|
@ -1,50 +0,0 @@
|
|||
# Go support for Protocol Buffers - Google's data interchange format
|
||||
#
|
||||
# Copyright 2010 The Go Authors. All rights reserved.
|
||||
# https://github.com/golang/protobuf
|
||||
#
|
||||
# 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 Google 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.
|
||||
|
||||
|
||||
include ../../Make.protobuf
|
||||
|
||||
all: regenerate
|
||||
|
||||
regenerate:
|
||||
rm -f test.pb.go
|
||||
make test.pb.go
|
||||
|
||||
# The following rules are just aids to development. Not needed for typical testing.
|
||||
|
||||
diff: regenerate
|
||||
git diff test.pb.go
|
||||
|
||||
restore:
|
||||
cp test.pb.go.golden test.pb.go
|
||||
|
||||
preserve:
|
||||
cp test.pb.go test.pb.go.golden
|
86
vendor/github.com/golang/protobuf/proto/testdata/golden_test.go
generated
vendored
86
vendor/github.com/golang/protobuf/proto/testdata/golden_test.go
generated
vendored
|
@ -1,86 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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 Google 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.
|
||||
|
||||
// Verify that the compiler output for test.proto is unchanged.
|
||||
|
||||
package testdata
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// sum returns in string form (for easy comparison) the SHA-1 hash of the named file.
|
||||
func sum(t *testing.T, name string) string {
|
||||
data, err := ioutil.ReadFile(name)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("sum(%q): length is %d", name, len(data))
|
||||
hash := sha1.New()
|
||||
_, err = hash.Write(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return fmt.Sprintf("% x", hash.Sum(nil))
|
||||
}
|
||||
|
||||
func run(t *testing.T, name string, args ...string) {
|
||||
cmd := exec.Command(name, args...)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGolden(t *testing.T) {
|
||||
// Compute the original checksum.
|
||||
goldenSum := sum(t, "test.pb.go")
|
||||
// Run the proto compiler.
|
||||
run(t, "protoc", "--go_out="+os.TempDir(), "test.proto")
|
||||
newFile := filepath.Join(os.TempDir(), "test.pb.go")
|
||||
defer os.Remove(newFile)
|
||||
// Compute the new checksum.
|
||||
newSum := sum(t, newFile)
|
||||
// Verify
|
||||
if newSum != goldenSum {
|
||||
run(t, "diff", "-u", "test.pb.go", newFile)
|
||||
t.Fatal("Code generated by protoc-gen-go has changed; update test.pb.go")
|
||||
}
|
||||
}
|
4056
vendor/github.com/golang/protobuf/proto/testdata/test.pb.go
generated
vendored
4056
vendor/github.com/golang/protobuf/proto/testdata/test.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
548
vendor/github.com/golang/protobuf/proto/testdata/test.proto
generated
vendored
548
vendor/github.com/golang/protobuf/proto/testdata/test.proto
generated
vendored
|
@ -1,548 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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 Google 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.
|
||||
|
||||
// A feature-rich test file for the protocol compiler and libraries.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package testdata;
|
||||
|
||||
enum FOO { FOO1 = 1; };
|
||||
|
||||
message GoEnum {
|
||||
required FOO foo = 1;
|
||||
}
|
||||
|
||||
message GoTestField {
|
||||
required string Label = 1;
|
||||
required string Type = 2;
|
||||
}
|
||||
|
||||
message GoTest {
|
||||
// An enum, for completeness.
|
||||
enum KIND {
|
||||
VOID = 0;
|
||||
|
||||
// Basic types
|
||||
BOOL = 1;
|
||||
BYTES = 2;
|
||||
FINGERPRINT = 3;
|
||||
FLOAT = 4;
|
||||
INT = 5;
|
||||
STRING = 6;
|
||||
TIME = 7;
|
||||
|
||||
// Groupings
|
||||
TUPLE = 8;
|
||||
ARRAY = 9;
|
||||
MAP = 10;
|
||||
|
||||
// Table types
|
||||
TABLE = 11;
|
||||
|
||||
// Functions
|
||||
FUNCTION = 12; // last tag
|
||||
};
|
||||
|
||||
// Some typical parameters
|
||||
required KIND Kind = 1;
|
||||
optional string Table = 2;
|
||||
optional int32 Param = 3;
|
||||
|
||||
// Required, repeated and optional foreign fields.
|
||||
required GoTestField RequiredField = 4;
|
||||
repeated GoTestField RepeatedField = 5;
|
||||
optional GoTestField OptionalField = 6;
|
||||
|
||||
// Required fields of all basic types
|
||||
required bool F_Bool_required = 10;
|
||||
required int32 F_Int32_required = 11;
|
||||
required int64 F_Int64_required = 12;
|
||||
required fixed32 F_Fixed32_required = 13;
|
||||
required fixed64 F_Fixed64_required = 14;
|
||||
required uint32 F_Uint32_required = 15;
|
||||
required uint64 F_Uint64_required = 16;
|
||||
required float F_Float_required = 17;
|
||||
required double F_Double_required = 18;
|
||||
required string F_String_required = 19;
|
||||
required bytes F_Bytes_required = 101;
|
||||
required sint32 F_Sint32_required = 102;
|
||||
required sint64 F_Sint64_required = 103;
|
||||
|
||||
// Repeated fields of all basic types
|
||||
repeated bool F_Bool_repeated = 20;
|
||||
repeated int32 F_Int32_repeated = 21;
|
||||
repeated int64 F_Int64_repeated = 22;
|
||||
repeated fixed32 F_Fixed32_repeated = 23;
|
||||
repeated fixed64 F_Fixed64_repeated = 24;
|
||||
repeated uint32 F_Uint32_repeated = 25;
|
||||
repeated uint64 F_Uint64_repeated = 26;
|
||||
repeated float F_Float_repeated = 27;
|
||||
repeated double F_Double_repeated = 28;
|
||||
repeated string F_String_repeated = 29;
|
||||
repeated bytes F_Bytes_repeated = 201;
|
||||
repeated sint32 F_Sint32_repeated = 202;
|
||||
repeated sint64 F_Sint64_repeated = 203;
|
||||
|
||||
// Optional fields of all basic types
|
||||
optional bool F_Bool_optional = 30;
|
||||
optional int32 F_Int32_optional = 31;
|
||||
optional int64 F_Int64_optional = 32;
|
||||
optional fixed32 F_Fixed32_optional = 33;
|
||||
optional fixed64 F_Fixed64_optional = 34;
|
||||
optional uint32 F_Uint32_optional = 35;
|
||||
optional uint64 F_Uint64_optional = 36;
|
||||
optional float F_Float_optional = 37;
|
||||
optional double F_Double_optional = 38;
|
||||
optional string F_String_optional = 39;
|
||||
optional bytes F_Bytes_optional = 301;
|
||||
optional sint32 F_Sint32_optional = 302;
|
||||
optional sint64 F_Sint64_optional = 303;
|
||||
|
||||
// Default-valued fields of all basic types
|
||||
optional bool F_Bool_defaulted = 40 [default=true];
|
||||
optional int32 F_Int32_defaulted = 41 [default=32];
|
||||
optional int64 F_Int64_defaulted = 42 [default=64];
|
||||
optional fixed32 F_Fixed32_defaulted = 43 [default=320];
|
||||
optional fixed64 F_Fixed64_defaulted = 44 [default=640];
|
||||
optional uint32 F_Uint32_defaulted = 45 [default=3200];
|
||||
optional uint64 F_Uint64_defaulted = 46 [default=6400];
|
||||
optional float F_Float_defaulted = 47 [default=314159.];
|
||||
optional double F_Double_defaulted = 48 [default=271828.];
|
||||
optional string F_String_defaulted = 49 [default="hello, \"world!\"\n"];
|
||||
optional bytes F_Bytes_defaulted = 401 [default="Bignose"];
|
||||
optional sint32 F_Sint32_defaulted = 402 [default = -32];
|
||||
optional sint64 F_Sint64_defaulted = 403 [default = -64];
|
||||
|
||||
// Packed repeated fields (no string or bytes).
|
||||
repeated bool F_Bool_repeated_packed = 50 [packed=true];
|
||||
repeated int32 F_Int32_repeated_packed = 51 [packed=true];
|
||||
repeated int64 F_Int64_repeated_packed = 52 [packed=true];
|
||||
repeated fixed32 F_Fixed32_repeated_packed = 53 [packed=true];
|
||||
repeated fixed64 F_Fixed64_repeated_packed = 54 [packed=true];
|
||||
repeated uint32 F_Uint32_repeated_packed = 55 [packed=true];
|
||||
repeated uint64 F_Uint64_repeated_packed = 56 [packed=true];
|
||||
repeated float F_Float_repeated_packed = 57 [packed=true];
|
||||
repeated double F_Double_repeated_packed = 58 [packed=true];
|
||||
repeated sint32 F_Sint32_repeated_packed = 502 [packed=true];
|
||||
repeated sint64 F_Sint64_repeated_packed = 503 [packed=true];
|
||||
|
||||
// Required, repeated, and optional groups.
|
||||
required group RequiredGroup = 70 {
|
||||
required string RequiredField = 71;
|
||||
};
|
||||
|
||||
repeated group RepeatedGroup = 80 {
|
||||
required string RequiredField = 81;
|
||||
};
|
||||
|
||||
optional group OptionalGroup = 90 {
|
||||
required string RequiredField = 91;
|
||||
};
|
||||
}
|
||||
|
||||
// For testing a group containing a required field.
|
||||
message GoTestRequiredGroupField {
|
||||
required group Group = 1 {
|
||||
required int32 Field = 2;
|
||||
};
|
||||
}
|
||||
|
||||
// For testing skipping of unrecognized fields.
|
||||
// Numbers are all big, larger than tag numbers in GoTestField,
|
||||
// the message used in the corresponding test.
|
||||
message GoSkipTest {
|
||||
required int32 skip_int32 = 11;
|
||||
required fixed32 skip_fixed32 = 12;
|
||||
required fixed64 skip_fixed64 = 13;
|
||||
required string skip_string = 14;
|
||||
required group SkipGroup = 15 {
|
||||
required int32 group_int32 = 16;
|
||||
required string group_string = 17;
|
||||
}
|
||||
}
|
||||
|
||||
// For testing packed/non-packed decoder switching.
|
||||
// A serialized instance of one should be deserializable as the other.
|
||||
message NonPackedTest {
|
||||
repeated int32 a = 1;
|
||||
}
|
||||
|
||||
message PackedTest {
|
||||
repeated int32 b = 1 [packed=true];
|
||||
}
|
||||
|
||||
message MaxTag {
|
||||
// Maximum possible tag number.
|
||||
optional string last_field = 536870911;
|
||||
}
|
||||
|
||||
message OldMessage {
|
||||
message Nested {
|
||||
optional string name = 1;
|
||||
}
|
||||
optional Nested nested = 1;
|
||||
|
||||
optional int32 num = 2;
|
||||
}
|
||||
|
||||
// NewMessage is wire compatible with OldMessage;
|
||||
// imagine it as a future version.
|
||||
message NewMessage {
|
||||
message Nested {
|
||||
optional string name = 1;
|
||||
optional string food_group = 2;
|
||||
}
|
||||
optional Nested nested = 1;
|
||||
|
||||
// This is an int32 in OldMessage.
|
||||
optional int64 num = 2;
|
||||
}
|
||||
|
||||
// Smaller tests for ASCII formatting.
|
||||
|
||||
message InnerMessage {
|
||||
required string host = 1;
|
||||
optional int32 port = 2 [default=4000];
|
||||
optional bool connected = 3;
|
||||
}
|
||||
|
||||
message OtherMessage {
|
||||
optional int64 key = 1;
|
||||
optional bytes value = 2;
|
||||
optional float weight = 3;
|
||||
optional InnerMessage inner = 4;
|
||||
|
||||
extensions 100 to max;
|
||||
}
|
||||
|
||||
message RequiredInnerMessage {
|
||||
required InnerMessage leo_finally_won_an_oscar = 1;
|
||||
}
|
||||
|
||||
message MyMessage {
|
||||
required int32 count = 1;
|
||||
optional string name = 2;
|
||||
optional string quote = 3;
|
||||
repeated string pet = 4;
|
||||
optional InnerMessage inner = 5;
|
||||
repeated OtherMessage others = 6;
|
||||
optional RequiredInnerMessage we_must_go_deeper = 13;
|
||||
repeated InnerMessage rep_inner = 12;
|
||||
|
||||
enum Color {
|
||||
RED = 0;
|
||||
GREEN = 1;
|
||||
BLUE = 2;
|
||||
};
|
||||
optional Color bikeshed = 7;
|
||||
|
||||
optional group SomeGroup = 8 {
|
||||
optional int32 group_field = 9;
|
||||
}
|
||||
|
||||
// This field becomes [][]byte in the generated code.
|
||||
repeated bytes rep_bytes = 10;
|
||||
|
||||
optional double bigfloat = 11;
|
||||
|
||||
extensions 100 to max;
|
||||
}
|
||||
|
||||
message Ext {
|
||||
extend MyMessage {
|
||||
optional Ext more = 103;
|
||||
optional string text = 104;
|
||||
optional int32 number = 105;
|
||||
}
|
||||
|
||||
optional string data = 1;
|
||||
}
|
||||
|
||||
extend MyMessage {
|
||||
repeated string greeting = 106;
|
||||
}
|
||||
|
||||
message ComplexExtension {
|
||||
optional int32 first = 1;
|
||||
optional int32 second = 2;
|
||||
repeated int32 third = 3;
|
||||
}
|
||||
|
||||
extend OtherMessage {
|
||||
optional ComplexExtension complex = 200;
|
||||
repeated ComplexExtension r_complex = 201;
|
||||
}
|
||||
|
||||
message DefaultsMessage {
|
||||
enum DefaultsEnum {
|
||||
ZERO = 0;
|
||||
ONE = 1;
|
||||
TWO = 2;
|
||||
};
|
||||
extensions 100 to max;
|
||||
}
|
||||
|
||||
extend DefaultsMessage {
|
||||
optional double no_default_double = 101;
|
||||
optional float no_default_float = 102;
|
||||
optional int32 no_default_int32 = 103;
|
||||
optional int64 no_default_int64 = 104;
|
||||
optional uint32 no_default_uint32 = 105;
|
||||
optional uint64 no_default_uint64 = 106;
|
||||
optional sint32 no_default_sint32 = 107;
|
||||
optional sint64 no_default_sint64 = 108;
|
||||
optional fixed32 no_default_fixed32 = 109;
|
||||
optional fixed64 no_default_fixed64 = 110;
|
||||
optional sfixed32 no_default_sfixed32 = 111;
|
||||
optional sfixed64 no_default_sfixed64 = 112;
|
||||
optional bool no_default_bool = 113;
|
||||
optional string no_default_string = 114;
|
||||
optional bytes no_default_bytes = 115;
|
||||
optional DefaultsMessage.DefaultsEnum no_default_enum = 116;
|
||||
|
||||
optional double default_double = 201 [default = 3.1415];
|
||||
optional float default_float = 202 [default = 3.14];
|
||||
optional int32 default_int32 = 203 [default = 42];
|
||||
optional int64 default_int64 = 204 [default = 43];
|
||||
optional uint32 default_uint32 = 205 [default = 44];
|
||||
optional uint64 default_uint64 = 206 [default = 45];
|
||||
optional sint32 default_sint32 = 207 [default = 46];
|
||||
optional sint64 default_sint64 = 208 [default = 47];
|
||||
optional fixed32 default_fixed32 = 209 [default = 48];
|
||||
optional fixed64 default_fixed64 = 210 [default = 49];
|
||||
optional sfixed32 default_sfixed32 = 211 [default = 50];
|
||||
optional sfixed64 default_sfixed64 = 212 [default = 51];
|
||||
optional bool default_bool = 213 [default = true];
|
||||
optional string default_string = 214 [default = "Hello, string"];
|
||||
optional bytes default_bytes = 215 [default = "Hello, bytes"];
|
||||
optional DefaultsMessage.DefaultsEnum default_enum = 216 [default = ONE];
|
||||
}
|
||||
|
||||
message MyMessageSet {
|
||||
option message_set_wire_format = true;
|
||||
extensions 100 to max;
|
||||
}
|
||||
|
||||
message Empty {
|
||||
}
|
||||
|
||||
extend MyMessageSet {
|
||||
optional Empty x201 = 201;
|
||||
optional Empty x202 = 202;
|
||||
optional Empty x203 = 203;
|
||||
optional Empty x204 = 204;
|
||||
optional Empty x205 = 205;
|
||||
optional Empty x206 = 206;
|
||||
optional Empty x207 = 207;
|
||||
optional Empty x208 = 208;
|
||||
optional Empty x209 = 209;
|
||||
optional Empty x210 = 210;
|
||||
optional Empty x211 = 211;
|
||||
optional Empty x212 = 212;
|
||||
optional Empty x213 = 213;
|
||||
optional Empty x214 = 214;
|
||||
optional Empty x215 = 215;
|
||||
optional Empty x216 = 216;
|
||||
optional Empty x217 = 217;
|
||||
optional Empty x218 = 218;
|
||||
optional Empty x219 = 219;
|
||||
optional Empty x220 = 220;
|
||||
optional Empty x221 = 221;
|
||||
optional Empty x222 = 222;
|
||||
optional Empty x223 = 223;
|
||||
optional Empty x224 = 224;
|
||||
optional Empty x225 = 225;
|
||||
optional Empty x226 = 226;
|
||||
optional Empty x227 = 227;
|
||||
optional Empty x228 = 228;
|
||||
optional Empty x229 = 229;
|
||||
optional Empty x230 = 230;
|
||||
optional Empty x231 = 231;
|
||||
optional Empty x232 = 232;
|
||||
optional Empty x233 = 233;
|
||||
optional Empty x234 = 234;
|
||||
optional Empty x235 = 235;
|
||||
optional Empty x236 = 236;
|
||||
optional Empty x237 = 237;
|
||||
optional Empty x238 = 238;
|
||||
optional Empty x239 = 239;
|
||||
optional Empty x240 = 240;
|
||||
optional Empty x241 = 241;
|
||||
optional Empty x242 = 242;
|
||||
optional Empty x243 = 243;
|
||||
optional Empty x244 = 244;
|
||||
optional Empty x245 = 245;
|
||||
optional Empty x246 = 246;
|
||||
optional Empty x247 = 247;
|
||||
optional Empty x248 = 248;
|
||||
optional Empty x249 = 249;
|
||||
optional Empty x250 = 250;
|
||||
}
|
||||
|
||||
message MessageList {
|
||||
repeated group Message = 1 {
|
||||
required string name = 2;
|
||||
required int32 count = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message Strings {
|
||||
optional string string_field = 1;
|
||||
optional bytes bytes_field = 2;
|
||||
}
|
||||
|
||||
message Defaults {
|
||||
enum Color {
|
||||
RED = 0;
|
||||
GREEN = 1;
|
||||
BLUE = 2;
|
||||
}
|
||||
|
||||
// Default-valued fields of all basic types.
|
||||
// Same as GoTest, but copied here to make testing easier.
|
||||
optional bool F_Bool = 1 [default=true];
|
||||
optional int32 F_Int32 = 2 [default=32];
|
||||
optional int64 F_Int64 = 3 [default=64];
|
||||
optional fixed32 F_Fixed32 = 4 [default=320];
|
||||
optional fixed64 F_Fixed64 = 5 [default=640];
|
||||
optional uint32 F_Uint32 = 6 [default=3200];
|
||||
optional uint64 F_Uint64 = 7 [default=6400];
|
||||
optional float F_Float = 8 [default=314159.];
|
||||
optional double F_Double = 9 [default=271828.];
|
||||
optional string F_String = 10 [default="hello, \"world!\"\n"];
|
||||
optional bytes F_Bytes = 11 [default="Bignose"];
|
||||
optional sint32 F_Sint32 = 12 [default=-32];
|
||||
optional sint64 F_Sint64 = 13 [default=-64];
|
||||
optional Color F_Enum = 14 [default=GREEN];
|
||||
|
||||
// More fields with crazy defaults.
|
||||
optional float F_Pinf = 15 [default=inf];
|
||||
optional float F_Ninf = 16 [default=-inf];
|
||||
optional float F_Nan = 17 [default=nan];
|
||||
|
||||
// Sub-message.
|
||||
optional SubDefaults sub = 18;
|
||||
|
||||
// Redundant but explicit defaults.
|
||||
optional string str_zero = 19 [default=""];
|
||||
}
|
||||
|
||||
message SubDefaults {
|
||||
optional int64 n = 1 [default=7];
|
||||
}
|
||||
|
||||
message RepeatedEnum {
|
||||
enum Color {
|
||||
RED = 1;
|
||||
}
|
||||
repeated Color color = 1;
|
||||
}
|
||||
|
||||
message MoreRepeated {
|
||||
repeated bool bools = 1;
|
||||
repeated bool bools_packed = 2 [packed=true];
|
||||
repeated int32 ints = 3;
|
||||
repeated int32 ints_packed = 4 [packed=true];
|
||||
repeated int64 int64s_packed = 7 [packed=true];
|
||||
repeated string strings = 5;
|
||||
repeated fixed32 fixeds = 6;
|
||||
}
|
||||
|
||||
// GroupOld and GroupNew have the same wire format.
|
||||
// GroupNew has a new field inside a group.
|
||||
|
||||
message GroupOld {
|
||||
optional group G = 101 {
|
||||
optional int32 x = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message GroupNew {
|
||||
optional group G = 101 {
|
||||
optional int32 x = 2;
|
||||
optional int32 y = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message FloatingPoint {
|
||||
required double f = 1;
|
||||
optional bool exact = 2;
|
||||
}
|
||||
|
||||
message MessageWithMap {
|
||||
map<int32, string> name_mapping = 1;
|
||||
map<sint64, FloatingPoint> msg_mapping = 2;
|
||||
map<bool, bytes> byte_mapping = 3;
|
||||
map<string, string> str_to_str = 4;
|
||||
}
|
||||
|
||||
message Oneof {
|
||||
oneof union {
|
||||
bool F_Bool = 1;
|
||||
int32 F_Int32 = 2;
|
||||
int64 F_Int64 = 3;
|
||||
fixed32 F_Fixed32 = 4;
|
||||
fixed64 F_Fixed64 = 5;
|
||||
uint32 F_Uint32 = 6;
|
||||
uint64 F_Uint64 = 7;
|
||||
float F_Float = 8;
|
||||
double F_Double = 9;
|
||||
string F_String = 10;
|
||||
bytes F_Bytes = 11;
|
||||
sint32 F_Sint32 = 12;
|
||||
sint64 F_Sint64 = 13;
|
||||
MyMessage.Color F_Enum = 14;
|
||||
GoTestField F_Message = 15;
|
||||
group F_Group = 16 {
|
||||
optional int32 x = 17;
|
||||
}
|
||||
int32 F_Largest_Tag = 536870911;
|
||||
}
|
||||
|
||||
oneof tormato {
|
||||
int32 value = 100;
|
||||
}
|
||||
}
|
||||
|
||||
message Communique {
|
||||
optional bool make_me_cry = 1;
|
||||
|
||||
// This is a oneof, called "union".
|
||||
oneof union {
|
||||
int32 number = 5;
|
||||
string name = 6;
|
||||
bytes data = 7;
|
||||
double temp_c = 8;
|
||||
MyMessage.Color col = 9;
|
||||
Strings msg = 10;
|
||||
}
|
||||
}
|
33
vendor/github.com/golang/protobuf/protoc-gen-go/Makefile
generated
vendored
33
vendor/github.com/golang/protobuf/protoc-gen-go/Makefile
generated
vendored
|
@ -1,33 +0,0 @@
|
|||
# Go support for Protocol Buffers - Google's data interchange format
|
||||
#
|
||||
# Copyright 2010 The Go Authors. All rights reserved.
|
||||
# https://github.com/golang/protobuf
|
||||
#
|
||||
# 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 Google 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.
|
||||
|
||||
test:
|
||||
cd testdata && make test
|
39
vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/Makefile
generated
vendored
39
vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/Makefile
generated
vendored
|
@ -1,39 +0,0 @@
|
|||
# Go support for Protocol Buffers - Google's data interchange format
|
||||
#
|
||||
# Copyright 2010 The Go Authors. All rights reserved.
|
||||
# https://github.com/golang/protobuf
|
||||
#
|
||||
# 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 Google 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.
|
||||
|
||||
# Not stored here, but descriptor.proto is in https://github.com/google/protobuf/
|
||||
# at src/google/protobuf/descriptor.proto
|
||||
regenerate:
|
||||
echo WARNING! THIS RULE IS PROBABLY NOT RIGHT FOR YOUR INSTALLATION
|
||||
protoc --go_out=. -I$(HOME)/src/protobuf/src $(HOME)/src/protobuf/src/google/protobuf/descriptor.proto && \
|
||||
sed 's,^package google_protobuf,package descriptor,' google/protobuf/descriptor.pb.go > \
|
||||
$(GOPATH)/src/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go && \
|
||||
rm -f google/protobuf/descriptor.pb.go
|
2075
vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go
generated
vendored
2075
vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
51
vendor/github.com/golang/protobuf/protoc-gen-go/doc.go
generated
vendored
51
vendor/github.com/golang/protobuf/protoc-gen-go/doc.go
generated
vendored
|
@ -1,51 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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 Google 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.
|
||||
|
||||
/*
|
||||
A plugin for the Google protocol buffer compiler to generate Go code.
|
||||
Run it by building this program and putting it in your path with the name
|
||||
protoc-gen-go
|
||||
That word 'go' at the end becomes part of the option string set for the
|
||||
protocol compiler, so once the protocol compiler (protoc) is installed
|
||||
you can run
|
||||
protoc --go_out=output_directory input_directory/file.proto
|
||||
to generate Go bindings for the protocol defined by file.proto.
|
||||
With that input, the output will be written to
|
||||
output_directory/file.pb.go
|
||||
|
||||
The generated code is documented in the package comment for
|
||||
the library.
|
||||
|
||||
See the README and documentation for protocol buffers to learn more:
|
||||
https://developers.google.com/protocol-buffers/
|
||||
|
||||
*/
|
||||
package documentation
|
40
vendor/github.com/golang/protobuf/protoc-gen-go/generator/Makefile
generated
vendored
40
vendor/github.com/golang/protobuf/protoc-gen-go/generator/Makefile
generated
vendored
|
@ -1,40 +0,0 @@
|
|||
# Go support for Protocol Buffers - Google's data interchange format
|
||||
#
|
||||
# Copyright 2010 The Go Authors. All rights reserved.
|
||||
# https://github.com/golang/protobuf
|
||||
#
|
||||
# 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 Google 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.
|
||||
|
||||
include $(GOROOT)/src/Make.inc
|
||||
|
||||
TARG=github.com/golang/protobuf/compiler/generator
|
||||
GOFILES=\
|
||||
generator.go\
|
||||
|
||||
DEPS=../descriptor ../plugin ../../proto
|
||||
|
||||
include $(GOROOT)/src/Make.pkg
|
2778
vendor/github.com/golang/protobuf/protoc-gen-go/generator/generator.go
generated
vendored
2778
vendor/github.com/golang/protobuf/protoc-gen-go/generator/generator.go
generated
vendored
File diff suppressed because it is too large
Load diff
85
vendor/github.com/golang/protobuf/protoc-gen-go/generator/name_test.go
generated
vendored
85
vendor/github.com/golang/protobuf/protoc-gen-go/generator/name_test.go
generated
vendored
|
@ -1,85 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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 Google 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.
|
||||
|
||||
package generator
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
)
|
||||
|
||||
func TestCamelCase(t *testing.T) {
|
||||
tests := []struct {
|
||||
in, want string
|
||||
}{
|
||||
{"one", "One"},
|
||||
{"one_two", "OneTwo"},
|
||||
{"_my_field_name_2", "XMyFieldName_2"},
|
||||
{"Something_Capped", "Something_Capped"},
|
||||
{"my_Name", "My_Name"},
|
||||
{"OneTwo", "OneTwo"},
|
||||
{"_", "X"},
|
||||
{"_a_", "XA_"},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
if got := CamelCase(tc.in); got != tc.want {
|
||||
t.Errorf("CamelCase(%q) = %q, want %q", tc.in, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoPackageOption(t *testing.T) {
|
||||
tests := []struct {
|
||||
in string
|
||||
impPath, pkg string
|
||||
ok bool
|
||||
}{
|
||||
{"", "", "", false},
|
||||
{"foo", "", "foo", true},
|
||||
{"github.com/golang/bar", "github.com/golang/bar", "bar", true},
|
||||
{"github.com/golang/bar;baz", "github.com/golang/bar", "baz", true},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
d := &FileDescriptor{
|
||||
FileDescriptorProto: &descriptor.FileDescriptorProto{
|
||||
Options: &descriptor.FileOptions{
|
||||
GoPackage: &tc.in,
|
||||
},
|
||||
},
|
||||
}
|
||||
impPath, pkg, ok := d.goPackageOption()
|
||||
if impPath != tc.impPath || pkg != tc.pkg || ok != tc.ok {
|
||||
t.Errorf("go_package = %q => (%q, %q, %t), want (%q, %q, %t)", tc.in,
|
||||
impPath, pkg, ok, tc.impPath, tc.pkg, tc.ok)
|
||||
}
|
||||
}
|
||||
}
|
463
vendor/github.com/golang/protobuf/protoc-gen-go/grpc/grpc.go
generated
vendored
463
vendor/github.com/golang/protobuf/protoc-gen-go/grpc/grpc.go
generated
vendored
|
@ -1,463 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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 Google 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.
|
||||
|
||||
// Package grpc outputs gRPC service descriptions in Go code.
|
||||
// It runs as a plugin for the Go protocol buffer compiler plugin.
|
||||
// It is linked in to protoc-gen-go.
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
pb "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/golang/protobuf/protoc-gen-go/generator"
|
||||
)
|
||||
|
||||
// generatedCodeVersion indicates a version of the generated code.
|
||||
// It is incremented whenever an incompatibility between the generated code and
|
||||
// the grpc package is introduced; the generated code references
|
||||
// a constant, grpc.SupportPackageIsVersionN (where N is generatedCodeVersion).
|
||||
const generatedCodeVersion = 3
|
||||
|
||||
// Paths for packages used by code generated in this file,
|
||||
// relative to the import_prefix of the generator.Generator.
|
||||
const (
|
||||
contextPkgPath = "golang.org/x/net/context"
|
||||
grpcPkgPath = "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
func init() {
|
||||
generator.RegisterPlugin(new(grpc))
|
||||
}
|
||||
|
||||
// grpc is an implementation of the Go protocol buffer compiler's
|
||||
// plugin architecture. It generates bindings for gRPC support.
|
||||
type grpc struct {
|
||||
gen *generator.Generator
|
||||
}
|
||||
|
||||
// Name returns the name of this plugin, "grpc".
|
||||
func (g *grpc) Name() string {
|
||||
return "grpc"
|
||||
}
|
||||
|
||||
// The names for packages imported in the generated code.
|
||||
// They may vary from the final path component of the import path
|
||||
// if the name is used by other packages.
|
||||
var (
|
||||
contextPkg string
|
||||
grpcPkg string
|
||||
)
|
||||
|
||||
// Init initializes the plugin.
|
||||
func (g *grpc) Init(gen *generator.Generator) {
|
||||
g.gen = gen
|
||||
contextPkg = generator.RegisterUniquePackageName("context", nil)
|
||||
grpcPkg = generator.RegisterUniquePackageName("grpc", nil)
|
||||
}
|
||||
|
||||
// Given a type name defined in a .proto, return its object.
|
||||
// Also record that we're using it, to guarantee the associated import.
|
||||
func (g *grpc) objectNamed(name string) generator.Object {
|
||||
g.gen.RecordTypeUse(name)
|
||||
return g.gen.ObjectNamed(name)
|
||||
}
|
||||
|
||||
// Given a type name defined in a .proto, return its name as we will print it.
|
||||
func (g *grpc) typeName(str string) string {
|
||||
return g.gen.TypeName(g.objectNamed(str))
|
||||
}
|
||||
|
||||
// P forwards to g.gen.P.
|
||||
func (g *grpc) P(args ...interface{}) { g.gen.P(args...) }
|
||||
|
||||
// Generate generates code for the services in the given file.
|
||||
func (g *grpc) Generate(file *generator.FileDescriptor) {
|
||||
if len(file.FileDescriptorProto.Service) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
g.P("// Reference imports to suppress errors if they are not otherwise used.")
|
||||
g.P("var _ ", contextPkg, ".Context")
|
||||
g.P("var _ ", grpcPkg, ".ClientConn")
|
||||
g.P()
|
||||
|
||||
// Assert version compatibility.
|
||||
g.P("// This is a compile-time assertion to ensure that this generated file")
|
||||
g.P("// is compatible with the grpc package it is being compiled against.")
|
||||
g.P("const _ = ", grpcPkg, ".SupportPackageIsVersion", generatedCodeVersion)
|
||||
g.P()
|
||||
|
||||
for i, service := range file.FileDescriptorProto.Service {
|
||||
g.generateService(file, service, i)
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateImports generates the import declaration for this file.
|
||||
func (g *grpc) GenerateImports(file *generator.FileDescriptor) {
|
||||
if len(file.FileDescriptorProto.Service) == 0 {
|
||||
return
|
||||
}
|
||||
g.P("import (")
|
||||
g.P(contextPkg, " ", strconv.Quote(path.Join(g.gen.ImportPrefix, contextPkgPath)))
|
||||
g.P(grpcPkg, " ", strconv.Quote(path.Join(g.gen.ImportPrefix, grpcPkgPath)))
|
||||
g.P(")")
|
||||
g.P()
|
||||
}
|
||||
|
||||
// reservedClientName records whether a client name is reserved on the client side.
|
||||
var reservedClientName = map[string]bool{
|
||||
// TODO: do we need any in gRPC?
|
||||
}
|
||||
|
||||
func unexport(s string) string { return strings.ToLower(s[:1]) + s[1:] }
|
||||
|
||||
// generateService generates all the code for the named service.
|
||||
func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.ServiceDescriptorProto, index int) {
|
||||
path := fmt.Sprintf("6,%d", index) // 6 means service.
|
||||
|
||||
origServName := service.GetName()
|
||||
fullServName := origServName
|
||||
if pkg := file.GetPackage(); pkg != "" {
|
||||
fullServName = pkg + "." + fullServName
|
||||
}
|
||||
servName := generator.CamelCase(origServName)
|
||||
|
||||
g.P()
|
||||
g.P("// Client API for ", servName, " service")
|
||||
g.P()
|
||||
|
||||
// Client interface.
|
||||
g.P("type ", servName, "Client interface {")
|
||||
for i, method := range service.Method {
|
||||
g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service.
|
||||
g.P(g.generateClientSignature(servName, method))
|
||||
}
|
||||
g.P("}")
|
||||
g.P()
|
||||
|
||||
// Client structure.
|
||||
g.P("type ", unexport(servName), "Client struct {")
|
||||
g.P("cc *", grpcPkg, ".ClientConn")
|
||||
g.P("}")
|
||||
g.P()
|
||||
|
||||
// NewClient factory.
|
||||
g.P("func New", servName, "Client (cc *", grpcPkg, ".ClientConn) ", servName, "Client {")
|
||||
g.P("return &", unexport(servName), "Client{cc}")
|
||||
g.P("}")
|
||||
g.P()
|
||||
|
||||
var methodIndex, streamIndex int
|
||||
serviceDescVar := "_" + servName + "_serviceDesc"
|
||||
// Client method implementations.
|
||||
for _, method := range service.Method {
|
||||
var descExpr string
|
||||
if !method.GetServerStreaming() && !method.GetClientStreaming() {
|
||||
// Unary RPC method
|
||||
descExpr = fmt.Sprintf("&%s.Methods[%d]", serviceDescVar, methodIndex)
|
||||
methodIndex++
|
||||
} else {
|
||||
// Streaming RPC method
|
||||
descExpr = fmt.Sprintf("&%s.Streams[%d]", serviceDescVar, streamIndex)
|
||||
streamIndex++
|
||||
}
|
||||
g.generateClientMethod(servName, fullServName, serviceDescVar, method, descExpr)
|
||||
}
|
||||
|
||||
g.P("// Server API for ", servName, " service")
|
||||
g.P()
|
||||
|
||||
// Server interface.
|
||||
serverType := servName + "Server"
|
||||
g.P("type ", serverType, " interface {")
|
||||
for i, method := range service.Method {
|
||||
g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service.
|
||||
g.P(g.generateServerSignature(servName, method))
|
||||
}
|
||||
g.P("}")
|
||||
g.P()
|
||||
|
||||
// Server registration.
|
||||
g.P("func Register", servName, "Server(s *", grpcPkg, ".Server, srv ", serverType, ") {")
|
||||
g.P("s.RegisterService(&", serviceDescVar, `, srv)`)
|
||||
g.P("}")
|
||||
g.P()
|
||||
|
||||
// Server handler implementations.
|
||||
var handlerNames []string
|
||||
for _, method := range service.Method {
|
||||
hname := g.generateServerMethod(servName, fullServName, method)
|
||||
handlerNames = append(handlerNames, hname)
|
||||
}
|
||||
|
||||
// Service descriptor.
|
||||
g.P("var ", serviceDescVar, " = ", grpcPkg, ".ServiceDesc {")
|
||||
g.P("ServiceName: ", strconv.Quote(fullServName), ",")
|
||||
g.P("HandlerType: (*", serverType, ")(nil),")
|
||||
g.P("Methods: []", grpcPkg, ".MethodDesc{")
|
||||
for i, method := range service.Method {
|
||||
if method.GetServerStreaming() || method.GetClientStreaming() {
|
||||
continue
|
||||
}
|
||||
g.P("{")
|
||||
g.P("MethodName: ", strconv.Quote(method.GetName()), ",")
|
||||
g.P("Handler: ", handlerNames[i], ",")
|
||||
g.P("},")
|
||||
}
|
||||
g.P("},")
|
||||
g.P("Streams: []", grpcPkg, ".StreamDesc{")
|
||||
for i, method := range service.Method {
|
||||
if !method.GetServerStreaming() && !method.GetClientStreaming() {
|
||||
continue
|
||||
}
|
||||
g.P("{")
|
||||
g.P("StreamName: ", strconv.Quote(method.GetName()), ",")
|
||||
g.P("Handler: ", handlerNames[i], ",")
|
||||
if method.GetServerStreaming() {
|
||||
g.P("ServerStreams: true,")
|
||||
}
|
||||
if method.GetClientStreaming() {
|
||||
g.P("ClientStreams: true,")
|
||||
}
|
||||
g.P("},")
|
||||
}
|
||||
g.P("},")
|
||||
g.P("Metadata: ", file.VarName(), ",")
|
||||
g.P("}")
|
||||
g.P()
|
||||
}
|
||||
|
||||
// generateClientSignature returns the client-side signature for a method.
|
||||
func (g *grpc) generateClientSignature(servName string, method *pb.MethodDescriptorProto) string {
|
||||
origMethName := method.GetName()
|
||||
methName := generator.CamelCase(origMethName)
|
||||
if reservedClientName[methName] {
|
||||
methName += "_"
|
||||
}
|
||||
reqArg := ", in *" + g.typeName(method.GetInputType())
|
||||
if method.GetClientStreaming() {
|
||||
reqArg = ""
|
||||
}
|
||||
respName := "*" + g.typeName(method.GetOutputType())
|
||||
if method.GetServerStreaming() || method.GetClientStreaming() {
|
||||
respName = servName + "_" + generator.CamelCase(origMethName) + "Client"
|
||||
}
|
||||
return fmt.Sprintf("%s(ctx %s.Context%s, opts ...%s.CallOption) (%s, error)", methName, contextPkg, reqArg, grpcPkg, respName)
|
||||
}
|
||||
|
||||
func (g *grpc) generateClientMethod(servName, fullServName, serviceDescVar string, method *pb.MethodDescriptorProto, descExpr string) {
|
||||
sname := fmt.Sprintf("/%s/%s", fullServName, method.GetName())
|
||||
methName := generator.CamelCase(method.GetName())
|
||||
inType := g.typeName(method.GetInputType())
|
||||
outType := g.typeName(method.GetOutputType())
|
||||
|
||||
g.P("func (c *", unexport(servName), "Client) ", g.generateClientSignature(servName, method), "{")
|
||||
if !method.GetServerStreaming() && !method.GetClientStreaming() {
|
||||
g.P("out := new(", outType, ")")
|
||||
// TODO: Pass descExpr to Invoke.
|
||||
g.P("err := ", grpcPkg, `.Invoke(ctx, "`, sname, `", in, out, c.cc, opts...)`)
|
||||
g.P("if err != nil { return nil, err }")
|
||||
g.P("return out, nil")
|
||||
g.P("}")
|
||||
g.P()
|
||||
return
|
||||
}
|
||||
streamType := unexport(servName) + methName + "Client"
|
||||
g.P("stream, err := ", grpcPkg, ".NewClientStream(ctx, ", descExpr, `, c.cc, "`, sname, `", opts...)`)
|
||||
g.P("if err != nil { return nil, err }")
|
||||
g.P("x := &", streamType, "{stream}")
|
||||
if !method.GetClientStreaming() {
|
||||
g.P("if err := x.ClientStream.SendMsg(in); err != nil { return nil, err }")
|
||||
g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }")
|
||||
}
|
||||
g.P("return x, nil")
|
||||
g.P("}")
|
||||
g.P()
|
||||
|
||||
genSend := method.GetClientStreaming()
|
||||
genRecv := method.GetServerStreaming()
|
||||
genCloseAndRecv := !method.GetServerStreaming()
|
||||
|
||||
// Stream auxiliary types and methods.
|
||||
g.P("type ", servName, "_", methName, "Client interface {")
|
||||
if genSend {
|
||||
g.P("Send(*", inType, ") error")
|
||||
}
|
||||
if genRecv {
|
||||
g.P("Recv() (*", outType, ", error)")
|
||||
}
|
||||
if genCloseAndRecv {
|
||||
g.P("CloseAndRecv() (*", outType, ", error)")
|
||||
}
|
||||
g.P(grpcPkg, ".ClientStream")
|
||||
g.P("}")
|
||||
g.P()
|
||||
|
||||
g.P("type ", streamType, " struct {")
|
||||
g.P(grpcPkg, ".ClientStream")
|
||||
g.P("}")
|
||||
g.P()
|
||||
|
||||
if genSend {
|
||||
g.P("func (x *", streamType, ") Send(m *", inType, ") error {")
|
||||
g.P("return x.ClientStream.SendMsg(m)")
|
||||
g.P("}")
|
||||
g.P()
|
||||
}
|
||||
if genRecv {
|
||||
g.P("func (x *", streamType, ") Recv() (*", outType, ", error) {")
|
||||
g.P("m := new(", outType, ")")
|
||||
g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }")
|
||||
g.P("return m, nil")
|
||||
g.P("}")
|
||||
g.P()
|
||||
}
|
||||
if genCloseAndRecv {
|
||||
g.P("func (x *", streamType, ") CloseAndRecv() (*", outType, ", error) {")
|
||||
g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }")
|
||||
g.P("m := new(", outType, ")")
|
||||
g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }")
|
||||
g.P("return m, nil")
|
||||
g.P("}")
|
||||
g.P()
|
||||
}
|
||||
}
|
||||
|
||||
// generateServerSignature returns the server-side signature for a method.
|
||||
func (g *grpc) generateServerSignature(servName string, method *pb.MethodDescriptorProto) string {
|
||||
origMethName := method.GetName()
|
||||
methName := generator.CamelCase(origMethName)
|
||||
if reservedClientName[methName] {
|
||||
methName += "_"
|
||||
}
|
||||
|
||||
var reqArgs []string
|
||||
ret := "error"
|
||||
if !method.GetServerStreaming() && !method.GetClientStreaming() {
|
||||
reqArgs = append(reqArgs, contextPkg+".Context")
|
||||
ret = "(*" + g.typeName(method.GetOutputType()) + ", error)"
|
||||
}
|
||||
if !method.GetClientStreaming() {
|
||||
reqArgs = append(reqArgs, "*"+g.typeName(method.GetInputType()))
|
||||
}
|
||||
if method.GetServerStreaming() || method.GetClientStreaming() {
|
||||
reqArgs = append(reqArgs, servName+"_"+generator.CamelCase(origMethName)+"Server")
|
||||
}
|
||||
|
||||
return methName + "(" + strings.Join(reqArgs, ", ") + ") " + ret
|
||||
}
|
||||
|
||||
func (g *grpc) generateServerMethod(servName, fullServName string, method *pb.MethodDescriptorProto) string {
|
||||
methName := generator.CamelCase(method.GetName())
|
||||
hname := fmt.Sprintf("_%s_%s_Handler", servName, methName)
|
||||
inType := g.typeName(method.GetInputType())
|
||||
outType := g.typeName(method.GetOutputType())
|
||||
|
||||
if !method.GetServerStreaming() && !method.GetClientStreaming() {
|
||||
g.P("func ", hname, "(srv interface{}, ctx ", contextPkg, ".Context, dec func(interface{}) error, interceptor ", grpcPkg, ".UnaryServerInterceptor) (interface{}, error) {")
|
||||
g.P("in := new(", inType, ")")
|
||||
g.P("if err := dec(in); err != nil { return nil, err }")
|
||||
g.P("if interceptor == nil { return srv.(", servName, "Server).", methName, "(ctx, in) }")
|
||||
g.P("info := &", grpcPkg, ".UnaryServerInfo{")
|
||||
g.P("Server: srv,")
|
||||
g.P("FullMethod: ", strconv.Quote(fmt.Sprintf("/%s/%s", fullServName, methName)), ",")
|
||||
g.P("}")
|
||||
g.P("handler := func(ctx ", contextPkg, ".Context, req interface{}) (interface{}, error) {")
|
||||
g.P("return srv.(", servName, "Server).", methName, "(ctx, req.(*", inType, "))")
|
||||
g.P("}")
|
||||
g.P("return interceptor(ctx, in, info, handler)")
|
||||
g.P("}")
|
||||
g.P()
|
||||
return hname
|
||||
}
|
||||
streamType := unexport(servName) + methName + "Server"
|
||||
g.P("func ", hname, "(srv interface{}, stream ", grpcPkg, ".ServerStream) error {")
|
||||
if !method.GetClientStreaming() {
|
||||
g.P("m := new(", inType, ")")
|
||||
g.P("if err := stream.RecvMsg(m); err != nil { return err }")
|
||||
g.P("return srv.(", servName, "Server).", methName, "(m, &", streamType, "{stream})")
|
||||
} else {
|
||||
g.P("return srv.(", servName, "Server).", methName, "(&", streamType, "{stream})")
|
||||
}
|
||||
g.P("}")
|
||||
g.P()
|
||||
|
||||
genSend := method.GetServerStreaming()
|
||||
genSendAndClose := !method.GetServerStreaming()
|
||||
genRecv := method.GetClientStreaming()
|
||||
|
||||
// Stream auxiliary types and methods.
|
||||
g.P("type ", servName, "_", methName, "Server interface {")
|
||||
if genSend {
|
||||
g.P("Send(*", outType, ") error")
|
||||
}
|
||||
if genSendAndClose {
|
||||
g.P("SendAndClose(*", outType, ") error")
|
||||
}
|
||||
if genRecv {
|
||||
g.P("Recv() (*", inType, ", error)")
|
||||
}
|
||||
g.P(grpcPkg, ".ServerStream")
|
||||
g.P("}")
|
||||
g.P()
|
||||
|
||||
g.P("type ", streamType, " struct {")
|
||||
g.P(grpcPkg, ".ServerStream")
|
||||
g.P("}")
|
||||
g.P()
|
||||
|
||||
if genSend {
|
||||
g.P("func (x *", streamType, ") Send(m *", outType, ") error {")
|
||||
g.P("return x.ServerStream.SendMsg(m)")
|
||||
g.P("}")
|
||||
g.P()
|
||||
}
|
||||
if genSendAndClose {
|
||||
g.P("func (x *", streamType, ") SendAndClose(m *", outType, ") error {")
|
||||
g.P("return x.ServerStream.SendMsg(m)")
|
||||
g.P("}")
|
||||
g.P()
|
||||
}
|
||||
if genRecv {
|
||||
g.P("func (x *", streamType, ") Recv() (*", inType, ", error) {")
|
||||
g.P("m := new(", inType, ")")
|
||||
g.P("if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err }")
|
||||
g.P("return m, nil")
|
||||
g.P("}")
|
||||
g.P()
|
||||
}
|
||||
|
||||
return hname
|
||||
}
|
34
vendor/github.com/golang/protobuf/protoc-gen-go/link_grpc.go
generated
vendored
34
vendor/github.com/golang/protobuf/protoc-gen-go/link_grpc.go
generated
vendored
|
@ -1,34 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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 Google 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.
|
||||
|
||||
package main
|
||||
|
||||
import _ "github.com/golang/protobuf/protoc-gen-go/grpc"
|
98
vendor/github.com/golang/protobuf/protoc-gen-go/main.go
generated
vendored
98
vendor/github.com/golang/protobuf/protoc-gen-go/main.go
generated
vendored
|
@ -1,98 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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 Google 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.
|
||||
|
||||
// protoc-gen-go is a plugin for the Google protocol buffer compiler to generate
|
||||
// Go code. Run it by building this program and putting it in your path with
|
||||
// the name
|
||||
// protoc-gen-go
|
||||
// That word 'go' at the end becomes part of the option string set for the
|
||||
// protocol compiler, so once the protocol compiler (protoc) is installed
|
||||
// you can run
|
||||
// protoc --go_out=output_directory input_directory/file.proto
|
||||
// to generate Go bindings for the protocol defined by file.proto.
|
||||
// With that input, the output will be written to
|
||||
// output_directory/file.pb.go
|
||||
//
|
||||
// The generated code is documented in the package comment for
|
||||
// the library.
|
||||
//
|
||||
// See the README and documentation for protocol buffers to learn more:
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/protoc-gen-go/generator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Begin by allocating a generator. The request and response structures are stored there
|
||||
// so we can do error handling easily - the response structure contains the field to
|
||||
// report failure.
|
||||
g := generator.New()
|
||||
|
||||
data, err := ioutil.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
g.Error(err, "reading input")
|
||||
}
|
||||
|
||||
if err := proto.Unmarshal(data, g.Request); err != nil {
|
||||
g.Error(err, "parsing input proto")
|
||||
}
|
||||
|
||||
if len(g.Request.FileToGenerate) == 0 {
|
||||
g.Fail("no files to generate")
|
||||
}
|
||||
|
||||
g.CommandLineParameters(g.Request.GetParameter())
|
||||
|
||||
// Create a wrapped version of the Descriptors and EnumDescriptors that
|
||||
// point to the file that defines them.
|
||||
g.WrapTypes()
|
||||
|
||||
g.SetPackageNames()
|
||||
g.BuildTypeNameMap()
|
||||
|
||||
g.GenerateAllFiles()
|
||||
|
||||
// Send back the results.
|
||||
data, err = proto.Marshal(g.Response)
|
||||
if err != nil {
|
||||
g.Error(err, "failed to marshal output proto")
|
||||
}
|
||||
_, err = os.Stdout.Write(data)
|
||||
if err != nil {
|
||||
g.Error(err, "failed to write output proto")
|
||||
}
|
||||
}
|
45
vendor/github.com/golang/protobuf/protoc-gen-go/plugin/Makefile
generated
vendored
45
vendor/github.com/golang/protobuf/protoc-gen-go/plugin/Makefile
generated
vendored
|
@ -1,45 +0,0 @@
|
|||
# Go support for Protocol Buffers - Google's data interchange format
|
||||
#
|
||||
# Copyright 2010 The Go Authors. All rights reserved.
|
||||
# https://github.com/golang/protobuf
|
||||
#
|
||||
# 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 Google 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.
|
||||
|
||||
# Not stored here, but plugin.proto is in https://github.com/google/protobuf/
|
||||
# at src/google/protobuf/compiler/plugin.proto
|
||||
# Also we need to fix an import.
|
||||
regenerate:
|
||||
echo WARNING! THIS RULE IS PROBABLY NOT RIGHT FOR YOUR INSTALLATION
|
||||
protoc --go_out=Mgoogle/protobuf/descriptor.proto=github.com/golang/protobuf/protoc-gen-go/descriptor:. \
|
||||
-I$(HOME)/src/protobuf/src $(HOME)/src/protobuf/src/google/protobuf/compiler/plugin.proto && \
|
||||
mv google/protobuf/compiler/plugin.pb.go $(GOPATH)/src/github.com/golang/protobuf/protoc-gen-go/plugin
|
||||
|
||||
restore:
|
||||
cp plugin.pb.golden plugin.pb.go
|
||||
|
||||
preserve:
|
||||
cp plugin.pb.go plugin.pb.golden
|
225
vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.go
generated
vendored
225
vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.go
generated
vendored
|
@ -1,225 +0,0 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// source: google/protobuf/compiler/plugin.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package plugin_go is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
google/protobuf/compiler/plugin.proto
|
||||
|
||||
It has these top-level messages:
|
||||
CodeGeneratorRequest
|
||||
CodeGeneratorResponse
|
||||
*/
|
||||
package plugin_go
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import google_protobuf "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
|
||||
// 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.
|
||||
const _ = proto.ProtoPackageIsVersion1
|
||||
|
||||
// An encoded CodeGeneratorRequest is written to the plugin's stdin.
|
||||
type CodeGeneratorRequest struct {
|
||||
// The .proto files that were explicitly listed on the command-line. The
|
||||
// code generator should generate code only for these files. Each file's
|
||||
// descriptor will be included in proto_file, below.
|
||||
FileToGenerate []string `protobuf:"bytes,1,rep,name=file_to_generate,json=fileToGenerate" json:"file_to_generate,omitempty"`
|
||||
// The generator parameter passed on the command-line.
|
||||
Parameter *string `protobuf:"bytes,2,opt,name=parameter" json:"parameter,omitempty"`
|
||||
// FileDescriptorProtos for all files in files_to_generate and everything
|
||||
// they import. The files will appear in topological order, so each file
|
||||
// appears before any file that imports it.
|
||||
//
|
||||
// protoc guarantees that all proto_files will be written after
|
||||
// the fields above, even though this is not technically guaranteed by the
|
||||
// protobuf wire format. This theoretically could allow a plugin to stream
|
||||
// in the FileDescriptorProtos and handle them one by one rather than read
|
||||
// the entire set into memory at once. However, as of this writing, this
|
||||
// is not similarly optimized on protoc's end -- it will store all fields in
|
||||
// memory at once before sending them to the plugin.
|
||||
ProtoFile []*google_protobuf.FileDescriptorProto `protobuf:"bytes,15,rep,name=proto_file,json=protoFile" json:"proto_file,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *CodeGeneratorRequest) Reset() { *m = CodeGeneratorRequest{} }
|
||||
func (m *CodeGeneratorRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*CodeGeneratorRequest) ProtoMessage() {}
|
||||
func (*CodeGeneratorRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func (m *CodeGeneratorRequest) GetFileToGenerate() []string {
|
||||
if m != nil {
|
||||
return m.FileToGenerate
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *CodeGeneratorRequest) GetParameter() string {
|
||||
if m != nil && m.Parameter != nil {
|
||||
return *m.Parameter
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *CodeGeneratorRequest) GetProtoFile() []*google_protobuf.FileDescriptorProto {
|
||||
if m != nil {
|
||||
return m.ProtoFile
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// The plugin writes an encoded CodeGeneratorResponse to stdout.
|
||||
type CodeGeneratorResponse struct {
|
||||
// Error message. If non-empty, code generation failed. The plugin process
|
||||
// should exit with status code zero even if it reports an error in this way.
|
||||
//
|
||||
// This should be used to indicate errors in .proto files which prevent the
|
||||
// code generator from generating correct code. Errors which indicate a
|
||||
// problem in protoc itself -- such as the input CodeGeneratorRequest being
|
||||
// unparseable -- should be reported by writing a message to stderr and
|
||||
// exiting with a non-zero status code.
|
||||
Error *string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"`
|
||||
File []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file" json:"file,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *CodeGeneratorResponse) Reset() { *m = CodeGeneratorResponse{} }
|
||||
func (m *CodeGeneratorResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*CodeGeneratorResponse) ProtoMessage() {}
|
||||
func (*CodeGeneratorResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *CodeGeneratorResponse) GetError() string {
|
||||
if m != nil && m.Error != nil {
|
||||
return *m.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *CodeGeneratorResponse) GetFile() []*CodeGeneratorResponse_File {
|
||||
if m != nil {
|
||||
return m.File
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Represents a single generated file.
|
||||
type CodeGeneratorResponse_File struct {
|
||||
// The file name, relative to the output directory. The name must not
|
||||
// contain "." or ".." components and must be relative, not be absolute (so,
|
||||
// the file cannot lie outside the output directory). "/" must be used as
|
||||
// the path separator, not "\".
|
||||
//
|
||||
// If the name is omitted, the content will be appended to the previous
|
||||
// file. This allows the generator to break large files into small chunks,
|
||||
// and allows the generated text to be streamed back to protoc so that large
|
||||
// files need not reside completely in memory at one time. Note that as of
|
||||
// this writing protoc does not optimize for this -- it will read the entire
|
||||
// CodeGeneratorResponse before writing files to disk.
|
||||
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
// If non-empty, indicates that the named file should already exist, and the
|
||||
// content here is to be inserted into that file at a defined insertion
|
||||
// point. This feature allows a code generator to extend the output
|
||||
// produced by another code generator. The original generator may provide
|
||||
// insertion points by placing special annotations in the file that look
|
||||
// like:
|
||||
// @@protoc_insertion_point(NAME)
|
||||
// The annotation can have arbitrary text before and after it on the line,
|
||||
// which allows it to be placed in a comment. NAME should be replaced with
|
||||
// an identifier naming the point -- this is what other generators will use
|
||||
// as the insertion_point. Code inserted at this point will be placed
|
||||
// immediately above the line containing the insertion point (thus multiple
|
||||
// insertions to the same point will come out in the order they were added).
|
||||
// The double-@ is intended to make it unlikely that the generated code
|
||||
// could contain things that look like insertion points by accident.
|
||||
//
|
||||
// For example, the C++ code generator places the following line in the
|
||||
// .pb.h files that it generates:
|
||||
// // @@protoc_insertion_point(namespace_scope)
|
||||
// This line appears within the scope of the file's package namespace, but
|
||||
// outside of any particular class. Another plugin can then specify the
|
||||
// insertion_point "namespace_scope" to generate additional classes or
|
||||
// other declarations that should be placed in this scope.
|
||||
//
|
||||
// Note that if the line containing the insertion point begins with
|
||||
// whitespace, the same whitespace will be added to every line of the
|
||||
// inserted text. This is useful for languages like Python, where
|
||||
// indentation matters. In these languages, the insertion point comment
|
||||
// should be indented the same amount as any inserted code will need to be
|
||||
// in order to work correctly in that context.
|
||||
//
|
||||
// The code generator that generates the initial file and the one which
|
||||
// inserts into it must both run as part of a single invocation of protoc.
|
||||
// Code generators are executed in the order in which they appear on the
|
||||
// command line.
|
||||
//
|
||||
// If |insertion_point| is present, |name| must also be present.
|
||||
InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point,json=insertionPoint" json:"insertion_point,omitempty"`
|
||||
// The file contents.
|
||||
Content *string `protobuf:"bytes,15,opt,name=content" json:"content,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *CodeGeneratorResponse_File) Reset() { *m = CodeGeneratorResponse_File{} }
|
||||
func (m *CodeGeneratorResponse_File) String() string { return proto.CompactTextString(m) }
|
||||
func (*CodeGeneratorResponse_File) ProtoMessage() {}
|
||||
func (*CodeGeneratorResponse_File) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1, 0} }
|
||||
|
||||
func (m *CodeGeneratorResponse_File) GetName() string {
|
||||
if m != nil && m.Name != nil {
|
||||
return *m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *CodeGeneratorResponse_File) GetInsertionPoint() string {
|
||||
if m != nil && m.InsertionPoint != nil {
|
||||
return *m.InsertionPoint
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *CodeGeneratorResponse_File) GetContent() string {
|
||||
if m != nil && m.Content != nil {
|
||||
return *m.Content
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*CodeGeneratorRequest)(nil), "google.protobuf.compiler.CodeGeneratorRequest")
|
||||
proto.RegisterType((*CodeGeneratorResponse)(nil), "google.protobuf.compiler.CodeGeneratorResponse")
|
||||
proto.RegisterType((*CodeGeneratorResponse_File)(nil), "google.protobuf.compiler.CodeGeneratorResponse.File")
|
||||
}
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 311 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x74, 0x91, 0xd1, 0x4a, 0xfb, 0x30,
|
||||
0x14, 0xc6, 0xe9, 0xff, 0x3f, 0x91, 0x1d, 0x65, 0x93, 0x30, 0xa1, 0x8c, 0x5d, 0x94, 0xa1, 0xb8,
|
||||
0xab, 0x14, 0x44, 0xf0, 0x7e, 0x13, 0xf5, 0xb2, 0x14, 0xaf, 0x04, 0x29, 0xb5, 0x3b, 0x2b, 0x81,
|
||||
0x2e, 0x27, 0xa6, 0xe9, 0x13, 0xf9, 0x4e, 0x3e, 0x8f, 0x49, 0xda, 0x4e, 0x29, 0xee, 0xaa, 0x3d,
|
||||
0xdf, 0xf9, 0xe5, 0x3b, 0x5f, 0x72, 0xe0, 0xba, 0x24, 0x2a, 0x2b, 0x8c, 0x95, 0x26, 0x43, 0xef,
|
||||
0xcd, 0x2e, 0x2e, 0x68, 0xaf, 0x44, 0x85, 0x3a, 0x56, 0x55, 0x53, 0x0a, 0xc9, 0x7d, 0x83, 0x85,
|
||||
0x2d, 0xc6, 0x7b, 0x8c, 0xf7, 0xd8, 0x3c, 0x1a, 0x1a, 0x6c, 0xb1, 0x2e, 0xb4, 0x50, 0x86, 0x74,
|
||||
0x4b, 0x2f, 0x3f, 0x03, 0x98, 0x6d, 0x68, 0x8b, 0x4f, 0x28, 0x51, 0xe7, 0x56, 0x4f, 0xf1, 0xa3,
|
||||
0xc1, 0xda, 0xb0, 0x15, 0x5c, 0xec, 0xac, 0x47, 0x66, 0x28, 0x2b, 0xdb, 0x1e, 0x86, 0x41, 0xf4,
|
||||
0x7f, 0x35, 0x4e, 0x27, 0x4e, 0x7f, 0xa1, 0xee, 0x04, 0xb2, 0x05, 0x8c, 0x55, 0xae, 0xf3, 0x3d,
|
||||
0x1a, 0xd4, 0xe1, 0xbf, 0x28, 0xb0, 0xc8, 0x8f, 0xc0, 0x36, 0x00, 0x7e, 0x52, 0xe6, 0x4e, 0x85,
|
||||
0x53, 0xeb, 0x70, 0x76, 0x7b, 0xc5, 0x87, 0x89, 0x1f, 0x6d, 0xf3, 0xe1, 0x90, 0x2d, 0x71, 0xb2,
|
||||
0x35, 0x71, 0x1f, 0xd7, 0x59, 0x7e, 0x05, 0x70, 0x39, 0x48, 0x59, 0x2b, 0x92, 0x35, 0xb2, 0x19,
|
||||
0x9c, 0xa0, 0xd6, 0xa4, 0x6d, 0x36, 0x37, 0xb8, 0x2d, 0xd8, 0x33, 0x8c, 0x7e, 0x8d, 0xbb, 0xe3,
|
||||
0xc7, 0x1e, 0x88, 0xff, 0x69, 0xea, 0xd3, 0xa4, 0xde, 0x61, 0xfe, 0x06, 0x23, 0x57, 0x31, 0x06,
|
||||
0x23, 0x69, 0x6f, 0xd4, 0x8d, 0xf1, 0xff, 0xec, 0x06, 0xa6, 0xc2, 0xe2, 0xda, 0x08, 0x92, 0x99,
|
||||
0x22, 0x21, 0x4d, 0x77, 0xfd, 0xc9, 0x41, 0x4e, 0x9c, 0xca, 0x42, 0x38, 0x2d, 0x48, 0x1a, 0xb4,
|
||||
0xc0, 0xd4, 0x03, 0x7d, 0xb9, 0xbe, 0x87, 0x85, 0xcd, 0x72, 0x34, 0xdf, 0xfa, 0x3c, 0xf1, 0x8b,
|
||||
0xf6, 0x0f, 0x52, 0xbf, 0x8e, 0xdb, 0xb5, 0x67, 0x25, 0x7d, 0x07, 0x00, 0x00, 0xff, 0xff, 0x83,
|
||||
0x7b, 0x5c, 0x7c, 0x1b, 0x02, 0x00, 0x00,
|
||||
}
|
83
vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.golden
generated
vendored
83
vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.golden
generated
vendored
|
@ -1,83 +0,0 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// source: google/protobuf/compiler/plugin.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
package google_protobuf_compiler
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import "math"
|
||||
import google_protobuf "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
|
||||
// Reference proto and math imports to suppress error if they are not otherwise used.
|
||||
var _ = proto.GetString
|
||||
var _ = math.Inf
|
||||
|
||||
type CodeGeneratorRequest struct {
|
||||
FileToGenerate []string `protobuf:"bytes,1,rep,name=file_to_generate" json:"file_to_generate,omitempty"`
|
||||
Parameter *string `protobuf:"bytes,2,opt,name=parameter" json:"parameter,omitempty"`
|
||||
ProtoFile []*google_protobuf.FileDescriptorProto `protobuf:"bytes,15,rep,name=proto_file" json:"proto_file,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (this *CodeGeneratorRequest) Reset() { *this = CodeGeneratorRequest{} }
|
||||
func (this *CodeGeneratorRequest) String() string { return proto.CompactTextString(this) }
|
||||
func (*CodeGeneratorRequest) ProtoMessage() {}
|
||||
|
||||
func (this *CodeGeneratorRequest) GetParameter() string {
|
||||
if this != nil && this.Parameter != nil {
|
||||
return *this.Parameter
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type CodeGeneratorResponse struct {
|
||||
Error *string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"`
|
||||
File []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file" json:"file,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (this *CodeGeneratorResponse) Reset() { *this = CodeGeneratorResponse{} }
|
||||
func (this *CodeGeneratorResponse) String() string { return proto.CompactTextString(this) }
|
||||
func (*CodeGeneratorResponse) ProtoMessage() {}
|
||||
|
||||
func (this *CodeGeneratorResponse) GetError() string {
|
||||
if this != nil && this.Error != nil {
|
||||
return *this.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type CodeGeneratorResponse_File struct {
|
||||
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point" json:"insertion_point,omitempty"`
|
||||
Content *string `protobuf:"bytes,15,opt,name=content" json:"content,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (this *CodeGeneratorResponse_File) Reset() { *this = CodeGeneratorResponse_File{} }
|
||||
func (this *CodeGeneratorResponse_File) String() string { return proto.CompactTextString(this) }
|
||||
func (*CodeGeneratorResponse_File) ProtoMessage() {}
|
||||
|
||||
func (this *CodeGeneratorResponse_File) GetName() string {
|
||||
if this != nil && this.Name != nil {
|
||||
return *this.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (this *CodeGeneratorResponse_File) GetInsertionPoint() string {
|
||||
if this != nil && this.InsertionPoint != nil {
|
||||
return *this.InsertionPoint
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (this *CodeGeneratorResponse_File) GetContent() string {
|
||||
if this != nil && this.Content != nil {
|
||||
return *this.Content
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
}
|
73
vendor/github.com/golang/protobuf/protoc-gen-go/testdata/Makefile
generated
vendored
73
vendor/github.com/golang/protobuf/protoc-gen-go/testdata/Makefile
generated
vendored
|
@ -1,73 +0,0 @@
|
|||
# Go support for Protocol Buffers - Google's data interchange format
|
||||
#
|
||||
# Copyright 2010 The Go Authors. All rights reserved.
|
||||
# https://github.com/golang/protobuf
|
||||
#
|
||||
# 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 Google 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.
|
||||
|
||||
all:
|
||||
@echo run make test
|
||||
|
||||
include ../../Make.protobuf
|
||||
|
||||
test: golden testbuild
|
||||
|
||||
#test: golden testbuild extension_test
|
||||
# ./extension_test
|
||||
# @echo PASS
|
||||
|
||||
my_test/test.pb.go: my_test/test.proto
|
||||
protoc --go_out=Mmulti/multi1.proto=github.com/golang/protobuf/protoc-gen-go/testdata/multi:. $<
|
||||
|
||||
golden:
|
||||
make -B my_test/test.pb.go
|
||||
sed -i '/return.*fileDescriptor/d' my_test/test.pb.go
|
||||
sed -i '/^var fileDescriptor/,/^}/d' my_test/test.pb.go
|
||||
sed -i '/proto.RegisterFile.*fileDescriptor/d' my_test/test.pb.go
|
||||
gofmt -w my_test/test.pb.go
|
||||
diff -w my_test/test.pb.go my_test/test.pb.go.golden
|
||||
|
||||
nuke: clean
|
||||
|
||||
testbuild: regenerate
|
||||
go test
|
||||
|
||||
regenerate:
|
||||
# Invoke protoc once to generate three independent .pb.go files in the same package.
|
||||
protoc --go_out=. multi/multi{1,2,3}.proto
|
||||
|
||||
#extension_test: extension_test.$O
|
||||
# $(LD) -L. -o $@ $<
|
||||
|
||||
#multi.a: multi3.pb.$O multi2.pb.$O multi1.pb.$O
|
||||
# rm -f multi.a
|
||||
# $(QUOTED_GOBIN)/gopack grc $@ $<
|
||||
|
||||
#test.pb.go: imp.pb.go
|
||||
#multi1.pb.go: multi2.pb.go multi3.pb.go
|
||||
#main.$O: imp.pb.$O test.pb.$O multi.a
|
||||
#extension_test.$O: extension_base.pb.$O extension_extra.pb.$O extension_user.pb.$O
|
46
vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_base.proto
generated
vendored
46
vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_base.proto
generated
vendored
|
@ -1,46 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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 Google 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.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package extension_base;
|
||||
|
||||
message BaseMessage {
|
||||
optional int32 height = 1;
|
||||
extensions 4 to 9;
|
||||
extensions 16 to max;
|
||||
}
|
||||
|
||||
// Another message that may be extended, using message_set_wire_format.
|
||||
message OldStyleMessage {
|
||||
option message_set_wire_format = true;
|
||||
extensions 100 to max;
|
||||
}
|
38
vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_extra.proto
generated
vendored
38
vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_extra.proto
generated
vendored
|
@ -1,38 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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 Google 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.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package extension_extra;
|
||||
|
||||
message ExtraMessage {
|
||||
optional int32 width = 1;
|
||||
}
|
210
vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_test.go
generated
vendored
210
vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_test.go
generated
vendored
|
@ -1,210 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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 Google 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.
|
||||
|
||||
// Test that we can use protocol buffers that use extensions.
|
||||
|
||||
package testdata
|
||||
|
||||
/*
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
base "extension_base.pb"
|
||||
user "extension_user.pb"
|
||||
)
|
||||
|
||||
func TestSingleFieldExtension(t *testing.T) {
|
||||
bm := &base.BaseMessage{
|
||||
Height: proto.Int32(178),
|
||||
}
|
||||
|
||||
// Use extension within scope of another type.
|
||||
vol := proto.Uint32(11)
|
||||
err := proto.SetExtension(bm, user.E_LoudMessage_Volume, vol)
|
||||
if err != nil {
|
||||
t.Fatal("Failed setting extension:", err)
|
||||
}
|
||||
buf, err := proto.Marshal(bm)
|
||||
if err != nil {
|
||||
t.Fatal("Failed encoding message with extension:", err)
|
||||
}
|
||||
bm_new := new(base.BaseMessage)
|
||||
if err := proto.Unmarshal(buf, bm_new); err != nil {
|
||||
t.Fatal("Failed decoding message with extension:", err)
|
||||
}
|
||||
if !proto.HasExtension(bm_new, user.E_LoudMessage_Volume) {
|
||||
t.Fatal("Decoded message didn't contain extension.")
|
||||
}
|
||||
vol_out, err := proto.GetExtension(bm_new, user.E_LoudMessage_Volume)
|
||||
if err != nil {
|
||||
t.Fatal("Failed getting extension:", err)
|
||||
}
|
||||
if v := vol_out.(*uint32); *v != *vol {
|
||||
t.Errorf("vol_out = %v, expected %v", *v, *vol)
|
||||
}
|
||||
proto.ClearExtension(bm_new, user.E_LoudMessage_Volume)
|
||||
if proto.HasExtension(bm_new, user.E_LoudMessage_Volume) {
|
||||
t.Fatal("Failed clearing extension.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMessageExtension(t *testing.T) {
|
||||
bm := &base.BaseMessage{
|
||||
Height: proto.Int32(179),
|
||||
}
|
||||
|
||||
// Use extension that is itself a message.
|
||||
um := &user.UserMessage{
|
||||
Name: proto.String("Dave"),
|
||||
Rank: proto.String("Major"),
|
||||
}
|
||||
err := proto.SetExtension(bm, user.E_LoginMessage_UserMessage, um)
|
||||
if err != nil {
|
||||
t.Fatal("Failed setting extension:", err)
|
||||
}
|
||||
buf, err := proto.Marshal(bm)
|
||||
if err != nil {
|
||||
t.Fatal("Failed encoding message with extension:", err)
|
||||
}
|
||||
bm_new := new(base.BaseMessage)
|
||||
if err := proto.Unmarshal(buf, bm_new); err != nil {
|
||||
t.Fatal("Failed decoding message with extension:", err)
|
||||
}
|
||||
if !proto.HasExtension(bm_new, user.E_LoginMessage_UserMessage) {
|
||||
t.Fatal("Decoded message didn't contain extension.")
|
||||
}
|
||||
um_out, err := proto.GetExtension(bm_new, user.E_LoginMessage_UserMessage)
|
||||
if err != nil {
|
||||
t.Fatal("Failed getting extension:", err)
|
||||
}
|
||||
if n := um_out.(*user.UserMessage).Name; *n != *um.Name {
|
||||
t.Errorf("um_out.Name = %q, expected %q", *n, *um.Name)
|
||||
}
|
||||
if r := um_out.(*user.UserMessage).Rank; *r != *um.Rank {
|
||||
t.Errorf("um_out.Rank = %q, expected %q", *r, *um.Rank)
|
||||
}
|
||||
proto.ClearExtension(bm_new, user.E_LoginMessage_UserMessage)
|
||||
if proto.HasExtension(bm_new, user.E_LoginMessage_UserMessage) {
|
||||
t.Fatal("Failed clearing extension.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTopLevelExtension(t *testing.T) {
|
||||
bm := &base.BaseMessage{
|
||||
Height: proto.Int32(179),
|
||||
}
|
||||
|
||||
width := proto.Int32(17)
|
||||
err := proto.SetExtension(bm, user.E_Width, width)
|
||||
if err != nil {
|
||||
t.Fatal("Failed setting extension:", err)
|
||||
}
|
||||
buf, err := proto.Marshal(bm)
|
||||
if err != nil {
|
||||
t.Fatal("Failed encoding message with extension:", err)
|
||||
}
|
||||
bm_new := new(base.BaseMessage)
|
||||
if err := proto.Unmarshal(buf, bm_new); err != nil {
|
||||
t.Fatal("Failed decoding message with extension:", err)
|
||||
}
|
||||
if !proto.HasExtension(bm_new, user.E_Width) {
|
||||
t.Fatal("Decoded message didn't contain extension.")
|
||||
}
|
||||
width_out, err := proto.GetExtension(bm_new, user.E_Width)
|
||||
if err != nil {
|
||||
t.Fatal("Failed getting extension:", err)
|
||||
}
|
||||
if w := width_out.(*int32); *w != *width {
|
||||
t.Errorf("width_out = %v, expected %v", *w, *width)
|
||||
}
|
||||
proto.ClearExtension(bm_new, user.E_Width)
|
||||
if proto.HasExtension(bm_new, user.E_Width) {
|
||||
t.Fatal("Failed clearing extension.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMessageSetWireFormat(t *testing.T) {
|
||||
osm := new(base.OldStyleMessage)
|
||||
osp := &user.OldStyleParcel{
|
||||
Name: proto.String("Dave"),
|
||||
Height: proto.Int32(178),
|
||||
}
|
||||
|
||||
err := proto.SetExtension(osm, user.E_OldStyleParcel_MessageSetExtension, osp)
|
||||
if err != nil {
|
||||
t.Fatal("Failed setting extension:", err)
|
||||
}
|
||||
|
||||
buf, err := proto.Marshal(osm)
|
||||
if err != nil {
|
||||
t.Fatal("Failed encoding message:", err)
|
||||
}
|
||||
|
||||
// Data generated from Python implementation.
|
||||
expected := []byte{
|
||||
11, 16, 209, 15, 26, 9, 10, 4, 68, 97, 118, 101, 16, 178, 1, 12,
|
||||
}
|
||||
|
||||
if !bytes.Equal(expected, buf) {
|
||||
t.Errorf("Encoding mismatch.\nwant %+v\n got %+v", expected, buf)
|
||||
}
|
||||
|
||||
// Check that it is restored correctly.
|
||||
osm = new(base.OldStyleMessage)
|
||||
if err := proto.Unmarshal(buf, osm); err != nil {
|
||||
t.Fatal("Failed decoding message:", err)
|
||||
}
|
||||
osp_out, err := proto.GetExtension(osm, user.E_OldStyleParcel_MessageSetExtension)
|
||||
if err != nil {
|
||||
t.Fatal("Failed getting extension:", err)
|
||||
}
|
||||
osp = osp_out.(*user.OldStyleParcel)
|
||||
if *osp.Name != "Dave" || *osp.Height != 178 {
|
||||
t.Errorf("Retrieved extension from decoded message is not correct: %+v", osp)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// simpler than rigging up gotest
|
||||
testing.Main(regexp.MatchString, []testing.InternalTest{
|
||||
{"TestSingleFieldExtension", TestSingleFieldExtension},
|
||||
{"TestMessageExtension", TestMessageExtension},
|
||||
{"TestTopLevelExtension", TestTopLevelExtension},
|
||||
},
|
||||
[]testing.InternalBenchmark{},
|
||||
[]testing.InternalExample{})
|
||||
}
|
||||
|
||||
*/
|
100
vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_user.proto
generated
vendored
100
vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_user.proto
generated
vendored
|
@ -1,100 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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 Google 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.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
import "extension_base.proto";
|
||||
import "extension_extra.proto";
|
||||
|
||||
package extension_user;
|
||||
|
||||
message UserMessage {
|
||||
optional string name = 1;
|
||||
optional string rank = 2;
|
||||
}
|
||||
|
||||
// Extend with a message
|
||||
extend extension_base.BaseMessage {
|
||||
optional UserMessage user_message = 5;
|
||||
}
|
||||
|
||||
// Extend with a foreign message
|
||||
extend extension_base.BaseMessage {
|
||||
optional extension_extra.ExtraMessage extra_message = 9;
|
||||
}
|
||||
|
||||
// Extend with some primitive types
|
||||
extend extension_base.BaseMessage {
|
||||
optional int32 width = 6;
|
||||
optional int64 area = 7;
|
||||
}
|
||||
|
||||
// Extend inside the scope of another type
|
||||
message LoudMessage {
|
||||
extend extension_base.BaseMessage {
|
||||
optional uint32 volume = 8;
|
||||
}
|
||||
extensions 100 to max;
|
||||
}
|
||||
|
||||
// Extend inside the scope of another type, using a message.
|
||||
message LoginMessage {
|
||||
extend extension_base.BaseMessage {
|
||||
optional UserMessage user_message = 16;
|
||||
}
|
||||
}
|
||||
|
||||
// Extend with a repeated field
|
||||
extend extension_base.BaseMessage {
|
||||
repeated Detail detail = 17;
|
||||
}
|
||||
|
||||
message Detail {
|
||||
optional string color = 1;
|
||||
}
|
||||
|
||||
// An extension of an extension
|
||||
message Announcement {
|
||||
optional string words = 1;
|
||||
extend LoudMessage {
|
||||
optional Announcement loud_ext = 100;
|
||||
}
|
||||
}
|
||||
|
||||
// Something that can be put in a message set.
|
||||
message OldStyleParcel {
|
||||
extend extension_base.OldStyleMessage {
|
||||
optional OldStyleParcel message_set_extension = 2001;
|
||||
}
|
||||
|
||||
required string name = 1;
|
||||
optional int32 height = 2;
|
||||
}
|
59
vendor/github.com/golang/protobuf/protoc-gen-go/testdata/grpc.proto
generated
vendored
59
vendor/github.com/golang/protobuf/protoc-gen-go/testdata/grpc.proto
generated
vendored
|
@ -1,59 +0,0 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// 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 Google 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.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package grpc.testing;
|
||||
|
||||
message SimpleRequest {
|
||||
}
|
||||
|
||||
message SimpleResponse {
|
||||
}
|
||||
|
||||
message StreamMsg {
|
||||
}
|
||||
|
||||
message StreamMsg2 {
|
||||
}
|
||||
|
||||
service Test {
|
||||
rpc UnaryCall(SimpleRequest) returns (SimpleResponse);
|
||||
|
||||
// This RPC streams from the server only.
|
||||
rpc Downstream(SimpleRequest) returns (stream StreamMsg);
|
||||
|
||||
// This RPC streams from the client.
|
||||
rpc Upstream(stream StreamMsg) returns (SimpleResponse);
|
||||
|
||||
// This one streams in both directions.
|
||||
rpc Bidi(stream StreamMsg) returns (stream StreamMsg2);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue