add driver management + moved implementation of default driver into 'driver/plugin'
This commit is contained in:
parent
8c02bc53a5
commit
3feae783dc
|
@ -0,0 +1,46 @@
|
||||||
|
package driver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"git.xdrm.io/go/aicra/err"
|
||||||
|
"git.xdrm.io/go/aicra/response"
|
||||||
|
"plugin"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Load implements the Driver interface
|
||||||
|
func (d *Plugin) Load(_path []string, _method string) (func(response.Arguments, *response.Response) response.Response, err.Error) {
|
||||||
|
|
||||||
|
/* (1) Build controller path */
|
||||||
|
path := strings.Join(_path, "-")
|
||||||
|
if len(path) == 0 {
|
||||||
|
path = fmt.Sprintf(".build/controller/ROOT.so")
|
||||||
|
} else {
|
||||||
|
path = fmt.Sprintf(".build/controller/%s.so", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (2) Format url */
|
||||||
|
tmp := []byte(strings.ToLower(_method))
|
||||||
|
tmp[0] = tmp[0] - ('a' - 'A')
|
||||||
|
method := string(tmp)
|
||||||
|
|
||||||
|
/* (2) Try to load plugin */
|
||||||
|
p, err2 := plugin.Open(path)
|
||||||
|
if err2 != nil {
|
||||||
|
return nil, err.UncallableController
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (3) Try to extract method */
|
||||||
|
m, err2 := p.Lookup(method)
|
||||||
|
if err2 != nil {
|
||||||
|
return nil, err.UncallableMethod
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (4) Check signature */
|
||||||
|
callable, validSignature := m.(func(response.Arguments, *response.Response) response.Response)
|
||||||
|
if !validSignature {
|
||||||
|
return nil, err.UncallableMethod
|
||||||
|
}
|
||||||
|
|
||||||
|
return callable, err.Success
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
package driver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.xdrm.io/go/aicra/err"
|
||||||
|
"git.xdrm.io/go/aicra/response"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Driver interface {
|
||||||
|
Load(_path []string, _method string) (func(response.Arguments, *response.Response) response.Response, err.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generic tells the aicra instance to use the generic driver to load controller's executables
|
||||||
|
//
|
||||||
|
// It will call an executable with the json input into the standard input
|
||||||
|
// the HTTP method is send as the key _HTTP_METHOD_ (in upper case)
|
||||||
|
// The standard output must be a json corresponding to the data
|
||||||
|
//
|
||||||
|
// FILE STRUCTURE
|
||||||
|
// --------------
|
||||||
|
// - the root (/) controller executable must be named <WORKDIR>/controller/ROOT
|
||||||
|
// - the a/b/c controller executable must be named <WORKDIR>/controller/a/b/c
|
||||||
|
type Generic struct{}
|
||||||
|
|
||||||
|
// Plugin tells the aicra instance to use the plugin driver to load controller's executables
|
||||||
|
//
|
||||||
|
// It will load go .so plugins with the following interface :
|
||||||
|
//
|
||||||
|
// type Plugin interface {
|
||||||
|
// Get(d i.Arguments, r *i.Response) i.Response
|
||||||
|
// Post(d i.Arguments, r *i.Response) i.Response
|
||||||
|
// Put(d i.Arguments, r *i.Response) i.Response
|
||||||
|
// Delete(d i.Arguments, r *i.Response) i.Response
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// FILE STRUCTURE
|
||||||
|
// --------------
|
||||||
|
// - the root (/) controller executable must be named <WORKDIR>/controller/ROOT/main.so
|
||||||
|
// - the a/b/c controller executable must be named <WORKDIR>/controller/a/b/c/main.so
|
||||||
|
//
|
||||||
|
// COMPILATION
|
||||||
|
// -----------
|
||||||
|
// The compilation is handled with the command-line tool `aicra <WORKDIR>`
|
||||||
|
type Plugin struct{}
|
||||||
|
|
||||||
|
// FastCGI tells the aicra instance to use the fastcgi driver to load controller's executables
|
||||||
|
//
|
||||||
|
// Warning: PHP only
|
||||||
|
//
|
||||||
|
// It will use the fastcgi protocol with php at <host>:<port>
|
||||||
|
//
|
||||||
|
// FILE STRUCTURE
|
||||||
|
// --------------
|
||||||
|
// - the root (/) controller executable must be named <WORKDIR>/controller/ROOT.php
|
||||||
|
// - the a/b/c controller executable must be named <WORKDIR>/controller/a/b/c.php
|
||||||
|
type FastCGI struct {
|
||||||
|
host string
|
||||||
|
port string
|
||||||
|
}
|
|
@ -3,11 +3,11 @@ package apirequest
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"git.xdrm.io/go/aicra/driver"
|
||||||
"git.xdrm.io/go/aicra/err"
|
"git.xdrm.io/go/aicra/err"
|
||||||
"git.xdrm.io/go/aicra/response"
|
"git.xdrm.io/go/aicra/response"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"plugin"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -94,39 +94,8 @@ func FetchFormData(req *http.Request) map[string]interface{} {
|
||||||
|
|
||||||
// LoadController tries to load a controller from its uri
|
// LoadController tries to load a controller from its uri
|
||||||
// checks for its given method ('Get', 'Post', 'Put', or 'Delete')
|
// checks for its given method ('Get', 'Post', 'Put', or 'Delete')
|
||||||
func (i *Request) LoadController(method string) (func(response.Arguments, *response.Response) response.Response, err.Error) {
|
func (i *Request) LoadController(_method string, _driver driver.Driver) (func(response.Arguments, *response.Response) response.Response, err.Error) {
|
||||||
|
|
||||||
/* (1) Build controller path */
|
return _driver.Load(i.Path, _method)
|
||||||
path := strings.Join(i.Path, "-")
|
|
||||||
if len(path) == 0 {
|
|
||||||
path = fmt.Sprintf(".build/controller/ROOT.so")
|
|
||||||
} else {
|
|
||||||
path = fmt.Sprintf(".build/controller/%s.so", path)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (2) Format url */
|
|
||||||
tmp := []byte(strings.ToLower(method))
|
|
||||||
tmp[0] = tmp[0] - ('a' - 'A')
|
|
||||||
method = string(tmp)
|
|
||||||
|
|
||||||
/* (2) Try to load plugin */
|
|
||||||
p, err2 := plugin.Open(path)
|
|
||||||
if err2 != nil {
|
|
||||||
return nil, err.UncallableController
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (3) Try to extract method */
|
|
||||||
m, err2 := p.Lookup(method)
|
|
||||||
if err2 != nil {
|
|
||||||
return nil, err.UncallableMethod
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (4) Check signature */
|
|
||||||
callable, validSignature := m.(func(response.Arguments, *response.Response) response.Response)
|
|
||||||
if !validSignature {
|
|
||||||
return nil, err.UncallableMethod
|
|
||||||
}
|
|
||||||
|
|
||||||
return callable, err.Success
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package controller
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
|
@ -1,4 +1,4 @@
|
||||||
package controller
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.xdrm.io/go/aicra/middleware"
|
"git.xdrm.io/go/aicra/middleware"
|
|
@ -1,4 +1,4 @@
|
||||||
package controller
|
package config
|
||||||
|
|
||||||
/* (1) Configuration
|
/* (1) Configuration
|
||||||
---------------------------------------------------------*/
|
---------------------------------------------------------*/
|
26
server.go
26
server.go
|
@ -1,10 +1,12 @@
|
||||||
package aicra
|
package aicra
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"git.xdrm.io/go/aicra/driver"
|
||||||
e "git.xdrm.io/go/aicra/err"
|
e "git.xdrm.io/go/aicra/err"
|
||||||
"git.xdrm.io/go/aicra/internal/apirequest"
|
"git.xdrm.io/go/aicra/internal/apirequest"
|
||||||
"git.xdrm.io/go/aicra/internal/checker"
|
"git.xdrm.io/go/aicra/internal/checker"
|
||||||
"git.xdrm.io/go/aicra/internal/controller"
|
"git.xdrm.io/go/aicra/internal/config"
|
||||||
"git.xdrm.io/go/aicra/middleware"
|
"git.xdrm.io/go/aicra/middleware"
|
||||||
"git.xdrm.io/go/aicra/response"
|
"git.xdrm.io/go/aicra/response"
|
||||||
"log"
|
"log"
|
||||||
|
@ -16,22 +18,30 @@ import (
|
||||||
// * its middlewares
|
// * its middlewares
|
||||||
// * its controllers (config)
|
// * its controllers (config)
|
||||||
type Server struct {
|
type Server struct {
|
||||||
controller *controller.Controller // controllers
|
controller *config.Controller // controllers
|
||||||
checker *checker.Registry // type checker registry
|
checker *checker.Registry // type checker registry
|
||||||
middleware *middleware.Registry // middlewares
|
middleware *middleware.Registry // middlewares
|
||||||
|
driver driver.Driver
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ErrNilDriver = errors.New("the driver is <nil>")
|
||||||
|
|
||||||
// New creates a framework instance from a configuration file
|
// New creates a framework instance from a configuration file
|
||||||
func New(path string) (*Server, error) {
|
func New(_path string, _driver driver.Driver) (*Server, error) {
|
||||||
|
|
||||||
|
if _driver == nil {
|
||||||
|
return nil, ErrNilDriver
|
||||||
|
}
|
||||||
|
|
||||||
/* (1) Init instance */
|
/* (1) Init instance */
|
||||||
var err error
|
var err error
|
||||||
var i = &Server{
|
var i = &Server{
|
||||||
controller: nil,
|
controller: nil,
|
||||||
|
driver: _driver,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (2) Load configuration */
|
/* (2) Load configuration */
|
||||||
i.controller, err = controller.Load(path)
|
i.controller, err = config.Load(_path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -90,7 +100,7 @@ func (s *Server) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
||||||
|
|
||||||
/* (5) Load controller
|
/* (5) Load controller
|
||||||
---------------------------------------------------------*/
|
---------------------------------------------------------*/
|
||||||
controllerImplementation, callErr := apiRequest.LoadController(req.Method)
|
controllerImplementation, callErr := apiRequest.LoadController(req.Method, s.driver)
|
||||||
if callErr.Code != e.Success.Code {
|
if callErr.Code != e.Success.Code {
|
||||||
httpError(res, callErr)
|
httpError(res, callErr)
|
||||||
log.Printf("[err] %s\n", err)
|
log.Printf("[err] %s\n", err)
|
||||||
|
@ -126,7 +136,7 @@ func (s *Server) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
||||||
|
|
||||||
// extractParameters extracts parameters for the request and checks
|
// extractParameters extracts parameters for the request and checks
|
||||||
// every single one according to configuration options
|
// every single one according to configuration options
|
||||||
func (s *Server) extractParameters(req *apirequest.Request, methodParam map[string]*controller.Parameter) (map[string]interface{}, e.Error) {
|
func (s *Server) extractParameters(req *apirequest.Request, methodParam map[string]*config.Parameter) (map[string]interface{}, e.Error) {
|
||||||
|
|
||||||
// init vars
|
// init vars
|
||||||
err := e.Success
|
err := e.Success
|
||||||
|
|
4
util.go
4
util.go
|
@ -4,13 +4,13 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"git.xdrm.io/go/aicra/err"
|
"git.xdrm.io/go/aicra/err"
|
||||||
"git.xdrm.io/go/aicra/internal/apirequest"
|
"git.xdrm.io/go/aicra/internal/apirequest"
|
||||||
"git.xdrm.io/go/aicra/internal/controller"
|
"git.xdrm.io/go/aicra/internal/config"
|
||||||
"git.xdrm.io/go/aicra/response"
|
"git.xdrm.io/go/aicra/response"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) matchController(req *apirequest.Request) *controller.Controller {
|
func (s *Server) matchController(req *apirequest.Request) *config.Controller {
|
||||||
|
|
||||||
/* (1) Try to browse by URI */
|
/* (1) Try to browse by URI */
|
||||||
pathi, ctl := s.controller.Browse(req.URI)
|
pathi, ctl := s.controller.Browse(req.URI)
|
||||||
|
|
Loading…
Reference in New Issue