Unlock a world of possibilities! Login now and discover the exclusive benefits awaiting you.
Hi,
I'm trying to get Powershell to import an App on the central node of a QS 2.1.1 deployment. It is multi-node (if that makes any difference).
So far, I have successfully set up a Virtual Proxy for header auth and tested it using such commands as:
<server>/qrs/user/count?xrfkey=<xrfkey>
and all the relevant headers. This powershell script is based on QRSAPI - Remove Unwanted Users with PowerShell
However, when I come to use the "/qrs/app/import?name={name}&keepdata={keepdata}&replace={replace}" call
I'm getting a "The remote server returned an error: (403) Forbidden." response.
I'm getting a "The remote server returned an error: (400) Bad Request" (I'd missed off the xrfkey in the above error on this specific call - doh)
The App is in %ProgramData%\Qlik\Sense\Apps folder.
Details:
----------
POST request to: http://<machinename>/<prefix>/qrs/app/import?name=<app name to be assigned>
Xrfkey, UserId and headers required by the virtual proxy have all been set correctly (I believe).
body = "{
'id':'00000000-0000-0000-0000-000000000000',
'columns':
[
{
'name':'current_filename.qvf',
}
]
}"
content type = "application/json"
I'm pretty certain that it is down to my usage of this API call as GET requests seem to work fine. Can anyone help please?
Thanks,
Dave
Hi David,
frist try this Import app example so you can check if its working on you server. Than you can go the next step and do it with PowerShell.
bye
Konrad
Thanks Konrad, we've got powershell to work with GETs and POSTs using a Virtual Proxy for header auth, so we know it's not a config issue.
We currently believe the problem is in the format of the POST for the specific API call to import
This works:
PS> QRScall.ps1
Command: http://<server.com>/<proxy_prefix>/qrs/license/requestaccesstype?Xrfkey=blah
Content-Type: application/json
Method: POST
Body: {
"sessionID": "xxxxxxx",
"hosttname": "[localhost, local]"
}
accessGranted accessType accessTypeResultCode schemaPath
------------- ---------- -------------------- ----------
False 0 3 AccessTypeResult
This doesn't:
PS> QRScall.ps1
Command: http://<server.com>/<proxy_prefix>/qrs/import?name=AppName?Xrfkey=blah
Content-Type: application/json
Method: POST
Body: {"name":"example.qvf"}
Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
At QRScall:64 char:21
+ $response = Invoke-RestMethod $command -ContentType $contenttype -Header ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
The only difference was the call URL and the content of body in the post.
Thanks,
Dave
Hi Dave,
to help you I would sugest 2 different things:
1. you attach your PS scripts or send them direct to me.
2. you try to make the upload with curl, if it is working use tools like fiddler / wireshark to record the real traffic between the server and the script for the curl upload and your ps1 upload and attach this.
bye Konrad
Hi Konrad,
Thanks for your help. I finally got it working remotely, using Python's request module.
One thing to note: even if it the docs say the body should be a string, actually, by submitting it as a json of a string, it worked. I appreciate there are a lot of API calls, so this might not always be the case, but it is for the import call.
Dave
Hi David,
Would you happen to have a code example to share for the Import POST call?
Struggling with the same thing here (actually looking to use the Upload call but figured once I get the Import working that should be easier to manage) and I'm running into the same issues as you I think.
Cheers,
Johannes
Hi Johannes,
Sorry for the slow reply, but here is what works with Python:
xrfkey
=
{
'key'
:
'Xrfkey'
,
'value'
:
'<something>'
}
headers
=
{
'X-Qlik-Xrfkey'
:
'<something>'
,
'Content-Type'
:
'application/json'
'Accept'
:
'application/json, text/plain, */*'
}
path_to_cert
=
<path to cert>
path_to_cert_key
=
<path to cert key>
AppName
=
'target name'
# what it will appear as in QS.
payload
=
'filename'
# that has already been moved to the PROGRAMDATA\Qlik\Sense\Apps folder, filename is a string at this point
qrs_url
=
'https://<domain_name>:4242/qrs/app/import?'
+
xrfkey[
'key'
]
+
'='
+
xrfkey[
'value'
]
+
'&name=<AppName>&keepdata=true'
# using json=payload ensure the string is encoded to JSON, which the QRS wants - it would not work for us as a string.
result
=
requests.post(
qrs_url, json
=
payload, cert
=
(
self
.path_to_cert,
self
.path_to_cert_key), headers
=
self
.headers, verify
=
False
,
)
Notes: we are using certificates, not the header authentication proxy.
Kind Regards,
Dave
Following node.js code works fine in my environment:
It imports an qvf file which is named as FindLongLat.qvf into qliksense server as an app which is named as FindLongLatImported.
----------------------------------------------------------------------------------------------------------------------
var https = require('https');
var fs = require('fs');
var options = {
"rejectUnauthorized": false,
hostname: '<hostname>',
path: '/qrs/app/import?xrfkey=0123456789abcdef&name=FindLongLatImported',
method: 'POST',
port:4242,
headers: {
'x-qlik-xrfkey' : '0123456789abcdef',
'X-Qlik-User' : 'UserDirectory= Internal; UserId= sa_repository',
'Content-Type': 'application/json'
},
key: fs.readFileSync("C:\\client_key.pem"),
cert: fs.readFileSync("C:\\client.pem"),
};
var req = https.request(options, function (res) {
var responseString = "";
res.on("data", function (data) {
responseString += data;
});
res.on("end", function () {
console.log(responseString);
});
});
req.write('"FindLongLat.qvf"');
req.end();
----------------------------------------------------------------------------------------------------------------------
Please note that the catch is the double quotes around the qvf file name which is passed as body to the request.
So, req.write('FindLongLat.qvf') does NOT work, whereas req.write('"FindLongLat.qvf"') works fine.
Hope it helps,
Regards,
Hi Dave,
I am using the similar code and facing an issue -- Call failed with code: 400, "The specified filename is invalid." Did you ever face this problem ? I am exactly using the same code as you have mentioned in python script !
Thanks,
Raghuveer G.
Hi Raghuveer,
I didn't have a problem in Python, can you tell me which file it is trying to/should access? If you can share the code that would be even better.
Kind Regards,
Dave