Passing Hook Response with a 404 HTTP Error

I am trying to obtain a json response from a website (REST API) when I get a 404 error. The site actually returns a valid json response with important data about the error, but it seems that this response is not passed back as the hook response. Rather, the cloud returns a non-json message "error status 404 from www.amilia.com" (as seen in the event stream in the Console). When I query the site using curl, the site actually returns a valid json message (in addition to the 404 error):

{"Message":"Person was not found","HttpCode":404,"MoreInformation":null,"TransactionId":"d27bea2f-8381-49a2-90da-311bdcdaf8c9"}

I would like to pick up this message in my Argon firmware; better still, I would like to process it using mustache filters in my hook response template. I suppose that I could create an errorResponseTopic and subscribe to it, but I am wondering if the webhook could somehow be configured to send back the json response that the site actually provides.

Here is a more extensive background to this issue, if you are so inclined to read it:

About 5 years ago, a colleague and I developed an RFID membership card system for a non-profit makerspace. The project is documented here:

The project has several flavors of Argon-based RFID card stations and each station provides members with access to the facility itself or various parts of the facility, based upon a set of configurable access control rules. There is also an administration station variant which is used to make RFID cards for members. The source of truth of the data that drives the access control rules is a cloud based CRM system. The CRM system has a REST API and we use webhooks to query this system for relevant, up to date member information.

The makerspace is currently transitioning to a new CRM system. The new system has a similar REST API to the old system but the queries and the json formatted responses differ significantly in the details. We wish to make as few firmware changes as possible (to the Argons) and we have largely succeeded in "faking out" the firmware written for the old CRM using new webhooks to perform the necessary queries on the new CRM system and mustache filters to reorganize the hook responses into a format compatible with the old CRM system.

There is, however, one difference that we cannot overcome. When making a card for a member at the administration system, the administrator types our internal member number into the station (via an app) and the station uses a query on this internal member number to obtain necessary information about the member, some of which must be burned onto the member's RFID card. The old CRM system has a single endpoint for this query and the member number is sent to this url as web data. The new CRM system includes the member number in the endpoint url itself. It is no problem to handle this difference in the new webhook. The problem occurs if the administrator mistypes the member number to one that is not in the CRM system. The old system (and its webhook) responds with an HTTP response code of 200 because the url is valid and the CRM system returns a json formatted error message which our firmware processes and the firmware then handles this gracefully. The new CRM system also returns a valid json error message, however it's HTTP response code is 404 because the url "technically" was not found. This appears to cause the webhook to return a non-json 404 message and not return the json response from the CRM system. If we could get the webhook to take the json response and pass it through a mustache filter and then back to the Argon, would could handle this situation without any firmware changes. However, we have not found a way to configure the webhook to ignore the HTTP status and just return the json response through the mustache filter.

The question is: is there some way to do this?

Hi, it could be that the webhook "engine" in the cloud sees this 404 as an ERROR.
So you would need to configure the error hook to be propagated (published back) to the devices.

Like here:

That would be 50% of the solution.
The other 50% would be achieved when your device subscribes to that error hook as explained on the docs.

Example:

Particle.subscribe(System.deviceID() + "/hook-error", myErrorHandler, MY_DEVICES);

In myErrorHandler(const char *event, const char *data) you will receive the full body of the message in the data parameter (or that's what I believe or remember), so you can parse it in your firmware.

Best.

1 Like

@gusgonnet's reply would let you get the error sometimes, but if you're going to commonly get 404s from the API then you'll run into some issues. We have a karma system on our webhooks that will back off if a server isn't returning 2xx status codes. This is to prevent us from hammering a server that is failing, we rapidly ramp back up once webhooks start succeeding again.

Webhook reference | Reference | Particle talks about this.

With our current system, direct integration with services that return non-2xx status codes as part of regular operation is not recommended, instead you'll need to proxy the request.

1 Like

@Wraithan: thanks for the information. We do not expect to get 404's regularly. This will only happen when an administrator types in an incorrect member ID - one that does not match any in the cloud-based CRM system. And yes, we are seeing repeated hook queries that get rate limited. We need to reset our administration (power cycle it) and have it reboot and re-request an access token from the CRM server, in which case the webhook is happy because the new token request returns with http 200 status.

@gusginnet - thanks as well for your suggestion. I was hoping to somehow modify the behavior of the webhook in the event of 404 errors, but I see the need to handle it in firmware, either using an errorResponse handler or detecting the message that comes back.

1 Like

@Wraithan : I implemented the errorResponseTopic to catch and process these 404 errors. However, the Particle cloud seems to be performing some retries when I get this error. Here is a screenshop of the Console event log when I perform a query that returns normally (status of 200):

Here is a screenshop of when I perform the same operation that returns 404 error:

Note that my firmware is not re-publishing to the webhook but Particle internal hook calls seem to be doing 2 retires (30 seconds apart).

Question: Is this normal? It doesn't bother me if it is, but I just wanted to check that something isn't going wrong here.

Yes, that is expected. We've built our webhook system around the idea that most folks are using it to egress data to their own servers or partners of theirs, since we expect to only get 2xx responses, we retry the others in case networking/servers have recovered. So you'll see an attempt to redeliver it up to 2 times with at least 30 seconds between attempts, for a total of 3 attempted deliveries.

The limits section of the webhook docs mentions this:

Events that were skipped will retried after 30 seconds and 1 minute before being dropped.

2 Likes

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.