ing
This commit is contained in:
commit
558c2aba94
68
.gitignore
vendored
Normal file
68
.gitignore
vendored
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
|
### JetBrains template
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff:
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/dictionaries
|
||||||
|
|
||||||
|
# Sensitive or high-churn files:
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.xml
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
|
||||||
|
# Gradle:
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Mongo Explorer plugin:
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
## File-based project format:
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
## Plugin-specific files:
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
### Go template
|
||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, build with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
|
*.out
|
||||||
|
|
||||||
|
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
|
||||||
|
.glide/
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
vendor/
|
||||||
|
glide.lock
|
||||||
|
.DS_Store
|
||||||
|
dist/
|
||||||
|
debug
|
32
.vscode/launch.json
vendored
Normal file
32
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Debug",
|
||||||
|
"type": "go",
|
||||||
|
"request": "launch",
|
||||||
|
"mode": "debug",
|
||||||
|
"remotePath": "",
|
||||||
|
"port": 2345,
|
||||||
|
"host": "127.0.0.1",
|
||||||
|
"program": "${workspaceRoot}/main.go",
|
||||||
|
"env": {},
|
||||||
|
"args": [],
|
||||||
|
"showLog": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "File Debug",
|
||||||
|
"type": "go",
|
||||||
|
"request": "launch",
|
||||||
|
"mode": "debug",
|
||||||
|
"remotePath": "",
|
||||||
|
"port": 2345,
|
||||||
|
"host": "127.0.0.1",
|
||||||
|
"program": "${fileDirname}",
|
||||||
|
"env": {},
|
||||||
|
"args": [],
|
||||||
|
"showLog": true
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
5
glide.yaml
Normal file
5
glide.yaml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
package: git.loafle.net/commons/rest-go
|
||||||
|
import:
|
||||||
|
- package: git.loafle.net/commons/util-go
|
||||||
|
subpackages:
|
||||||
|
- encoding/json
|
6
registry/registry.go
Normal file
6
registry/registry.go
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package registry
|
||||||
|
|
||||||
|
type RESTInvoker interface {
|
||||||
|
HasMethod(method string) bool
|
||||||
|
Invoke(method string, params []string, leadingParams ...interface{}) (result interface{}, err error)
|
||||||
|
}
|
156
registry/rest-registry.go
Normal file
156
registry/rest-registry.go
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
package registry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
cuej "git.loafle.net/commons/util-go/encoding/json"
|
||||||
|
cus "git.loafle.net/commons/util-go/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewRESTRegistry returns a new REST registry.
|
||||||
|
func NewRESTRegistry() RESTRegistry {
|
||||||
|
return &restRegistry{
|
||||||
|
serviceRegistry: new(cus.ServiceRegistry),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type RESTRegistry interface {
|
||||||
|
RESTInvoker
|
||||||
|
GetService(name string) interface{}
|
||||||
|
RegisterService(receiver interface{}, name string) error
|
||||||
|
RegisterServices(receivers ...interface{}) error
|
||||||
|
RegisterServiceMap(keysAndValues map[string]interface{}) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// RESTRegistry serves registered REST services using registered codecs.
|
||||||
|
type restRegistry struct {
|
||||||
|
serviceRegistry *cus.ServiceRegistry
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterService adds a new service to the server.
|
||||||
|
//
|
||||||
|
// The name parameter is optional: if empty it will be inferred from
|
||||||
|
// the receiver type name.
|
||||||
|
//
|
||||||
|
// Methods from the receiver will be extracted if these rules are satisfied:
|
||||||
|
//
|
||||||
|
// - The receiver is exported (begins with an upper case letter) or local
|
||||||
|
// (defined in the package registering the service).
|
||||||
|
// - The method name is exported.
|
||||||
|
// - The method has two arguments: *args, *reply.
|
||||||
|
// - All two arguments are pointers.
|
||||||
|
// - The first and second arguments are exported or local.
|
||||||
|
// - The method has return type error.
|
||||||
|
//
|
||||||
|
// All other methods are ignored.
|
||||||
|
func (rr *restRegistry) RegisterService(receiver interface{}, name string) error {
|
||||||
|
return rr.serviceRegistry.Register(receiver, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rr *restRegistry) RegisterServices(receivers ...interface{}) error {
|
||||||
|
if nil == receivers || 0 == len(receivers) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, receiver := range receivers {
|
||||||
|
if err := rr.serviceRegistry.Register(receiver, ""); nil != err {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rr *restRegistry) RegisterServiceMap(keysAndValues map[string]interface{}) error {
|
||||||
|
if nil == keysAndValues || 0 == len(keysAndValues) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, receiver := range keysAndValues {
|
||||||
|
if err := rr.serviceRegistry.Register(receiver, name); nil != err {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rr *restRegistry) GetService(name string) interface{} {
|
||||||
|
return rr.serviceRegistry.GetService(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasMethod returns true if the given method is registered.
|
||||||
|
//
|
||||||
|
// The method uses a dotted notation as in "Service.Method".
|
||||||
|
func (rr *restRegistry) HasMethod(method string) bool {
|
||||||
|
if _, _, err := rr.serviceRegistry.Get(method); err == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoke execute a method.
|
||||||
|
//
|
||||||
|
// Codecs are defined to process a given serialization scheme, e.g., JSON or
|
||||||
|
// XML. A codec is chosen based on the "Content-Type" header from the request,
|
||||||
|
// excluding the charset definition.
|
||||||
|
func (rr *restRegistry) Invoke(method string, params []string, leadingParams ...interface{}) (result interface{}, err error) {
|
||||||
|
serviceSpec, methodSpec, errGet := rr.serviceRegistry.Get(method)
|
||||||
|
if nil != errGet {
|
||||||
|
return nil, errGet
|
||||||
|
}
|
||||||
|
// Decode the args.
|
||||||
|
|
||||||
|
var in []reflect.Value
|
||||||
|
pValues, pInstances := methodSpec.ParamValues()
|
||||||
|
var lParamLen int
|
||||||
|
if nil != leadingParams {
|
||||||
|
lParamLen = len(leadingParams)
|
||||||
|
}
|
||||||
|
|
||||||
|
if nil != pInstances && 0 < len(pInstances) {
|
||||||
|
if err := cuej.SetValueWithJSONStringArray(params, pInstances[lParamLen:]); nil != err {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for indexI := 0; indexI < lParamLen; indexI++ {
|
||||||
|
i := pInstances[indexI]
|
||||||
|
rv := reflect.ValueOf(i)
|
||||||
|
iv := reflect.ValueOf(leadingParams[indexI])
|
||||||
|
switch reflect.TypeOf(i).Elem().Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
rv.Elem().Set(iv.Elem())
|
||||||
|
default:
|
||||||
|
rv.Elem().Set(iv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pCount := len(pInstances)
|
||||||
|
in = make([]reflect.Value, pCount+1)
|
||||||
|
|
||||||
|
for indexI := 0; indexI < pCount; indexI++ {
|
||||||
|
if pValues[indexI].Type().Kind() == reflect.Ptr && pValues[indexI].Type().Elem().Kind() != reflect.Struct {
|
||||||
|
in[indexI+1] = reflect.Indirect(pValues[indexI])
|
||||||
|
} else {
|
||||||
|
in[indexI+1] = pValues[indexI]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
in = make([]reflect.Value, 1)
|
||||||
|
}
|
||||||
|
in[0] = serviceSpec.ReceiverValue()
|
||||||
|
|
||||||
|
// Call the service method.
|
||||||
|
returnValues := methodSpec.Call(in)
|
||||||
|
|
||||||
|
if nil != methodSpec.ReturnType() {
|
||||||
|
result = returnValues[0].Interface()
|
||||||
|
if nil != returnValues[1].Interface() {
|
||||||
|
err = returnValues[1].Interface().(error)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if nil != returnValues[0].Interface() {
|
||||||
|
err = returnValues[0].Interface().(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user