Voltz Posted March 18, 2019 Posted March 18, 2019 Hello, I have been trying to figure out how to add my own parts of the API for an application I'm working on. I have tried doing research to find out how to do this and I've been searching for probably an hour and feel dumb if there is something on how to do this. But a lot of the docs / examples for developers is minimal or not documented (at least looking at the docs for what I want to do). I've tried looking at the core applications of IPS4 and recreating the way APIs are created in that application or even using a code hook. I can't seem to get it to work properly. I have gotten to a point where it registers the API request but when trying to access it I get the error: { "errorCode": "2S290\/5", "errorMessage": "INVALID_CONTROLLER" } Here is the code I'm using just to test, its the core/members/{id} was just using it as a way to test (Ik you shouldn't really do it but even making my own and customizing the annotations to my request it still gave same error) class _ethereal extends \IPS\Api\Controller // Also tried code hooks { /** * GET /my_request/members/hwid/{id} * Get information about a specific member * * @param int $id ID Number * @apiparam array otherFields An array of additional non-standard fields to return via the REST API * @throws 1C292/2 INVALID_ID The member ID does not exist * @return \IPS\Member */ public function GETitem( $id ) // Also have tried public function GETitem_myItem( $id ) { try { $member = \IPS\Member::load( $id ); if ( !$member->member_id ) { throw new \OutOfRangeException; } return new \IPS\Api\Response( 200, $member->apiOutput( $this->member, ( isset( \IPS\Request::i()->otherFields ) ) ? \IPS\Request::i()->otherFields : NULL ) ); } catch ( \OutOfRangeException $e ) { throw new \IPS\Api\Exception( 'INVALID_ID', '1C292/2', 404 ); } } }
bfarber Posted March 18, 2019 Posted March 18, 2019 You don't need to use a hook, you can add your own API class as you've done (make sure to give permissions to your API key afterwards - your new class won't be permitted by an existing API key by default). The request will need to be made to {your-application-key}/{api-class}/{optional-id}. Thus, if your application key is "my_request" (based on the phpdoc block) then the request there should be for "/my_request/ethereal/{id}" since ethereal is your class name. The format of the URL is very-specific. "/core/members/1" would load member ID 1 by routing to application "core", API class "members" calling function GETitem( 1 ).
Voltz Posted March 18, 2019 Author Posted March 18, 2019 1 hour ago, bfarber said: You don't need to use a hook, you can add your own API class as you've done (make sure to give permissions to your API key afterwards - your new class won't be permitted by an existing API key by default). The request will need to be made to {your-application-key}/{api-class}/{optional-id}. Thus, if your application key is "my_request" (based on the phpdoc block) then the request there should be for "/my_request/ethereal/{id}" since ethereal is your class name. The format of the URL is very-specific. "/core/members/1" would load member ID 1 by routing to application "core", API class "members" calling function GETitem( 1 ). I'm currently trying to get this to work, when putting the API key then the api request it gives me: { "errorCode": "3S290\/3", "errorMessage": "INVALID_APP" } Otherwise it gives me INVALID_CONTROLLER error that I was previously getting. When going to the API reference and for that request it says it doesn't return a response, all I am trying to do is return a VARCHAR or String from the member model (custom column for the application). And not sure how to construct the API response for it / the annotation for making sure it actually shows. Would there be a way for me to modify the /core/members/{id} request and add another column from the member it returns? It would be nice if more stuff was actually documented there isn't really that much documented most of the stuff I've done I had to figure out myself or figure out by looking at the source of the core applications. EDIT: Even just replicating one of the core requests but changing the PATH it says invalid controller or invalid app depending on if the key is first or after the request. EDIT: I do know when constructing the request for core/members/{id} you can do /core/members/{id}&otherFields[]=my_field but it would still be nice to know how to add onto the API for future things.
bfarber Posted March 18, 2019 Posted March 18, 2019 You haven't really provided enough information for me to tell you definitively what the problem is, however hopefully this small code snippet will help you figure it out: /* Get the controller */ $class = 'IPS\\' . $app->directory . '\\api\\' . $controller; if ( !class_exists( $class ) ) { throw new \IPS\Api\Exception( 'INVALID_CONTROLLER', '2S290/5', 404 ); } What is the application directory, what is the controller name (is it ethereal I'm guessing, based on the class you supplied earlier?) and what URL path are you request? Either your application directory in the URL is wrong, your controller filename is wrong, or you controller classname is wrong. There are only a few possibilities here really. If your class name is "_ethereal" then this should be in a file named ethereal.php underneath your application's /api/ directory.
Voltz Posted March 19, 2019 Author Posted March 19, 2019 21 hours ago, bfarber said: You haven't really provided enough information for me to tell you definitively what the problem is, however hopefully this small code snippet will help you figure it out: /* Get the controller */ $class = 'IPS\\' . $app->directory . '\\api\\' . $controller; if ( !class_exists( $class ) ) { throw new \IPS\Api\Exception( 'INVALID_CONTROLLER', '2S290/5', 404 ); } What is the application directory, what is the controller name (is it ethereal I'm guessing, based on the class you supplied earlier?) and what URL path are you request? Either your application directory in the URL is wrong, your controller filename is wrong, or you controller classname is wrong. There are only a few possibilities here really. If your class name is "_ethereal" then this should be in a file named ethereal.php underneath your application's /api/ directory. The filename was ethereal.php yes, and I followed the request provided from the API Reference tab, with the api site.com/api/index.php?ethereal/members/hwid/{id}&key=my_license
newbie LAC Posted March 20, 2019 Posted March 20, 2019 Hello, 15 hours ago, Tammy Wagner said: and I followed the request provided from the API Reference tab, with the api Pay attention on what bfarber said On 3/18/2019 at 11:43 PM, bfarber said: The request will need to be made to {your-application-key}/{api-class}/{optional-id}. Thus, if your application key is "my_request" (based on the phpdoc block) then the request there should be for "/my_request/ethereal/{id}" since ethereal is your class name. The format of the URL is very-specific. "/core/members/1" would load member ID 1 by routing to application "core", API class "members" calling function GETitem( 1 ). 15 hours ago, Tammy Wagner said: The filename was ethereal.php yes, and I followed the request provided from the API Reference tab, with the api site.com/api/index.php?ethereal/members/hwid/{id}&key=my_license This mean you have in phpdoc block /** * GET ethereal/members/hwid/{id}&key=my_license If your app folder is hwid and file ethereal.php (applications/hwid/api/ethereal.php) the above line should be /** * GET /hwid/ethereal/{id}
bfarber Posted March 20, 2019 Posted March 20, 2019 Yes, the path you put in the phpdoc block after GET is irrelevant - that's only to help make the documentation clearer when you view in the AdminCP. What matters is the actual file path on disk. See @newbie LAC's example above which maybe will help clarify. For the path you are supplying, you would need application directory "ethereal", API filename of "members.php" and the class name "_members" (already I can tell this is wrong since you said the filename is ethereal.php), and then a method named "GETitem_hwid( $id )" (which, again, does not match the example code you supplied earlier). The API URL you are attempting to call is not correct.
Recommended Posts
Archived
This topic is now archived and is closed to further replies.