update readme

This commit is contained in:
Adrien Marquès 2018-10-03 17:08:36 +02:00
parent 54d4b860de
commit 672a4d8ad5
1 changed files with 83 additions and 152 deletions

View File

@ -99,144 +99,38 @@ The API uses the routes defined in the _api.json_ configuration to export your c
* `PUT` to edit an existing article * `PUT` to edit an existing article
* `DELETE` to delete an exisint article * `DELETE` to delete an exisint article
*Note that each method must be a valid HTTP METHOD*. *Note that these are all the available methods handled by aicra*
# **III.** Project Configuration # **III.** Project Configuration
The documentation consists of directions for how to compile and run the project controllers, middle-wares and type checkers.
The documentation consists of a _chain_ of urls each one can contain several HTTP method specifications.
Note that each url can be chained apart the method specifications.
## **1** - configuration format ## **1** - configuration format
The configuration is a set of `uri` paths that can contain up to 4 method types: **POST**, **DELETE**, **PUT**, **GET** or `uri` subpaths.
For instance the 4 methods directly inside `uri1` will be triggered when the calling URI is `/uri1`, the ones directly inside `uri2` will be triggered when calling `/uri1/uri2` and so on..
You can also set full paths if you don't need transitional methods, for instance the path `uri5/uri6/uri7` will be triggered by the url `/uri5/uri6/uri7`.
**Example:** The example file loaded with the default configuration can be found [here](./../../src/config/api/3.0/modules.json).
```json ```json
{ {
"uri1" : { "root": "<project-root>",
"GET": method.definition, "driver": "<driver>",
"POST": method.definition, "types": {
"PUT": method.definition, "default": true,
"DELETE": method.definition, "folder": "<custom-types-folder>"
"uri2": {
"GET": method.definition,
"POST": method.definition,
"PUT": method.definition,
"DELETE": method.definition,
"uri3": {}
}
}, },
"controllers": {
"uri5/uri6/uri7": { "folder": "<controllers-folder"
"GET": method.definition, },
"POST": method.definition, "middlewares": {
"PUT": method.definition, "folder": "<middlewares-folder"
"DELETE": method.definition
} }
} }
``` ```
**Note**: It is possible to trigger the *root uri* (`/`), so you can set methods directly at the root of the JSON file. **Note**: The following fields are optional :
## **2** - method.definition - `types.default` is by default "types"
```json -
{
"des": method.description,
"per": method.permissions,
"par": method.parameters,
"out": method.output_format,
"opt": method.options
}
```
## **2.1** - method.description
The *description* field must be a **string** containing the human-readable description of what the method does.
## **2.2** - method.permissions
The *permissions* field must be an array. You can manage **OR** and **AND** permission combinations.
- **OR** is applied between each **0-depth** array
- **AND** is applied between each **1-depth** array
For instance the following permission `[ ["a","b"], ["c"] ]` means you need the permissions **a** and **b** combined or only the permission **c**.
## **2.3** - method.parameters
The *parameters* field must be an object containing each required or optional parameter needed for the implementation.
```json
"parameter.name": {
"des": parameter.description,
"typ": parameter.checker_type,
"opt": parameter.is_optional,
"ren": parameter.rename,
"def": parameter.default_value,
}
```
#### parameter.name
The *name* field must be a **string** containing variable name that will be asked for the caller.
Note that you can set any string for **body parameters**, but **GET parameters** must be named `URL#`, where `#` is the index within the URI, beginning with 0.
#### parameter.description
The *description* field must be a **string** containing the human-readable description of what the parameter is or must be.
#### parameter.checker_type
The *checker_type* field must be a **string** corresponding to a `\api\core\Checker` type that will be checked before calling the implementation.
#### parameter.is_optional
The *is_optional* field must be a **boolean** set to `true` if the parameter can be ommited. By default, the field is set to `false` so each parameter is required.
#### parameter.rename
The *rename* field must be a **string** corresponding to the *variable name* given to the implementation. It is useful for **GET parameters** because they need to be called `URL#`, where `#` is the position in the URI. (cf. [paramter.name](#parametername)))
If ommited, by default, `parameter.name` will be used.
#### parameter.default_value
The *default_value* field must be of any type according to the *checker_type* field, it will be used only for **optional** parameters when ommited by the caller
By default, each optional parameter will exist and will be set to `null` to the implementation.
## **2.4** - method.output_format
The *output_format* field must have the same format as `method.parameters` but will only be used to generate a documentation or to tell other developers what the method returns if no error occurs.
## **2.5** - method.options
The *options* field must be an **object** containing the available options.
The only option available for now is:
```json
"download": true
```
Your implementation must return 2 fields:
- `body` a string containing the file body
- `headers` an array containing as an associative array file headers
If the API is called with HTTP directly, it will not print the **json** response (only on error), but will instead directly return the created file.
*AJAX:* If called with ajax, you must give the header `HTTP_X_REQUESTED_WITH` set to `XMLHttpRequest`. In that case only, it will return a normal JSON response with the field `link` containing the link to call for downloading the created file. **You must take care of deleting not used files** - there is no such mechanism.
@ -395,31 +289,7 @@ If the API is called with HTTP directly, it will not print the **json** response
## **1** - middle-wares ## **1** - middle-wares
In order to implement your Permission System you have to implement the **interface** `AuthSystem` located in `/build/api/core/AuthSystem`. Each middle-ware must implement the [driver.Middleware](https://godoc.org/git.xdrm.io/go/aicra/driver#Middleware) interface.
You must register your custom authentification system before each api call.
For instance, lets suppose your implementation is called `myAuthSystem`.
```php
\api\core\Request::setAuthSystem(new myAuthSystem);
```
**Note**: By default the API will try to find `\api\core\AuthSystemDefault`.
## **2** - core implementation
### classes
Each module's implementation is represented as a **file** so as a **class** located in `/build/api/module/`. In order for the autoloader to work, you must name the **file** the same name as the **class**.
Also the **namespace** must match, it corresponds to the path (starting at `/api`).
For instance if you have in your configuration a path called `/uri1/uri2/uri3`, you will create the file `/build/api/module/uri1/uri2/uri3.php`.
*Specific*: For the root (`/`) path, it will trigger the class `\api\module\root`, so you have to create the file `/build/api/module/root.php`. (cf. [configuration format](#1---configuration-format))
### methods
Each middle-wares must implement the [driver.Middleware](https://godoc.org/git.xdrm.io/go/aicra/driver#Middleware) interface.
The `Inspect(http.Request, *[]string)` method gives you the actual http request. And you must edit the string list to add scope elements. After all middle-wares are executed, the final scope is used to check the **method.permission** field to decide whether the controller can be accessed. The `Inspect(http.Request, *[]string)` method gives you the actual http request. And you must edit the string list to add scope elements. After all middle-wares are executed, the final scope is used to check the **method.permission** field to decide whether the controller can be accessed.
@ -454,12 +324,74 @@ func (tm TokenManager) Inspect(req http.Request, scope *[]string) {
*Note*: Functions `isTokenValid()` and `getTokenPermissions()` do not exist, it was in order for all to understand the example. *Note*: Functions `isTokenValid()` and `getTokenPermissions()` do not exist, it was in order for all to understand the example.
## **2** - controller
Each controller must implement the [driver.Controller](https://godoc.org/git.xdrm.io/go/aicra/driver#Controller) interface.
The `Get(response.Arguments) response.Response` method defines the controller implementation for the `GET` method. Other methods are `Post`, `Put`, and `Delete`. Each controller will be given the arguments according to the <u>api definition</u>.
### example
For instance here, we implement a simple **user** controller.
```go
package main
import (
"git.xdrm.io/aicra/driver"
"git.xdrm.io/aicra/response"
"git.xdrm.io/aicra/err"
)
// for the API code to export our middle-ware
func Export() driver.Controller { return new(UserController) }
// mockup type to implement the driver.Controller interface
type UserController interface{}
func (ctl UserController) Get(args response.Arguments) response.Response {
res := response.New()
// extract user ID argument
user_id, ok := args["user_id"].(float64)
if !ok {
res.Err = e.Failure
return *res
}
// fetch user data
res.Set("user", getUserData(user_id))
return res
}
func (ctl UserController) Post(args response.Arguments) response.Response {
res := response.New()
// extract user ID argument
username, ok := args["username"].(string)
password, ok1 := args["password"].(string)
if !ok || !ok1 {
res.Err = e.Failure
return *res
}
// store user data
res.Set("created", storeUser(username, password))
return res
}
```
*Note*: Functions `getUserData(int) map[string]string` and `storeUser(string,string) bool` do not exist, it was in order for all to understand the example.
# **V.** Type Checker # **V.** Type Checker
Each type checker checks the parameter values according to the type given in the api definition. Each type checker checks http request extracted values according to the type given in the api definition.
The default types below are available in the default package. The default types below are available in the `$GOPATH/src/git.xdrm.io/go/aicra/internal/checker/default`, they are loaded by default in any project. You can choose not to load them by settings `types`.`default` to `false` in the project configuration. To add custom types you must implement the [driver.Checker](https://godoc.org/git.xdrm.io/go/aicra/driver#Checker) interface and export it in order for aicra to dynamically load it.
To add a new type, just open the file `/build/api/Checker.php` and add an entry in the `switch` statement.
## **1** - Default types ## **1** - Default types
@ -481,7 +413,6 @@ To add a new type, just open the file `/build/api/Checker.php` and add an entry
|`float`|`-10.2`, `23.5`|Any float| |`float`|`-10.2`, `23.5`|Any float|
|`string`|`"Hello!"`|String that can be of any length (even empty)| |`string`|`"Hello!"`|String that can be of any length (even empty)|
|`digest(L)`|`"4612473aa81f93a878..."`|String with a length of `L`, containing only hexadecimal lowercase characters.| |`digest(L)`|`"4612473aa81f93a878..."`|String with a length of `L`, containing only hexadecimal lowercase characters.|
|`mail`|`"a.b@c.def"`|Valid email address|
|`array`|`[]`, `[1, "a"]`|Any array| |`array`|`[]`, `[1, "a"]`|Any array|
|`bool`|`true`, `false`|Boolean| |`bool`|`true`, `false`|Boolean|
|`varchar(a,b)`|`"Hello!"`|String with a length between `a` and `b` (included)| |`varchar(a,b)`|`"Hello!"`|String with a length between `a` and `b` (included)|