Giter Site home page Giter Site logo

phalcon / rest-api Goto Github PK

View Code? Open in Web Editor NEW
87.0 23.0 34.0 912 KB

Implementation of an API application using the Phalcon Framework

Home Page: https://phalcon.io

License: MIT License

PHP 97.27% Shell 1.75% Dockerfile 0.99%
phalcon jwt jsonapi json-api api rest-api phalcon-php tutorial rest restful-api

rest-api's Introduction

phalcon-api

Sample API using Phalcon

Scrutinizer Code Quality Code Coverage Build Status

Implementation of an API application using the Phalcon Framework https://phalcon.io

Installation

  • Clone the project
  • In the project folder run nanobox run php-server
  • Hit the IP address with postman

NOTE This requires nanobox to be present in your system. Visit their site for installation instructions.

Features

JWT Tokens

As part of the security of the API, JWT are used. JSON Web Tokens offer an easy way for a consumer of the API to send requests without the need to authenticate all the time. The expiry of each token depends on the setup of the API. An admin can easily keep the expiry very short, thus consumers will always have to log in first and then access a resource, or they can increase the "life" of each token, thus having less calls to the API.

Middleware
  • Lazy loading to save resources per request
  • Stop execution as early as possible when an error occurs
  • Execution
    • NotFound - 404 when the resource requested is not found
    • Authentication - After a /login checks the Authentication header
    • TokenUser - When a token is supplied, check if it corresponds to a user in the database
    • TokenVerification - When a token is supplied, check if it is correctly signed
    • TokenValidation - When a token is supplied, check if it is valid (issuedAt, notBefore, expires)
JSONAPI

This implementation follows the JSON API standard. All responses are formatted according to the standard, which offers a uniformed way of presenting data, simple or compound documents, includes (related data), sparse fieldsets, sorting, patination and filtering.

Usage

Requests

The routes available are:

Method Route Parameters Action
POST login username, password Login - get Token
POST companies name, address, city, phone Add a company record in the database
GET companies Get companies. Empty resultset if no data present
GET companies Numeric Id Get company by id. 404 if record does not exist
GET individuals Get individuals. Empty resultset if no data present
GET individuals Numeric Id Get individual by id. 404 if record does not exist
GET individual-types Get individual types. Empty resultset if no data present
GET individual-types Numeric Id Get individual type by id. 404 if record does not exist
GET products Get products. Empty resultset if no data present
GET products Numeric Id Get product by id. 404 if record does not exist
GET product-types Get product types. Empty resultset if no data present
GET product-types Numeric Id Get product type by id. 404 if record does not exist
GET users Get users. Empty resultset if no data present
GET users Numeric Id Get user by id. 404 if record does not exist

Relationships

/companies/<number>?included=<individuals>,<products>

individuals/<number>?included=<companies>,<individual-types>

individual-types/<number>?included=<individuals>

products/<number>?included=<companies>,<product-types>

product-types/<number>?included=<products>

Fields

/companies?fields[<relationship>]=<field>,<field>&fields[<relationship>]=<field>,<field>

Sorting

/companies?sort=<[-]id>,<[-]status>,<[-]username>,<[-]issuer>

individuals?sort=<[-]id',<[-]companyId>,<[-]typeId>,<[-]prefix>,<[-]first>,<[-]middle>,<[-]last>,<[-]suffix'>,

individual-types?sort=<[-]id>,<[-]name>

products?sort=<[-]id',<[-]typeId>,<[-]name>,<[-]quantity>,<[-]price>

product-types?sort=<[-]id>,<[-]name>

Responses

Structure

Top Elements

  • jsonapi Contains the version of the API as a sub element
  • data Data returned. Is not present if the errors is present
  • errors Collection of errors that occurred in this request. Is not present if the data is present
  • meta Contains timestamp and hash of the json_encode($data) or json_encode($errors)

After a GET the API will always return a collection of records, even if there is only one returned. If no data is found, an empty resultset will be returned.

Each endpoint returns records that follow this structure:

{
  "id": 1051,
  "type": "users",
  "attributes": {
    "status": 1,
    "username": "niden",
    "issuer": "https:\/\/niden.net",
    "tokenPassword": "11110000",
    "tokenId": "11001100"
  }
}

The record always has id and type present at the top level. id is the unique id of the record in the database. type is a string representation of what the object is. In the above example it is a users record. Additional data from each record are under the attributes node.

Samples

404

{
  "jsonapi": {
    "version": "1.0"
  },
  "errors": {
    "404 not found"
  },
  "meta": {
    "timestamp": "2018-06-08T15:04:34+00:00",
    "hash": "e6d4d57162ae0f220c8649ae50a2b79fd1cb2c60"
  }
}

Error

{
  "jsonapi": {
    "version": "1.0"
  },
  "errors": {
    "Description of the error no 1",
    "Description of the error no 2"
  },
  "meta": {
    "timestamp": "2018-06-08T15:04:34+00:00",
    "hash": "e6d4d57162ae0f220c8649ae50a2b79fd1cb2c60"
  }
}
Success
{
  "jsonapi": {
    "version": "1.0"
  },
  "data": [
  ],
  "meta": {
    "timestamp": "2018-06-08T15:04:34+00:00",
    "hash": "e6d4d57162ae0f220c8649ae50a2b79fd1cb2c60"
  }
}

/products/1134?includes=companies,product-types

{
  "jsonapi": {
    "version": "1.0"
  },
  "data": [
    {
      "type": "products",
      "id": "1134",
      "attributes": {
        "typeId": 890,
        "name": "prd-a-5b64af7e70741",
        "description": "5b64af7e7074a",
        "quantity": 25,
        "price": "19.99"
      },
      "links": {
        "self": "http:\/\/api.phalcon.ld\/products\/1134"
      },
      "relationships": {
        "companies": {
          "links": {
            "self": "http:\/\/api.phalcon.ld\/products\/1134\/relationships\/companies",
            "related": "http:\/\/api.phalcon.ld\/products\/1134\/companies"
          },
          "data": [
            {
              "type": "companies",
              "id": "1430"
            },
            {
              "type": "companies",
              "id": "1431"
            }
          ]
        },
        "product-types": {
          "links": {
            "self": "http:\/\/api.phalcon.ld\/products\/1134\/relationships\/product-types",
            "related": "http:\/\/api.phalcon.ld\/products\/1134\/product-types"
          },
          "data": {
            "type": "product-types",
            "id": "890"
          }
        }
      }
    }
  ],
  "included": [
    {
      "type": "companies",
      "id": "1430",
      "attributes": {
        "name": "com-a5b64af7e6c846",
        "address": "5b64af7e6c84f",
        "city": "5b64af7e6c855",
        "phone": "5b64af7e6c85c"
      },
      "links": {
        "self": "http:\/\/api.phalcon.ld\/companies\/1430"
      }
    },
    {
      "type": "companies",
      "id": "1431",
      "attributes": {
        "name": "com-b5b64af7e6e3d3",
        "address": "5b64af7e6e3dc",
        "city": "5b64af7e6e3e2",
        "phone": "5b64af7e6e3e9"
      },
      "links": {
        "self": "http:\/\/api.phalcon.ld\/companies\/1431"
      }
    },
    {
      "type": "product-types",
      "id": "890",
      "attributes": {
        "name": "prt-a-5b64af7e6f638",
        "description": "5b64af7e6f641"
      },
      "links": {
        "self": "http:\/\/api.phalcon.ld\/product-types\/890"
      }
    }
  ],
  "meta": {
    "timestamp": "2018-08-03T19:39:42+00:00",
    "hash": "384c6b3772727b1a9532865d2ae2d51c095c0fd9"
  }
}

For more information regarding responses, please check JSON API

TODO

  • Work on companies GET
  • Work on included data
  • Work on sorting
  • Write examples of code to send to the client
  • Create docs endpoint
  • Work on relationships
  • Work on pagination
  • Work on filters
  • Sorting on related resources
  • Perhaps add a new claim to the token tied to the device? setClaim('deviceId', 'Web-Server'). This will allow the client application to invalidate access to a device that has already been logged in.

Sponsors

Become a sponsor and get your logo on our README on Github with a link to your site. [Become a sponsor]

Backers

Support us with a monthly donation and help us continue our activities. [Become a backer]

rest-api's People

Contributors

arhell avatar jeckerson avatar niden avatar ruudboon avatar sergeyklay avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rest-api's Issues

running without nanobox

Hi, I'm more comfortable running php apps without nanobox, docker etc, I can understand better..

I managed to do following:

  1. built the app with composer install
  2. ran vendor/bin/phinx migrate that created tables
  3. ran vendor/bin/phinx seed:run --> nothing seems to happen -- is there any sample data? if not how do i create password
  4. checked db and tables are there but no data

once i do this, i am encountered with 2 issues

  1. GET URL like /companies gives "Invalid Token" -- i guess this is understanble as i've not logged in got token
  2. POST URL like /login gives 500 Internal server error
    PHP Fatal error: Uncaught Phalcon\Mvc\Model\Exception: Failed to store metaData to the cache adapter in /apps/phalcon/rest-api/library/Traits/QueryTrait.php:137

Any ideas how to resolve this .. thanks

Phalcon v4 [Iteration 2]

  • Change domain to phalcon.io
  • Add license to header in .php files
  • Rename namespaces from Niden to Phalcon\Api
  • Change usage of Phalcon\Plugin to Injectable
  • Review rest of comments and suggestions in comments of #22 PR
  • Return back usage of use Phalcon\Filter; (#22 (comment))
  • Psalm integration with (less strict) level 8 of checks
  • PSR-2 (in code)
  • Bug fixes (if any)
  • Minor code refactors
  • Refactor tests/unit/BootstrapCest.php by moving into bootstrap or/and module initialization
  • Fix env CODECEPTION_* variables
  • Adapt Cache Service Provider to get adapter from config and not work only with memcached
  • See if envValue() function is needed
  • Create conditional import of Phalcon\Filter for 4.0.0-beta.2
  • Travis integration (#25)
  • Scrutinizer CI fix/reboot (#26)

Sparse Fieldsets

  • A client MAY request that an endpoint return only specific fields in the response on a per-type basis by including a fields[TYPE] parameter.
  • The value of the fields parameter MUST be a comma-separated (U+002C COMMA, “,”) list that refers to the name(s) of the fields to be returned.
  • If a client requests a restricted set of fields for a given resource type, an endpoint MUST NOT include additional fields in resource objects of that type in its response.
GET /articles?include=author&fields[articles]=title,body&fields[people]=name HTTP/1.1
Accept: application/vnd.api+json

Note: The above example URI shows unencoded [ and ] characters simply for readability. In practice, these characters must be percent-encoded, per the requirements in RFC 3986.

[NFR] Publish library as package

It would be great if the essential reusable files become part of a package (composer), allowing to build and api based on this project and have the possibility to upgrade the package when new fixes are done.

Unable to write to metaData

Hello,

I've built this project around Docker and have configured the right dependencies, project, but when I run a request to login, I keep getting an error exception thrown the MetaData class.

Here is the exact error:

<br />
<b>Fatal error</b>:  Uncaught Phalcon\Mvc\Model\Exception: Failed to store metaData to the cache adapter in /api/library/Traits/QueryTrait.php:139
Stack trace:
#0 [internal function]: Phalcon\Mvc\Model\MetaData-&gt;throwWriteException(true)
#1 [internal function]: Phalcon\Mvc\Model\MetaData-&gt;write('map-phalcon\\api...', Array)
#2 [internal function]: Phalcon\Mvc\Model\MetaData-&gt;initialize(Object(Phalcon\Api\Models\Users), NULL, NULL, NULL)
#3 [internal function]: Phalcon\Mvc\Model\MetaData-&gt;readColumnMapIndex(Object(Phalcon\Api\Models\Users), 1)
#4 [internal function]: Phalcon\Mvc\Model\MetaData-&gt;getReverseColumnMap(Object(Phalcon\Api\Models\Users))
#5 [internal function]: Phalcon\Mvc\Model\MetaData-&gt;hasAttribute(Object(Phalcon\Api\Models\Users), 'username')
#6 [internal function]: Phalcon\Mvc\Model\Query-&gt;_getQualified(Array)
#7 [internal function]: Phalcon\Mvc\Model\Query-&gt;_getExpression(Array, true)
#8 [internal function]: Phalcon\Mvc\Model\Query-&gt;_getExpression(Array, true)
#9 [internal function]: Phalcon\Mvc\Model\Query-&gt;_getEx in <b>/api/library/Traits/QueryTrait.php</b> on line <b>139</b><br />

I did make sure that memcached was installed and also running on my machine. Permissions seem to be correct on the folders as it is able to write logs within the storage directory.

Do you have any suggestions?

[NFR] Add ACL

Would it be possible to add some kind of ACL allowing resource access to certain users?

Introduce Relationships

  • A server MUST support fetching relationship data for every relationship URL provided as a self link as part of a relationship’s links object.
GET /articles/1/relationships/author HTTP/1.1
Accept: application/vnd.api+json

Responses

200 OK
  • A server MUST respond to a successful request to fetch a relationship with a 200 OK response.
  • The primary data in the response document MUST match the appropriate value for resource linkage, as described above for relationship objects.
  • The top-level links object MAY contain self and related links, as described above for relationship objects.
  • A one to one relationship returns the object.
  • One to many an array of objects.
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "links": {
    "self": "/articles/1/relationships/tags",
    "related": "/articles/1/tags"
  },
  "data": [
    { "type": "tags", "id": "2" },
    { "type": "tags", "id": "3" }
  ]
}
  • No data returns an empty array
404 Not Found
  • A server MUST return 404 Not Found when processing a request to fetch a relationship link URL that does not exist. Note: This can happen when the parent resource of the relationship does not exist. For example, when /articles/1 does not exist, request to /articles/1/relationships/tags returns 404 Not Found.

  • If a relationship link URL exists but the relationship is empty, then 200 OK MUST be returned, as described above.

  • A server MAY respond with other HTTP status codes.

  • A server MAY include error details with error responses.

MongoDB integration

Hi bro,
I appreciate your effort, this is a great project but long time no see any update.
I have some resource in MongoDB, can you give me some suggestions for integration in this project

How to use automatical Routing?

In Phalcon we can define a default route that includes a module wildcard:

<?php

use Phalcon\Mvc\Router;

$router = new Router(false);

$router->add(
    '/:module/:controller/:action/:params',
    [
        'module'     => 1,
        'controller' => 2,
        'action'     => 3,
        'params'     => 4,
    ]
);

How to use automatical routing in the REST api? It seems to be added manually:

$routes = [
            // Class, Method, Route, Handler
            [LoginController::class,        '/login',     'post', '/'],
            [CompaniesAddController::class, '/companies', 'post', '/'],
            [UsersGetController::class,     '/users',     'get',  '/'],
            [UsersGetController::class,     '/users',     'get',  '/{recordId:[0-9]+}'],
        ];

Introduce sort capability

Per the documentation

  • A server MAY choose to support requests to sort resource collections according to one or more criteria (“sort fields”).
  • An endpoint MAY support requests to sort the primary data with a sort query parameter. The value for sort MUST represent sort fields.
  • An endpoint MAY support multiple sort fields by allowing comma-separated (U+002C COMMA, “,”) sort fields. Sort fields SHOULD be applied in the order specified.
  • The sort order for each sort field MUST be ascending unless it is prefixed with a minus (U+002D HYPHEN-MINUS, “-“), in which case it MUST be descending.
  • If the server does not support sorting as specified in the query parameter sort, it MUST return 400 Bad Request.
  • If sorting is supported by the server and requested by the client via query parameter sort, the server MUST return elements of the top-level data array of the response ordered according to the criteria specified. The server MAY apply default sorting rules to top-level data if request parameter sort is not specified.

How to access users, companies... with request?

For example, when I visit with postman http://localhost/users, It returns Invalid Token:

{"jsonapi":{"version":"1.0"},"errors":["Invalid Token"],"meta":{"timestamp":"2020-02-10","hash":"76f4972fb2132f97070a0c8904c0f61de14a"}}

How to access the lists of users, companies...etc.

Introduce Pagination

  • A server MAY choose to limit the number of resources returned in a response to a subset (“page”) of the whole set available.
  • A server MAY provide links to traverse a paginated data set (“pagination links”).
  • Pagination links MUST appear in the links object that corresponds to a collection. To paginate the primary data, supply pagination links in the top-level links object. To paginate an included collection returned in a compound document, supply pagination links in the corresponding links object.
  • The following keys MUST be used for pagination links:
  • first: the first page of data
  • last: the last page of data
  • prev: the previous page of data
  • next: the next page of data
  • Keys MUST either be omitted or have a null value to indicate that a particular link is unavailable.
  • Concepts of order, as expressed in the naming of pagination links, MUST remain consistent with JSON API’s sorting rules.
  • The page query parameter is reserved for pagination. Servers and clients SHOULD use this key for - [ ] Introduction of page based pagination.
  • Introduction of page chunk size (config)
  • page[number] is to be used

Documentation

Hello,

I would like to help on the auto-documentation part.

Do you have in mind a composer class you would prefer to use ?

It could be phalcon-swagger or swagger-php for API
and ApiGen for docs.

Thanks a lot for this lib

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.