Skip to content

Commit

Permalink
some refactoring in the docs generator container
Browse files Browse the repository at this point in the history
  • Loading branch information
Mahmoudz committed Mar 23, 2017
1 parent 438a018 commit cdd7152
Show file tree
Hide file tree
Showing 7 changed files with 325 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ Homestead.yaml
.env
storage/logs/laravel.log
/public/api/
/public/api-markdowns/
/public/api-rendered-markdowns/
/public/uploads/
/laradock*/
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use App\Containers\Documentation\Tasks\GenerateAPIDocsTask;
use App\Containers\Documentation\Tasks\GetDocsTypesTask;
use App\Containers\Documentation\Tasks\ProcessMarkdownTemplatesTask;
use App\Containers\Documentation\Tasks\RenderTemplatesTask;
use App\Ship\Parents\Actions\Action;

/**
Expand All @@ -21,7 +22,7 @@ class GenerateDocumentationAction extends Action
public function run($console)
{
// parse the markdown file.
$this->call(ProcessMarkdownTemplatesTask::class);
$this->call(RenderTemplatesTask::class);

// get docs types that needs to be generated by the user base on his configs.
$types = $this->call(GetDocsTypesTask::class);
Expand Down
2 changes: 1 addition & 1 deletion app/Containers/Documentation/ApiDocJs/private/apidoc.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
"header": {
"title": "API Overview",
"filename": "../public/api-markdowns/header.md"
"filename": "../public/api-rendered-markdowns/header.md"
},
"order": [

Expand Down
2 changes: 1 addition & 1 deletion app/Containers/Documentation/ApiDocJs/public/apidoc.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
"header": {
"title": "API Overview",
"filename": "../public/api-markdowns/header.md"
"filename": "../public/api-rendered-markdowns/header.md"
},
"order": [

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,19 @@
use Illuminate\Support\Facades\Config;

/**
* Class ProcessMarkdownTemplatesTask.
* Class RenderTemplatesTask.
*
* @author Mahmoud Zalt <[email protected]>
*/
class ProcessMarkdownTemplatesTask extends Task
class RenderTemplatesTask extends Task
{

use DocsGeneratorTrait;

protected $headerMarkdownContent;

const TEMPLATE_PATH = 'Containers/Documentation/ApiDocJs/shared/';
const OUTPUT_PATH = 'api-markdowns/';
const OUTPUT_PATH = 'api-rendered-markdowns/';

/**
* Read the markdown header template and fill it with some real data from the .env file.
Expand All @@ -35,8 +36,14 @@ public function run()
$this->replace('{{token-expires-minutes}}', Config::get('jwt.ttl'));
$this->replace('{{pagination-limit}}', Config::get('repository.pagination.limit'));

// this is what the apidoc.json file will point to to load the header.md
// example: "filename": "../public/api-rendered-markdowns/header.md"
$path = public_path(self::OUTPUT_PATH . 'header.md');

// write the actual file
file_put_contents(public_path(self::OUTPUT_PATH . 'header.md'), $this->headerMarkdownContent);
file_put_contents($path, $this->headerMarkdownContent);

return $path;
}

}
File renamed without changes.
309 changes: 309 additions & 0 deletions public/api-rendered-markdowns/header.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,309 @@
## Usage Overview

Here are some information that should help you understand the basic usage of our RESTful API.
Including info about authenticating users, making requests, responses, potential errors, rate limiting, pagination, query parameters and more.



## **Headers**

Certain API calls require you to send data in a particular format as part of the API call.
By default, all API calls expect input in `JSON` format, however you need to inform the server that you are sending a JSON-formatted payload.
And to do that you must include the `Accept => application/json` HTTP header with every call.


| Header | Value Sample | When to send it |
|---------------|------------------------------|------------------------------------------------------------------------------|
| Accept | `application/json` | MUST be sent with every endpoint. |
| Authorization | `Bearer {Access-Token-Here}` | MUST be sent whenever the endpoint requires (Authenticated User) permission. |



## **Rate limiting**

All REST API requests are throttled to prevent abuse and ensure stability.
The exact number of calls that your application can make per day varies based on the type of request you are making.

The rate limit window is `5` minutes per endpoint, with most individual calls allowing for `100` requests in each window.

*In other words, each user is allowed `100` calls per endpoint per `5` minutes for each unique access token.*


For how many hits you can preform on an endpoint, you can always check the header:

```
X-RateLimit-Limit →100
X-RateLimit-Remaining →50
X-RateLimit-Reset →1487227542
```


## **Tokens**

The Access Token lives for `30 days, 0 hours, 0 minutes and 0 seconds`. (equivalent to `43200` minutes).

*You will need to re-autneticate the user when the token expires.*


## **Pagination**

By default, all fetch requests return the first `10` items in the list. Check the **Query Parameters** for how to controll the pagination.


## **Responses**

Unless otherwise specified, all of API endpoints will return the information that you request in the JSON data format.


#### Normal response example

```shell
{
"data": {
"object": "Role",
"id": "owpmaymq",
"name": "admin",
"description": "Administrator",
"display_name": null,
"permissions": {
"data": [
{
"object": "Permission",
"id": "wkxmdazl",
"name": "update-users",
"description": "Update a User.",
"display_name": null
},
{
"object": "Permission",
"id": "qrvzpjzb",
"name": "delete-users",
"description": "Delete a User.",
"display_name": null
}
]
}
}
}
```


#### Pagination

*The pagination object is always returned in the **meta** when pagination is available on the endpoint.*

```shell
"data": [...],
"meta": {
"pagination": {
"total": 2000,
"count": 30,
"per_page": 30,
"current_page": 22,
"total_pages": 1111,
"links": {
"previous": "http://api.hello.dev/endpoint?page=21"
}
}
}
```

#### Header

Header Response :

```
Cache-Control →private, must-revalidate
Connection →keep-alive
Content-Type →application/json
Date →Thu, 14 Feb 2014 22:33:55 GMT
ETag →"9c83bf4cf0d09c34782572727281b85879dd4ff6"
Server →nginx
Transfer-Encoding →chunked
X-Powered-By →PHP/7.0.9
X-RateLimit-Limit →100
X-RateLimit-Remaining →99
X-RateLimit-Reset →1487277532
```



## **Query Parameters**

Query parameters are optional, you can apply them to some endopints whenever you need them.

### Ordering

The `?orderBy=` parameter can be applied to any **`GET`** HTTP request responsible for listing records.


**Usage:**

```
api.hello.dev/endpoint?orderBy=created_at
```



### Sorting

The `?sortedBy=` parameter is usually used with the `orderBy` parameter.

By default the `orderBy` sorts the data in **Ascending** order, if you want the data sorted in **Descending** order, you can add `&sortedBy=desc`.



**Usage:**

```
api.hello.dev/endpoint?orderBy=name&sortedBy=desc
```

Order By Accepts:

- `asc` for Ascending.
- `desc` for Descending.





### Searching

The `?search=` parameter can be applied to any **`GET`** HTTP request.


**Usage:**

#### Search any field:

```
api.hello.dev/endpoint?search=keyword here
```

> Space should be replaced with `%20` (search=keyword%20here).
#### Search any field for multiple keywords:

```
api.hello.dev/endpoint?search=first keyword;second keyword
```

#### Search in specific field:
```
api.hello.dev/endpoint?search=field:keyword here
```

#### Search in specific fields for multiple keywords:
```
api.hello.dev/endpoint?search=field1:first field keyword;field2:second field keyword
```

#### Define query condition:

```
api.hello.dev/endpoint?search=field:keyword&searchFields=name:like
```

Available Conditions:

- `like`: string like the field. (SQL query `%keyword%`).
- `=`: string exact match.


#### Define query condition for multiple fields:

```
api.hello.dev/endpoint?search=field1:first keyword;field2:second keyword&searchFields=field1:like;field2:=;
```



### Filtering

The `?orderBy=` parameter can be applied to any **`GET`** HTTP request. And is used to request only certain fields.

**Usage:**

Return only ID and Name from that Model, (everything else will be returned as `null`).

```
api.hello.dev/endpoint?filter=id;name
```


### Paginating

The `?page=` parameter can be applied to any **`GET`** HTTP request responsible for listing records (mainly for Paginated data).

**Usage:**

```
api.hello.dev/endpoint?page=200
```


### Relationships

The `?include=` parameter can be used with any endpoint, only if it supports it.

How to use it: let's say there's a Driver object and Car object. And there's an endopint `/cars` that returns all the cars objects.
The include allows getting the cars with their drivers `/cars?include=drivers`.

However, for this parameter to work, the endpoint `/cars` should clearly define that it
accepts `driver` as relationship (in the **Available Relationships** section).

**Usage:**

```
api.hello.dev/endpoint?include=relationship
```



### Caching

Some endpoints stores their response data in memory (chaching) after quering them for the first time, to speed up the response time.
The `?skipCache=` parameter can be used to force skip loading the response data from the server cache and instead get a fresh data from the database upon the request.

**Usage:**

```
api.hello.dev/endpoint?skipCache=true
```




## **Errors**


General Errors:

| Error Code | Message | Reason |
|------------|---------------------------------------------------------------------------------------|-----------------------------------------------------|
| 401 | Wrong number of segments. | Wrong Token. |
| 401 | Failed to authenticate because of bad credentials or an invalid authorization header. | Missing parts of the Token. |
| 401 | Could not decode token: The token ... is an invalid JWS. | Missing Token. |
| 405 | Method Not Allowed. | Wrong Endpoint URL. |
| 422 | Invalid Input. | Validation Error. |
| 500 | Internal Server Error. | {Report this error as soon as you get it.} |
| 500 | This action is unauthorized. | Using wrong HTTP Verb. OR using unauthorized token. |

TO BE CONTINUE...


## **Requests**

Calling unprotected endpoint example:

```shell
curl -X POST -H "Accept: application/json" -H "Content-Type: multipart/form-data; -F "[email protected]" -F "password=admin" -F "=" "http://api.hello.dev/login"
```
Calling protected endpoint (passing Bearer Token) example:
```shell
curl -X GET -H "Accept: application/json" -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." -H "http://api.hello.dev/users"
```

0 comments on commit cdd7152

Please sign in to comment.