diff --git a/doc/README.md b/doc/README.md deleted file mode 100644 index 0cafae4..0000000 --- a/doc/README.md +++ /dev/null @@ -1,539 +0,0 @@ -```yaml -module: api -version: 1.2 -``` - -For developers -==== - -[**I.** Overview](#i-overview) - -- [**1** Introduction & features](#1-introduction--features) -- [**2** Basic knowledge](#2-basic-knowledge) - -[**II.** Usage](#ii-usage) - -- [**1** REST API](#1-rest-api) -- [**2** Internal use (PHP)](#2-internal-use) - -[**III.** Configuration](#iii-configuration) - -- [**1** Configuration format](#1---configuration-format) -- [**2** Method definition](#2---methoddefinition) - - [**2.1** Method description](#21---methoddescription) - - [**2.2** Method permissions](#22---methodpermissions) - - [**2.3** Method parameters](#23---methodparameters) - - [parameter name](#parametername) - - [parameter description](#parameterdescription) - - [parameter type](#parameterchecker_type) - - [parameter optional vs. required](#parameteris_optional) - - [parameter rename](#parameterrename) - - [parameter default value](#parameterdefault_value) - - [**2.4** Method output format](#24---methodoutput_format) - - [**2.5** Method options](#25---methodoptions) - -[**IV.** Implementation](#iv-implementation) - -- [**1** Permissions : AuthSystem](#1---permissions--authsystem) -- [**2** Core implementation](#2---core-implementation) - - [Classes](#classes) - - [Methods](#methods) - - [Method arguments](#method-arguments) - - [Return statement](#return-statement) - - [Before and After scripts](#before-and-after-scripts) - - [Example](#example) - -[**V.** Type Checker](#v-type-checker) - -- [**1** Default Types](#1---default-types) -- [**2** Complex Types](#2---complex-types) - -[**VI.** Documentation](#vi-documentation) - -- [**1** API accessible documentation](#1---api-accessible-documentation) - - -For clients -==== - -[**I.** Simple request](#i-simple-request) - -- [**1** URL](#1---URL) -- [**2** variables](#2---variables) - -[**II.** Usage](#ii-usage) - - - - -# **I.** Overview -## **1** Introduction & features - -The `api` package (v1.2) allows you to easily create and manage a REST API for your applications. - -The aim of this package is to make your life easier working with APIs and internal delegation. The only things you have to do is to implement your controllers, middle-wares and write 2 configuration files, the package will do the rest. - -Things you **have** to do : -- write the project configuration file (cf. [project configuration](#iii-project-configuration)) -- write the API definition file (cf. [api definition](#iv-api-definition)) -- implement your middle-wares to manage authentication, csrf, etc (cf. [AuthSystem](#1---middle-wares)) -- implement your controllers (cf. ???) -- implement additional project-specific type checkers (cf. ???) - -Things you **don't have** to do : -- check the input variables (cf. [Checker](#v-type-checker)) -- multiple permission management -- optional or required input -- Form data type : x-www-urlencoded, multipart, or file upload -- URL variables (slash separated at the end of the route, like standard uri) -- and a lot more ... - -## **2** Basic knowledge - -The API uses the routes defined in the _api.json_ configuration to export your code (in compiled go or other language). Middle-wares are executed when receiving a new request, then the controllers will be loaded according to the URI. - -Example: -* the module `article` contains methods: - * `GET` to get article data - * `POST` to post a new article - * `PUT` to edit an existing article - * `DELETE` to delete an exisint article - -*Note that these are all the available methods handled by aicra* - - - - -# **III.** Project Configuration - -The documentation consists of directions for how to compile and run the project controllers, middle-wares and type checkers. - -## **1** - configuration format - -```json -{ - "root": "", - "driver": "", - "types": { - "default": true, - "folder": "" - }, - "controllers": { - "folder": " - - - -# **IV.** Implementation - -## **1** - middle-wares - -Each middle-ware 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. - -### example - -For instance here, we check if a token is sent inside the **Authorization** HTTP header. The token if valid defines scope permissions. - -```go -package main - -import ( - "git.xdrm.io/aicra/driver" - "net/http" -) - -// for the API code to export our middle-ware -func Export() driver.Middleware { return new(TokenManager) } - -// mockup type to implement the driver.Middleware interface -type TokenManager interface{} - -func (tm TokenManager) Inspect(req http.Request, scope *[]string) { - token := req.Header.Get("Authorization") - if !isTokenValid(token) { - return - } - - scope = append(scope, getTokenPermissions(token)...) -} -``` - -*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 api definition. - -### 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 - -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 `$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. - -## **1** - Default types - -**Warning :** All received values are extracted using JSON format if possible, else values are considered raw strings. - -- `2`, `-3.2` are extracted as floats -- `true` and `false` are stored as booleans -- `null` is stored as null -- `[x, y, z]` is stored as an array containing **x**, **y**, and **z** that can be themselves JSON-decoded if possible. -- `{ "a": x }` is stored as a map containing **x** at the key "a", **x** can be itself JSON-decoded if possible. -- `"some string"` is stored as a string -- `some string` here, the decoding will fail (it is no valid JSON) so it will be stored as a string - -|Type|Example|Description| -|---|---|---| -|`any`|`[9,"a"]`, `"a"`|Any data (can be simple or complex)| -|`id`|`10`, `23`|Positive integer number| -|`int`|`-10`, `23`|Any integer number| -|`float`|`-10.2`, `23.5`|Any float| -|`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.| -|`array`|`[]`, `[1, "a"]`|Any array| -|`bool`|`true`, `false`|Boolean| -|`varchar(a,b)`|`"Hello!"`|String with a length between `a` and `b` (included)| - -## **2** - Complex types - -|Type|Sub-Type|Description| -|---|---|---| -|`array`|`a`|Array containing only entries matching the type `a`| -|`FILE`|_a raw file send in `multipart/form-data`|A raw file sent by `multipart/form-data`| - -> **Note:** It is possible to chain `array` type as many as needed. - -**Ex.:** `array>` - Will only match an array containing arrays that only contains `id` entries. - - - -# **VI.** Documentation - -With the *all-in-config* method, we can generate a consistent documentation or other documents from the `/config/modules.json` file. - -## **1** - API accessible documentation - -You can request the API for information about the current URI by using the `OPTIONS` HTTP method. - - -==== - - -# **I.** Simple request -## **1** - URL - -### format -The `uri` format is as defined: `{base}/{path}/{GET_parameters}`, where -- `{base}` is the server's *API* base uri (ex: `https://example.com/api/v1` or `https://api.exampl.com`) -- `{path}` is the effective path you want to access (ex: `article/author`) -- `{GET_parameters}` is a set of slash-separated values (ex: `val0/val1/val2//val4`) - -*Note:* GET parameters are not used as usual (`?var1=val1&var2=val2...`), instead the position in the URL gives them an implicit name which is `URL#`, where `#` is the index in the uri (beginning with 0). - -### example 1 - -If you want to edit an article with the server's REST API, it could be defined as following: - -```yaml -http: PUT -path: article/{id_article} -input: - body: new content of the article -output: - updated: the updated article data -``` - -Let's take the example where you want to update the article which id is **23** and set its body to "**blabla new content**" - -`HTTP REQUEST` -``` -PUT article/23 HTTP/1.0 - -body=blabla+new+content -``` - - -`HTTP RESPONSE` -``` -HTTP/1.0 200 OK -Content-Type: application/json - -{ - "error": 0, - "ErrorDescription": "all right", - - "updated": { - "id_article": 23, - "title": "article 23", - "body": "blabla new content" - } - -} -``` - -### example 2 - -If you want to get a specific article line, the request could be defined as following - -```yaml -http: GET -path: article/line/{id_article}/{no_line} -input: - -output: - articles: the list of matching lines -``` - -Let's take the example where you want to get **all articles** because `id_article` is set to optional, but you only want the first line of each so you have to give only the second parameter set to `1` (first line). - -*Solution:* The position in the `uri` where `id_article` must be, have to be left empty: it will result of 2 slashes (`//`). - -`HTTP REQUEST` -``` -GET article/line//1 HTTP/1.0 -``` - - -`HTTP RESPONSE` -``` -HTTP/1.0 200 OK -Content-Type: application/json - -{ - "error": 0, - "ErrorDescription": "all right", - - "articles": [ - { - "id_article": 23, - "line": [ 0: "blabla new content" - },{ - "id_article": 25, - "line": [ 0: "some article" - } - ] - -} -``` \ No newline at end of file