apigee / apigee-edge-drupal

The Apigee Edge module enables you to integrate a Drupal 9 or 8 site with Apigee.
https://www.drupal.org/project/apigee_edge
GNU General Public License v2.0
32 stars 45 forks source link

Throw more meaningful/ helpful error messages when Apigee edge API returns exception. #221

Closed arunz6161 closed 3 years ago

arunz6161 commented 5 years ago

Is your feature request related to a problem? Please describe. Noticed an issue when upon clicking on "Apps" as an external developer, error Cannot reach management server. An administrator should check the configuration of this site. was thrown. This was not helpful as the connection test on "Apigee edge general settings" page was returning successful test results. It was only when debug was enabled, the error indicated a possible issue with permissions:

Forbidden Apigee\Edge\HttpClient\Plugin\ResponseHandlerPlugin->decodeResponse() (line 104 of /home/D8/vendor/apigee/apigee-client-php/src/HttpClient/Plugin/ResponseHandlerPlugin.php).
#0 /home/D8/vendor/apigee/apigee-client-php/src/HttpClient/Plugin/ResponseHandlerPlugin.php(69): Apigee\Edge\HttpClient\Plugin\ResponseHandlerPlugin->decodeResponse(Object(GuzzleHttp\Psr7\Response), Object(GuzzleHttp\Psr7\Request))
#1 /home/D8/vendor/php-http/httplug/src/Promise/HttpRejectedPromise.php(33): Apigee\Edge\HttpClient\Plugin\ResponseHandlerPlugin->Apigee\Edge\HttpClient\Plugin\{closure}(Object(Http\Client\Exception\HttpException))
#2 /home/D8/vendor/apigee/apigee-client-php/src/HttpClient/Plugin/ResponseHandlerPlugin.php(75): Http\Client\Promise\HttpRejectedPromise->then(Object(Closure), Object(Closure))
#3 /home/D8/vendor/php-http/client-common/src/PluginClient.php(161): Apigee\Edge\HttpClient\Plugin\ResponseHandlerPlugin->handleRequest(Object(GuzzleHttp\Psr7\Request), Object(Closure), Object(Closure))
#4 /home/D8/vendor/php-http/client-common/src/Plugin/HistoryPlugin.php(39): Http\Client\Common\PluginClient->Http\Client\Common\{closure}(Object(GuzzleHttp\Psr7\Request))
#5 /home/D8/vendor/php-http/client-common/src/PluginClient.php(161): Http\Client\Common\Plugin\HistoryPlugin->handleRequest(Object(GuzzleHttp\Psr7\Request), Object(Closure), Object(Closure))
#6 /home/D8/vendor/php-http/client-common/src/Plugin/AuthenticationPlugin.php(36): Http\Client\Common\PluginClient->Http\Client\Common\{closure}(Object(GuzzleHttp\Psr7\Request))
#7 /home/D8/vendor/php-http/client-common/src/PluginClient.php(161): Http\Client\Common\Plugin\AuthenticationPlugin->handleRequest(Object(GuzzleHttp\Psr7\Request), Object(Closure), Object(Closure))
#8 /home/D8/vendor/php-http/client-common/src/Plugin/HeaderDefaultsPlugin.php(41): Http\Client\Common\PluginClient->Http\Client\Common\{closure}(Object(GuzzleHttp\Psr7\Request))
#9 /home/D8/vendor/php-http/client-common/src/PluginClient.php(161): Http\Client\Common\Plugin\HeaderDefaultsPlugin->handleRequest(Object(GuzzleHttp\Psr7\Request), Object(Closure), Object(Closure))
#10 /home/D8/vendor/php-http/client-common/src/Plugin/AddHostPlugin.php(64): Http\Client\Common\PluginClient->Http\Client\Common\{closure}(Object(GuzzleHttp\Psr7\Request))
#11 /home/D8/vendor/php-http/client-common/src/Plugin/BaseUriPlugin.php(45): Http\Client\Common\Plugin\AddHostPlugin->handleRequest(Object(GuzzleHttp\Psr7\Request), Object(Closure), Object(Closure))
#12 /home/D8/vendor/php-http/client-common/src/Plugin/AddPathPlugin.php(58): Http\Client\Common\Plugin\BaseUriPlugin->Http\Client\Common\Plugin\{closure}(Object(GuzzleHttp\Psr7\Request))
#13 /home/D8/vendor/php-http/client-common/src/Plugin/BaseUriPlugin.php(49): Http\Client\Common\Plugin\AddPathPlugin->handleRequest(Object(GuzzleHttp\Psr7\Request), Object(Closure), Object(Closure))
#14 /home/D8/vendor/php-http/client-common/src/PluginClient.php(161): Http\Client\Common\Plugin\BaseUriPlugin->handleRequest(Object(GuzzleHttp\Psr7\Request), Object(Closure), Object(Closure))
#15 /home/D8/vendor/php-http/client-common/src/PluginClient.php(175): Http\Client\Common\PluginClient->Http\Client\Common\{closure}(Object(GuzzleHttp\Psr7\Request))
#16 /home/D8/vendor/php-http/client-common/src/PluginClient.php(88): Http\Client\Common\PluginClient->Http\Client\Common\{closure}(Object(GuzzleHttp\Psr7\Request))
#17 /home/D8/vendor/apigee/apigee-client-php/src/Client.php(241): Http\Client\Common\PluginClient->sendRequest(Object(GuzzleHttp\Psr7\Request))
#18 /home/D8/vendor/apigee/apigee-client-php/src/Client.php(388): Apigee\Edge\Client->sendRequest(Object(GuzzleHttp\Psr7\Request))
#19 /home/D8/vendor/apigee/apigee-client-php/src/Client.php(193): Apigee\Edge\Client->send('GET', Object(GuzzleHttp\Psr7\Uri), Array, NULL)
#20 /home/D8/vendor/apigee/apigee-client-php/src/Controller/PaginationHelperTrait.php(277): Apigee\Edge\Client->get(Object(GuzzleHttp\Psr7\Uri))
#21 /home/D8/vendor/apigee/apigee-client-php/src/Controller/PaginationHelperTrait.php(320): Apigee\Edge\Api\Management\Controller\AppByOwnerController->getResultsInRange(Object(class@anonymous), Array)
#22 /home/D8/vendor/apigee/apigee-client-php/src/Controller/PaginationHelperTrait.php(139): Apigee\Edge\Api\Management\Controller\AppByOwnerController->listEntityIdsWithCps(NULL, Array)
#23 /home/D8/vendor/apigee/apigee-client-php/src/Controller/PaginatedEntityIdListingControllerTrait.php(35): Apigee\Edge\Api\Management\Controller\AppByOwnerController->listEntityIds(NULL)
#24 /home/D8/web/modules/contrib/apigee_edge/src/Entity/Controller/CachedPaginatedEntityIdListingControllerTrait.php(70): Apigee\Edge\Api\Management\Controller\AppByOwnerController->getEntityIds(NULL)
#25 /home/D8/web/modules/contrib/apigee_edge/src/Entity/Query/AppQueryBase.php(169): Drupal\apigee_edge\Entity\Controller\AppByOwnerController->getEntityIds()
#26 /home/D8/web/modules/contrib/apigee_edge/src/Entity/Query/Query.php(86): Drupal\apigee_edge\Entity\Query\AppQueryBase->getFromStorage()
#27 /home/D8/web/modules/contrib/apigee_edge/src/Entity/ListBuilder/EdgeEntityListBuilder.php(71): Drupal\apigee_edge\Entity\Query\Query->execute()
#28 /home/D8/web/core/lib/Drupal/Core/Entity/EntityListBuilder.php(86): Drupal\apigee_edge\Entity\ListBuilder\EdgeEntityListBuilder->getEntityIds()
#29 /home/D8/web/profiles/contrib/apigee_devportal_kickstart/modules/custom/apigee_kickstart_enhancement/src/Entity/ListBuilder/DeveloperAppListBuilder.php(35): Drupal\Core\Entity\EntityListBuilder->load()
#30 [internal function]: Drupal\apigee_kickstart_enhancement\Entity\ListBuilder\DeveloperAppListBuilder->render()
#31 /home/D8/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array(Array, Array)
#32 /home/D8/web/core/lib/Drupal/Core/Render/Renderer.php(582): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#33 /home/D8/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
#34 /home/D8/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array)
#35 /home/D8/vendor/symfony/http-kernel/HttpKernel.php(151): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#36 /home/D8/vendor/symfony/http-kernel/HttpKernel.php(68): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
#37 /home/D8/web/core/lib/Drupal/Core/StackMiddleware/Session.php(57): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#38 /home/D8/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(47): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#39 /home/D8/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#40 /home/D8/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#41 /home/D8/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(47): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#42 /home/D8/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(52): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#43 /home/D8/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#44 /home/D8/web/core/lib/Drupal/Core/DrupalKernel.php(693): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#45 /home/D8/web/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#46 {main}

Describe the solution you'd like The generic error Cannot reach management server seems to indicate a possible connectivity issue between portal and edge API which was not the case here. Better error translation is needed to quickly diagnose such issues.

Describe alternatives you've considered Enabling apigee debug module and then cross checking "devadmin" user permissions on edge helped narrow down the issue.

Additional context None.

mxr576 commented 5 years ago

This is kinda related to #115.

"Forbidden" at the beginning of the log message was a clear indication of the issue.

I agree that "Cannot reach management server" as an error message could be misleading because this error message indicates that the server could have been reached (connected error) but it could be reached and it returned an HTTP 403.

I think we should rather display different error messages on this error page for

We should never expose the raw HTTP responses (status codes, etc) or error messages from API response payloads (like "Developer with testelek@example.com email address not found." in #115) to simple authenticated users because these could potentially expose too many details that simple users should not know.

We could consider exposing more information in place to admins besides asking them to "check the configuration of this site" but we should define who we call as "an admin" in this sense:

github-actions[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.