Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide web-api support #303

Closed
Ragazzo opened this issue May 17, 2013 · 233 comments
Closed

Provide web-api support #303

Ragazzo opened this issue May 17, 2013 · 233 comments

Comments

@Ragazzo
Copy link
Contributor

@Ragazzo Ragazzo commented May 17, 2013

I think it can be useful if Yii will provide some web-api support, for example REST, with catching event when request starts, also if Yii will provide some CRestAction < CAction, maybe other workaround can be here to fit REST, what do u think? Situation is common enough so if Yii will give developers some basis it can be good.

Features to implement

  • API Testing Framework (RC)
  • File upload support (RC) moved to #4477
  • Batch queries with transactions support and error handling. (GA or post GA) moved to #4478
  • Searching and filtering (GA or post GA) moved to #4479
  • Automatic API Documentation Generation (e.g. via https://developers.helloreverb.com/swagger/) (GA or post GA) moved to #2684
  • Ability to serve in multiple formats: JSON, JSONP, XML.
  • Pagination for collections.
  • Documentation about which HTTP codes to return when.
  • Documentation on how to implement authentication.
@samdark
Copy link
Member

@samdark samdark commented May 17, 2013

I'm for implementing a base layer for rest APIs. Do you have any good ideas about requirements?

@Ragazzo
Copy link
Contributor Author

@Ragazzo Ragazzo commented May 17, 2013

yes, will post them later today here, with maybe some links to resources that also can be useful.

@bwoester
Copy link
Contributor

@bwoester bwoester commented May 17, 2013

More support for RESTful apps would be definitely a good idea. But if something like this is implemented, imo it should be a really solid foundation.

I certainly don't wanna start to flame here, but just to give a negative example: SOAP-support in 1.x. The idea was really cool, and providing a SOAP service basically by simply annotating your methods could have been a killer feature. But the lack of interoperability with other technologies like java or .net really limited its usability. Also, it didn't provide some enhanced features like the ws-* extensions (never checked if they could have been implemented as extensions though, which would have been okay).

For support of RESTful apps, I think some of the most important requirements would be:

  • authentication - pops up in the forum again and again. Can't be provided out of the box, but definitely should be documented in more detail
  • paged collections - unpaged just won't scale
  • for sub-collections, there should be a ways to switch between including them directly and referencing them
  • include/ exclude resource attributes by default, with the possibility for the client to override these defaults
  • service discoverability
  • possibility to use custom output renderers - while I think json would be a good default, xml remains an alternative
  • obviously, it should be easy to re-use your existing models as REST resources

I liked the REST with spring series, it explains a lot of the concepts around REST, so it's worth reading even if you don't use spring.

@samdark
Copy link
Member

@samdark samdark commented May 17, 2013

I'm for never including sub-collection data directly. A reference in a good API should be URL.

Can you elaborate about the following?

  1. include/ exclude resource attributes by default, with the possibility for the client to override these defaults
  2. service discoverability
@ghost ghost assigned samdark May 17, 2013
@Ragazzo
Copy link
Contributor Author

@Ragazzo Ragazzo commented May 17, 2013

@samdark i think we need to create new topic on forum and discuss all there to avoid big comments here, what do u think? can u than create topic and link it here in comments?

@Ragazzo
Copy link
Contributor Author

@Ragazzo Ragazzo commented May 17, 2013

also this book covers some common features to implement with comparison of other API implementation, worth to read this https://blog.apigee.com/detail/is_your_api_naked_10_api_roadmap_considerations_part_1_visibility

@bwoester
Copy link
Contributor

@bwoester bwoester commented May 17, 2013

Agree, references should be (absolute) URLs.

But simply never including sub-collections won't be the right solution imo. It might be a default, but there are enough use cases where the data you get is really useful and saves you from doing a lot of additional requests. As an example, think about a gallery that has a collection of categories, each category has a collection of images. If you include the sub-collection of images (maybe with a small page size like 5), you have enough data at hand to display some fancy category preview. And it saves you from introducing a special preview-image attribute in your category (which is purely presentation related and thus shouldn't be part of the resource).

I'll wait for the suggested thread for elaborating on the other stuff. Or if you prefer having it all in one place, I'll comment here later.

@samdark
Copy link
Member

@samdark samdark commented May 17, 2013

@bwoester batch queries will solve it.

@samdark
Copy link
Member

@samdark samdark commented May 17, 2013

@Ragazzo thanks for the book, will read it.

@bwoester
Copy link
Contributor

@bwoester bwoester commented May 17, 2013

@samdark you mean like "get image-collections for categories 1-N"?

@bwoester
Copy link
Contributor

@bwoester bwoester commented May 17, 2013

About "include/ exclude resource attributes by default, with the possibility for the client to override these defaults": "Web API design" refers to it as "partial response" (p. 16). At least, this is the "possibility for the client to override" portion of what I meant.

@cebe
Copy link
Member

@cebe cebe commented May 18, 2013

I implemented REST actions some time ago for a project with yii 1.1. They implement the basic CRUD actions and can handle normal CRUD via HTML but also REST requests by returning differen formats like JSON, csv or ical(used for date objects in this project).

Here is a gist with the actions:
https://gist.github.com/cebe/5604091

And this is how a controller uses them:
https://gist.github.com/cebe/5604091#file-myrestcontroller-php

Hope this is good for inspiration and helps finding a good solution :)

@bwoester
Copy link
Contributor

@bwoester bwoester commented May 18, 2013

"Some time ago" made me remember. 😉

Here's my try. It's really work in progress, I did this "some time ago" and then stopped working on it, so it's a bit messy, not completed at all, but hopefully with a few ideas that might the helpful: https://github.com/bwoester/yii-rest-extension

I read through the source and tried to remember how things were meant to work, put that all in the README.md and pushed it.

@tonydspaniard
Copy link
Contributor

@tonydspaniard tonydspaniard commented May 23, 2013

I experiment on Yiinitializr-advanced boilerplate, and created https://github.com/tonydspaniard/yiinitializr-advanced/tree/master/api/extensions, allowing UrlManager to handle the routing (POST|GET|PUT|DELETE) hope it helps

ps: It only supports Json format

@tjconcept
Copy link

@tjconcept tjconcept commented May 29, 2013

"Native" rest support would be amazing. I think it would be best handled by a new REST application extending \yii\web\Application.

@cebe
Copy link
Member

@cebe cebe commented May 29, 2013

FYI: Created yii\web\VerbFilter yesterday which can be used together with these actions.

@cebe
Copy link
Member

@cebe cebe commented May 30, 2013

Here is a proposal for RESTful routing: https://gist.github.com/cebe/5674918
Will implement changes to UrlManager soon.

cebe added a commit to cebe/yii2 that referenced this issue May 30, 2013
@bwoester
Copy link
Contributor

@bwoester bwoester commented May 30, 2013

Does this proposal for restful routing imply you're concentrating on a solution where each controller implements rest behavior for its own model?

@cebe
Copy link
Member

@cebe cebe commented May 30, 2013

Does this proposal for restful routing imply you're concentrating on a solution where each controller implements rest behavior for its own model?

Why should it? Can't see why other approaches should not work then?

@bwoester
Copy link
Contributor

@bwoester bwoester commented May 30, 2013

Other approaches would still work, sure. The proposal only made me think about pros and cons. For example, activating rest behavior on a per controller level might be easier to get started with.

@cebe
Copy link
Member

@cebe cebe commented May 30, 2013

you mean not using <controller> but explicit name? This would of course work. but for the example I think it is better to show what is possible.
More documentation will of course come to explain all the details and best practices.

@bwoester
Copy link
Contributor

@bwoester bwoester commented May 30, 2013

Nope, I didn't mean using <controller> or an explicit controller name.

What I mean is: Most earlier approaches concentrated on a solution with one single controller that is responsible for all REST actions. Only the resource/ model on which the controller operated changed.

Your new proposal seems to suggest handling REST actions in multiple controllers, one for each resource/ model.

Thinking about it, I see both pros and cons. The nice thing is, it is closer to the normal yii request life cycle. People are used to it and thus it will be easy for them to start writing REST backends.

On the other hand, you want have a uniform API for all your REST resources. You want the API to behave equally, regardless of the resource type you're operating on. Examples for this include the ability to accept and respond with different message formats like json or xml. Or to respond with appropriate http headers.

@cebe
Copy link
Member

@cebe cebe commented May 31, 2013

Yeah, now I see your point. Both variants are good dependent on the situation. I do not concentrate on one of them. Both benefit from this new syntax and this is of course not the most important thing to implement for this issue.

@bobonov
Copy link

@bobonov bobonov commented Jun 7, 2013

Issue 303 and 489 are both closed referencing to each other, is it an error?

@samdark
Copy link
Member

@samdark samdark commented Jun 7, 2013

303 isn't closed.

@bobonov
Copy link

@bobonov bobonov commented Jun 7, 2013

Sorry my error, I had bot issue open on 2 different tabs, I looked wrongly and posted same message on both.

@cebe
Copy link
Member

@cebe cebe commented Mar 28, 2014

what exactly is your question?

@githubjeka
Copy link
Contributor

@githubjeka githubjeka commented Mar 28, 2014

How off HttpBasicAuth for OPTIONS method?
OR
How to fix it:
When I send POST, CORS before my POST send own OPTIONS and not send header Authorization.

@qiangxue
Copy link
Member

@qiangxue qiangxue commented Mar 28, 2014

Override yii\rest\Controller::authenticate(), check $action->id and skip options action.

@cebe cebe removed the severity:critical label Apr 4, 2014
@subdee subdee mentioned this issue Apr 7, 2014
@qiangxue qiangxue modified the milestones: 2.0 GA, 2.0 RC Apr 16, 2014
@franciscorangel
Copy link

@franciscorangel franciscorangel commented May 6, 2014

When I use two methods to autenticate, example:

public function behaviors()
    {
        return ArrayHelper::merge(parent::behaviors(), [
            'authenticator' => [
                'class' => CompositeAuth::className(),
                'authMethods' => [
                    \yii\filters\auth\HttpBasicAuth::className(),
                    \yii\filters\auth\HttpBearerAuth::className(),
                ],
            ],
        ]);
    }

HttpBasicAuth and HttpBearerAuth call same method in my class user:

User::findIdentityByAccessToken

I want validate in two different forms, I think is better if Basic and Bearer go to different methods then I don't need to check which autenticate form and I don't need to override anything.

Am I wrong? How is the best way to do it?

@qiangxue
Copy link
Member

@qiangxue qiangxue commented May 6, 2014

The format of your access token should be different. You can call different validation methods based on the format in findIdentityByAccessToken.

@franciscorangel
Copy link

@franciscorangel franciscorangel commented May 6, 2014

@qiangxue Thanks for your reply.

If I put on header:
Autorization Bearer AbCdEf123456
Autorization Basic YWRtaW46YWRtaW4=

In the User::findIdentityByAccessToken my token is:
AbCdEf123456, Basic YWRtaW46YWRtaW4=

If I put on header unlike:
Autorization Basic YWRtaW46YWRtaW4=
Autorization Bearer AbCdEf123456

In the User::findIdentityByAccessToken my token is:
admin

I think the order I put on header can't influence on the result.

I don't know if I'm doing something wrong or this expression is wrong:

//HttpBearerAuth->authenticate($user, $request, $response);

preg_match("/^Bearer\\s+(.*?)$/", $authHeader, $matches)
@qiangxue
Copy link
Member

@qiangxue qiangxue commented May 6, 2014

Could you create a separate issue about this? Thanks.

@adamaltman
Copy link
Contributor

@adamaltman adamaltman commented May 16, 2014

I'm not clear on the strategy for versioning. Here is an example:

API v1
Resource: car
Attributes: make, model, year

API v2
Resource: car
Months later, we realized we forgot color
Attributes: make, model, year, color.

In this case, we need a migration to add the color column, and a change in the model to validate it. Now, how would we implement v1 and v2? Of course, it's a non-breaking change if color can be null. But, for this example, let's say it must be required when you create POST a car.

I guess there are multiple strategies to doing this -- I'm not clear what the options are, and what may be considered the best approach.

@iJackUA
Copy link
Contributor

@iJackUA iJackUA commented May 16, 2014

As I understand it is supposed that each developer should implement his own strategy - as it is very specific per each app and each kind of differences between versions. You could have different versions of your Model and keep tack of backward compatibility of them (you can extend v1 from v2 or have completely different classes), have different versions of Components and utility code... so it seems for me very hard to have any generalized way.

@subdee
Copy link
Contributor

@subdee subdee commented May 16, 2014

General concept is that if you are making breaking changes then you change major version, v1 to v2, but if you are making non-breaking changes you should update minor versions. The docs provide examples on how to do both I think.

In the end, you're free to make your own implementations.

@Ragazzo
Copy link
Contributor Author

@Ragazzo Ragazzo commented Jun 27, 2014

Marked testing as complete

@Ragazzo
Copy link
Contributor Author

@Ragazzo Ragazzo commented Jun 27, 2014

@qiangxue is it safe now to implement it on applications with maybe some tests example since Codeception have REST module ?

@qiangxue
Copy link
Member

@qiangxue qiangxue commented Jun 27, 2014

Yes.

@qiangxue qiangxue modified the milestones: 2.0.1, 2.0 RC Jul 25, 2014
@fernandezekiel
Copy link
Contributor

@fernandezekiel fernandezekiel commented Jul 27, 2014

for our current design, what's the best way to implement URLs like this one:
POST /accounts/13456/transactions

@cebe cebe modified the milestones: 2.0 RC, 2.0.1 Jul 27, 2014
@cebe
Copy link
Member

@cebe cebe commented Jul 27, 2014

@fernandezekiel please open a new issue or ask in the forum or on IRC if it is just a question.
This issue has too much content.
Split it up into #4477 #4478 and #4479.

@cebe cebe closed this Jul 27, 2014
@yiisoft yiisoft locked and limited conversation to collaborators Jul 27, 2014
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Linked pull requests

Successfully merging a pull request may close this issue.

You can’t perform that action at this time.