ady624 / CoRE

CoRE - Community's own Rule Engine
GNU General Public License v3.0
222 stars 663 forks source link

Ability to do a web call without passing in any variables #51

Closed TheFuzz4 closed 8 years ago

TheFuzz4 commented 8 years ago

Hey ADY,

When setting up CORE to do a web call. Its mandatory that I give it some sort of a variable. But for zoneminder https://zoneminder.readthedocs.io/en/stable/api.html with its api I just make a call to a specific URL and it does what I want it to do. Can we remove the mandatory setting on that field? Or perhaps have a different POST method for like POST-NOTHING? Thank you for your help with this and you're code is awesome as always.

TheFuzz4 commented 8 years ago

Also the ability to make it do an internal LAN call instead of WAN would be awesome too.

ady624 commented 8 years ago

Added that last night, can you please test it? It won't return any data back to CoRE since local Hub actions are async. Looking into ways for that, maybe a later event or something. Use the Make web request, but start your URL with :/path

Please let me know if it works as expected

v0.3.157.20160928 - RC - Added support for local http requests - simply use a local IP in the HTTP request and CoRE will use the hub for that request - don't expect any results back yet :(

TheFuzz4 commented 8 years ago

So I can see that it did attempt it: 18519ead-448b-493e-a6bf-e0f3913fea7e 7:58:50 AM: debug ║║░░ Processing command task [taskId:1, time:1475071130543, idx:1, marker:1475071130276, created:1475071130629, ownerId:1, data:[p:[[d:path:/192.168.1.138/zm/api/states/change/day.json, t:text, i:0], [d:POST, t:enum, i:1], [d:JSON, t:enum, i:2], [d:null, t:variables, i:3], [d:false, t:bool, i:4], [d:null, t:text, i:5]]], type:cmd]

But it zoneminder didn't do anything.

If I do this in my browser 192.168.1.138/zm/api/states/change/day.json

It will cause zoneminder to switch over to day mode. I"m not sure if has something to do with me telling it in CORE that its json or what. For zoneminder I don't have to pass in anything to it I can just hit that url and it does what its told to do. Thank you for implementing the local lan calls this is awesome. Let me know what your thoughts are on this. Thank you so much for your help

TheFuzz4 commented 8 years ago

And now I just saw this. 18519ead-448b-493e-a6bf-e0f3913fea7e 8:04:51 AM: warn ║║░░ Invalid URI for web request 18519ead-448b-493e-a6bf-e0f3913fea7e 8:04:51 AM: debug ║║░░ Processing command task [taskId:1, time:1475071491340, idx:1, marker:1475071491182, created:1475071491442, ownerId:1, data:[p:[[d:path:/192.168.1.138/zm/api/states/change/day.json, t:text, i:0], [d:POST, t:enum, i:1], [d:JSON, t:enum, i:2], [d:null, t:variables, i:3], [d:false, t:bool, i:4], [d:null, t:text, i:5]]], type:cmd]

Nevermind I see what I did wrong damnt

Ok yeah still getting the invalid URI

8:09:38 AM: warn ║║░░ Invalid URI for web request 18519ead-448b-493e-a6bf-e0f3913fea7e 8:09:37 AM: debug ║║░░ Processing command task [taskId:1, time:1475071777671, idx:1, marker:1475071777392, created:1475071777761, ownerId:1, data:[p:[[d::/192.168.1.138/zm/api/states/change/day.json, t:text, i:0], [d:POST, t:enum, i:1], [d:JSON, t:enum, i:2], [d:null, t:variables, i:3], [d:false, t:bool, i:4], [d:null, t:text, i:5]]], type:cmd]

With the path just being the :/path as suggested above.

TheFuzz4 commented 8 years ago

So I can see here in your code where you're looking for the internal def internal = uri.startsWith("10.") || uri.startsWith("192.168.") if ((!internal) && uri.startsWith("172.")) { //check for the 172.16.x.x/12 class def b = uri.substring(4,2) if (b.isInteger()) { b = b.toInteger() internal = (b >= 16) && (b <= 31) } } def data = [:] for(variable in variables) { data[variable] = getVariable(variable) } if (internal) { try { sendHubCommand(new physicalgraph.device.HubAction( method: method, path: (uri.indexOf("/") > 0) ? uri.substring(uri.indexOf("/")) : "", headers: [ HOST: (uri.indexOf("/") > 0) ? uri.substring(0, uri.indexOf("/")) : uri, ], query: data )) } catch (all) { debug "Error executing internal web request: $all", null, "error" } I've tried to preface my URI with :// and :/ and just the straight IP. It just doesn't look like its detecting that I'm using my internal IP even though you're looking for that in the field. I'm continuing to dig into this and see what I can find out but as my coding is limited :). I can read but my knowledge of what to write is small so I'll see what I can figure out here.

TheFuzz4 commented 8 years ago

So I commented out the portion for the external web calls so all it can do is just the internals. ` private task_vcmd_httpRequest(devices, action, task, suffix = "") { def params = (task && task.data && task.data.p && task.data.p.size()) ? task.data.p : [] if (params.size() != 6) return false def uri = params[0].d def method = params[1].d def contentType = params[2].d def variables = params[3].d def importData = !!params[4].d def importPrefix = params[5].d ?: "" if (!uri) return false def protocol = "https" def uriParts = uri.tokenize("://") if (uriParts.size() > 2) { debug "Invalid URI for web request", null, "warn" return false } if (uriParts.size() == 2) { //remove the httpX:// from the uri protocol = uriParts[0].toLowerCase() uri = uriParts[1] } def internal = uri.startsWith("10.") || uri.startsWith("192.168.") debug "We're internal" if ((!internal) && uri.startsWith("172.")) { //check for the 172.16.x.x/12 class def b = uri.substring(4,2) if (b.isInteger()) { b = b.toInteger() internal = (b >= 16) && (b <= 31) } } def data = [:] for(variable in variables) { data[variable] = getVariable(variable) } if (internal) {
try { sendHubCommand(new physicalgraph.device.HubAction( method: method, path: (uri.indexOf("/") > 0) ? uri.substring(uri.indexOf("/")) : "", headers: [ HOST: (uri.indexOf("/") > 0) ? uri.substring(0, uri.indexOf("/")) : uri, ], query: data )) } catch (all) { debug "Error executing internal web request: $all", null, "error" }

} /*else {
    try {
        def requestParams = [
            uri:  "${protocol}://${uri}",
            query: method == "GET" ? data : null,
            requestContentType: (method != "GET") && (contentType == "JSON") ? "application/json" : "application/x-www-form-urlencoded",
            body: method != "GET" ? data : null
        ]
        def func = ""
        switch(method) {
            case "GET":
                func = "httpGet"
                break
            case "POST":
                func = "httpPost"
                break
            case "PUT":
                func = "httpPut"
                break
            case "DELETE":
                func = "httpDelete"
                break
            case "HEAD":
                func = "httpHead"
                break
        }
        if (func) {
            "$func"(requestParams) { response ->
                setVariable("\$httpStatusCode", response.status, true)            
                setVariable("\$httpStatusOk", response.status == 200, true)            
                if (importData && (response.status == 200) && response.data) {
                    try {
                        def jsonData = response.data instanceof Map ? response.data : new groovy.json.JsonSlurper().parseText(response.data)
                        importVariables(jsonData, importPrefix)
                    } catch (all) {
                        debug "Error parsing JSON response for web request: $all", null, "error"
                    }
                }
            }
        }
    } catch (all) {
        debug "Error executing external web request: $all", null, "error"
    }
}
return true */

} `

As you can see I added a debug line in there to let me know if we got into the internal block but nothing is showing in the logs that we made it into that part.

Next step is what I'm trying to figure out now. Sorry for the spam on this just trying to document what I'm doing so you know and hopefully this will help you out as well.

ady624 commented 8 years ago

Fixed and added local web request support too. Bonus, huh?