(Translated by https://www.hiragana.jp/)
Add support for using blank identifiers in `@kok(param)` · Issue #15 · RussellLuo/kun · GitHub
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for using blank identifiers in @kok(param) #15

Closed
RussellLuo opened this issue Jul 13, 2021 · 0 comments
Closed

Add support for using blank identifiers in @kok(param) #15

RussellLuo opened this issue Jul 13, 2021 · 0 comments

Comments

@RussellLuo
Copy link
Owner

RussellLuo commented Jul 13, 2021

Problem

Sometimes, an HTTP request parameter is only used in the Transport/Endpoint layer, and no further argument binding (in the Service layer) is needed.

Taking the following GetUser operation as an example:

type Service interface {
	// @kok(op): GET /users/{id}
	// @kok(success): body:user
	GetUser(ctx context.Context, id int) (user User, err error)
}

In order to protect the operation, we may implement service-to-service authentication via the Authorization header. Meanwhile, there is no corresponding argument in GetUser to be mapped to.

So how to represent this Authorization header in kok's HTTP annotation?

Proposed Solution

Add support for the blank identifier __ (double underscore, similar to Go's blank identifier) in @kok(param):

type Service interface {
	// @kok(op): GET /users/{id}
	// @kok(param): __ < in:header,name:Authorization,required:true
	// @kok(success): body:user
	GetUser(ctx context.Context, id int) (user User, err error)
}

And here is the possible codec.go for the Authorization header:

import (
	"fmt"

	"github.com/RussellLuo/kok/pkg/codec/httpcodec"
)

const (
	authPrivateKey = "AUTH_PRIVATE_KEY"
)

// AuthCodec is used to encode and decode the `Authorization` header. It can be reused wherever needed.
type AuthCodec struct{}

func (c AuthCodec) Decode(in []string, out interface{}) error {
	// NOTE: never use out, which is nil here.

	if len(in) == 0 || in[0] != authPrivateKey {
		return fmt.Errorf("authentication failed")
	}
	return nil
}

func (c AuthCodec) Encode(in interface{}) (out []string) {
	// NOTE: never use in, which is nil here.

	return []string{authPrivateKey}
}

func NewCodecs() *httpcodec.DefaultCodecs {
	// Use AuthCodec to encode and decode the argument named "__", if exists,
	// for the operation named "GetUser".
	return httpcodec.NewDefaultCodecs(nil,
		httpcodec.Op("GetUser", httpcodec.NewPatcher(httpcodec.JSON{}).Param("__", AuthCodec{})))
}

Multiple blank identifiers

In complicated cases, where multiple blank identifiers are involved and need to be differentiated from one another (typically for applying different encoders and decoders), we can use meaningful names, each with a double underscore prefix __ (e.g. __auth).

In summary, any name with a double underscore prefix __ is a valid blank identifier:

  • __
  • __auth
  • __other
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant