12 KiB
| aicra |
Aicra is a self-working REST API engine coded in Go that allows anyone to create a fully featured API. It features type checking, authentication management through middlewares, file upload, rich argument parsing (i.e. url slash-separated, urlencoded, form-data, json), nested routes, project compiler (i.e. aicra), etc.
All the REST API management is done for you, you just need to implement :
- the controllers
- the middlewares (to manage authentication, csrf, etc)
- the type checkers to check if input arguments follows some rules
There is 2 drivers that lets you implement these features in Go or whatever language.
This framework is based over some of the following concepts.
concept | explanation |
---|---|
meaningful defaults | Defaults and default values work without further understanding |
configuration driven | Avoid information duplication. Automate anything that can be automated without losing control. Have one configuration that summarizes the whole project, its behavior and its automation flow. |
A working example is available here
Table of contents
I. Installation
You need a recent machine with go
installed.
This package has not been tested under the version 1.10.
1. Download and install the package
go get -u git.xdrm.io/go/aicra/cmd/aicra
The library should now be available locally and available for your imports. Moreover, the project compilet have been installed as the aicra
command.
The executable
aicra
will be placed into your$GOPATH/bin
folder, if added to your environment PATH it should be available as a standalone command in your terminal. If not, you can simply run$GOPATH/bin/aicra
to use the command or create a symlink into/usr/local/bin
for instance.
II. Setup a project
The default project structure for aicra is as follows :
├── main.go - entry point
|
├── aicra.json - server configuration file
├── api.json - API configuration file
|
├── middleware - middleware implementations
├── controller - controller implementations
└── type - custom type checkers
1. Compilation configuration
The aicra.json
configuration file defines where are located your controllers, type checkers, and middlewares ; also it contains what driver you want to use, you have 2 choices :
- plugin - for Go implementations
- generic - for any language implementation (uses standard input and output)
field | description | example value |
---|---|---|
root | The project folder path | ./some-path |
driver | The driver to use for loading controllers, middlewares and type checkers | plugin orgeneric |
types.default | Whether to load default types into the project | true , false |
types.folder | The folder (relative to the project root) where type checkers' implementations are located | ./type |
controllers.folder | The folder (relative to the project root) where controllers' implementations are located | ./controller |
middlewares.folder | The folder (relative to the project root) where middlewares' implementations are located | ./middleware |
A sample file can be found here.
2. API Configuration
The whole project behavior is described inside the api.json
file. For a better understanding of the format, take a look at this working template. This file defines :
- resource routes and their methods
- every input for each method (called argument)
- every output for each method
- scope permissions (list of permissions you can compose)
- input policy :
- type of argument
- required/optional
- default value
- variable renaming
3. Controllers
Controllers implement Get
, Post
, Put
, and Delete
methods, and have access to special variables surrounded by underscores :
_HTTP_METHOD_
the request's HTTP method in uppercase_SCOPE_
the scope filled by middlewares_AUTHORIZATION_
the request's Authorization header
Also special variables found in the return data are processed with special actions :
_REDIRECT_
will redirect to the URL contained in the variable
Plugin driver
For each route, you'll have to place your implementation into the controller
folder (according to the aicra.json configuration) following the naming convention : add /main.go
at the end of the route.
Example -
/path/to/some/uri
will be insidecontroller/path/to/some/uri/main.go
Exception -
/
will be insidecontroller/ROOT/main.go
A sample directory structure is available here.
Each controller must implement the git.xdrm.io/go/aicra/driver.Controller
interface. In addition you must declare the function func Export() Controller
to allow dynamic loading of your controller.
Generic driver
This is the same as with the plugin driver but instead of without /main.go
at the end.
Example -
/path/to/some/uri
will be insidecontroller/path/to/some/uri
where the uri file is an executable.
Exception -
/
will be insidecontroller/ROOT
.
A sample directory structure is available here.
4. Middlewares
In order for your project to manage authentication, the best solution is to create middlewares, there are programs that updates a Scope (i.e. a list of strings) according to internal or persistent (i.e. database) information and the actual http request. They are all run before each request is forwarded to your controller. The scope are used to match the scope
field in the configuration file and automatically block non-authenticated requests. Scopes can also be used for implementation-specific behavior such as CSRF management. Controllers have access to the scope through the variable _SCOPE_
.
Plugin driver
Each middleware must be directly inside the middleware
folder (according to the aicra.json configuration).
Example - the
1-authentication
middleware will be insidemiddleware/1-authentication/main.go
.
Note - middleware execution will be ordered by name. Prefixing your middlewares with their order is a good practice.
A sample directory structure is available here.
Each middleware must implement the git.xdrm.io/go/aicra/driver.Middleware
interface. In addition you must declare the function func Export() Middleware
to allow dynamic loading of your middleware.
Generic driver
This is the same as with the plugin driver but instead of without /main.go
at the end.
Example - the
1-authentication
middleware will be insidemiddleware/1-authentication
where 1-authentication is an executable
A sample directory structure is available here.
5. Custom types
In your configuration you will have to use built-in types (e.g. int, any, varchar), but if you want project-specific ones, you can add your own types inside the type
folder. You can check what structure to follow by looking at the built-in types. Also it is not required that you use built-in types, you can ignore them by setting types.default = false
in the aicra.json configuration.
Each type must be directly inside the type
folder. The package name is arbitrary and does not have to match the name (but it is better if it is explicit), because the Match()
method already matches the name.
Plugin driver
Each type checker must be directly inside the type
folder (according to the aicra.json configuration).
Example - the
number
type checker will be insidetype/number/main.go
.
A sample directory structure is available here.
Generic driver
This is the same as with the plugin driver but instead of without /main.go
at the end.
Example - the
number
type checker will be insidetype/number
where number is an executable
A sample directory structure is available here.
III. Build your project
After each controller, middleware or type implementation, you'll have to compile the project. This can be achieved through the command-line builder.
Usage is aicra /path/to/your/project
.
Usually you just have to run the following command inside your project directory :
aicra .
The output should look like
IV. Main
The main default program is pretty small as below :
package main
import (
"git.xdrm.io/go/aicra"
"net/http"
)
func main() {
// 1. create the API from the configuration file
server, err := aicra.New("api.json")
if err != nil {
panic(err)
}
// 2. listen to incoming http requests
err = http.ListenAndServe("127.0.0.1:4242", server)
if err != nil {
panic(err)
}
}
V. Change Log
- human-readable json configuration
- nested routes (i.e.
/user/:id:
and/user/post/:id:
) - nested URL arguments (i.e.
/user/:id:
and/user/:id:/post/:id:
) - useful http methods: GET, POST, PUT, DELETE
- manage URL, query and body arguments:
- multipart/form-data (variables and file uploads)
- application/x-www-form-urlencoded
- application/json
- required vs. optional parameters with a default value
- parameter renaming
- generic authentication system (i.e. you can override the built-in one)
- generic type check (i.e. implement custom types alongside built-in ones)
- built-in types
any
- wildcard matching all valuesint
- any number (e.g. float, int, uint)string
- any textvarchar(min, max)
- any string with a length betweenmin
andmax
<a>
- array containing only elements matchinga
type<a:b>
- map containing only keys of typea
and values of typeb
(a or b can be ommited)
- generic controllers implementation (shared objects)
- response interface
- devmode watcher : watch manifest, watch plugins to compile + hot reload them
- driver for Go plugins
- controllers
- middlewares
- type checkers
- driver working with any executable through standard input and output
- controllers
- middlewares
- type checkers
- project configuration file to select driver, source folders and whether to load default type checkers.
- used to compile the project by the
aicra
command - used to create an API from
aicra.New()
- used to compile the project by the