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