add goa examples

This commit is contained in:
CaptainNEO 2022-03-07 20:49:02 +08:00
commit e2fd9f666e
39 changed files with 3858 additions and 0 deletions

81
README.md Normal file
View File

@ -0,0 +1,81 @@
# OpenAPI3 Framworks Compare
本文会横向对比几种支持OpenAPI文档生成的工具/框架。
OpenAPI 规范OAS定义了一个标准的、语言无关的 RESTful API 接口规范,它可以同时允许开发人员和操作系统查看并理解某个服务的功能,而无需访问源代码,文档或网络流量检查(既方便人类学习和阅读,也方便机器阅读)。正确定义 OAS 后,开发者可以使用最少的实现逻辑来理解远程服务并与之交互。
此外,文档生成工具可以使用 OpenAPI 规范来生成 API 文档代码生成工具可以生成各种编程语言下的服务端和客户端代码测试代码和其他用例。OpenAPI官方提供了各种语言的服务端和客户端的代码生成工具比较著名的如[OpenAPI Generator](https://github.com/OpenAPITools/openapi-generator),当然也有很多优秀的第三方开发者开发的工具。
> 相关参考
>
> - [OpenAPI3 Specification官方文档(v3.0.3)](https://spec.openapis.org/oas/v3.0.3) Published 20 February 2020
> - [OpenAPI3 Specification官方文档(v3.1.0)](https://spec.openapis.org/oas/v3.1.0) Published 15 February 2021
> - [Awesome OpenAPI3](https://apis.guru/awesome-openapi3)
## 1. 背景描述
使用如上几种框架分别实现Swagger官方用例[petstore](https://petstore.swagger.io)中的一部分然后分析这些框架的实现方式和背后生成OpenAPI的逻辑
## 2. 参赛选手介绍
| 语言 | 框架 | Web功能完备 | OpenAPI版本 | Github Stars | 当前版本 | first release datae |
|--------|--------------------------------------------------------------------------|-------------|-------------|--------------------------------------------------------------------------------|------------------------------------------------------------------------------------|---------------------|
| Go | [goa](https://github.com/goadesign/goa) | 是 | 3 | ![stars](https://img.shields.io/github/stars/goadesign/goa.svg) | ![Release](https://img.shields.io/github/tag/goadesign/goa.svg) | 2016-08-03 |
| Go | [swag](https://github.com/swaggo/swag) | 否 | 2 | ![stars](https://img.shields.io/github/stars/swaggo/swag.svg) | ![Release](https://img.shields.io/github/release/swaggo/swag.svg) | 2017-11-30 |
| Go | [grpc-gateway](https://github.com/grpc-ecosystem/grpc-gateway) | 是 | 2 | ![stars](https://img.shields.io/github/stars/grpc-ecosystem/grpc-gateway.svg) | ![Release](https://img.shields.io/github/release/grpc-ecosystem/grpc-gateway.svg) | 2016-07-11 |
| Go | [fizz](https://github.com/wI2L/fizz) | 是 | 3 | ![stars](https://img.shields.io/github/stars/wI2L/fizz.svg) | ![Release](https://img.shields.io/github/release/wI2L/fizz.svg) | 2019-11-06 |
| Python | [Django REST framework](https://github.com/encode/django-rest-framework) | 是 | 3 | ![stars](https://img.shields.io/github/stars/encode/django-rest-framework.svg) | ![Release](https://img.shields.io/github/release/encode/django-rest-framework.svg) | 2011-02-22 |
| Python | [FastAPI](https://github.com/tiangolo/fastapi) | 是 | 3 | ![stars](https://img.shields.io/github/stars/tiangolo/fastapi.svg) | ![Release](https://img.shields.io/github/release/tiangolo/fastapi.svg) | 2018-12-16 |
| Rust | [Poem](https://github.com/poem-web/poem) | 是 | 3 | ![stars](https://img.shields.io/github/stars/poem-web/poem.svg) | ![Release](https://img.shields.io/github/tag/poem-web/poem.svg) | 2021-10-14 |
## 3. 实现过程介绍
### 1. Goa
```bash
## 1. 安装goa提供的代码生成工具
go install goa.design/goa/v3/cmd/goa@v3
## 2. 创建一个design文件夹用于描述API
mkdir -p goa_example/design
## 3. 使用goa提供的dsl描述API
## 4. 生成代码模板
goa gen goa_example/design
# 该步骤会生成gen文件夹中的所有文件包括design文件中定义的所有接口信息、Model描述、验证方式、Protobuf描述(如果有)等所有相关信息的Go描述
## 5. (optional) 生成实现的一个example
goa example goa_example/design
# 该步骤会生成cmd文件夹包括http server和 grpc server的启动
# 和项目根目录/{service_name}.go的文件其中包含了各方法的默认实现(fmt.Println())
# 接下来只需要修改各方法中的具体实现为真实业务逻辑即可
```
1. 优点
## 4. FAQ
### 1. Swagger和OpenAPI的关系和区别
简单来说
- OpenAPI: Specification(规范)
- Swagger: Tools for implementing the specification(实现规范的一系列工具)
Swagger最初是在2010年设计RESTful API的简单开源规范。还开发了包括Swagger UI、Swagger Editor和Swagger Codegen等开源工具以更好地实现和可视化规范中定义的 API。由规范和开源工具组成的Swagger项目变得非常流行创建了一个庞大的社区驱动工具生态系统。
在2015年Swagger项目被SmartBear Software收购。Swagger规范被捐赠给Linux基金会并更名为OpenAPI Specification(OAS)是描述REST API的标准规范。
此后Swagger已成为最受欢迎的工具套件可在整个 API 生命周期中充分利用 OAS 的强大功能。
SmartBear Software 支持的 Swagger 工具是最流行的实现 OpenAPI 规范的工具之一,并将继续保持 Swagger 名称Swagger Editor、Swagger UI、SwaggerHub 等)
### 2. JSON Schema?
JSON Schema 是一种定义JSON格式的规范相关生态已经比较完备各种语言的校验工具基本都有实现。
例如vscode中配置文件的代码补全和校验就是基于json schema完成的。
OpenAPI中对Json对象的描述就是使用Json schema来描述的
目前为止已经发布了多个版本的草案,其中
OAS3.0.3 采用的是Draft 00
OAS3.1.0 采用的是Draft 2020-12

View File

@ -0,0 +1,19 @@
package main
import (
"fmt"
cli "goa_example/gen/grpc/cli/host"
"os"
goa "goa.design/goa/v3/pkg"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func doGRPC(scheme, host string, timeout int, debug bool) (goa.Endpoint, interface{}, error) {
conn, err := grpc.Dial(host, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
fmt.Fprintf(os.Stderr, "could not connect to gRPC server at %s: %v\n", host, err)
}
return cli.ParseEndpoint(conn)
}

View File

@ -0,0 +1,39 @@
package main
import (
cli "goa_example/gen/http/cli/host"
"net/http"
"time"
goahttp "goa.design/goa/v3/http"
goa "goa.design/goa/v3/pkg"
)
func doHTTP(scheme, host string, timeout int, debug bool) (goa.Endpoint, interface{}, error) {
var (
doer goahttp.Doer
)
{
doer = &http.Client{Timeout: time.Duration(timeout) * time.Second}
if debug {
doer = goahttp.NewDebugDoer(doer)
}
}
return cli.ParseEndpoint(
scheme,
host,
doer,
goahttp.RequestEncoder,
goahttp.ResponseDecoder,
debug,
)
}
func httpUsageCommands() string {
return cli.UsageCommands()
}
func httpUsageExamples() string {
return cli.UsageExamples()
}

View File

@ -0,0 +1,124 @@
package main
import (
"context"
"encoding/json"
"flag"
"fmt"
"net/url"
"os"
"strings"
goa "goa.design/goa/v3/pkg"
)
func main() {
var (
hostF = flag.String("host", "localhost", "Server host (valid values: localhost, integration)")
addrF = flag.String("url", "", "URL to service host")
verboseF = flag.Bool("verbose", false, "Print request and response details")
vF = flag.Bool("v", false, "Print request and response details")
timeoutF = flag.Int("timeout", 30, "Maximum number of seconds to wait for response")
)
flag.Usage = usage
flag.Parse()
var (
addr string
timeout int
debug bool
)
{
addr = *addrF
if addr == "" {
switch *hostF {
case "localhost":
addr = "http://localhost:8088"
case "integration":
addr = "http://localhost:8088"
default:
fmt.Fprintf(os.Stderr, "invalid host argument: %q (valid hosts: localhost|integration)\n", *hostF)
os.Exit(1)
}
}
timeout = *timeoutF
debug = *verboseF || *vF
}
var (
scheme string
host string
)
{
u, err := url.Parse(addr)
if err != nil {
fmt.Fprintf(os.Stderr, "invalid URL %#v: %s\n", addr, err)
os.Exit(1)
}
scheme = u.Scheme
host = u.Host
}
var (
endpoint goa.Endpoint
payload interface{}
err error
)
{
switch scheme {
case "http", "https":
endpoint, payload, err = doHTTP(scheme, host, timeout, debug)
case "grpc", "grpcs":
endpoint, payload, err = doGRPC(scheme, host, timeout, debug)
default:
fmt.Fprintf(os.Stderr, "invalid scheme: %q (valid schemes: grpc|http)\n", scheme)
os.Exit(1)
}
}
if err != nil {
if err == flag.ErrHelp {
os.Exit(0)
}
fmt.Fprintln(os.Stderr, err.Error())
fmt.Fprintln(os.Stderr, "run '"+os.Args[0]+" --help' for detailed usage.")
os.Exit(1)
}
data, err := endpoint(context.Background(), payload)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}
if data != nil {
m, _ := json.MarshalIndent(data, "", " ")
fmt.Println(string(m))
}
}
func usage() {
fmt.Fprintf(os.Stderr, `%s is a command line client for the Example Service API.
Usage:
%s [-host HOST][-url URL][-timeout SECONDS][-verbose|-v] SERVICE ENDPOINT [flags]
-host HOST: server host (localhost). valid values: localhost, integration
-url URL: specify service URL overriding host URL (http://localhost:8080)
-timeout: maximum number of seconds to wait for response (30)
-verbose|-v: print request and response details (false)
Commands:
%s
Additional help:
%s SERVICE [ENDPOINT] --help
Example:
%s
`, os.Args[0], os.Args[0], indent(httpUsageCommands()), os.Args[0], indent(httpUsageExamples()))
}
func indent(s string) string {
if s == "" {
return ""
}
return " " + strings.Replace(s, "\n", "\n ", -1)
}

View File

@ -0,0 +1,82 @@
package main
import (
"context"
pet_storepb "goa_example/gen/grpc/pet_store/pb"
petstoresvr "goa_example/gen/grpc/pet_store/server"
petstore "goa_example/gen/pet_store"
"log"
"net"
"net/url"
"sync"
grpcmiddleware "github.com/grpc-ecosystem/go-grpc-middleware"
grpcmdlwr "goa.design/goa/v3/grpc/middleware"
"goa.design/goa/v3/middleware"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)
// handleGRPCServer starts configures and starts a gRPC server on the given
// URL. It shuts down the server if any error is received in the error channel.
func handleGRPCServer(ctx context.Context, u *url.URL, petStoreEndpoints *petstore.Endpoints, wg *sync.WaitGroup, errc chan error, logger *log.Logger, debug bool) {
// Setup goa log adapter.
var (
adapter middleware.Logger
)
{
adapter = middleware.NewLogger(logger)
}
// Wrap the endpoints with the transport specific layers. The generated
// server packages contains code generated from the design which maps
// the service input and output data structures to gRPC requests and
// responses.
var (
petStoreServer *petstoresvr.Server
)
{
petStoreServer = petstoresvr.New(petStoreEndpoints, nil)
}
// Initialize gRPC server with the middleware.
srv := grpc.NewServer(
grpcmiddleware.WithUnaryServerChain(
grpcmdlwr.UnaryRequestID(),
grpcmdlwr.UnaryServerLog(adapter),
),
)
// Register the servers.
pet_storepb.RegisterPetStoreServer(srv, petStoreServer)
for svc, info := range srv.GetServiceInfo() {
for _, m := range info.Methods {
logger.Printf("serving gRPC method %s", svc+"/"+m.Name)
}
}
// Register the server reflection service on the server.
// See https://grpc.github.io/grpc/core/md_doc_server-reflection.html.
reflection.Register(srv)
(*wg).Add(1)
go func() {
defer (*wg).Done()
// Start gRPC server in a separate goroutine.
go func() {
lis, err := net.Listen("tcp", u.Host)
if err != nil {
errc <- err
}
logger.Printf("gRPC server listening on %q", u.Host)
errc <- srv.Serve(lis)
}()
<-ctx.Done()
logger.Printf("shutting down gRPC server at %q", u.Host)
srv.Stop()
}()
}

View File

@ -0,0 +1,112 @@
package main
import (
"context"
petstoresvr "goa_example/gen/http/pet_store/server"
petstore "goa_example/gen/pet_store"
"log"
"net/http"
"net/url"
"os"
"sync"
"time"
goahttp "goa.design/goa/v3/http"
httpmdlwr "goa.design/goa/v3/http/middleware"
"goa.design/goa/v3/middleware"
)
// handleHTTPServer starts configures and starts a HTTP server on the given
// URL. It shuts down the server if any error is received in the error channel.
func handleHTTPServer(ctx context.Context, u *url.URL, petStoreEndpoints *petstore.Endpoints, wg *sync.WaitGroup, errc chan error, logger *log.Logger, debug bool) {
// Setup goa log adapter.
var (
adapter middleware.Logger
)
{
adapter = middleware.NewLogger(logger)
}
// Provide the transport specific request decoder and response encoder.
// The goa http package has built-in support for JSON, XML and gob.
// Other encodings can be used by providing the corresponding functions,
// see goa.design/implement/encoding.
var (
dec = goahttp.RequestDecoder
enc = goahttp.ResponseEncoder
)
// Build the service HTTP request multiplexer and configure it to serve
// HTTP requests to the service endpoints.
var mux goahttp.Muxer
{
mux = goahttp.NewMuxer()
}
// Wrap the endpoints with the transport specific layers. The generated
// server packages contains code generated from the design which maps
// the service input and output data structures to HTTP requests and
// responses.
var (
petStoreServer *petstoresvr.Server
)
{
eh := errorHandler(logger)
petStoreServer = petstoresvr.New(petStoreEndpoints, mux, dec, enc, eh, nil)
if debug {
servers := goahttp.Servers{
petStoreServer,
}
servers.Use(httpmdlwr.Debug(mux, os.Stdout))
}
}
// Configure the mux.
petstoresvr.Mount(mux, petStoreServer)
// Wrap the multiplexer with additional middlewares. Middlewares mounted
// here apply to all the service endpoints.
var handler http.Handler = mux
{
handler = httpmdlwr.Log(adapter)(handler)
handler = httpmdlwr.RequestID()(handler)
}
// Start HTTP server using default configuration, change the code to
// configure the server as required by your service.
srv := &http.Server{Addr: u.Host, Handler: handler}
for _, m := range petStoreServer.Mounts {
logger.Printf("HTTP %q mounted on %s %s", m.Method, m.Verb, m.Pattern)
}
(*wg).Add(1)
go func() {
defer (*wg).Done()
// Start HTTP server in a separate goroutine.
go func() {
logger.Printf("HTTP server listening on %q", u.Host)
errc <- srv.ListenAndServe()
}()
<-ctx.Done()
logger.Printf("shutting down HTTP server at %q", u.Host)
// Shutdown gracefully with a 30s timeout.
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
_ = srv.Shutdown(ctx)
}()
}
// errorHandler returns a function that writes and logs the given error.
// The function also writes and logs the error unique ID so that it's possible
// to correlate.
func errorHandler(logger *log.Logger) func(context.Context, http.ResponseWriter, error) {
return func(ctx context.Context, w http.ResponseWriter, err error) {
id := ctx.Value(middleware.RequestIDKey).(string)
_, _ = w.Write([]byte("[" + id + "] encoding: " + err.Error()))
logger.Printf("[%s] ERROR: %s", id, err.Error())
}
}

View File

@ -0,0 +1,191 @@
package main
import (
"context"
"flag"
"fmt"
exampleservice "goa_example"
petstore "goa_example/gen/pet_store"
"log"
"net"
"net/url"
"os"
"os/signal"
"sync"
"syscall"
)
func main() {
// Define command line flags, add any other flag required to configure the
// service.
var (
hostF = flag.String("host", "localhost", "Server host (valid values: localhost, integration)")
domainF = flag.String("domain", "", "Host domain name (overrides host domain specified in service design)")
httpPortF = flag.String("http-port", "", "HTTP port (overrides host HTTP port specified in service design)")
grpcPortF = flag.String("grpc-port", "", "gRPC port (overrides host gRPC port specified in service design)")
secureF = flag.Bool("secure", false, "Use secure scheme (https or grpcs)")
dbgF = flag.Bool("debug", false, "Log request and response bodies")
)
flag.Parse()
// Setup logger. Replace logger with your own log package of choice.
var (
logger *log.Logger
)
{
logger = log.New(os.Stderr, "[exampleservice] ", log.Ltime)
}
// Initialize the services.
var (
petStoreSvc petstore.Service
)
{
petStoreSvc = exampleservice.NewPetStore(logger)
}
// Wrap the services in endpoints that can be invoked from other services
// potentially running in different processes.
var (
petStoreEndpoints *petstore.Endpoints
)
{
petStoreEndpoints = petstore.NewEndpoints(petStoreSvc)
}
// Create channel used by both the signal handler and server goroutines
// to notify the main goroutine when to stop the server.
errc := make(chan error)
// Setup interrupt handler. This optional step configures the process so
// that SIGINT and SIGTERM signals cause the services to stop gracefully.
go func() {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
errc <- fmt.Errorf("%s", <-c)
}()
var wg sync.WaitGroup
ctx, cancel := context.WithCancel(context.Background())
// Start the servers and send errors (if any) to the error channel.
switch *hostF {
case "localhost":
{
addr := "http://localhost:8088"
u, err := url.Parse(addr)
if err != nil {
fmt.Fprintf(os.Stderr, "invalid URL %#v: %s\n", addr, err)
os.Exit(1)
}
if *secureF {
u.Scheme = "https"
}
if *domainF != "" {
u.Host = *domainF
}
if *httpPortF != "" {
h, _, err := net.SplitHostPort(u.Host)
if err != nil {
fmt.Fprintf(os.Stderr, "invalid URL %#v: %s\n", u.Host, err)
os.Exit(1)
}
u.Host = net.JoinHostPort(h, *httpPortF)
} else if u.Port() == "" {
u.Host = net.JoinHostPort(u.Host, "80")
}
handleHTTPServer(ctx, u, petStoreEndpoints, &wg, errc, logger, *dbgF)
}
{
addr := "grpc://localhost:8080"
u, err := url.Parse(addr)
if err != nil {
fmt.Fprintf(os.Stderr, "invalid URL %#v: %s\n", addr, err)
os.Exit(1)
}
if *secureF {
u.Scheme = "grpcs"
}
if *domainF != "" {
u.Host = *domainF
}
if *grpcPortF != "" {
h, _, err := net.SplitHostPort(u.Host)
if err != nil {
fmt.Fprintf(os.Stderr, "invalid URL %#v: %s\n", u.Host, err)
os.Exit(1)
}
u.Host = net.JoinHostPort(h, *grpcPortF)
} else if u.Port() == "" {
u.Host = net.JoinHostPort(u.Host, "8080")
}
handleGRPCServer(ctx, u, petStoreEndpoints, &wg, errc, logger, *dbgF)
}
case "integration":
{
addr := "http://localhost:8088"
u, err := url.Parse(addr)
if err != nil {
fmt.Fprintf(os.Stderr, "invalid URL %#v: %s\n", addr, err)
os.Exit(1)
}
if *secureF {
u.Scheme = "https"
}
if *domainF != "" {
u.Host = *domainF
}
if *httpPortF != "" {
h, _, err := net.SplitHostPort(u.Host)
if err != nil {
fmt.Fprintf(os.Stderr, "invalid URL %#v: %s\n", u.Host, err)
os.Exit(1)
}
u.Host = net.JoinHostPort(h, *httpPortF)
} else if u.Port() == "" {
u.Host = net.JoinHostPort(u.Host, "80")
}
handleHTTPServer(ctx, u, petStoreEndpoints, &wg, errc, logger, *dbgF)
}
{
addr := "grpc://localhost:8080"
u, err := url.Parse(addr)
if err != nil {
fmt.Fprintf(os.Stderr, "invalid URL %#v: %s\n", addr, err)
os.Exit(1)
}
if *secureF {
u.Scheme = "grpcs"
}
if *domainF != "" {
u.Host = *domainF
}
if *grpcPortF != "" {
h, _, err := net.SplitHostPort(u.Host)
if err != nil {
fmt.Fprintf(os.Stderr, "invalid URL %#v: %s\n", u.Host, err)
os.Exit(1)
}
u.Host = net.JoinHostPort(h, *grpcPortF)
} else if u.Port() == "" {
u.Host = net.JoinHostPort(u.Host, "8080")
}
handleGRPCServer(ctx, u, petStoreEndpoints, &wg, errc, logger, *dbgF)
}
default:
fmt.Fprintf(os.Stderr, "invalid host argument: %q (valid hosts: localhost|integration)\n", *hostF)
}
// Wait for signal.
logger.Printf("exiting (%v)", <-errc)
// Send cancellation signal to the goroutines.
cancel()
wg.Wait()
logger.Println("exited")
}

View File

@ -0,0 +1,117 @@
package design
import . "goa.design/goa/v3/dsl"
// 描述一个API的基本信息
var _ = API("Example Service", func() {
Title("A Goa Example Service")
Description("HTTP service for test")
Server("host", func() {
Host("localhost", func() { URI("http://localhost:8088") })
Host("integration", func() { URI("http://localhost:8088") })
})
})
// JWTAuth 描述了一个security scheme使用JWT tokens.
var JWTAuth = JWTSecurity("jwt", func() {
Description(`Secures endpoint by requiring a valid JWT token retrieved via the signin endpoint. Supports scopes "api:read" and "api:write".`)
})
// BasicAuth 描述了一个security scheme使用basic authentication.
var BasicAuth = BasicAuthSecurity("basic", func() {
Description("Basic authentication used to authenticate security principal during signin")
})
// Creds 描述了一个Json对象包含3个字段
var Creds = Type("Creds", func() {
Field(1, "jwt", String, "JWT token", func() {
Example("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ")
})
Field(2, "api_key", String, "API Key", func() {
Example("abcdef12345")
})
Field(3, "oauth_token", String, "OAuth2 token", func() {
Example("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ")
})
Required("jwt", "api_key", "oauth_token")
})
// 使用Service描述一个服务
var _ = Service("Service1", func() {
// 服务的描述信息
Description("The secured service exposes endpoints that require valid authorization credentials.")
// 该服务可能出现的异常情况
Error("unauthorized", String, "Credentials are invalid")
// 描述本服务全局可能可能返回的异常情况的状态码
HTTP(func() {
// 会匹配Error中描述的unauthorized
Response("unauthorized", StatusUnauthorized)
})
GRPC(func() {
Response("unauthorized", CodeUnauthenticated)
})
// 使用Method描述一个具体的请求(Operation)或grpc方法
Method("signin", func() {
// 本方法使用BasicAuth进行认证
Security(BasicAuth)
// 使用Payload描述请求的参数信息(Parameters)
// 如下描述了一个简单的包含了两个参数的请求
Payload(func() {
Description("Credentials used to authenticate to retrieve JWT token")
UsernameField(1, "username", String, "Username used to perform signin", func() {
Example("user")
})
PasswordField(2, "password", String, "Password used to perform signin", func() {
Example("password")
})
Required("username", "password")
})
// 接口正常时的返回结果
Result(Creds)
// HTTP描述
HTTP(func() {
// 使用POST方法请求这个时候Payload会以JSON Body的形式传入
POST("/signin")
// 接口返回时可能出现的状态码
Response(StatusOK)
Response(StatusBadRequest)
})
// GRPC描述
GRPC(func() {
// 接口返回时可能出现的状态码
Response(CodeOK)
Response(CodeInternal)
})
})
Method("secure", func() {
Description("这是一个需要JWT认证的接口")
// 定义使用JWT 认证
Security(JWTAuth)
// Payload信息
Payload(func() {
Field(1, "fail", Boolean, func() {
Description("Whether to force auth failure even with a valid JWT")
})
// 特殊的Field用于让Goa识别该字段为Token且在Header中
TokenField(2, "token", String, func() {
Description("JWT used for authentication")
})
Required("token")
})
// 返回的类型为字符串
Result(String)
HTTP(func() {
GET("/secure")
Response(StatusOK)
})
GRPC(func() {
Response(CodeOK)
})
})
})

View File

@ -0,0 +1,172 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// host gRPC client CLI support package
//
// Command:
// $ goa gen goa_example/design
package cli
import (
"flag"
"fmt"
service1c "goa_example/gen/grpc/service1/client"
"os"
goa "goa.design/goa/v3/pkg"
grpc "google.golang.org/grpc"
)
// UsageCommands returns the set of commands and sub-commands using the format
//
// command (subcommand1|subcommand2|...)
//
func UsageCommands() string {
return `service1 (signin|secure)
`
}
// UsageExamples produces an example of a valid invocation of the CLI tool.
func UsageExamples() string {
return os.Args[0] + ` service1 signin --username "user" --password "password"` + "\n" +
""
}
// ParseEndpoint returns the endpoint and payload as specified on the command
// line.
func ParseEndpoint(cc *grpc.ClientConn, opts ...grpc.CallOption) (goa.Endpoint, interface{}, error) {
var (
service1Flags = flag.NewFlagSet("service1", flag.ContinueOnError)
service1SigninFlags = flag.NewFlagSet("signin", flag.ExitOnError)
service1SigninUsernameFlag = service1SigninFlags.String("username", "REQUIRED", "")
service1SigninPasswordFlag = service1SigninFlags.String("password", "REQUIRED", "")
service1SecureFlags = flag.NewFlagSet("secure", flag.ExitOnError)
service1SecureMessageFlag = service1SecureFlags.String("message", "", "")
service1SecureTokenFlag = service1SecureFlags.String("token", "REQUIRED", "")
)
service1Flags.Usage = service1Usage
service1SigninFlags.Usage = service1SigninUsage
service1SecureFlags.Usage = service1SecureUsage
if err := flag.CommandLine.Parse(os.Args[1:]); err != nil {
return nil, nil, err
}
if flag.NArg() < 2 { // two non flag args are required: SERVICE and ENDPOINT (aka COMMAND)
return nil, nil, fmt.Errorf("not enough arguments")
}
var (
svcn string
svcf *flag.FlagSet
)
{
svcn = flag.Arg(0)
switch svcn {
case "service1":
svcf = service1Flags
default:
return nil, nil, fmt.Errorf("unknown service %q", svcn)
}
}
if err := svcf.Parse(flag.Args()[1:]); err != nil {
return nil, nil, err
}
var (
epn string
epf *flag.FlagSet
)
{
epn = svcf.Arg(0)
switch svcn {
case "service1":
switch epn {
case "signin":
epf = service1SigninFlags
case "secure":
epf = service1SecureFlags
}
}
}
if epf == nil {
return nil, nil, fmt.Errorf("unknown %q endpoint %q", svcn, epn)
}
// Parse endpoint flags if any
if svcf.NArg() > 1 {
if err := epf.Parse(svcf.Args()[1:]); err != nil {
return nil, nil, err
}
}
var (
data interface{}
endpoint goa.Endpoint
err error
)
{
switch svcn {
case "service1":
c := service1c.NewClient(cc, opts...)
switch epn {
case "signin":
endpoint = c.Signin()
data, err = service1c.BuildSigninPayload(*service1SigninUsernameFlag, *service1SigninPasswordFlag)
case "secure":
endpoint = c.Secure()
data, err = service1c.BuildSecurePayload(*service1SecureMessageFlag, *service1SecureTokenFlag)
}
}
}
if err != nil {
return nil, nil, err
}
return endpoint, data, nil
}
// service1Usage displays the usage of the service1 command and its subcommands.
func service1Usage() {
fmt.Fprintf(os.Stderr, `The secured service exposes endpoints that require valid authorization credentials.
Usage:
%[1]s [globalflags] service1 COMMAND [flags]
COMMAND:
signin: Signin implements signin.
secure: 这是一个需要JWT认证的接口
Additional help:
%[1]s service1 COMMAND --help
`, os.Args[0])
}
func service1SigninUsage() {
fmt.Fprintf(os.Stderr, `%[1]s [flags] service1 signin -username STRING -password STRING
Signin implements signin.
-username STRING:
-password STRING:
Example:
%[1]s service1 signin --username "user" --password "password"
`, os.Args[0])
}
func service1SecureUsage() {
fmt.Fprintf(os.Stderr, `%[1]s [flags] service1 secure -message JSON -token STRING
这是一个需要JWT认证的接口
-message JSON:
-token STRING:
Example:
%[1]s service1 secure --message '{
"fail": true
}' --token "Quia omnis amet et rerum quis."
`, os.Args[0])
}

View File

@ -0,0 +1,58 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// Service1 gRPC client CLI support package
//
// Command:
// $ goa gen goa_example/design
package client
import (
"encoding/json"
"fmt"
service1pb "goa_example/gen/grpc/service1/pb"
service1 "goa_example/gen/service1"
)
// BuildSigninPayload builds the payload for the Service1 signin endpoint from
// CLI flags.
func BuildSigninPayload(service1SigninUsername string, service1SigninPassword string) (*service1.SigninPayload, error) {
var username string
{
username = service1SigninUsername
}
var password string
{
password = service1SigninPassword
}
v := &service1.SigninPayload{}
v.Username = username
v.Password = password
return v, nil
}
// BuildSecurePayload builds the payload for the Service1 secure endpoint from
// CLI flags.
func BuildSecurePayload(service1SecureMessage string, service1SecureToken string) (*service1.SecurePayload, error) {
var err error
var message service1pb.SecureRequest
{
if service1SecureMessage != "" {
err = json.Unmarshal([]byte(service1SecureMessage), &message)
if err != nil {
return nil, fmt.Errorf("invalid JSON for message, \nerror: %s, \nexample of valid JSON:\n%s", err, "'{\n \"fail\": true\n }'")
}
}
}
var token string
{
token = service1SecureToken
}
v := &service1.SecurePayload{
Fail: &message.Fail,
}
v.Token = token
return v, nil
}

View File

@ -0,0 +1,74 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// Service1 gRPC client
//
// Command:
// $ goa gen goa_example/design
package client
import (
"context"
service1pb "goa_example/gen/grpc/service1/pb"
goagrpc "goa.design/goa/v3/grpc"
goapb "goa.design/goa/v3/grpc/pb"
goa "goa.design/goa/v3/pkg"
"google.golang.org/grpc"
)
// Client lists the service endpoint gRPC clients.
type Client struct {
grpccli service1pb.Service1Client
opts []grpc.CallOption
}
// NewClient instantiates gRPC client for all the Service1 service servers.
func NewClient(cc *grpc.ClientConn, opts ...grpc.CallOption) *Client {
return &Client{
grpccli: service1pb.NewService1Client(cc),
opts: opts,
}
}
// Signin calls the "Signin" function in service1pb.Service1Client interface.
func (c *Client) Signin() goa.Endpoint {
return func(ctx context.Context, v interface{}) (interface{}, error) {
inv := goagrpc.NewInvoker(
BuildSigninFunc(c.grpccli, c.opts...),
EncodeSigninRequest,
DecodeSigninResponse)
res, err := inv.Invoke(ctx, v)
if err != nil {
resp := goagrpc.DecodeError(err)
switch message := resp.(type) {
case *goapb.ErrorResponse:
return nil, goagrpc.NewServiceError(message)
default:
return nil, goa.Fault(err.Error())
}
}
return res, nil
}
}
// Secure calls the "Secure" function in service1pb.Service1Client interface.
func (c *Client) Secure() goa.Endpoint {
return func(ctx context.Context, v interface{}) (interface{}, error) {
inv := goagrpc.NewInvoker(
BuildSecureFunc(c.grpccli, c.opts...),
EncodeSecureRequest,
DecodeSecureResponse)
res, err := inv.Invoke(ctx, v)
if err != nil {
resp := goagrpc.DecodeError(err)
switch message := resp.(type) {
case *goapb.ErrorResponse:
return nil, goagrpc.NewServiceError(message)
default:
return nil, goa.Fault(err.Error())
}
}
return res, nil
}
}

View File

@ -0,0 +1,87 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// Service1 gRPC client encoders and decoders
//
// Command:
// $ goa gen goa_example/design
package client
import (
"context"
service1pb "goa_example/gen/grpc/service1/pb"
service1 "goa_example/gen/service1"
goagrpc "goa.design/goa/v3/grpc"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)
// BuildSigninFunc builds the remote method to invoke for "Service1" service
// "signin" endpoint.
func BuildSigninFunc(grpccli service1pb.Service1Client, cliopts ...grpc.CallOption) goagrpc.RemoteFunc {
return func(ctx context.Context, reqpb interface{}, opts ...grpc.CallOption) (interface{}, error) {
for _, opt := range cliopts {
opts = append(opts, opt)
}
if reqpb != nil {
return grpccli.Signin(ctx, reqpb.(*service1pb.SigninRequest), opts...)
}
return grpccli.Signin(ctx, &service1pb.SigninRequest{}, opts...)
}
}
// EncodeSigninRequest encodes requests sent to Service1 signin endpoint.
func EncodeSigninRequest(ctx context.Context, v interface{}, md *metadata.MD) (interface{}, error) {
payload, ok := v.(*service1.SigninPayload)
if !ok {
return nil, goagrpc.ErrInvalidType("Service1", "signin", "*service1.SigninPayload", v)
}
(*md).Append("username", payload.Username)
(*md).Append("password", payload.Password)
return NewSigninRequest(), nil
}
// DecodeSigninResponse decodes responses from the Service1 signin endpoint.
func DecodeSigninResponse(ctx context.Context, v interface{}, hdr, trlr metadata.MD) (interface{}, error) {
message, ok := v.(*service1pb.SigninResponse)
if !ok {
return nil, goagrpc.ErrInvalidType("Service1", "signin", "*service1pb.SigninResponse", v)
}
res := NewSigninResult(message)
return res, nil
}
// BuildSecureFunc builds the remote method to invoke for "Service1" service
// "secure" endpoint.
func BuildSecureFunc(grpccli service1pb.Service1Client, cliopts ...grpc.CallOption) goagrpc.RemoteFunc {
return func(ctx context.Context, reqpb interface{}, opts ...grpc.CallOption) (interface{}, error) {
for _, opt := range cliopts {
opts = append(opts, opt)
}
if reqpb != nil {
return grpccli.Secure(ctx, reqpb.(*service1pb.SecureRequest), opts...)
}
return grpccli.Secure(ctx, &service1pb.SecureRequest{}, opts...)
}
}
// EncodeSecureRequest encodes requests sent to Service1 secure endpoint.
func EncodeSecureRequest(ctx context.Context, v interface{}, md *metadata.MD) (interface{}, error) {
payload, ok := v.(*service1.SecurePayload)
if !ok {
return nil, goagrpc.ErrInvalidType("Service1", "secure", "*service1.SecurePayload", v)
}
(*md).Append("authorization", payload.Token)
return NewSecureRequest(payload), nil
}
// DecodeSecureResponse decodes responses from the Service1 secure endpoint.
func DecodeSecureResponse(ctx context.Context, v interface{}, hdr, trlr metadata.MD) (interface{}, error) {
message, ok := v.(*service1pb.SecureResponse)
if !ok {
return nil, goagrpc.ErrInvalidType("Service1", "secure", "*service1pb.SecureResponse", v)
}
res := NewSecureResult(message)
return res, nil
}

View File

@ -0,0 +1,48 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// Service1 gRPC client types
//
// Command:
// $ goa gen goa_example/design
package client
import (
service1pb "goa_example/gen/grpc/service1/pb"
service1 "goa_example/gen/service1"
)
// NewSigninRequest builds the gRPC request type from the payload of the
// "signin" endpoint of the "Service1" service.
func NewSigninRequest() *service1pb.SigninRequest {
message := &service1pb.SigninRequest{}
return message
}
// NewSigninResult builds the result type of the "signin" endpoint of the
// "Service1" service from the gRPC response type.
func NewSigninResult(message *service1pb.SigninResponse) *service1.Creds {
result := &service1.Creds{
JWT: message.Jwt,
APIKey: message.ApiKey,
OauthToken: message.OauthToken,
}
return result
}
// NewSecureRequest builds the gRPC request type from the payload of the
// "secure" endpoint of the "Service1" service.
func NewSecureRequest(payload *service1.SecurePayload) *service1pb.SecureRequest {
message := &service1pb.SecureRequest{}
if payload.Fail != nil {
message.Fail = *payload.Fail
}
return message
}
// NewSecureResult builds the result type of the "secure" endpoint of the
// "Service1" service from the gRPC response type.
func NewSecureResult(message *service1pb.SecureResponse) string {
result := message.Field
return result
}

View File

@ -0,0 +1,363 @@
// Code generated with goa v3.6.0, DO NOT EDIT.
//
// Service1 protocol buffer definition
//
// Command:
// $ goa gen goa_example/design
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.19.4
// source: goadesign_goagen_service1.proto
package service1pb
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type SigninRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *SigninRequest) Reset() {
*x = SigninRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_goadesign_goagen_service1_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SigninRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SigninRequest) ProtoMessage() {}
func (x *SigninRequest) ProtoReflect() protoreflect.Message {
mi := &file_goadesign_goagen_service1_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SigninRequest.ProtoReflect.Descriptor instead.
func (*SigninRequest) Descriptor() ([]byte, []int) {
return file_goadesign_goagen_service1_proto_rawDescGZIP(), []int{0}
}
type SigninResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// JWT token
Jwt string `protobuf:"bytes,1,opt,name=jwt,proto3" json:"jwt,omitempty"`
// API Key
ApiKey string `protobuf:"bytes,2,opt,name=api_key,json=apiKey,proto3" json:"api_key,omitempty"`
// OAuth2 token
OauthToken string `protobuf:"bytes,3,opt,name=oauth_token,json=oauthToken,proto3" json:"oauth_token,omitempty"`
}
func (x *SigninResponse) Reset() {
*x = SigninResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_goadesign_goagen_service1_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SigninResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SigninResponse) ProtoMessage() {}
func (x *SigninResponse) ProtoReflect() protoreflect.Message {
mi := &file_goadesign_goagen_service1_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SigninResponse.ProtoReflect.Descriptor instead.
func (*SigninResponse) Descriptor() ([]byte, []int) {
return file_goadesign_goagen_service1_proto_rawDescGZIP(), []int{1}
}
func (x *SigninResponse) GetJwt() string {
if x != nil {
return x.Jwt
}
return ""
}
func (x *SigninResponse) GetApiKey() string {
if x != nil {
return x.ApiKey
}
return ""
}
func (x *SigninResponse) GetOauthToken() string {
if x != nil {
return x.OauthToken
}
return ""
}
type SecureRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Whether to force auth failure even with a valid JWT
Fail bool `protobuf:"varint,1,opt,name=fail,proto3" json:"fail,omitempty"`
}
func (x *SecureRequest) Reset() {
*x = SecureRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_goadesign_goagen_service1_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SecureRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SecureRequest) ProtoMessage() {}
func (x *SecureRequest) ProtoReflect() protoreflect.Message {
mi := &file_goadesign_goagen_service1_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SecureRequest.ProtoReflect.Descriptor instead.
func (*SecureRequest) Descriptor() ([]byte, []int) {
return file_goadesign_goagen_service1_proto_rawDescGZIP(), []int{2}
}
func (x *SecureRequest) GetFail() bool {
if x != nil {
return x.Fail
}
return false
}
type SecureResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Field string `protobuf:"bytes,1,opt,name=field,proto3" json:"field,omitempty"`
}
func (x *SecureResponse) Reset() {
*x = SecureResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_goadesign_goagen_service1_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SecureResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SecureResponse) ProtoMessage() {}
func (x *SecureResponse) ProtoReflect() protoreflect.Message {
mi := &file_goadesign_goagen_service1_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SecureResponse.ProtoReflect.Descriptor instead.
func (*SecureResponse) Descriptor() ([]byte, []int) {
return file_goadesign_goagen_service1_proto_rawDescGZIP(), []int{3}
}
func (x *SecureResponse) GetField() string {
if x != nil {
return x.Field
}
return ""
}
var File_goadesign_goagen_service1_proto protoreflect.FileDescriptor
var file_goadesign_goagen_service1_proto_rawDesc = []byte{
0x0a, 0x1f, 0x67, 0x6f, 0x61, 0x64, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x67, 0x6f, 0x61, 0x67,
0x65, 0x6e, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x12, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x31, 0x22, 0x0f, 0x0a, 0x0d, 0x53,
0x69, 0x67, 0x6e, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x5c, 0x0a, 0x0e,
0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10,
0x0a, 0x03, 0x6a, 0x77, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6a, 0x77, 0x74,
0x12, 0x17, 0x0a, 0x07, 0x61, 0x70, 0x69, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x06, 0x61, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x61, 0x75,
0x74, 0x68, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
0x6f, 0x61, 0x75, 0x74, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x23, 0x0a, 0x0d, 0x53, 0x65,
0x63, 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66,
0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x66, 0x61, 0x69, 0x6c, 0x22,
0x26, 0x0a, 0x0e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x32, 0x84, 0x01, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x31, 0x12, 0x3b, 0x0a, 0x06, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x12, 0x17,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x3b, 0x0a, 0x06, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x12, 0x17, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x31, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x31, 0x2e,
0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0d,
0x5a, 0x0b, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x31, 0x70, 0x62, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_goadesign_goagen_service1_proto_rawDescOnce sync.Once
file_goadesign_goagen_service1_proto_rawDescData = file_goadesign_goagen_service1_proto_rawDesc
)
func file_goadesign_goagen_service1_proto_rawDescGZIP() []byte {
file_goadesign_goagen_service1_proto_rawDescOnce.Do(func() {
file_goadesign_goagen_service1_proto_rawDescData = protoimpl.X.CompressGZIP(file_goadesign_goagen_service1_proto_rawDescData)
})
return file_goadesign_goagen_service1_proto_rawDescData
}
var file_goadesign_goagen_service1_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_goadesign_goagen_service1_proto_goTypes = []interface{}{
(*SigninRequest)(nil), // 0: service1.SigninRequest
(*SigninResponse)(nil), // 1: service1.SigninResponse
(*SecureRequest)(nil), // 2: service1.SecureRequest
(*SecureResponse)(nil), // 3: service1.SecureResponse
}
var file_goadesign_goagen_service1_proto_depIdxs = []int32{
0, // 0: service1.Service1.Signin:input_type -> service1.SigninRequest
2, // 1: service1.Service1.Secure:input_type -> service1.SecureRequest
1, // 2: service1.Service1.Signin:output_type -> service1.SigninResponse
3, // 3: service1.Service1.Secure:output_type -> service1.SecureResponse
2, // [2:4] is the sub-list for method output_type
0, // [0:2] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_goadesign_goagen_service1_proto_init() }
func file_goadesign_goagen_service1_proto_init() {
if File_goadesign_goagen_service1_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_goadesign_goagen_service1_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SigninRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_goadesign_goagen_service1_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SigninResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_goadesign_goagen_service1_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SecureRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_goadesign_goagen_service1_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SecureResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_goadesign_goagen_service1_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_goadesign_goagen_service1_proto_goTypes,
DependencyIndexes: file_goadesign_goagen_service1_proto_depIdxs,
MessageInfos: file_goadesign_goagen_service1_proto_msgTypes,
}.Build()
File_goadesign_goagen_service1_proto = out.File
file_goadesign_goagen_service1_proto_rawDesc = nil
file_goadesign_goagen_service1_proto_goTypes = nil
file_goadesign_goagen_service1_proto_depIdxs = nil
}

View File

@ -0,0 +1,42 @@
// Code generated with goa v3.6.0, DO NOT EDIT.
//
// Service1 protocol buffer definition
//
// Command:
// $ goa gen goa_example/design
syntax = "proto3";
package service1;
option go_package = "/service1pb";
// The secured service exposes endpoints that require valid authorization
// credentials.
service Service1 {
// Signin implements signin.
rpc Signin (SigninRequest) returns (SigninResponse);
// JWT认证的接口
rpc Secure (SecureRequest) returns (SecureResponse);
}
message SigninRequest {
}
message SigninResponse {
// JWT token
string jwt = 1;
// API Key
string api_key = 2;
// OAuth2 token
string oauth_token = 3;
}
message SecureRequest {
// Whether to force auth failure even with a valid JWT
bool fail = 1;
}
message SecureResponse {
string field = 1;
}

View File

@ -0,0 +1,145 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.2.0
// - protoc v3.19.4
// source: goadesign_goagen_service1.proto
package service1pb
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// Service1Client is the client API for Service1 service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type Service1Client interface {
// Signin implements signin.
Signin(ctx context.Context, in *SigninRequest, opts ...grpc.CallOption) (*SigninResponse, error)
// 这是一个需要JWT认证的接口
Secure(ctx context.Context, in *SecureRequest, opts ...grpc.CallOption) (*SecureResponse, error)
}
type service1Client struct {
cc grpc.ClientConnInterface
}
func NewService1Client(cc grpc.ClientConnInterface) Service1Client {
return &service1Client{cc}
}
func (c *service1Client) Signin(ctx context.Context, in *SigninRequest, opts ...grpc.CallOption) (*SigninResponse, error) {
out := new(SigninResponse)
err := c.cc.Invoke(ctx, "/service1.Service1/Signin", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *service1Client) Secure(ctx context.Context, in *SecureRequest, opts ...grpc.CallOption) (*SecureResponse, error) {
out := new(SecureResponse)
err := c.cc.Invoke(ctx, "/service1.Service1/Secure", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Service1Server is the server API for Service1 service.
// All implementations must embed UnimplementedService1Server
// for forward compatibility
type Service1Server interface {
// Signin implements signin.
Signin(context.Context, *SigninRequest) (*SigninResponse, error)
// 这是一个需要JWT认证的接口
Secure(context.Context, *SecureRequest) (*SecureResponse, error)
mustEmbedUnimplementedService1Server()
}
// UnimplementedService1Server must be embedded to have forward compatible implementations.
type UnimplementedService1Server struct {
}
func (UnimplementedService1Server) Signin(context.Context, *SigninRequest) (*SigninResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Signin not implemented")
}
func (UnimplementedService1Server) Secure(context.Context, *SecureRequest) (*SecureResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Secure not implemented")
}
func (UnimplementedService1Server) mustEmbedUnimplementedService1Server() {}
// UnsafeService1Server may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to Service1Server will
// result in compilation errors.
type UnsafeService1Server interface {
mustEmbedUnimplementedService1Server()
}
func RegisterService1Server(s grpc.ServiceRegistrar, srv Service1Server) {
s.RegisterService(&Service1_ServiceDesc, srv)
}
func _Service1_Signin_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SigninRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(Service1Server).Signin(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/service1.Service1/Signin",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(Service1Server).Signin(ctx, req.(*SigninRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Service1_Secure_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SecureRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(Service1Server).Secure(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/service1.Service1/Secure",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(Service1Server).Secure(ctx, req.(*SecureRequest))
}
return interceptor(ctx, in, info, handler)
}
// Service1_ServiceDesc is the grpc.ServiceDesc for Service1 service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var Service1_ServiceDesc = grpc.ServiceDesc{
ServiceName: "service1.Service1",
HandlerType: (*Service1Server)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Signin",
Handler: _Service1_Signin_Handler,
},
{
MethodName: "Secure",
Handler: _Service1_Secure_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "goadesign_goagen_service1.proto",
}

View File

@ -0,0 +1,109 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// Service1 gRPC server encoders and decoders
//
// Command:
// $ goa gen goa_example/design
package server
import (
"context"
service1pb "goa_example/gen/grpc/service1/pb"
service1 "goa_example/gen/service1"
"strings"
goagrpc "goa.design/goa/v3/grpc"
goa "goa.design/goa/v3/pkg"
"google.golang.org/grpc/metadata"
)
// EncodeSigninResponse encodes responses from the "Service1" service "signin"
// endpoint.
func EncodeSigninResponse(ctx context.Context, v interface{}, hdr, trlr *metadata.MD) (interface{}, error) {
result, ok := v.(*service1.Creds)
if !ok {
return nil, goagrpc.ErrInvalidType("Service1", "signin", "*service1.Creds", v)
}
resp := NewSigninResponse(result)
return resp, nil
}
// DecodeSigninRequest decodes requests sent to "Service1" service "signin"
// endpoint.
func DecodeSigninRequest(ctx context.Context, v interface{}, md metadata.MD) (interface{}, error) {
var (
username string
password string
err error
)
{
if vals := md.Get("username"); len(vals) == 0 {
err = goa.MergeErrors(err, goa.MissingFieldError("username", "metadata"))
} else {
username = vals[0]
}
if vals := md.Get("password"); len(vals) == 0 {
err = goa.MergeErrors(err, goa.MissingFieldError("password", "metadata"))
} else {
password = vals[0]
}
}
if err != nil {
return nil, err
}
var payload *service1.SigninPayload
{
payload = NewSigninPayload(username, password)
}
return payload, nil
}
// EncodeSecureResponse encodes responses from the "Service1" service "secure"
// endpoint.
func EncodeSecureResponse(ctx context.Context, v interface{}, hdr, trlr *metadata.MD) (interface{}, error) {
result, ok := v.(string)
if !ok {
return nil, goagrpc.ErrInvalidType("Service1", "secure", "string", v)
}
resp := NewSecureResponse(result)
return resp, nil
}
// DecodeSecureRequest decodes requests sent to "Service1" service "secure"
// endpoint.
func DecodeSecureRequest(ctx context.Context, v interface{}, md metadata.MD) (interface{}, error) {
var (
token string
err error
)
{
if vals := md.Get("authorization"); len(vals) == 0 {
err = goa.MergeErrors(err, goa.MissingFieldError("authorization", "metadata"))
} else {
token = vals[0]
}
}
if err != nil {
return nil, err
}
var (
message *service1pb.SecureRequest
ok bool
)
{
if message, ok = v.(*service1pb.SecureRequest); !ok {
return nil, goagrpc.ErrInvalidType("Service1", "secure", "*service1pb.SecureRequest", v)
}
}
var payload *service1.SecurePayload
{
payload = NewSecurePayload(message, token)
if strings.Contains(payload.Token, " ") {
// Remove authorization scheme prefix (e.g. "Bearer")
cred := strings.SplitN(payload.Token, " ", 2)[1]
payload.Token = cred
}
}
return payload, nil
}

View File

@ -0,0 +1,94 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// Service1 gRPC server
//
// Command:
// $ goa gen goa_example/design
package server
import (
"context"
"errors"
service1pb "goa_example/gen/grpc/service1/pb"
service1 "goa_example/gen/service1"
goagrpc "goa.design/goa/v3/grpc"
goa "goa.design/goa/v3/pkg"
"google.golang.org/grpc/codes"
)
// Server implements the service1pb.Service1Server interface.
type Server struct {
SigninH goagrpc.UnaryHandler
SecureH goagrpc.UnaryHandler
service1pb.UnimplementedService1Server
}
// ErrorNamer is an interface implemented by generated error structs that
// exposes the name of the error as defined in the expr.
type ErrorNamer interface {
ErrorName() string
}
// New instantiates the server struct with the Service1 service endpoints.
func New(e *service1.Endpoints, uh goagrpc.UnaryHandler) *Server {
return &Server{
SigninH: NewSigninHandler(e.Signin, uh),
SecureH: NewSecureHandler(e.Secure, uh),
}
}
// NewSigninHandler creates a gRPC handler which serves the "Service1" service
// "signin" endpoint.
func NewSigninHandler(endpoint goa.Endpoint, h goagrpc.UnaryHandler) goagrpc.UnaryHandler {
if h == nil {
h = goagrpc.NewUnaryHandler(endpoint, DecodeSigninRequest, EncodeSigninResponse)
}
return h
}
// Signin implements the "Signin" method in service1pb.Service1Server interface.
func (s *Server) Signin(ctx context.Context, message *service1pb.SigninRequest) (*service1pb.SigninResponse, error) {
ctx = context.WithValue(ctx, goa.MethodKey, "signin")
ctx = context.WithValue(ctx, goa.ServiceKey, "Service1")
resp, err := s.SigninH.Handle(ctx, message)
if err != nil {
var en ErrorNamer
if errors.As(err, &en) {
switch en.ErrorName() {
case "unauthorized":
return nil, goagrpc.NewStatusError(codes.Unauthenticated, err, goagrpc.NewErrorResponse(err))
}
}
return nil, goagrpc.EncodeError(err)
}
return resp.(*service1pb.SigninResponse), nil
}
// NewSecureHandler creates a gRPC handler which serves the "Service1" service
// "secure" endpoint.
func NewSecureHandler(endpoint goa.Endpoint, h goagrpc.UnaryHandler) goagrpc.UnaryHandler {
if h == nil {
h = goagrpc.NewUnaryHandler(endpoint, DecodeSecureRequest, EncodeSecureResponse)
}
return h
}
// Secure implements the "Secure" method in service1pb.Service1Server interface.
func (s *Server) Secure(ctx context.Context, message *service1pb.SecureRequest) (*service1pb.SecureResponse, error) {
ctx = context.WithValue(ctx, goa.MethodKey, "secure")
ctx = context.WithValue(ctx, goa.ServiceKey, "Service1")
resp, err := s.SecureH.Handle(ctx, message)
if err != nil {
var en ErrorNamer
if errors.As(err, &en) {
switch en.ErrorName() {
case "unauthorized":
return nil, goagrpc.NewStatusError(codes.Unauthenticated, err, goagrpc.NewErrorResponse(err))
}
}
return nil, goagrpc.EncodeError(err)
}
return resp.(*service1pb.SecureResponse), nil
}

View File

@ -0,0 +1,51 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// Service1 gRPC server types
//
// Command:
// $ goa gen goa_example/design
package server
import (
service1pb "goa_example/gen/grpc/service1/pb"
service1 "goa_example/gen/service1"
)
// NewSigninPayload builds the payload of the "signin" endpoint of the
// "Service1" service from the gRPC request type.
func NewSigninPayload(username string, password string) *service1.SigninPayload {
v := &service1.SigninPayload{}
v.Username = username
v.Password = password
return v
}
// NewSigninResponse builds the gRPC response type from the result of the
// "signin" endpoint of the "Service1" service.
func NewSigninResponse(result *service1.Creds) *service1pb.SigninResponse {
message := &service1pb.SigninResponse{
Jwt: result.JWT,
ApiKey: result.APIKey,
OauthToken: result.OauthToken,
}
return message
}
// NewSecurePayload builds the payload of the "secure" endpoint of the
// "Service1" service from the gRPC request type.
func NewSecurePayload(message *service1pb.SecureRequest, token string) *service1.SecurePayload {
v := &service1.SecurePayload{
Fail: &message.Fail,
}
v.Token = token
return v
}
// NewSecureResponse builds the gRPC response type from the result of the
// "secure" endpoint of the "Service1" service.
func NewSecureResponse(result string) *service1pb.SecureResponse {
message := &service1pb.SecureResponse{}
message.Field = result
return message
}

View File

@ -0,0 +1,179 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// host HTTP client CLI support package
//
// Command:
// $ goa gen goa_example/design
package cli
import (
"flag"
"fmt"
service1c "goa_example/gen/http/service1/client"
"net/http"
"os"
goahttp "goa.design/goa/v3/http"
goa "goa.design/goa/v3/pkg"
)
// UsageCommands returns the set of commands and sub-commands using the format
//
// command (subcommand1|subcommand2|...)
//
func UsageCommands() string {
return `service1 (signin|secure)
`
}
// UsageExamples produces an example of a valid invocation of the CLI tool.
func UsageExamples() string {
return os.Args[0] + ` service1 signin --username "user" --password "password"` + "\n" +
""
}
// ParseEndpoint returns the endpoint and payload as specified on the command
// line.
func ParseEndpoint(
scheme, host string,
doer goahttp.Doer,
enc func(*http.Request) goahttp.Encoder,
dec func(*http.Response) goahttp.Decoder,
restore bool,
) (goa.Endpoint, interface{}, error) {
var (
service1Flags = flag.NewFlagSet("service1", flag.ContinueOnError)
service1SigninFlags = flag.NewFlagSet("signin", flag.ExitOnError)
service1SigninUsernameFlag = service1SigninFlags.String("username", "REQUIRED", "Username used to perform signin")
service1SigninPasswordFlag = service1SigninFlags.String("password", "REQUIRED", "Password used to perform signin")
service1SecureFlags = flag.NewFlagSet("secure", flag.ExitOnError)
service1SecureBodyFlag = service1SecureFlags.String("body", "REQUIRED", "")
service1SecureTokenFlag = service1SecureFlags.String("token", "REQUIRED", "")
)
service1Flags.Usage = service1Usage
service1SigninFlags.Usage = service1SigninUsage
service1SecureFlags.Usage = service1SecureUsage
if err := flag.CommandLine.Parse(os.Args[1:]); err != nil {
return nil, nil, err
}
if flag.NArg() < 2 { // two non flag args are required: SERVICE and ENDPOINT (aka COMMAND)
return nil, nil, fmt.Errorf("not enough arguments")
}
var (
svcn string
svcf *flag.FlagSet
)
{
svcn = flag.Arg(0)
switch svcn {
case "service1":
svcf = service1Flags
default:
return nil, nil, fmt.Errorf("unknown service %q", svcn)
}
}
if err := svcf.Parse(flag.Args()[1:]); err != nil {
return nil, nil, err
}
var (
epn string
epf *flag.FlagSet
)
{
epn = svcf.Arg(0)
switch svcn {
case "service1":
switch epn {
case "signin":
epf = service1SigninFlags
case "secure":
epf = service1SecureFlags
}
}
}
if epf == nil {
return nil, nil, fmt.Errorf("unknown %q endpoint %q", svcn, epn)
}
// Parse endpoint flags if any
if svcf.NArg() > 1 {
if err := epf.Parse(svcf.Args()[1:]); err != nil {
return nil, nil, err
}
}
var (
data interface{}
endpoint goa.Endpoint
err error
)
{
switch svcn {
case "service1":
c := service1c.NewClient(scheme, host, doer, enc, dec, restore)
switch epn {
case "signin":
endpoint = c.Signin()
data, err = service1c.BuildSigninPayload(*service1SigninUsernameFlag, *service1SigninPasswordFlag)
case "secure":
endpoint = c.Secure()
data, err = service1c.BuildSecurePayload(*service1SecureBodyFlag, *service1SecureTokenFlag)
}
}
}
if err != nil {
return nil, nil, err
}
return endpoint, data, nil
}
// service1Usage displays the usage of the service1 command and its subcommands.
func service1Usage() {
fmt.Fprintf(os.Stderr, `The secured service exposes endpoints that require valid authorization credentials.
Usage:
%[1]s [globalflags] service1 COMMAND [flags]
COMMAND:
signin: Signin implements signin.
secure: 这是一个需要JWT认证的接口
Additional help:
%[1]s service1 COMMAND --help
`, os.Args[0])
}
func service1SigninUsage() {
fmt.Fprintf(os.Stderr, `%[1]s [flags] service1 signin -username STRING -password STRING
Signin implements signin.
-username STRING: Username used to perform signin
-password STRING: Password used to perform signin
Example:
%[1]s service1 signin --username "user" --password "password"
`, os.Args[0])
}
func service1SecureUsage() {
fmt.Fprintf(os.Stderr, `%[1]s [flags] service1 secure -body JSON -token STRING
这是一个需要JWT认证的接口
-body JSON:
-token STRING:
Example:
%[1]s service1 secure --body '{
"fail": true
}' --token "Ducimus aut similique."
`, os.Args[0])
}

View File

@ -0,0 +1 @@
{"swagger":"2.0","info":{"title":"A Goa Example Service","description":"HTTP service for test","version":""},"host":"localhost:8088","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/secure":{"get":{"tags":["Service1"],"summary":"secure Service1","description":"这是一个需要JWT认证的接口","operationId":"Service1#secure","parameters":[{"name":"Authorization","in":"header","description":"JWT used for authentication","required":true,"type":"string"},{"name":"SecureRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/Service1SecureRequestBody"}}],"responses":{"200":{"description":"OK response.","schema":{"type":"string"}},"401":{"description":"Unauthorized response.","schema":{"type":"string"}}},"schemes":["http"],"security":[{"jwt_header_Authorization":[]}]}},"/signin":{"post":{"tags":["Service1"],"summary":"signin Service1","operationId":"Service1#signin","parameters":[{"name":"Authorization","in":"header","description":"Basic Auth security using Basic scheme (https://tools.ietf.org/html/rfc7617)","required":true,"type":"string"}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/Service1SigninOKResponseBody","required":["jwt","api_key","oauth_token"]}},"400":{"description":"Bad Request response.","schema":{"$ref":"#/definitions/Service1SigninBadRequestResponseBody","required":["jwt","api_key","oauth_token"]}},"401":{"description":"Unauthorized response.","schema":{"type":"string"}}},"schemes":["http"],"security":[{"basic_header_Authorization":[]}]}}},"definitions":{"Service1SecureRequestBody":{"title":"Service1SecureRequestBody","type":"object","properties":{"fail":{"type":"boolean","description":"Whether to force auth failure even with a valid JWT","example":false}},"example":{"fail":false}},"Service1SigninBadRequestResponseBody":{"title":"Service1SigninBadRequestResponseBody","type":"object","properties":{"api_key":{"type":"string","description":"API Key","example":"abcdef12345"},"jwt":{"type":"string","description":"JWT token","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"},"oauth_token":{"type":"string","description":"OAuth2 token","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"}},"example":{"api_key":"abcdef12345","jwt":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ","oauth_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"},"required":["jwt","api_key","oauth_token"]},"Service1SigninOKResponseBody":{"title":"Service1SigninOKResponseBody","type":"object","properties":{"api_key":{"type":"string","description":"API Key","example":"abcdef12345"},"jwt":{"type":"string","description":"JWT token","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"},"oauth_token":{"type":"string","description":"OAuth2 token","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"}},"example":{"api_key":"abcdef12345","jwt":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ","oauth_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"},"required":["jwt","api_key","oauth_token"]}},"securityDefinitions":{"basic_header_Authorization":{"type":"basic","description":"Basic authentication used to authenticate security principal during signin"},"jwt_header_Authorization":{"type":"apiKey","description":"Secures endpoint by requiring a valid JWT token retrieved via the signin endpoint. Supports scopes \"api:read\" and \"api:write\".","name":"Authorization","in":"header"}}}

View File

@ -0,0 +1,153 @@
swagger: "2.0"
info:
title: A Goa Example Service
description: HTTP service for test
version: ""
host: localhost:8088
consumes:
- application/json
- application/xml
- application/gob
produces:
- application/json
- application/xml
- application/gob
paths:
/secure:
get:
tags:
- Service1
summary: secure Service1
description: 这是一个需要JWT认证的接口
operationId: Service1#secure
parameters:
- name: Authorization
in: header
description: JWT used for authentication
required: true
type: string
- name: SecureRequestBody
in: body
required: true
schema:
$ref: '#/definitions/Service1SecureRequestBody'
responses:
"200":
description: OK response.
schema:
type: string
"401":
description: Unauthorized response.
schema:
type: string
schemes:
- http
security:
- jwt_header_Authorization: []
/signin:
post:
tags:
- Service1
summary: signin Service1
operationId: Service1#signin
parameters:
- name: Authorization
in: header
description: Basic Auth security using Basic scheme (https://tools.ietf.org/html/rfc7617)
required: true
type: string
responses:
"200":
description: OK response.
schema:
$ref: '#/definitions/Service1SigninOKResponseBody'
required:
- jwt
- api_key
- oauth_token
"400":
description: Bad Request response.
schema:
$ref: '#/definitions/Service1SigninBadRequestResponseBody'
required:
- jwt
- api_key
- oauth_token
"401":
description: Unauthorized response.
schema:
type: string
schemes:
- http
security:
- basic_header_Authorization: []
definitions:
Service1SecureRequestBody:
title: Service1SecureRequestBody
type: object
properties:
fail:
type: boolean
description: Whether to force auth failure even with a valid JWT
example: false
example:
fail: false
Service1SigninBadRequestResponseBody:
title: Service1SigninBadRequestResponseBody
type: object
properties:
api_key:
type: string
description: API Key
example: abcdef12345
jwt:
type: string
description: JWT token
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
oauth_token:
type: string
description: OAuth2 token
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
example:
api_key: abcdef12345
jwt: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
oauth_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
required:
- jwt
- api_key
- oauth_token
Service1SigninOKResponseBody:
title: Service1SigninOKResponseBody
type: object
properties:
api_key:
type: string
description: API Key
example: abcdef12345
jwt:
type: string
description: JWT token
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
oauth_token:
type: string
description: OAuth2 token
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
example:
api_key: abcdef12345
jwt: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
oauth_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
required:
- jwt
- api_key
- oauth_token
securityDefinitions:
basic_header_Authorization:
type: basic
description: Basic authentication used to authenticate security principal during
signin
jwt_header_Authorization:
type: apiKey
description: Secures endpoint by requiring a valid JWT token retrieved via the
signin endpoint. Supports scopes "api:read" and "api:write".
name: Authorization
in: header

View File

@ -0,0 +1 @@
{"openapi":"3.0.3","info":{"title":"A Goa Example Service","description":"HTTP service for test","version":"1.0"},"servers":[{"url":"http://localhost:8088"},{"url":"http://localhost:8088"}],"paths":{"/secure":{"get":{"tags":["Service1"],"summary":"secure Service1","description":"这是一个需要JWT认证的接口","operationId":"Service1#secure","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecureRequestBody"},"example":{"fail":true}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","example":"Commodi earum ut dolorem qui."},"example":"Aliquid corrupti facere voluptate."}}},"401":{"description":"Unauthorized response.","content":{"application/json":{"schema":{"type":"string","example":"Alias placeat est tenetur ad distinctio nesciunt."},"example":"Odit qui ut culpa est."}}}},"security":[{"jwt_header_Authorization":[]}]}},"/signin":{"post":{"tags":["Service1"],"summary":"signin Service1","operationId":"Service1#signin","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Creds"},"example":{"api_key":"abcdef12345","jwt":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ","oauth_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"}}}},"400":{"description":"Bad Request response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Creds"},"example":{"api_key":"abcdef12345","jwt":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ","oauth_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"}}}},"401":{"description":"Unauthorized response.","content":{"application/json":{"schema":{"type":"string","example":"Voluptate non dolore autem ipsam omnis."},"example":"Et necessitatibus cupiditate repudiandae iste."}}}},"security":[{"basic_header_Authorization":[]}]}}},"components":{"schemas":{"Creds":{"type":"object","properties":{"api_key":{"type":"string","description":"API Key","example":"abcdef12345"},"jwt":{"type":"string","description":"JWT token","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"},"oauth_token":{"type":"string","description":"OAuth2 token","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"}},"example":{"api_key":"abcdef12345","jwt":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ","oauth_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"},"required":["jwt","api_key","oauth_token"]},"SecureRequestBody":{"type":"object","properties":{"fail":{"type":"boolean","description":"Whether to force auth failure even with a valid JWT","example":false}},"example":{"fail":false}}},"securitySchemes":{"basic_header_Authorization":{"type":"http","description":"Basic authentication used to authenticate security principal during signin","scheme":"basic"},"jwt_header_Authorization":{"type":"http","description":"Secures endpoint by requiring a valid JWT token retrieved via the signin endpoint. Supports scopes \"api:read\" and \"api:write\".","scheme":"bearer"}}},"tags":[{"name":"Service1","description":"The secured service exposes endpoints that require valid authorization credentials."}]}

View File

@ -0,0 +1,129 @@
openapi: 3.0.3
info:
title: A Goa Example Service
description: HTTP service for test
version: "1.0"
servers:
- url: http://localhost:8088
- url: http://localhost:8088
paths:
/secure:
get:
tags:
- Service1
summary: secure Service1
description: 这是一个需要JWT认证的接口
operationId: Service1#secure
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SecureRequestBody'
example:
fail: true
responses:
"200":
description: OK response.
content:
application/json:
schema:
type: string
example: Commodi earum ut dolorem qui.
example: Aliquid corrupti facere voluptate.
"401":
description: Unauthorized response.
content:
application/json:
schema:
type: string
example: Alias placeat est tenetur ad distinctio nesciunt.
example: Odit qui ut culpa est.
security:
- jwt_header_Authorization: []
/signin:
post:
tags:
- Service1
summary: signin Service1
operationId: Service1#signin
responses:
"200":
description: OK response.
content:
application/json:
schema:
$ref: '#/components/schemas/Creds'
example:
api_key: abcdef12345
jwt: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
oauth_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
"400":
description: Bad Request response.
content:
application/json:
schema:
$ref: '#/components/schemas/Creds'
example:
api_key: abcdef12345
jwt: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
oauth_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
"401":
description: Unauthorized response.
content:
application/json:
schema:
type: string
example: Voluptate non dolore autem ipsam omnis.
example: Et necessitatibus cupiditate repudiandae iste.
security:
- basic_header_Authorization: []
components:
schemas:
Creds:
type: object
properties:
api_key:
type: string
description: API Key
example: abcdef12345
jwt:
type: string
description: JWT token
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
oauth_token:
type: string
description: OAuth2 token
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
example:
api_key: abcdef12345
jwt: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
oauth_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
required:
- jwt
- api_key
- oauth_token
SecureRequestBody:
type: object
properties:
fail:
type: boolean
description: Whether to force auth failure even with a valid JWT
example: false
example:
fail: false
securitySchemes:
basic_header_Authorization:
type: http
description: Basic authentication used to authenticate security principal during
signin
scheme: basic
jwt_header_Authorization:
type: http
description: Secures endpoint by requiring a valid JWT token retrieved via the
signin endpoint. Supports scopes "api:read" and "api:write".
scheme: bearer
tags:
- name: Service1
description: The secured service exposes endpoints that require valid authorization
credentials.

View File

@ -0,0 +1,55 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// Service1 HTTP client CLI support package
//
// Command:
// $ goa gen goa_example/design
package client
import (
"encoding/json"
"fmt"
service1 "goa_example/gen/service1"
)
// BuildSigninPayload builds the payload for the Service1 signin endpoint from
// CLI flags.
func BuildSigninPayload(service1SigninUsername string, service1SigninPassword string) (*service1.SigninPayload, error) {
var username string
{
username = service1SigninUsername
}
var password string
{
password = service1SigninPassword
}
v := &service1.SigninPayload{}
v.Username = username
v.Password = password
return v, nil
}
// BuildSecurePayload builds the payload for the Service1 secure endpoint from
// CLI flags.
func BuildSecurePayload(service1SecureBody string, service1SecureToken string) (*service1.SecurePayload, error) {
var err error
var body SecureRequestBody
{
err = json.Unmarshal([]byte(service1SecureBody), &body)
if err != nil {
return nil, fmt.Errorf("invalid JSON for body, \nerror: %s, \nexample of valid JSON:\n%s", err, "'{\n \"fail\": true\n }'")
}
}
var token string
{
token = service1SecureToken
}
v := &service1.SecurePayload{
Fail: body.Fail,
}
v.Token = token
return v, nil
}

View File

@ -0,0 +1,102 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// Service1 client HTTP transport
//
// Command:
// $ goa gen goa_example/design
package client
import (
"context"
"net/http"
goahttp "goa.design/goa/v3/http"
goa "goa.design/goa/v3/pkg"
)
// Client lists the Service1 service endpoint HTTP clients.
type Client struct {
// Signin Doer is the HTTP client used to make requests to the signin endpoint.
SigninDoer goahttp.Doer
// Secure Doer is the HTTP client used to make requests to the secure endpoint.
SecureDoer goahttp.Doer
// RestoreResponseBody controls whether the response bodies are reset after
// decoding so they can be read again.
RestoreResponseBody bool
scheme string
host string
encoder func(*http.Request) goahttp.Encoder
decoder func(*http.Response) goahttp.Decoder
}
// NewClient instantiates HTTP clients for all the Service1 service servers.
func NewClient(
scheme string,
host string,
doer goahttp.Doer,
enc func(*http.Request) goahttp.Encoder,
dec func(*http.Response) goahttp.Decoder,
restoreBody bool,
) *Client {
return &Client{
SigninDoer: doer,
SecureDoer: doer,
RestoreResponseBody: restoreBody,
scheme: scheme,
host: host,
decoder: dec,
encoder: enc,
}
}
// Signin returns an endpoint that makes HTTP requests to the Service1 service
// signin server.
func (c *Client) Signin() goa.Endpoint {
var (
encodeRequest = EncodeSigninRequest(c.encoder)
decodeResponse = DecodeSigninResponse(c.decoder, c.RestoreResponseBody)
)
return func(ctx context.Context, v interface{}) (interface{}, error) {
req, err := c.BuildSigninRequest(ctx, v)
if err != nil {
return nil, err
}
err = encodeRequest(req, v)
if err != nil {
return nil, err
}
resp, err := c.SigninDoer.Do(req)
if err != nil {
return nil, goahttp.ErrRequestError("Service1", "signin", err)
}
return decodeResponse(resp)
}
}
// Secure returns an endpoint that makes HTTP requests to the Service1 service
// secure server.
func (c *Client) Secure() goa.Endpoint {
var (
encodeRequest = EncodeSecureRequest(c.encoder)
decodeResponse = DecodeSecureResponse(c.decoder, c.RestoreResponseBody)
)
return func(ctx context.Context, v interface{}) (interface{}, error) {
req, err := c.BuildSecureRequest(ctx, v)
if err != nil {
return nil, err
}
err = encodeRequest(req, v)
if err != nil {
return nil, err
}
resp, err := c.SecureDoer.Do(req)
if err != nil {
return nil, goahttp.ErrRequestError("Service1", "secure", err)
}
return decodeResponse(resp)
}
}

View File

@ -0,0 +1,188 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// Service1 HTTP client encoders and decoders
//
// Command:
// $ goa gen goa_example/design
package client
import (
"bytes"
"context"
service1 "goa_example/gen/service1"
"io/ioutil"
"net/http"
"net/url"
"strings"
goahttp "goa.design/goa/v3/http"
)
// BuildSigninRequest instantiates a HTTP request object with method and path
// set to call the "Service1" service "signin" endpoint
func (c *Client) BuildSigninRequest(ctx context.Context, v interface{}) (*http.Request, error) {
u := &url.URL{Scheme: c.scheme, Host: c.host, Path: SigninService1Path()}
req, err := http.NewRequest("POST", u.String(), nil)
if err != nil {
return nil, goahttp.ErrInvalidURL("Service1", "signin", u.String(), err)
}
if ctx != nil {
req = req.WithContext(ctx)
}
return req, nil
}
// EncodeSigninRequest returns an encoder for requests sent to the Service1
// signin server.
func EncodeSigninRequest(encoder func(*http.Request) goahttp.Encoder) func(*http.Request, interface{}) error {
return func(req *http.Request, v interface{}) error {
p, ok := v.(*service1.SigninPayload)
if !ok {
return goahttp.ErrInvalidType("Service1", "signin", "*service1.SigninPayload", v)
}
req.SetBasicAuth(p.Username, p.Password)
return nil
}
}
// DecodeSigninResponse returns a decoder for responses returned by the
// Service1 signin endpoint. restoreBody controls whether the response body
// should be restored after having been read.
// DecodeSigninResponse may return the following errors:
// - "unauthorized" (type service1.Unauthorized): http.StatusUnauthorized
// - error: internal error
func DecodeSigninResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody bool) func(*http.Response) (interface{}, error) {
return func(resp *http.Response) (interface{}, error) {
if restoreBody {
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
resp.Body = ioutil.NopCloser(bytes.NewBuffer(b))
defer func() {
resp.Body = ioutil.NopCloser(bytes.NewBuffer(b))
}()
} else {
defer resp.Body.Close()
}
switch resp.StatusCode {
case http.StatusOK:
var (
body SigninOKResponseBody
err error
)
err = decoder(resp).Decode(&body)
if err != nil {
return nil, goahttp.ErrDecodingError("Service1", "signin", err)
}
err = ValidateSigninOKResponseBody(&body)
if err != nil {
return nil, goahttp.ErrValidationError("Service1", "signin", err)
}
res := NewSigninCredsOK(&body)
return res, nil
case http.StatusUnauthorized:
var (
body string
err error
)
err = decoder(resp).Decode(&body)
if err != nil {
return nil, goahttp.ErrDecodingError("Service1", "signin", err)
}
return nil, NewSigninUnauthorized(body)
default:
body, _ := ioutil.ReadAll(resp.Body)
return nil, goahttp.ErrInvalidResponse("Service1", "signin", resp.StatusCode, string(body))
}
}
}
// BuildSecureRequest instantiates a HTTP request object with method and path
// set to call the "Service1" service "secure" endpoint
func (c *Client) BuildSecureRequest(ctx context.Context, v interface{}) (*http.Request, error) {
u := &url.URL{Scheme: c.scheme, Host: c.host, Path: SecureService1Path()}
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
return nil, goahttp.ErrInvalidURL("Service1", "secure", u.String(), err)
}
if ctx != nil {
req = req.WithContext(ctx)
}
return req, nil
}
// EncodeSecureRequest returns an encoder for requests sent to the Service1
// secure server.
func EncodeSecureRequest(encoder func(*http.Request) goahttp.Encoder) func(*http.Request, interface{}) error {
return func(req *http.Request, v interface{}) error {
p, ok := v.(*service1.SecurePayload)
if !ok {
return goahttp.ErrInvalidType("Service1", "secure", "*service1.SecurePayload", v)
}
{
head := p.Token
if !strings.Contains(head, " ") {
req.Header.Set("Authorization", "Bearer "+head)
} else {
req.Header.Set("Authorization", head)
}
}
body := NewSecureRequestBody(p)
if err := encoder(req).Encode(&body); err != nil {
return goahttp.ErrEncodingError("Service1", "secure", err)
}
return nil
}
}
// DecodeSecureResponse returns a decoder for responses returned by the
// Service1 secure endpoint. restoreBody controls whether the response body
// should be restored after having been read.
// DecodeSecureResponse may return the following errors:
// - "unauthorized" (type service1.Unauthorized): http.StatusUnauthorized
// - error: internal error
func DecodeSecureResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody bool) func(*http.Response) (interface{}, error) {
return func(resp *http.Response) (interface{}, error) {
if restoreBody {
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
resp.Body = ioutil.NopCloser(bytes.NewBuffer(b))
defer func() {
resp.Body = ioutil.NopCloser(bytes.NewBuffer(b))
}()
} else {
defer resp.Body.Close()
}
switch resp.StatusCode {
case http.StatusOK:
var (
body string
err error
)
err = decoder(resp).Decode(&body)
if err != nil {
return nil, goahttp.ErrDecodingError("Service1", "secure", err)
}
return body, nil
case http.StatusUnauthorized:
var (
body string
err error
)
err = decoder(resp).Decode(&body)
if err != nil {
return nil, goahttp.ErrDecodingError("Service1", "secure", err)
}
return nil, NewSecureUnauthorized(body)
default:
body, _ := ioutil.ReadAll(resp.Body)
return nil, goahttp.ErrInvalidResponse("Service1", "secure", resp.StatusCode, string(body))
}
}
}

View File

@ -0,0 +1,18 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// HTTP request path constructors for the Service1 service.
//
// Command:
// $ goa gen goa_example/design
package client
// SigninService1Path returns the URL path to the Service1 service signin HTTP endpoint.
func SigninService1Path() string {
return "/signin"
}
// SecureService1Path returns the URL path to the Service1 service secure HTTP endpoint.
func SecureService1Path() string {
return "/secure"
}

View File

@ -0,0 +1,109 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// Service1 HTTP client types
//
// Command:
// $ goa gen goa_example/design
package client
import (
service1 "goa_example/gen/service1"
goa "goa.design/goa/v3/pkg"
)
// SecureRequestBody is the type of the "Service1" service "secure" endpoint
// HTTP request body.
type SecureRequestBody struct {
// Whether to force auth failure even with a valid JWT
Fail *bool `form:"fail,omitempty" json:"fail,omitempty" xml:"fail,omitempty"`
}
// SigninOKResponseBody is the type of the "Service1" service "signin" endpoint
// HTTP response body.
type SigninOKResponseBody struct {
// JWT token
JWT *string `form:"jwt,omitempty" json:"jwt,omitempty" xml:"jwt,omitempty"`
// API Key
APIKey *string `form:"api_key,omitempty" json:"api_key,omitempty" xml:"api_key,omitempty"`
// OAuth2 token
OauthToken *string `form:"oauth_token,omitempty" json:"oauth_token,omitempty" xml:"oauth_token,omitempty"`
}
// SigninBadRequestResponseBody is used to define fields on response body types.
type SigninBadRequestResponseBody struct {
// JWT token
JWT *string `form:"jwt,omitempty" json:"jwt,omitempty" xml:"jwt,omitempty"`
// API Key
APIKey *string `form:"api_key,omitempty" json:"api_key,omitempty" xml:"api_key,omitempty"`
// OAuth2 token
OauthToken *string `form:"oauth_token,omitempty" json:"oauth_token,omitempty" xml:"oauth_token,omitempty"`
}
// NewSecureRequestBody builds the HTTP request body from the payload of the
// "secure" endpoint of the "Service1" service.
func NewSecureRequestBody(p *service1.SecurePayload) *SecureRequestBody {
body := &SecureRequestBody{
Fail: p.Fail,
}
return body
}
// NewSigninCredsOK builds a "Service1" service "signin" endpoint result from a
// HTTP "OK" response.
func NewSigninCredsOK(body *SigninOKResponseBody) *service1.Creds {
v := &service1.Creds{
JWT: *body.JWT,
APIKey: *body.APIKey,
OauthToken: *body.OauthToken,
}
return v
}
// NewSigninUnauthorized builds a Service1 service signin endpoint unauthorized
// error.
func NewSigninUnauthorized(body string) service1.Unauthorized {
v := service1.Unauthorized(body)
return v
}
// NewSecureUnauthorized builds a Service1 service secure endpoint unauthorized
// error.
func NewSecureUnauthorized(body string) service1.Unauthorized {
v := service1.Unauthorized(body)
return v
}
// ValidateSigninOKResponseBody runs the validations defined on
// SigninOKResponseBody
func ValidateSigninOKResponseBody(body *SigninOKResponseBody) (err error) {
if body.JWT == nil {
err = goa.MergeErrors(err, goa.MissingFieldError("jwt", "body"))
}
if body.APIKey == nil {
err = goa.MergeErrors(err, goa.MissingFieldError("api_key", "body"))
}
if body.OauthToken == nil {
err = goa.MergeErrors(err, goa.MissingFieldError("oauth_token", "body"))
}
return
}
// ValidateSigninBadRequestResponseBody runs the validations defined on
// SigninBad RequestResponseBody
func ValidateSigninBadRequestResponseBody(body *SigninBadRequestResponseBody) (err error) {
if body.JWT == nil {
err = goa.MergeErrors(err, goa.MissingFieldError("jwt", "body"))
}
if body.APIKey == nil {
err = goa.MergeErrors(err, goa.MissingFieldError("api_key", "body"))
}
if body.OauthToken == nil {
err = goa.MergeErrors(err, goa.MissingFieldError("oauth_token", "body"))
}
return
}

View File

@ -0,0 +1,143 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// Service1 HTTP server encoders and decoders
//
// Command:
// $ goa gen goa_example/design
package server
import (
"context"
"errors"
service1 "goa_example/gen/service1"
"io"
"net/http"
"strings"
goahttp "goa.design/goa/v3/http"
goa "goa.design/goa/v3/pkg"
)
// EncodeSigninResponse returns an encoder for responses returned by the
// Service1 signin endpoint.
func EncodeSigninResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, interface{}) error {
return func(ctx context.Context, w http.ResponseWriter, v interface{}) error {
res, _ := v.(*service1.Creds)
enc := encoder(ctx, w)
body := NewSigninOKResponseBody(res)
w.WriteHeader(http.StatusOK)
return enc.Encode(body)
}
}
// DecodeSigninRequest returns a decoder for requests sent to the Service1
// signin endpoint.
func DecodeSigninRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (interface{}, error) {
return func(r *http.Request) (interface{}, error) {
payload := NewSigninPayload()
user, pass, ok := r.BasicAuth()
if !ok {
return nil, goa.MissingFieldError("Authorization", "header")
}
payload.Username = user
payload.Password = pass
return payload, nil
}
}
// EncodeSigninError returns an encoder for errors returned by the signin
// Service1 endpoint.
func EncodeSigninError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error {
encodeError := goahttp.ErrorEncoder(encoder, formatter)
return func(ctx context.Context, w http.ResponseWriter, v error) error {
var en ErrorNamer
if !errors.As(v, &en) {
return encodeError(ctx, w, v)
}
switch en.ErrorName() {
case "unauthorized":
res := v.(service1.Unauthorized)
enc := encoder(ctx, w)
body := res
w.Header().Set("goa-error", res.ErrorName())
w.WriteHeader(http.StatusUnauthorized)
return enc.Encode(body)
default:
return encodeError(ctx, w, v)
}
}
}
// EncodeSecureResponse returns an encoder for responses returned by the
// Service1 secure endpoint.
func EncodeSecureResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, interface{}) error {
return func(ctx context.Context, w http.ResponseWriter, v interface{}) error {
res, _ := v.(string)
enc := encoder(ctx, w)
body := res
w.WriteHeader(http.StatusOK)
return enc.Encode(body)
}
}
// DecodeSecureRequest returns a decoder for requests sent to the Service1
// secure endpoint.
func DecodeSecureRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (interface{}, error) {
return func(r *http.Request) (interface{}, error) {
var (
body SecureRequestBody
err error
)
err = decoder(r).Decode(&body)
if err != nil {
if err == io.EOF {
return nil, goa.MissingPayloadError()
}
return nil, goa.DecodePayloadError(err.Error())
}
var (
token string
)
token = r.Header.Get("Authorization")
if token == "" {
err = goa.MergeErrors(err, goa.MissingFieldError("Authorization", "header"))
}
if err != nil {
return nil, err
}
payload := NewSecurePayload(&body, token)
if strings.Contains(payload.Token, " ") {
// Remove authorization scheme prefix (e.g. "Bearer")
cred := strings.SplitN(payload.Token, " ", 2)[1]
payload.Token = cred
}
return payload, nil
}
}
// EncodeSecureError returns an encoder for errors returned by the secure
// Service1 endpoint.
func EncodeSecureError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error {
encodeError := goahttp.ErrorEncoder(encoder, formatter)
return func(ctx context.Context, w http.ResponseWriter, v error) error {
var en ErrorNamer
if !errors.As(v, &en) {
return encodeError(ctx, w, v)
}
switch en.ErrorName() {
case "unauthorized":
res := v.(service1.Unauthorized)
enc := encoder(ctx, w)
body := res
w.Header().Set("goa-error", res.ErrorName())
w.WriteHeader(http.StatusUnauthorized)
return enc.Encode(body)
default:
return encodeError(ctx, w, v)
}
}
}

View File

@ -0,0 +1,18 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// HTTP request path constructors for the Service1 service.
//
// Command:
// $ goa gen goa_example/design
package server
// SigninService1Path returns the URL path to the Service1 service signin HTTP endpoint.
func SigninService1Path() string {
return "/signin"
}
// SecureService1Path returns the URL path to the Service1 service secure HTTP endpoint.
func SecureService1Path() string {
return "/secure"
}

View File

@ -0,0 +1,187 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// Service1 HTTP server
//
// Command:
// $ goa gen goa_example/design
package server
import (
"context"
service1 "goa_example/gen/service1"
"net/http"
goahttp "goa.design/goa/v3/http"
goa "goa.design/goa/v3/pkg"
)
// Server lists the Service1 service endpoint HTTP handlers.
type Server struct {
Mounts []*MountPoint
Signin http.Handler
Secure http.Handler
}
// ErrorNamer is an interface implemented by generated error structs that
// exposes the name of the error as defined in the design.
type ErrorNamer interface {
ErrorName() string
}
// MountPoint holds information about the mounted endpoints.
type MountPoint struct {
// Method is the name of the service method served by the mounted HTTP handler.
Method string
// Verb is the HTTP method used to match requests to the mounted handler.
Verb string
// Pattern is the HTTP request path pattern used to match requests to the
// mounted handler.
Pattern string
}
// New instantiates HTTP handlers for all the Service1 service endpoints using
// the provided encoder and decoder. The handlers are mounted on the given mux
// using the HTTP verb and path defined in the design. errhandler is called
// whenever a response fails to be encoded. formatter is used to format errors
// returned by the service methods prior to encoding. Both errhandler and
// formatter are optional and can be nil.
func New(
e *service1.Endpoints,
mux goahttp.Muxer,
decoder func(*http.Request) goahttp.Decoder,
encoder func(context.Context, http.ResponseWriter) goahttp.Encoder,
errhandler func(context.Context, http.ResponseWriter, error),
formatter func(err error) goahttp.Statuser,
) *Server {
return &Server{
Mounts: []*MountPoint{
{"Signin", "POST", "/signin"},
{"Secure", "GET", "/secure"},
},
Signin: NewSigninHandler(e.Signin, mux, decoder, encoder, errhandler, formatter),
Secure: NewSecureHandler(e.Secure, mux, decoder, encoder, errhandler, formatter),
}
}
// Service returns the name of the service served.
func (s *Server) Service() string { return "Service1" }
// Use wraps the server handlers with the given middleware.
func (s *Server) Use(m func(http.Handler) http.Handler) {
s.Signin = m(s.Signin)
s.Secure = m(s.Secure)
}
// Mount configures the mux to serve the Service1 endpoints.
func Mount(mux goahttp.Muxer, h *Server) {
MountSigninHandler(mux, h.Signin)
MountSecureHandler(mux, h.Secure)
}
// Mount configures the mux to serve the Service1 endpoints.
func (s *Server) Mount(mux goahttp.Muxer) {
Mount(mux, s)
}
// MountSigninHandler configures the mux to serve the "Service1" service
// "signin" endpoint.
func MountSigninHandler(mux goahttp.Muxer, h http.Handler) {
f, ok := h.(http.HandlerFunc)
if !ok {
f = func(w http.ResponseWriter, r *http.Request) {
h.ServeHTTP(w, r)
}
}
mux.Handle("POST", "/signin", f)
}
// NewSigninHandler creates a HTTP handler which loads the HTTP request and
// calls the "Service1" service "signin" endpoint.
func NewSigninHandler(
endpoint goa.Endpoint,
mux goahttp.Muxer,
decoder func(*http.Request) goahttp.Decoder,
encoder func(context.Context, http.ResponseWriter) goahttp.Encoder,
errhandler func(context.Context, http.ResponseWriter, error),
formatter func(err error) goahttp.Statuser,
) http.Handler {
var (
decodeRequest = DecodeSigninRequest(mux, decoder)
encodeResponse = EncodeSigninResponse(encoder)
encodeError = EncodeSigninError(encoder, formatter)
)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(r.Context(), goahttp.AcceptTypeKey, r.Header.Get("Accept"))
ctx = context.WithValue(ctx, goa.MethodKey, "signin")
ctx = context.WithValue(ctx, goa.ServiceKey, "Service1")
payload, err := decodeRequest(r)
if err != nil {
if err := encodeError(ctx, w, err); err != nil {
errhandler(ctx, w, err)
}
return
}
res, err := endpoint(ctx, payload)
if err != nil {
if err := encodeError(ctx, w, err); err != nil {
errhandler(ctx, w, err)
}
return
}
if err := encodeResponse(ctx, w, res); err != nil {
errhandler(ctx, w, err)
}
})
}
// MountSecureHandler configures the mux to serve the "Service1" service
// "secure" endpoint.
func MountSecureHandler(mux goahttp.Muxer, h http.Handler) {
f, ok := h.(http.HandlerFunc)
if !ok {
f = func(w http.ResponseWriter, r *http.Request) {
h.ServeHTTP(w, r)
}
}
mux.Handle("GET", "/secure", f)
}
// NewSecureHandler creates a HTTP handler which loads the HTTP request and
// calls the "Service1" service "secure" endpoint.
func NewSecureHandler(
endpoint goa.Endpoint,
mux goahttp.Muxer,
decoder func(*http.Request) goahttp.Decoder,
encoder func(context.Context, http.ResponseWriter) goahttp.Encoder,
errhandler func(context.Context, http.ResponseWriter, error),
formatter func(err error) goahttp.Statuser,
) http.Handler {
var (
decodeRequest = DecodeSecureRequest(mux, decoder)
encodeResponse = EncodeSecureResponse(encoder)
encodeError = EncodeSecureError(encoder, formatter)
)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(r.Context(), goahttp.AcceptTypeKey, r.Header.Get("Accept"))
ctx = context.WithValue(ctx, goa.MethodKey, "secure")
ctx = context.WithValue(ctx, goa.ServiceKey, "Service1")
payload, err := decodeRequest(r)
if err != nil {
if err := encodeError(ctx, w, err); err != nil {
errhandler(ctx, w, err)
}
return
}
res, err := endpoint(ctx, payload)
if err != nil {
if err := encodeError(ctx, w, err); err != nil {
errhandler(ctx, w, err)
}
return
}
if err := encodeResponse(ctx, w, res); err != nil {
errhandler(ctx, w, err)
}
})
}

View File

@ -0,0 +1,58 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// Service1 HTTP server types
//
// Command:
// $ goa gen goa_example/design
package server
import (
service1 "goa_example/gen/service1"
)
// SecureRequestBody is the type of the "Service1" service "secure" endpoint
// HTTP request body.
type SecureRequestBody struct {
// Whether to force auth failure even with a valid JWT
Fail *bool `form:"fail,omitempty" json:"fail,omitempty" xml:"fail,omitempty"`
}
// SigninOKResponseBody is the type of the "Service1" service "signin" endpoint
// HTTP response body.
type SigninOKResponseBody struct {
// JWT token
JWT string `form:"jwt" json:"jwt" xml:"jwt"`
// API Key
APIKey string `form:"api_key" json:"api_key" xml:"api_key"`
// OAuth2 token
OauthToken string `form:"oauth_token" json:"oauth_token" xml:"oauth_token"`
}
// NewSigninOKResponseBody builds the HTTP response body from the result of the
// "signin" endpoint of the "Service1" service.
func NewSigninOKResponseBody(res *service1.Creds) *SigninOKResponseBody {
body := &SigninOKResponseBody{
JWT: res.JWT,
APIKey: res.APIKey,
OauthToken: res.OauthToken,
}
return body
}
// NewSigninPayload builds a Service1 service signin endpoint payload.
func NewSigninPayload() *service1.SigninPayload {
v := &service1.SigninPayload{}
return v
}
// NewSecurePayload builds a Service1 service secure endpoint payload.
func NewSecurePayload(body *SecureRequestBody, token string) *service1.SecurePayload {
v := &service1.SecurePayload{
Fail: body.Fail,
}
v.Token = token
return v
}

View File

@ -0,0 +1,48 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// Service1 client
//
// Command:
// $ goa gen goa_example/design
package service1
import (
"context"
goa "goa.design/goa/v3/pkg"
)
// Client is the "Service1" service client.
type Client struct {
SigninEndpoint goa.Endpoint
SecureEndpoint goa.Endpoint
}
// NewClient initializes a "Service1" service client given the endpoints.
func NewClient(signin, secure goa.Endpoint) *Client {
return &Client{
SigninEndpoint: signin,
SecureEndpoint: secure,
}
}
// Signin calls the "signin" endpoint of the "Service1" service.
func (c *Client) Signin(ctx context.Context, p *SigninPayload) (res *Creds, err error) {
var ires interface{}
ires, err = c.SigninEndpoint(ctx, p)
if err != nil {
return
}
return ires.(*Creds), nil
}
// Secure calls the "secure" endpoint of the "Service1" service.
func (c *Client) Secure(ctx context.Context, p *SecurePayload) (res string, err error) {
var ires interface{}
ires, err = c.SecureEndpoint(ctx, p)
if err != nil {
return
}
return ires.(string), nil
}

View File

@ -0,0 +1,75 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// Service1 endpoints
//
// Command:
// $ goa gen goa_example/design
package service1
import (
"context"
goa "goa.design/goa/v3/pkg"
"goa.design/goa/v3/security"
)
// Endpoints wraps the "Service1" service endpoints.
type Endpoints struct {
Signin goa.Endpoint
Secure goa.Endpoint
}
// NewEndpoints wraps the methods of the "Service1" service with endpoints.
func NewEndpoints(s Service) *Endpoints {
// Casting service to Auther interface
a := s.(Auther)
return &Endpoints{
Signin: NewSigninEndpoint(s, a.BasicAuth),
Secure: NewSecureEndpoint(s, a.JWTAuth),
}
}
// Use applies the given middleware to all the "Service1" service endpoints.
func (e *Endpoints) Use(m func(goa.Endpoint) goa.Endpoint) {
e.Signin = m(e.Signin)
e.Secure = m(e.Secure)
}
// NewSigninEndpoint returns an endpoint function that calls the method
// "signin" of service "Service1".
func NewSigninEndpoint(s Service, authBasicFn security.AuthBasicFunc) goa.Endpoint {
return func(ctx context.Context, req interface{}) (interface{}, error) {
p := req.(*SigninPayload)
var err error
sc := security.BasicScheme{
Name: "basic",
Scopes: []string{},
RequiredScopes: []string{},
}
ctx, err = authBasicFn(ctx, p.Username, p.Password, &sc)
if err != nil {
return nil, err
}
return s.Signin(ctx, p)
}
}
// NewSecureEndpoint returns an endpoint function that calls the method
// "secure" of service "Service1".
func NewSecureEndpoint(s Service, authJWTFn security.AuthJWTFunc) goa.Endpoint {
return func(ctx context.Context, req interface{}) (interface{}, error) {
p := req.(*SecurePayload)
var err error
sc := security.JWTScheme{
Name: "jwt",
Scopes: []string{},
RequiredScopes: []string{},
}
ctx, err = authJWTFn(ctx, p.Token, &sc)
if err != nil {
return nil, err
}
return s.Secure(ctx, p)
}
}

View File

@ -0,0 +1,80 @@
// Code generated by goa v3.6.0, DO NOT EDIT.
//
// Service1 service
//
// Command:
// $ goa gen goa_example/design
package service1
import (
"context"
"goa.design/goa/v3/security"
)
// The secured service exposes endpoints that require valid authorization
// credentials.
type Service interface {
// Signin implements signin.
Signin(context.Context, *SigninPayload) (res *Creds, err error)
// 这是一个需要JWT认证的接口
Secure(context.Context, *SecurePayload) (res string, err error)
}
// Auther defines the authorization functions to be implemented by the service.
type Auther interface {
// BasicAuth implements the authorization logic for the Basic security scheme.
BasicAuth(ctx context.Context, user, pass string, schema *security.BasicScheme) (context.Context, error)
// JWTAuth implements the authorization logic for the JWT security scheme.
JWTAuth(ctx context.Context, token string, schema *security.JWTScheme) (context.Context, error)
}
// ServiceName is the name of the service as defined in the design. This is the
// same value that is set in the endpoint request contexts under the ServiceKey
// key.
const ServiceName = "Service1"
// MethodNames lists the service method names as defined in the design. These
// are the same values that are set in the endpoint request contexts under the
// MethodKey key.
var MethodNames = [2]string{"signin", "secure"}
// Creds is the result type of the Service1 service signin method.
type Creds struct {
// JWT token
JWT string
// API Key
APIKey string
// OAuth2 token
OauthToken string
}
// SecurePayload is the payload type of the Service1 service secure method.
type SecurePayload struct {
// Whether to force auth failure even with a valid JWT
Fail *bool
// JWT used for authentication
Token string
}
// Credentials used to authenticate to retrieve JWT token
type SigninPayload struct {
// Username used to perform signin
Username string
// Password used to perform signin
Password string
}
// Credentials are invalid
type Unauthorized string
// Error returns an error description.
func (e Unauthorized) Error() string {
return "Credentials are invalid"
}
// ErrorName returns "unauthorized".
func (e Unauthorized) ErrorName() string {
return "unauthorized"
}

26
go/goa_example/go.mod Normal file
View File

@ -0,0 +1,26 @@
module goa_example
go 1.17
require goa.design/goa/v3 v3.6.0
require (
github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
github.com/jtolds/gls v4.20.0+incompatible // indirect
github.com/kr/text v0.2.0 // indirect
github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/sergi/go-diff v1.2.0 // indirect
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect
github.com/stretchr/testify v1.7.0 // indirect
github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea // indirect
golang.org/x/mod v0.5.1 // indirect
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect
golang.org/x/tools v0.1.9 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
)

206
go/goa_example/go.sum Normal file
View File

@ -0,0 +1,206 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI=
github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598/go.mod h1:0FpDmbrt36utu8jEmeU05dPC9AB5tsLYVVi+ZHfyuwI=
github.com/dimfeld/httptreemux/v5 v5.4.0/go.mod h1:QeEylH57C0v3VO0tkKraVz9oD3Uu93CKPnTLbsidvSw=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/getkin/kin-openapi v0.90.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.13/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gxui v0.0.0-20151028112939-f85e0a97b3a4 h1:OL2d27ueTKnlQJoqLW2fc9pWYulFnJYLWzomGV7HqZo=
github.com/google/gxui v0.0.0-20151028112939-f85e0a97b3a4/go.mod h1:Pw1H1OjSNHiqeuxAduB1BKYXIwFtsyrY47nEqSgEiCM=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ=
github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s=
github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4=
github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b/go.mod h1:Bj8LjjP0ReT1eKt5QlKjwgi5AFm5mI6O1A2G4ChI0Ag=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea h1:CyhwejzVGvZ3Q2PSbQ4NRRYn+ZWv5eS1vlaEusT+bAI=
github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea/go.mod h1:eNr558nEUjP8acGw8FFjTeWvSgU1stO7FAO6eknhHe4=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
goa.design/goa/v3 v3.6.0 h1:sjOlBL3b4zC1sCdFuv26leFTJGbk48nLRhhTr1suyFA=
goa.design/goa/v3 v3.6.0/go.mod h1:Dmdfd7lWtKpCzpf5HWjvx63ds/lltkbOu4vJSGePq7k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.9 h1:j9KsMiaP1c3B0OTQGth0/k+miLGTgLsAFUCrF2vLcF8=
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -0,0 +1,74 @@
package exampleservice
import (
"context"
"fmt"
service1 "goa_example/gen/service1"
"log"
"goa.design/goa/v3/security"
)
// Service1 service example implementation.
// The example methods log the requests and return zero values.
type service1srvc struct {
logger *log.Logger
}
// NewService1 returns the Service1 service implementation.
func NewService1(logger *log.Logger) service1.Service {
return &service1srvc{logger}
}
// BasicAuth implements the authorization logic for service "Service1" for the
// "basic" security scheme.
func (s *service1srvc) BasicAuth(ctx context.Context, user, pass string, scheme *security.BasicScheme) (context.Context, error) {
//
// TBD: add authorization logic.
//
// In case of authorization failure this function should return
// one of the generated error structs, e.g.:
//
// return ctx, myservice.MakeUnauthorizedError("invalid token")
//
// Alternatively this function may return an instance of
// goa.ServiceError with a Name field value that matches one of
// the design error names, e.g:
//
// return ctx, goa.PermanentError("unauthorized", "invalid token")
//
return ctx, fmt.Errorf("not implemented")
}
// JWTAuth implements the authorization logic for service "Service1" for the
// "jwt" security scheme.
func (s *service1srvc) JWTAuth(ctx context.Context, token string, scheme *security.JWTScheme) (context.Context, error) {
//
// TBD: add authorization logic.
//
// In case of authorization failure this function should return
// one of the generated error structs, e.g.:
//
// return ctx, myservice.MakeUnauthorizedError("invalid token")
//
// Alternatively this function may return an instance of
// goa.ServiceError with a Name field value that matches one of
// the design error names, e.g:
//
// return ctx, goa.PermanentError("unauthorized", "invalid token")
//
return ctx, fmt.Errorf("not implemented")
}
// Signin implements signin.
func (s *service1srvc) Signin(ctx context.Context, p *service1.SigninPayload) (res *service1.Creds, err error) {
res = &service1.Creds{}
s.logger.Print("service1.signin")
return
}
// 这是一个需要JWT认证的接口
func (s *service1srvc) Secure(ctx context.Context, p *service1.SecurePayload) (res string, err error) {
s.logger.Print("service1.secure")
return
}