Jump to content

New Module: AppApi


Sebi

Recommended Posts

Hi @Sebi

thanks for your reply. I've thought about it again. The website where I'm working on will be fully headless. The URLs mappings are then handled by a vuejs frontend. So in this case it does not matter much if it's controlled by a var or URL segement (Forgot about this when asking :roll_eyes:).

The requirements of the site are still a bit unclear but it looks I do not need the c-u-d of C-R-U-D. This is why I most likely will just build a small API with the new URL Hooks. This is how I would handle the language there (Quick and dirty example):

        $this->wire()->addHook('/{lang}/api/books', function($event) {
            $books = $this->pages->find("template=books");
            $response_arr = [];          
            foreach ($books as $book){
                $current_page = [];
                $current_page['title'] = $book->getLanguageValue($event->lang, 'title');
                $current_page['author'] = $book->getLanguageValue($event->lang, 'author');
				// ...
                array_push($res, $current_page);
            }
        	header('Content-Type: application/json; charset=utf-8');
        	echo json_encode( $response_arr );
        });

But it's great to have your Extension available in case there is some "heavier" API to build ;))

@Jukka Nice to hear!!

Link to comment
Share on other sites

@Sebi

Thanks for this great module, I'm testing it for a project right now. 

However I'm running into a slight problem, not sure if this is a bug or it's something on my end.
I'm testing it on two PW 3.0.165 instances and in one of them everything works perfect.

In the other I can't seem to edit an application to set an apiKey in the admin. When clicking it (/processwire/setup/appapi/application/edit/1) it renders the 404 of the website instead of showing the edit page of the application. I have two languages setup for this project and also formBuilder module. Other than that, I don't see any differences with the other working project.

The applications overview (/processwire/setup/appapi/applications) does work the way it should.

Do you have any idea where this could be going wrong?

 

Update: I removed all modules from the failing project that I had installed (FormBuilder, Language support), but to no avail.
I can navigate to /processwire/setup/appapi/applications/ which lists all applications, and /processwire/setup/appapi/application/edit (without an ID and it will give me a missing ID message within the admin). As soon as I add an ID (/processwire/setup/appapi/application/edit/1) it will fail, throws a 404 outside of the admin.

I also cleared out my ready.php to prevent any hooks causing issues.

 

@ryan You obviously can't provide support for a custom module, but is there anything here that sounds familiar? Could there be a routing or permission issue here? Is there some caching going on somewhere that might be causing this?

Edited by PascalKonings
Link to comment
Share on other sites

On 5/10/2022 at 12:46 PM, PascalKonings said:

@Sebi

Thanks for this great module, I'm testing it for a project right now. 

However I'm running into a slight problem, not sure if this is a bug or it's something on my end.
I'm testing it on two PW 3.0.165 instances and in one of them everything works perfect.

In the other I can't seem to edit an application to set an apiKey in the admin. When clicking it (/processwire/setup/appapi/application/edit/1) it renders the 404 of the website instead of showing the edit page of the application. I have two languages setup for this project and also formBuilder module. Other than that, I don't see any differences with the other working project.

The applications overview (/processwire/setup/appapi/applications) does work the way it should.

Do you have any idea where this could be going wrong?

 

Update: I removed all modules from the failing project that I had installed (FormBuilder, Language support), but to no avail.
I can navigate to /processwire/setup/appapi/applications/ which lists all applications, and /processwire/setup/appapi/application/edit (without an ID and it will give me a missing ID message within the admin). As soon as I add an ID (/processwire/setup/appapi/application/edit/1) it will fail, throws a 404 outside of the admin.

I also cleared out my ready.php to prevent any hooks causing issues.

 

@ryan You obviously can't provide support for a custom module, but is there anything here that sounds familiar? Could there be a routing or permission issue here? Is there some caching going on somewhere that might be causing this?

@ryan @Sebi Found it! I had maxUrlSegments set to 2 in my config file #doh

  • Like 1
Link to comment
Share on other sites

@Sebi

I'm running into a problem deleting a repeater item through the API, or any page for that matter.

Using my code below I'm getting an error

public static function deleteEvent($data) {
  $data = AppApiHelper::checkAndSanitizeRequiredParameters($data, ['id|int']);

  // $data->id returns an integer
  wire('pages')->get($data->id)->delete();

  // Using a static ID also fails
  // wire('pages')->get(1066)->delete();

  return [
  'message' => 'deletion successful',
  'status' => 200
  ];
}

 

The error I'm getting is:

devmessage: {message: "Trying to get property 'id' of non-object", location: '/myDev/wire/core/PagesEditor.php', line: 296}
error: "Internal Server Error"

 

This line is within the isDeleteable function, where it tries to get the ID of the page that needs to be deleted, however it seems the $page:

else if($page->id === $this->wire('page')->id && $this->wire('config')->installedAfter('2019-04-04')) {
	$error = "it is the current page being viewed, try \$pages->trash() instead";
}

 

I've set up the route without any auth or roles, so it should work from that perspective. Other routes getting and posting are working fine! And running the API from the template directly works perfectly: 

wire('pages')->get(1066)->delete();

 

Am I missing something here?

Link to comment
Share on other sites

  • 2 weeks later...

This error is related to Processwire, not to the module. Check the documentation for the Repeater field in the section "Using the API to add or remove repeater items":  https://processwire.com/docs/fields/repeaters/ You can also check this post that talks about the same problem: https://processwire.com/talk/topic/16276-remove-repeater-item-by-page-id-rather-than-item-id/

 

  • Like 2
Link to comment
Share on other sites

Because I'm using the LoginRegisterPro module, users use their email to log in. So I'm wondering, for authentication, should i make an endpoint that returns the username for a given email address and use that to authenticate or is there a better way to solve this that doesn't use an extra request.

Link to comment
Share on other sites

  • 1 month later...

Great module, @Sebi! As it is out there for almost 2 years now, maybe someone found an elegant solution for caching the generated output (and rebuilding that cache if a page or child page is updated)?

I have seen @toni´s approach and could build something on top of that for my specific use case, but I guess there are a lot of people having similar needs and would love to see something that is more ready to use. I am not experienced with ProCache, but I think being able to use ProCache to cache API output would not only be the most elegant way, but also one of the fastest possible. 

  • Like 1
Link to comment
Share on other sites

  • 1 month later...

Hi!

I'm having problems with the authorization.

I've installed the module and created a Double JWT-Application.

The Test-Route answers correct, so the module is working.

2022-08-28_17-30.png.515946a900d38add8cad4ad37a6240be.png

 

When i GET /api/auth/, also the correct answer appears.

2022-08-28_17-32.png.3aad6710f26a97a48f9d290ef3383254.png

But, when i POST /api/auth/ (x-api-key is set correctly), then i get this internal server error:

2022-08-28_17-33.thumb.png.81092e49246110211c6c2efb7e036b4a.png

I'm using ProcessWire 3.0.204 dev and PHP 8.1.6.

Any ideas how to fix this?

Thank you,
Christian

Link to comment
Share on other sites

Hey @paulbrause,

I managed to update my test-setup to ProcessWire 3.0.204 and PHP 8.1.1, but I cannot reproduce this error. Login via POST to /api/auth/ with a Basic Auth header still works fine. But of course I would still like to help you and fix a possible bug - maybe in a special edge case.

  1. Can you maybe downgrade your PHP version to 8.1.1 to rule out that it's not a bug regarding the PHP version?
  2. The error comes from a function call to the quote function of WireDatabasePDO. I do not call that function directly in AppApi, but it could be called from any other database function that I use. Can you please verify that the api-application that you created in ProcessWire's backend does not have any empty field? Are the secrets correctly set?

Thank you for using AppApi and I hope that we can quickly find the cause of this error!

Link to comment
Share on other sites

Hey @Sebi,

thanks for your quick response.

I downgraded PHP to version 8.1.1 and installed a clean PW v3.0.200 master and AppApi v1.2.3, but still no success.

It seems, that the secrets are correctly set.
AppApi-Settings.thumb.png.1061dc8337e2152a24b04b87ab046516.png

Always error 500. ?

AppApi-Error.thumb.png.54eb5f8eb088da77df0fceac28851367.png

But, the module created the Apptokens:

AppApi-AppToken.thumb.png.02e3075496d777b3e658010e72700941.pngAppApi-AppToken-Detail.thumb.png.1a6f23d9de7343dc05eafa37e7102706.png

Is there anything else i could have done wrong? ?‍♂️

Thank you,
Christian

Link to comment
Share on other sites

With AppApi's new version 1.2.4 we now use URL Path Hooks!
The old ProcessPageView::pageNotFound hook still remains, but is only used as a fallback if the ProcessWire version does not support the url path hooks. Thanks to @kongondo and @adrian who kept pushing me in the direction of including url path hooks!

I also revised the logging a little bit. In the access log (which can be activated via the module settings) the correct paths from the request are now entered. And an entry in the access log really only occurs if no error has occurred. Otherwise an entry is triggered in the appapi-exceptions log.

You can download the new version now in the ProcessWire modules page, Github or via auto-update in your ProcessWire UI. Thanks for using AppApi! ?

  • Like 4
  • Thanks 2
Link to comment
Share on other sites

A quick update... Version 1.2.5 allows you to deactivate url hooks and fallback into the legacy ProcessPageView::pageNotFound behavior. That's now possible in the module config.

I discovered, embarrassingly just after the release of the new version 1.2.4, a case where switching to the URL hook actually causes a breaking change. In all tests before this was not noticed, so sorry if anyone discovered something similar. Now, in any case, it is easy to switch back to the old hook. Now to the problem: Maybe someone reading this has some deeper insight and can help me to understand the issue.

I have a page on which I have included @Wanze`s SeoMaestro field and wanted to read the values from it via Api:

<?php
$page = wire('pages')->get('/');
if ($page->template->hasField('seo')) {
	$seoString = @$page->seo->render();
}

That actually works fine when it's done in an ProcessPageView::pageNotFound hook. But if I use a url hook and call it, the seo->render() call will throw the following error:

{
  "error": "Method Page::localUrl does not exist or is not callable in this context",
  "devmessage": {
    "class": "ProcessWire\\WireException",
    "code": 0,
    "message": "Method Page::localUrl does not exist or is not callable in this context",
    "location": "\/processwire\/wire\/core\/Wire.php",
    "line": 564
  }
}

I've managed to step through the code and find out the source of the exception. It's a call of page->localUrl in SeoMaestro's PageFieldValue class:
https://github.com/wanze/SeoMaestro/blob/master/src/PageFieldValue.php#L158

Any ideas? ?

  • Like 3
Link to comment
Share on other sites

  • 1 month later...

Hi, I maybe just found a very strange bug.

I'm using Processwire with a React front end and I setup it in a subdomain like so https://api.mydomain.com/  so just to avoid using api twice i changed the API endpoint into "v" using versions so my base api endpoint is https://api.mydomain.com/v/1/

Now, everything works fine except when I call a route with a GET parameter starting with "v", it cuts out the v from the slug, for example if I call

https://api.mydomain.com/v/1/category/variety the get parameter I get it's "ariety" and this happens on all characters I put in the api endpoint, not just for one character

This is the route I'm using

'category' => [
	['OPTIONS', '{slug:\S+}', ['GET']],
	['GET', '{slug:\S+}', Blog::class, 'getCategory',['application' => 1]], 
],

and this is the function which receives the parameter

 public static function getCategory($data) {
        $data = AppApiHelper::checkAndSanitizeRequiredParameters($data, ['slug|pageName']);
...

// $data->slug returns "ariety"

 

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...
On 10/12/2022 at 8:17 AM, Frank Vèssia said:

https://api.mydomain.com/v/1/category/variety the get parameter I get it's "ariety" and this happens on all characters I put in the api endpoint, not just for one character

Hi @Frank Vèssia,

I finally found time to recreate this once in my test environment. Unfortunately, I cannot reproduce the error.

My routes definition looks like yours:

$routes = [
	'v' => [
		'1' => [
			'category' => [
				['OPTIONS', '{slug:\S+}', ['GET']],
				['GET', '{slug:\S+}', AppApiTEST::class, 'getCategory'],
			]
		]
	]
];

When I simply dump $data->slug, I get the full "variety" slug when calling the /v/1/category/variety url:

class AppApiTest {
	public static function getCategory($data) {
		$data = AppApiHelper::checkAndSanitizeRequiredParameters($data, ['slug|pageName']);
		var_dump($data->slug);
		die();
	}
}

Can you try out if maybe my latest v1.2.6 update, where I improved the route-merging logic, fixed the issue for you? Or could it be something else which is special to your environment (PHP version? Modules or hooks, that could interfer with the AppApi handlers? Maybe it helps to deactivate the new ProcessWire URL Hook in AppApi's settings?)

  • Like 1
Link to comment
Share on other sites

19 hours ago, Sebi said:

Hi @Frank Vèssia,

I finally found time to recreate this once in my test environment. Unfortunately, I cannot reproduce the error.

My routes definition looks like yours:

$routes = [
	'v' => [
		'1' => [
			'category' => [
				['OPTIONS', '{slug:\S+}', ['GET']],
				['GET', '{slug:\S+}', AppApiTEST::class, 'getCategory'],
			]
		]
	]
];

When I simply dump $data->slug, I get the full "variety" slug when calling the /v/1/category/variety url:

class AppApiTest {
	public static function getCategory($data) {
		$data = AppApiHelper::checkAndSanitizeRequiredParameters($data, ['slug|pageName']);
		var_dump($data->slug);
		die();
	}
}

Can you try out if maybe my latest v1.2.6 update, where I improved the route-merging logic, fixed the issue for you? Or could it be something else which is special to your environment (PHP version? Modules or hooks, that could interfer with the AppApi handlers? Maybe it helps to deactivate the new ProcessWire URL Hook in AppApi's settings?)

mmm....I tried to update the module with no luck, at this point I don't know what it is...I also tried to deactivate some modules...anyway I will do some more test and let you know, thanks for now.

Link to comment
Share on other sites

  • 3 months later...

Hi! I have problem to get value from Select Option field (FieldtypeOptions) when using AppApi. If i add this type of field to page and try to access it with $page->selectfield i can't get any data from it. I have also tried $page->selectfield->value and $page->selectfield->title but none of these methods doesn't seams to work. Input type for this field is SELECT (Single value). I don't know if this problem only affects AppApi or if this is more related to Processwire?

// Any of these methods doesn't work
// sf = Select Options field
$page->sf;
$page->sf->value;
$page->sf->title;

// This way I got value from object key but not title
$item = $page->get("sf.value");
$value = array_get_first($item);

What is strange is that If i add Select input field that is inside of Combo field it works as expected.

// When Select field is inside Combo field everything works
// cmb = Combo field
// sf = Select field inside combo
$page->cmb->sf->value;
$page->cmb->sf->title;

 

Link to comment
Share on other sites

Hey @Jukka, I don't know when I find time to test that out, but can you maybe try if deactivating the URL hook in the AppApi module settings helps? I had problems with reading values of SeoMaestro when the "new" hooks were activated. Maybe its something related...

Link to comment
Share on other sites

On 1/27/2023 at 6:01 PM, Sebi said:

Hey @Jukka, I don't know when I find time to test that out, but can you maybe try if deactivating the URL hook in the AppApi module settings helps? I had problems with reading values of SeoMaestro when the "new" hooks were activated. Maybe its something related...

Hi @Sebi! I tried your trick to Deactivate URL hook but it doesn't seem to affect in this SelectOption problem.

Btw I updated my site to the newest PW development version (3.0.211) and now I got $page->sf->title method working - URL Hook activated or deactivated, it doesn't seem to matter. But I still can't get actual value of a field any other way than that I descriped before. Do you have any ideas where the problem could be?

Link to comment
Share on other sites

Not sure if this helps anything, but I also had localUrl() problems (same error as with SEO module above) in my helper classes that prepare the output for the API and could solve it by manually redeclare the hook as described here: 

When deactivating the URL hook in the module settings, it works flawlessly without the adjustments above.

Link to comment
Share on other sites

Hey @Jukka,

I finally got some spare time to set up a select field in my test environment. 

This is my static function, that is called my Routes.php:

	public static function fieldTest($data) {
		$page = wire('pages')->findOne('id=8226');
		return [
			'selectedValue' => AppApi::getAjaxOf($page->test_options)
		];
	}

My SelectOption field is called "test_options". Calling the route returns the following JSON:

{
  "selectedValue": [
    {
      "id": 3,
      "title": "My Test Value",
      "value": ""
    }
  ]
}

That is the item that I've selected on my test-page. It's also possible to get the title via `$page->test_options->title` and the id via `$page->test_options->id`. Is the id the "value" that you expect? I did not work with SelectOption very much, so please excuse the maybe stupid question 😬

Link to comment
Share on other sites

  • 2 weeks later...

I have just released the newest version 1.2.8 of AppApi. No breaking changes, but it should fix an issue that could lead to installation-errors when the used MariaDB version does not support JSON as db column type. Additionally I have included some bugfixes to the email-authentication logic.

  • Like 3
Link to comment
Share on other sites

  • 3 months later...

Big news! Version 1.3.0 is out - the big documentation update!

The new version will activate a new view in the AppApi UI under Setup->AppApi. The button "See endpoints" will lead you to a new overview page which lists all registered api-endpoints. That includes the default /auth endpoints from AppApi, your custom endpoints from routes.php and all endpoints that were registered by a custom api-module like AppApiFile. I found it useful to see where the handler-functions for each endpoint are located, so I included that as well. 

And wait, there is more: The overview page has a button to auto-generate an OpenAPI 3.0.3 json, that can be imported in tools like Postman or Swagger. And you are now able to add documentation details in the routes definition, to make the generated json even more powerful. Read more about this in the new wiki-chapter.

I have worked some time on this new feature and hope that it will bring much joy into your api-developer lifes ☺️
(Please consider buying me a coffee if you like my work)

  • Like 2
  • Thanks 3
Link to comment
Share on other sites

51 minutes ago, Sebi said:

Big news! Version 1.3.0 is out

Just installed the previous version to get it up and running in my projects - finally.
So... this is a very welcomed update or at least a nice surprise to work with.

It's weird that I read through the whole docs today and made my notes just to see this update coming in.
Be prepared to answer my stupid questions the next days. 😁

  • Haha 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...