Async HTTP Get troubleshooting

hi there, i'm writing a driver, looking to do asynchttpget to replicate what can be easily & reliably done with curl.

curl command which works fine:
curl --insecure -H “X-authID: abcdefg” -v “https://192.168.0.12/www/access?authKey=123456”
(reply is text/plain)

When making this call using asyncHttpGet, I keep getting a response status of 404 (not found), despite the fact that the debug logs show the URI and PATH fields to look perfect.
I have tried numerous header options, including a few different content types, Bearer Authorization using the authKey...but not sure where to go from here in terms of troubleshooting. Anyone have any ideas?

LOGS
debug GetHandler: asynchttp error {404}
trace errorData=ret=PARAM NG,msg=404 Not Found
trace errorMessage=Not Found
trace status=404
trace class=class hubitat.scheduling.AsyncResponse
trace warningMessages=[]
trace headers={Content-Length=30, Content-Type=text/plain}
debug getHandler: response status: {404}
debug Get() params: {[uri:https://192.168.0.12:443, path:/www/access?authKey=123456, requestContentType:text/plain, contentType:text/plain, headers:[X-authID:abcdefg, User-Agent:Hubitat, Accept:/], ignoreSSLIssues:true, timeout:5]}

CODE CHUNKS
queryPath = "/www/access?authKey=" + authKey
asyncGetParams = getParams(queryPath)
asynchttpGet("getHandler", asyncGetParams)

def getParams(qPath) {
def akey = device.currentValue("authKey")
def params = [
uri: "https://" + getHostAddress(),
path: qPath,
requestContentType: 'text/plain',
contentType: 'text/plain',
headers: [ "X-authID": akey, "User-Agent": "Hubitat", "Accept": "/" ],
ignoreSSLIssues: true,
timeout: 5
]
return params
}

def getHandler(getResp, data)
error checking & logging code

I can't see anything obvious, though maybe I'm missing something. It's a bit odd that your handler method appears to be throwing an error regarding getStatus() when your logs suggest that you're accessing the status property just fine later (and on the same object these should basically be equivalent), but it's hard to say more since you didn't provide that section of code--not that it would necessarily help.

It's possible there's some oddity with HTTPS, but the only thing I can think of there is what you should already be accounting for (and doesn't seem indicative of this error) with the ignoreSSLIssues flag. The only other thing I can think of is if you have separate networks or vLANs or any kind of special setup, where what Hubitat sees might not be the same as whatever computer you're trying curl on sees. What kind of device is this, by the way? If it's something someone else might have, perhaps you could share a complete minimal, non-working app (or driver) script.

Have you tried putting the query parameter (key) in the query map rather than attach it to the path?

1 Like

Also notice that the query parameter in the curl command is "authKey" but in the queryPath is "key".

hi @bertabcd1234 thanks for the response! no VLANs or network weirdness, just one flat L2 network.

yes its strange that the 'status' Callback handler method for (sync)httpGet seems to work (getResp.status yields 404), when the hubitat method documentation for asyncHttpGet states that the correct status method is getResp.getStatus() which doesn't work. could there be some level of "incompleteness" in the implementation of the async vs the 'traditional' sync httpGet methods?

tbh i'll use whatever method works for status, though, as long as the basic calls can be made to work.

the device is a wifi air-con unit adapter. there is an existing driver that uses sync calls, which doesn't work in a lot of ways, and i've been needing to re-write it for some time to fix a lot of the issues, as well as make it more efficient (one example, async vs sync calls to prevent any process delays).
so my approach is to get the api calls working, and focus on driver logic & features from there.

my callback looks like:

def getHandler(getResp, data) {
if (debugOutput) { log.debug "getHandler: response status: {$getResp.status}" }
//if (debugOutput) { log.debug "getHandler: getResp.data: {$getResp.data}" }
getResp.properties.each {
log.trace (it)
}
try {
if (getResp.getStatus() == 200) {
//do stuff
}
else {
log.debug "getHandler: asynchttp error {$getResp.getStatus}"
//do stuff?
}
} catch(e) {
log.debug "getHandler: Asynchttp call unsuccessful: {$e}"
//do stuff?
if(getResp.hasError()) {
log.warn (getResp.getErrorMessage())
}
}

This is caused by this:

I think You can use either getResp.status or getResp.getStatus() but not getResp.getStatus

hi tony, thanks for the suggestion but you can see from the logs that the path is resolving correctly from the variables...if you compare the path in the logs with the curl command you'll see its a match.
"akey" is the just the local working variable which gets passed back to the originating method..

ah nice find. let me check that...missed the brackets on the method

Yes, I see.

The code must have been before it was fixed?

ok i added brackets to the log commands, still gets the same error.

log.debug "getHandler: asynchttp error {$getResp.getStatus()}: Registration Error"

gives me the same error in the log:

getHandler: Asynchttp call unsuccessful: {groovy.lang.MissingPropertyException: No such property: getStatus for class: hubitat.scheduling.AsyncResponse}

ah yes, sorry thats a copy/paste issue me getting it into notepad from the config and log screens, and over to the community page.
yep: the http path in the logs matches what i want it to be, but the asyncHttpGet call just doesn't work, and the message is very misleading because the path is (seems to be) correct.
but not sure where to go in terms of troubleshooting from here.

ok that missing property error is now sorted. it didn't like me calling the method from other methods, simple workaround to use an intermediate variable. :face_with_raised_eyebrow:

def callStatus = getResp.getStatus()
log.debug "getHandler: asynchttp error {$callStatus}: Registration Error"

Back to the real issue: the async call is not working for some reason :zombie:

i'll update the log entries in the original post above accordingly to show current status of the problem.

well i have tried adding Authorization: "Bearer ${authKey}" to the headers. That didn't work.
specifically what are you suggesting? adding body: authKey ?
there is no -D in the curl command, so i have not explored adding anything to the body of the asyncHttpGet...

thanks @tony.fleisher that did it, i hadn't really noticed that query parameter before...
much appreciated! :clap:

1 Like