Get SQL results from DB2 on cloud to Power Query via API - api

I try to connect to db2 on cloud via Excel Power Query.
Based on documentation this is format of curl request:
curl -X POST https://hostname.com/dbapi/v4/sql_query_export -H 'authorization: Bearer MyToken' -H 'content-type: text/csv' -d '{"command":"select * from mytable"}'
I tried to go via GUI but this gives me error
I am pretty sure I am not doing it right, but I could not even google how to pass my parameters.
Could someone please navigate how to assembly M code for this?
I tried this according to #nfgl answer
let
body = [#"command"="select * from mytable"]
,json = Json.FromValue(body)
,wc = Web.Contents("https://hostname.com/dbapi/v4/sql_query_export", [Headers=[#"content-type"="text/csv", authorization="Bearer XXX"]])
,Source = Csv.Document(wc,[Delimiter=",", Encoding=65001, QuoteStyle=QuoteStyle.Csv])
in
Source
However cannot go around credentials ui anonymously:
When I try Web API with token:
BTW, everything works with python:
import http.client
conn = http.client.HTTPSConnection("hostname.com")
payload = "{\"command\":\"select * from mytable\"}"
headers = {
'content-type': "text/csv",
'authorization': "Bearer XXX"
}
conn.request("POST", "/dbapi/v4/sql_query_export", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

You can't do it via GUI, command JSON must be in request content, and content-type is the one you send, ie JSON, open advanced editor and do something like this
let
url = "https://showcase.api.linx.twenty57.net/UnixTime/fromunixtimestamp",
body = [#"UnixTimeStamp"= 1589772280, #"Timezone"=""],
json = Json.FromValue(body),
wc = Web.Contents(url, [Headers=[#"Content-Type"="application/json"], Content=json]),
Source = Csv.Document(wc,[Delimiter=",", Encoding=65001, QuoteStyle=QuoteStyle.Csv])
in
Source

Related

UPS API OAuth token request fails

In the UPS developer portal, I have created an application that has a Client Id and a Client Secret. Next, I want to obtain an OAuth token so I can use it to access their other APIs. I am creating my token request as per the spec and I am receiving the following error:
{"response":{"errors":[{"code":"10400","message":"Invalid/Missing Authorization Header"}]}}
The spec has a "try it out" feature where you can obtain a test token. It prompts the user to fill in a x-merchant-id parameter and a grant_type form variable and creates a curl request that looks like this:
curl -X POST "https://wwwcie.ups.com/security/v1/oauth/token"
-H "accept: application/json"
-H "x-merchant-id: {My_Client_Id_Goes_Here}"
-H "Content-Type: application/x-www-form-urlencoded"
-d "grant_type=client_credentials"
For x-merchant_id, I have used my app’s Client Id. It is not clear if the value for grant_type should be the phrase client_credentials (the page makes it seem like this is the only valid value) or my app’s actual Client Secret. I have tried both and get the same error each time.
There are a million examples out there on how to use their (old style) API keys, but practically nothing about how to obtain an OAuth token except for the instructions linked above!
Your curl looks good to me, just missing the Authorization header which is a base64(id:secret)
curl -X POST "https://wwwcie.ups.com/security/v1/oauth/token"
-H "Authorization: Basic {id}:{secret}"
-H "accept: application/json"
-H "x-merchant-id: {My_Client_Id_Goes_Here}"
-H "Content-Type: application/x-www-form-urlencoded"
-d "grant_type=client_credentials"
If you're using the 'Try out' feature, select the Authorize button at the top and enter the client id and secret, that's where its used to set the Authorization header. One thing to note, the 'Try out' feature only work with the Test product(s) assigned to your app
Additional info
UPS have 2 environments
Testing: wwwcie.ups.com
Production: onlinetools.ups.com
Testing env only accepts Test Products, so note the product(s) that was added to your app
I was stuck with this issue for a long time.
Your comments did eventually help me. But I wanted to make it more clear for someone else reading this later....
Instead of using UPS username and password in the authorization header. You need to encode the clientId and secret with a colon between and send that.
For PHP:
$clientID = base64_encode("{clientID}:{clientSecret}");
$headers = array();
$headers[] = "Authorization: Basic $clientID";
$headers[] = 'Accept: application/json';
$headers[] = "X-Merchant-Id: {clientID}";
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
One more addition to the other answers: make sure you add the "OAuth" product to your UPS app. I had added "tracking" and "tracking test", but not OAuth. I was getting the "{"code":"10401","message":"ClientId is Invalid"}" response when I tried to get a token, even though I was sure I had everything else right.
Adding OAuth to my UPS app presumably added my ClientID to their OAuth system, and my token requests started working.
Just in case somebody with .NET/C# background will be looking for the similar topic - an UPS RESTFul API authorization and tracking info processing solution here is the one working well for me using proposed here approach:
#define TEST_MODE
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
var myClientID = "{Type your ClientId here}";
var mySecretID = "{Type your SecretID here}";
#if TEST_MODE
var baseAddress = "https://wwwcie.ups.com"; // testing
#else
var baseAddress = "https://onlinetools.ups.com"; // production
#endif
var accessID = $"{myClientID}:{mySecretID}";
var base64AccessID = Convert.ToBase64String(Encoding.ASCII.GetBytes(accessID));
using (var client = new HttpClient())
{
// Get Access Token
var request = new HttpRequestMessage()
{
Method = HttpMethod.Post,
RequestUri = new Uri($"{baseAddress}/security/v1/oauth/token"),
Content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "client_credentials")
})
};
request.Headers.Add("Authorization", $"Basic {base64AccessID}");
var response = await client.SendAsync(request);
var jsonResult = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<JsonObject>(jsonResult);
var access_token = result?["access_token"]?.ToString();
// Get Tracking Info
var trackingNumber = "1Z5338FF0107231059"; // provided by UPS for testing
request = new HttpRequestMessage()
{
Method = HttpMethod.Get,
RequestUri = new Uri($"{baseAddress}/api/track/v1/details/{trackingNumber}")
};
request.Headers.Add("Authorization", $"Bearer {access_token}");
request.Headers.Add("transId", $"{DateTime.Now.Ticks}");
#if TEST_MODE
request.Headers.Add("transactionSrc", $"testing");
#else
request.Headers.Add("transactionSrc", $"{App Name and version}");
#endif
response = await client.SendAsync(request);
jsonResult = await response.Content.ReadAsStringAsync();
Console.WriteLine(jsonResult);
}

Gnome Shell Extension: Send Request with Authorization Bearer Headers

I am trying to build a gnome shell extension (using gjs) that I need to communicate with an external REST API. In order to do so, I need to accompany my requests with the header: Authorization: Bearer <token> and with a Content-Type: application/json.
I have looked all over for questions like this and I did find some similar ones but none of them works. The documentation is not helpful at all, and, if anything, it has only confused me more.
With curl I could send that request as follows:
curl -X GET -H "Authorization: Bearer <token>" -H "Content-Type: application/json" <url>
So far, I have only created extensions that send simple GET requests with no headers. Then I would do the following:
const Soup = imports.gi.Soup;
let soupSyncSession = new Soup.SessionSync();
let message = Soup.Message.new('GET', url);
let responseCode = soupSyncSession.send_message(message);
let res;
if(responseCode == 200) {
res = JSON.parse(message['response-body'].data);
}
Any idea on how I can add the headers? Any help would be appreciated!
EDIT:
By using #ptomato's answer I ended up using the following code:
function send_request(url, type='GET') {
let message = Soup.Message.new(type, url);
message.request_headers.append(
'Authorization',
`Bearer ${token}`
)
message.request_headers.set_content_type("application/json", null);
let responseCode = soupSyncSession.send_message(message);
let out;
if(responseCode == 200) {
try {
out = JSON.parse(message['response-body'].data);
} catch(error) {
log(error);
}
}
return out;
}
Initial Comment:
So, I managed to find a workaround but it is not efficient and so I will not mark it as the accepted answer. If anyone knows how to answer my question using Soup, please answer!
My workaround involves using the imports.misc.util file which includes the function spawnCommandLine for executing shell commands. So, I used curl in order to download the json to a file (the path variable below):
Util.spawnCommandLine(`/usr/bin/curl -X ${type} -H "Authorization: Bearer ${token}" -H "Content-Type: application/json" ${url} -o ${path}`);
and then I read the contents by using the following:
let text = GLib.file_get_contents(path)[1];
let json_result = JSON.parse(text);
This is not efficient at all and there should be an easier way around. But, until that is found, I hope this will be able to help someone else.
message.request_headers is a Soup.MessageHeaders object to which you can append() the authorization and content type headers.
Additionally there is a convenient set_content_type() method for the content type header specifically.

Linking to Fidel API via Flutter http.dart package

probably a basic question, but I'm new to this:
I am trying to link to the Fidel test API environment. They give examples (https://reference.fidel.uk/reference#get-transaction) of how to do this via cURL. In this case the example is:
curl -X GET \
https://api.fidel.uk/v1/transactions/84782884-6ab8-4885-820f-4cd081dd658f \
-H 'Content-Type: application/json' \
-H 'Fidel-Key: sk_test_50ea90b6-2a3b-4a56-814d-1bc592ba4d63'
If I run this in my terminal it works perfectly. But I can't get anything back if I try to run the same in my browser, or if I try to run it via the http.dart package in Flutter, which is where I need it to run eventually.
In Flutter I am writing it as:
void getData() async {
Response response = await get(
"https://api.fidel.uk/v1/transactions/84782884-6ab8-4885-820f-4cd081dd658f \'Content-Type: application/json' \'Fidel-Key: sk_test_50ea90b6-2a3b-4a56-814d-1bc592ba4d63'");
print(response.body);
}
I am sure it's a syntax thing that I don't understand. Any help would be appreciated.
It was just syntax! I solved by saying
Response response = await get(
'https://api.fidel.uk/v1/transactions/84782884-6ab8-4885-820f-4cd081dd658f',
headers: {
'Content-Type': 'application/json',
'Fidel-Key': 'sk_test_50ea90b6-2a3b-4a56-814d-1bc592ba4d63',
});
Will leave here in case anyone else, like me, gets stuck on the basics.

PUT requests to upload a file in form data Using karate

I've tried to write equivalent karate script for below curl request
curl -X PUT \
'http://localhost:8055/uploadfile' \
-H 'content-type: multipart/form-data;' \
-F code=#/Users/test/Downloads/Next.zip
Tried karate script
Given path 'uploadfile'
#Given header Content-Type = 'multipart/form-data'
And form field code = '/Users/test/Downloads/Next.zip'
#And multipart file code = { read: '/Users/test/Downloads/Next.zip' , contentType: 'application/zip' }
When method PUT
Then status 200
Am I doing something mistake here (tried different things)? Still not getting expected API response.
FYI : I've got that curl command from postman and it is working fine.
It is hard to tell with the limited info you have provided. Try this:
Given url 'http://localhost:8055/uploadfile'
And multipart file code = { read: 'file:/Users/test/Downloads/Next.zip', filename: 'Next.zip', contentType: 'application/zip' }
When method put
If you are still stuck follow this process: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue (or use postman ;)

How can i update a jenkins job using the api

I have to create/update a jenkins job using its api because all of my jobs are using parameters which are also used by other scripts and I am trying to centralize the scripts so when i change it in one place, the change reflects in all.
currently, if someone changes the script, they they also have to manually edit the parameters of the jenkins job as well.
I saw the example of the Remote API for creating jobs and was able to successfully create test jobs but how can i edit an existing job besides deleting it and creating it again(which isnt an option as i have to maintain the build history).
You could use python like this:
from jenkinsapi.jenkins import Jenkins
jenkinsSource = 'http://10.52.123.124:8080/'
server = Jenkins(jenkinsSource, username = 'XXXXX', password = 'YYYYY')
myJob=server.get_job("__test")
myConfig=myJob.get_config()
print myConfig
new = myConfig.replace('<string>clean</string>', '<string>string bean</string>')
myJob.update_config(new)
in case anyone else is also looking for the same answer,
It appears the solution is far easier, all you have to do is update the config.xml and post the updated config.xml back to jenkins and your job will be updated.
You can also POST an updated config.xml to the URL which can fetch config.xml, to programmatically update the configuration of a job.
The fetch url pattern: $JENKINS_SERVER/job/$JOB_NAME/config.xml
detailed doc pattern: $JENKINS_SERVER/job/$JOB_NAME/api
example: https://ci.jenkins-ci.org/job/infra_atlassian-base/api/
http://asheepapart.blogspot.ca/2014/03/use-jenkins-rest-api-to-update-job.html
That little bit of scripting looks to be what you are looking for. Uses the REST API to get and set the config with some regex S&R in the middle.
Edit: Code below based on comment. It is copied directly from the blog so I take no credit for it.
# First, get the http://jenkins.example.com/job/folder-name/job/sample-job--template/configure looking like you want
read -s token
# type token from http://jenkins.example.com/user/$userName/configure
# Download the configuration XML for the template job (which will be our model template)
curl -v -u "bvanevery:$token" http://jenkins.example.com/job/folder-name/job/sample-job--template/config.xml > generic-config.xml
# My modules
declare modules=('module1' 'module2' 'module3')
# POST the updated configuration XML to Jenkins
for m in ${modules[#]}; do
echo "module $m";
sed "s/MODULE/$m/g" generic-config.xml > $m-config.xml;
curl -v -X POST --data-binary #$m-config.xml -u "bvanevery:$token" \
-H 'Content-Type: application/xml' \
"http://jenkins.example.com/job/folder-name/job/$m/config.xml" ;
done
For those using RestSharp, I found that I needed to make sure that:
The user ID performing the update had permission to do so under Manage > Global Security > Authorization Matrix
I had a current Jenkins Crumb token, required once CSRF (also under Manage > Security) is enabled.
Send the updated XML using a parameter of the Request object with the value of [ParameterType.RequestBody] (link)1 for the type argument.
private XmlDocument JobConfigGet()
{
Uri JobConfigURI = GetJenkinsURI("job/" + _args.JobName + "/config.xml", null);
RestClient restClient = new RestClient(JobConfigURI);
RestRequest restRequest = new RestRequest(Method.GET);
byte[] ua = Encoding.ASCII.GetBytes(Properties.Settings.Default.UserID + ":" + Properties.Settings.Default.UserPassword);
restRequest.AddHeader("authorization", "Basic " + Convert.ToBase64String(ua));
IRestResponse restResponse = restClient.Execute(restRequest);
if (restResponse.ResponseStatus != ResponseStatus.Completed || restResponse.StatusCode != HttpStatusCode.OK)
throw new Exception(string.Format("Unable to retrieve job config: {0}. Wrong ResponseStatus ({1}) or StatusCode ({2}) returned.\nURL: {3}", _args.JobName, restResponse.ResponseStatus.ToString(), restResponse.StatusCode.ToString(), restClient.BaseUrl.AbsoluteUri));
if (restResponse.ContentType != "application/xml")
throw new Exception("Unexpected data type returned for job config: " + _args.JobName + ". Expected 'application/xml'. Got: " + restResponse.ContentType + ".\nURL: " + restClient.BaseUrl.AbsoluteUri);
XmlDocument jobConfig = new XmlDocument();
jobConfig.LoadXml(restResponse.Content);
return jobConfig;
}
private void JobConfigUpdate(XmlDocument JobConfig, string JenkinCrumb)
{
// Update JobConfig XML as needed here.
Uri JobConfigURI = GetJenkinsURI("job/" + _args.JobName + "/config.xml", null);
RestClient restClient = new RestClient(JobConfigURI);
RestRequest restRequest = new RestRequest(Method.POST);
byte[] ua = Encoding.ASCII.GetBytes(Properties.Settings.Default.UserID + ":" + Properties.Settings.Default.UserPassword);
restRequest.AddHeader("authorization", "Basic " + Convert.ToBase64String(ua));
string[] crumbSplit = JenkinCrumb.Split(':');
restRequest.AddHeader(crumbSplit[0], crumbSplit[1]);
restRequest.AddParameter("text/xml", JobConfig.InnerXml, ParameterType.RequestBody);
IRestResponse restResponse = restClient.Execute(restRequest);
string resp = restResponse.Content;
}
curl -v -X POST https://jenkinsurl.fr:8443/job/jobname/config.xml --data-binary "#config.xml" -u "jenkinsusername:yourjenkinstoken" -H "Content-Type: application/xml"