Code Monkey home page Code Monkey logo

nette-restroute's Introduction

REST route for Nette Framework

Build Status

Route automatically maps CRUD to Presenters and actions in the defined module. And creates parameters which are accessible in Presenter.

  • format
  • id (autodetected)
  • associations (an array with associations)
  • data (raw data from the request)
  • query (an array of items from the query string)

Format detection:

Variable $format is detected from HTTP header Accept. If header is not present Route try detect format from the URL (.../foo.json). If no format is in the URL Route use a default format json.

Installation:

The best way to install Nette-RestRoute is using Composer:

$ composer require adamstipak/nette-rest-route

Usage:

use AdamStipak\RestRoute;

// $router is an instance of Nette\Application\Routers\RouteList  

// No parameters needed. Presenter name will be generated.
$router[] = new RestRoute;

// With module.
$router[] = new RestRoute('Api');

// With module and xml as a default format.
$router[] = new RestRoute('Api', 'xml');

// With URL module versioning
$router[] = (new RestRoute())
    ->useURLModuleVersioning(
        '/v[0-9\.]+/',     // Regex for URL version
        [                  // URL fragment to module mapping
          NULL => 'V1',    // Default version module is V1
          'v1' => 'V1',    // /v1 to module V1
          'v2' => 'V2'     // /v2 to module V2
        ]
    );

First parameter is a name of the module where the route will sends an Request. URL prefix will be generated. See examples. ####Examples:

NULL      => /<generated presenter name>
'Api'     => /api/<generated presenter name>
'My:Api'  => /my/api/<generated presenter name>
...

Second parameter is default format. By default the default format is json. RestRoute support only 2 formats:

  • json (default)
  • xml

Examples

Read all:

URL: /api/users\ApiModule\UsersPresenter::actionReadAll
HTTP HEADER Accept: application/json
Method: GET
Request body: Empty
Params:

format = json
associations = array(0)
data = ""
query = array(0)

Flag readAll was dropped and Route automatically generate action readAll if no Resource ID was not found in the URL.


Read with resource ID

URL: /api/users/123\ApiModule\UsersPresenter::actionRead
HTTP HEADER Accept: application/json
Method: GET
Request body: Empty
Params:

format = json
id = 123
associations = array(0)
data = ""
query = array(0)

Query params:

URL: /api/users?foo=bar&page=1\ApiModule\UsersPresenter::actionReadAll
HTTP HEADER Accept: application/json
Method: GET
Request body: Empty
Params:

format = json
associations = array(0)
data = ""
query = array(
	foo => "bar"
	page => 1
)

Create:

URL: /api/users\ApiModule\UsersPresenter::actionCreate
HTTP HEADER Accept: application/json
Method: POST
Request body:

{
	"foo": "bar",
	"nested": {
		"foo": "bar"	
	}
}

Params:

format = json
associations = array(0)
data = {"foo": "bar", "nested": {"foo": "bar"}}
query = array(0)

Update:

URL: /api/users/123\ApiModule\UsersPresenter::actionUpdate
HTTP HEADER Accept: application/json
Method: PUT
Request body:

{
	"foo": "bar",
	"nested": {
		"foo": "bar"	
	}
}

Params:

format = json
id = 123
associations = array(0)
data = {"foo": "bar", "nested": {"foo": "bar"}}
query = array(0)

Partial update:

URL: /api/users/123\ApiModule\UsersPresenter::actionPartialUpdate
HTTP HEADER Accept: application/json
Method: PATCH
Request body:

{
	"foo": "bar",
	"nested": {
		"foo": "bar"	
	}
}

Params:

format = json
id = 123
associations = array(0)
data = {"foo": "bar", "nested": {"foo": "bar"}}
query = array(0)

Delete:

URL: /api/users/123\ApiModule\UsersPresenter::actionDelete
HTTP HEADER Accept: application/json
Method: DELETE
Request body: Empty
Params:

format = json
id = 123
associations = array(0)
data = ""
query = array(0)

Options:

For more about OPTIONS documentation see w3.org.

URL: /api/users\ApiModule\UsersPresenter::actionOptions
HTTP HEADER Accept: application/json
Method: OPTIONS
Request body: Empty
Params:

format = json
associations = array(0)
data = ""
query = array(0)

Associations:

Last item (pair) before . is main resource. Everything what is before the last item are associations (apigee.com).

URL: /api/users/1/comments\ApiModule\CommentsPresenter::actionReadAll|actionCreate|actionUpdate|actionDelete
HTTP HEADER Accept: application/json
Method: GET, POST, PUT, DELETE
Request body: Empty
Params:

format = json
associations = array(
	users => 1
)
data = ""
query = array(0)

URL: /api/users/123/comments/456\ApiModule\CommentsPresenter::actionRead|actionCreate|actionUpdate|actionDelete
HTTP HEADER Accept: application/json
Method: GET, POST, PUT, DELETE
Request body: Empty
Params:

format = json
id = 456
associations = array(
	users => 123
)
data = ""
query = array(0)

URL: /api/users/1/blogs/2/comments\ApiModule\CommentsPresenter::actionReadAll|actionCreate|actionUpdate|actionDelete
HTTP HEADER Accept: application/json
Method: GET, POST, PUT, DELETE
Request body: Empty
Params:

format = json
id = 1
associations = array(
	users => 1
	blogs => 2
)
data = ""
query = array(0)

URL versioning:

RestRoute provides you with option to version your API in URL. Each version is represented by separate module in your application.

First, you define regexp which is used to detect if the version parameter is present in URL. It must be in the begging of the path. Then, you define version to module mapping. NULL key stands for default module, if version parameter doesn't get detected.

$router[] = (new RestRoute('Api')) // Optional module
    ->useURLModuleVersioning(
        RestRoute::MODULE_VERSION_PATH_PREFIX_PATTERN,     // Regex for URL version
        [                  // URL fragment to module mapping
          NULL => 'V1',    // Default version module is V1
          'v1' => 'V1',    // /v1 to module V1
          'v2' => 'V2'     // /v2 to module V2
        ]
    );

RestRoute will now map your requests to presenters like this (URL -> Presenter):

/api/foo        ->  Api:V1:Foo
/api/v1/foo     ->  Api:V1:Foo
/api/v2/foo     ->  Api:V2:Foo

File uploads:

RestRoute reads standard PHP input and data puts to $data param in action. This is fit for one file upload or upload with chunks because it is a RAW data.

For multiple file upload RestRoute just set files when creates \Nette\Application\Request. In presenter just inject \Nette\Application\Request service and use these files.

class FooPresenter {
  /** @var \Nette\Application\Request @inject */
  public $request;

  public function actionCreate () {
    $files = $this->request->getFiles();
  }
}

Development

RestRoute is developed in Docker container via docker-compose command.

Example:

$ docker-compose run --rm default install  # install deps via composer
$ docker-compose run --rm default  # runs tests in container

Attach to container:

$ docker-compose run --rm default bash # runs bash in container and attach tty

nette-restroute's People

Contributors

f3l1x avatar fabiancz avatar freezy-sk avatar jsifalda avatar khorsky avatar klimesf avatar michal-loksik avatar newpope avatar skrivy avatar vvoody- 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nette-restroute's Issues

Undefined $params[...]

Na čistém sandboxu mi to házelo undefined $params na řádcích https://github.com/newPOPE/Nette-RestRoute/blob/master/src/RestRoute.php#L179-L181, https://github.com/newPOPE/Nette-RestRoute/blob/master/src/RestRoute.php#L191, https://github.com/newPOPE/Nette-RestRoute/blob/master/src/RestRoute.php#L193-L195 a možná ještě nějakých, všechno ve stejném duchu. Pro rychlý fix jsem si tam zatím doplnil issety a víc to nezkoumal a nepřemýšlel nad tím.

Chyba se projevila jentak při otevření Homepage:default. Nette aktuální 2.0.7.

Jinak je to výborný pomocník, zdá se :).

How can I make this route work over SSL only?

Hello, thanks for this route implementation. :)

I was just wondering if I can force this route to work for https URL only? Adding IRouter::SECURED to the definition does not work.

Creating links from API presenter does not work

At presenter I would like to have possibility to create link by call $this->presenter->link(...). In API class $this->presenter->link everytime returns link to current action (eventually with parameters) not depend on first parameter of $this->presenter->link.

I would like to use this created link in Location header to return link to created entity.

class cannot be found

when using composer installation, the class cannot be found. i think you're missing the autoload definition in composer.json

always_populate_raw_post_data

I recieved an error via Tracy: "Cannot modify header information - headers already sent" etc. There weren't any BOM, so I've turned of Tracy and this appers:

Deprecated: Automatically populating $HTTP_RAW_POST_DATA is deprecated and will be removed in a future version. To avoid this warning set 'always_populate_raw_post_data' to '-1' in php.ini and use the php://input stream instead. in Unknown on line 0

Warning: Cannot modify header information - headers already sent in Unknown on line 0

I absotutely don´t know if it's my incorrectly set up PHP (5.6.13) or if It can be some general . When I uncomment the line in php.ini (-1 has been there yet) everything works even on my Wedos webhosting (PHP 5.6.5) where always_populate_raw_post_data = 0.

Doc enhancement

Its not clear that the presenters should in case of URL: /api/users → \ApiModule\UsersPresenter::read
should use traditional actionRead|renderRead methods, as usual (just to clear things up a bit)

API url redirects to weird url

router is defined as follows:

$router[] = new RestRoute('Api', 'json');

I have defined Api modules with Test presenter

when I visit BASEURL/api/test?access_token=test

it redirects me to BASEURL/api/test?action=read&format=xml&data=&query[action]=read&query[format]=xml&query[data]=&query[query][access_token]=test

*BASEURL is just placeholder for domain name

exactly same thing happesn with nette 2.2.x and 2.3

Argument $query passed to ApiModule\TeamsPresenter::actionRead() must be scalar, array given

Narazil jsem na problém při pokusu o čtení $query v actionRead metodě. V presenteru moje metoda vypadá asi takto:

/**
  * Search for specific teams by a search query
  */
public function actionRead($query)
{
...
}

Nezáleží tak úplně co je v ní, protože se to do ní ani nedostane a hodí to následující chybu:

Argument $query passed to ApiModule\TeamsPresenter::actionRead() must be scalar, array given

Při volání této url:

http://localhost/muj-projekt/api/teams/?q=cokoliv

Je to chyba v RestRoute nebo někde jinde? Díky moc.

dont require format parameter

The enforced requirement of a request in this form is not a correct REST behaviour:

api/.?params=...

the format should not be a part of the resource name

correctly it should be optional, defaulting to json, then it would be written like this:

api/?params=...&format=json

is there any reason why a format should be specified?

/api/users?foo=bar&page=1 automaticky spadne do actionReadAll

Podle dokumentace by se $query měla definovat v URL takto:

/api/users?foo=bar&page=1

Pokud to ale takto nadefinuji, tak mi ta $query spadne do actionReadAll metody. Místo toho to musím nadefinovat takto:

/api/users/?foo=bar&page=1

(přidat /) aby to fungovalo správně. Je to záměr, aby to padalo do actionReadAll nebo jsi jenom zapomněl v dokumentaci přidat lomítko? Kdybych neměl nadefinovanou actionReadAll, tak bych na to asi nepřišel.

Api module - subdomain route

Hello,

I would like to use api.domain.tld/v1/resource routes instead of domain.tld/api/v1/resource is there possible to put it on the feature requests list, please?

Thanks

OPTIONS method is not allowed

We use RestRoute to create API for communication with mobile app. Mobile app is sending OPTIONS before POST and check if we returns 200 code. RestRoute dont allow this method and throw exception.

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.