I got an HTTP call implemented with C# which calls to an Azure API:
public async Task<string> CheckPipelineRunStatus(string pipelineId, string pipelineRunId, CancellationToken cancellationToken = default)
{
string responseBody = "";
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "", _token))));
var requestUrl = $"https://dev.azure.com/{_organization}/{_project}/_apis/pipelines/{pipelineId}/runs/{pipelineRunId}?api-version={_api_version}";
using (HttpResponseMessage response = await client.GetAsync(requestUrl, cancellationToken))
{
response.EnsureSuccessStatusCode();
responseBody = await response.Content.ReadAsStringAsync();
}
}
return responseBody;
}
I need to do the same call in a Javascript call and I'm not sure how exactly am I suppose to send the Authorization header.
Here's what I got so far without the header (question in comment inside the code):
async function checkPipelineStatus(url)
{
var params = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
//is the auth supposed to be here? what to do with that 64base string?
}
};
const fetchResult = await fetch(url, params);
const result = await fetchResult.text();
if (!fetchResult.ok)
{
throw result;
}
return result;
}
As requested, here's your JavaScript code with the header inserted:
async function checkPipelineStatus(url)
{
let base64Credentials = btoa(':' + _token);
var params = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
// Insert your own Base64 credentials here:
'Authorization': `Basic ${base64Credentials}`
}
};
const fetchResult = await fetch(url, params);
const result = await fetchResult.text();
if (!fetchResult.ok)
{
throw result;
}
return result;
}
Related
My api is as follows..
const { URL, URLSearchParams } = require("url");
async callSendApi(requestBody) {
let url = new URL(`${API_URL}/${PAGE_ID}/messages`);
url.search = new URLSearchParams({
access_token: `${PAGE_ACCESS_TOKEN}`,
});
console.warn("Request body is\n" + JSON.stringify(requestBody));
let response = await axios.post(url, {
headers: { "Content-Type": "application/json" },
body: JSON.stringify(requestBody),
});
if (!response.ok) {
consoleconst`Unable to call Send API: ${response.statusText}`,
await response.json();
}
}
The error I get :
message: 'Unknown path components: /messagesaccess_token="access_token"
I cannot find any wrong in this api. but still I get above error.. so I tried following...
async callSendApi(requestBody) {
let url = new URL(`${API_URL}/${PAGE_ID}/messages`);
console.warn("Request body is\n" + JSON.stringify(requestBody));
let response = await axios.post(url, {
headers: { "Content-Type": "application/json" },
body: JSON.stringify(requestBody),
access_token: `${PAGE_ACCESS_TOKEN}`,
});
if (!response.ok) {
consoleconst`Unable to call Send API: ${response.statusText}`,
await response.json();
}
}
then I get a error saying that cannot set headers after sending to the client..
please help!
So i been trying to get access to the reddit api.
I registered to reddit. verified my mail. opened an app and got my credentials.
Followed this official documentation and also came across to this tutorial
All my efforts have failed and don't get any respond.
I am using nodejs. but also tried in postman and failed.
Tried 2 options using fetch and using axios:
const axios = require('axios');
const fetch = require('node-fetch')
const { URLSearchParams } = require('url')
class RedditApi {
clientId2 = "get ur own credentials by opening an app here https://www.reddit.com/prefs/apps";
clientSecret2 = "get ur own credentials by opening an app here https://www.reddit.com/prefs/apps";
authenticationUrl = `https://www.reddit.com/api/v1/access_token`;
BASE_URL = 'https://www.reddit.com/';
tokenAuth = null;
tokenExpirationTime = null;
currencyObj = null;
constructor(currencyObj) {
this.currencyObj = currencyObj;
console.log("constructor service")
}
async getAuthToken() {
const bodyParams = new URLSearchParams({
grant_type: "https://oauth.reddit.com/grants/installed_client",
device_id: "DO_NOT_TRACK_THIS_DEVICE"
});
console.log(this.clientId2, 'this.clientId');
debugger;
const headersObj = {
'Authorization': `Basic ${Buffer.from(`${this.clientId2}:`).toString('base64')}`,
'Content-Type': 'application/x-www-form-urlencoded',
};
let response = null;
try {
response = await axios.post(this.authenticationUrl,
bodyParams,
{
headers: headersObj
});
debugger;
} catch (error) {
debugger;
console.error(error);
console.log(error.stack);
return null;
}
}
async getAuthToken2() {
try {
// Creating Body for the POST request which are URL encoded
const params = new URLSearchParams()
params.append('grant_type', 'https://www.reddit.com/api/v1/access_token')
params.append('device_id', 'DO_NOT_TRACK_THIS_DEVICE')
// Trigger POST to get the access token
const tokenData = await fetch('https://oauth.reddit.com/grants/installed_client', {
method: 'POST',
body: params,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Basic ${Buffer.from(`${this.clientId2}:`).toString('base64')}` // Put password as empty
}
}).then(res => {
debugger;
return res.text()
})
debugger;
if (!tokenData.error) {
debugger;
res.send(trendingResult)
}
res.status(tokenData.error).send(tokenData.message)
} catch (error) {
debugger;
console.log(error)
}
}
}
module.exports = RedditApi;
when using axios i get this respond: "Request failed with status code 401"
When using fetch i get this respond: "'403 Forbidden\nRequest forbidden by administrative rules.\n\n'"
Anybody knows what is the problem and how can i fix it?
Many thanks!
Multiple people have brought up issues similar to mine in this community and cloudflare's community. It still seems largely unsolved so I’m asking in hopes of a solution.
I’m trying to create a feature for users to sign up through mailchimp. User info goes from browser to workers to mail chimp. I’m getting the following errors:
TypeError: Failed to execute function: parameter 1 is not of type
‘Response’. at line 0, col -2
Request.Body is not being read
Request from Client:
const response = await axios({
method: "post",
url: "http://127.0.0.1:8787/signup",
data: {
MERGE0: email,
MERGE1: firstName,
MERGE2: lastName,
},
headers: {
"Content-Type": "application/json",
}
});
Workers part 1 (function to read request body):
https://developers.cloudflare.com/workers/examples/read-post
async function readRequestBody(request) {
const { headers } = request
const contentType = headers.get('content-type') || ''
if (contentType.includes('application/json')) {
return JSON.stringify(await request.json())
} else if (contentType.includes('application/text')) {
return request.text()
} else if (contentType.includes('text/html')) {
return request.text()
} else if (contentType.includes('form')) {
const formData = await request.formData()
const body = {}
for (const entry of formData.entries()) {
body[entry[0]] = entry[1]
}
return JSON.stringify(body)
} else {
// Perhaps some other type of data was submitted in the form
// like an image, or some other binary data.
return 'a file'
}
}
Workers part 2 (to Post JSON File to Mail Chimp):
https://developers.cloudflare.com/workers/examples/post-json
async function gatherResponse(response) {
const { headers } = response
const contentType = headers.get('content-type') || ''
if (contentType.includes('application/json')) {
return JSON.stringify(await response.json())
} else if (contentType.includes('application/text')) {
return response.text()
} else if (contentType.includes('text/html')) {
return response.text()
} else {
return response.text()
}
}
Workers Part 3 (to Handle Post Request):
async function eventHandler(request) {
const pathname = request.url
try {
if (pathname.indexOf('signup') !== -1) {
const reqBody = await readRequestBody(request)
const { MERGE0, MERGE1, MERGE2 } = reqBody
// Construct req data
const data = {
members: [
{
email_address: MERGE0,
status: 'subscribed',
merge_fields: {
FNAME: MERGE1,
LNAME: MERGE2,
},
},
],
}
const postData = JSON.stringify(data)
const options = {
method: 'POST',
headers: {
Authorization: `auth ${MAILCHIMP_API_KEY}`,
},
body: postData,
}
const url = `https://us5.api.mailchimp.com/3.0/lists/${MAILCHIMP_AUDIENCE_ID}`
const res = await fetch(url, options)
const results = await gatherResponse(res)
return results
}
} catch (err) {
console.log(err)
}
}
addEventListener('fetch', event => {
event.respondWith(eventHandler(event.request))
})
A few other posts I’ve referenced:
https://community.cloudflare.com/t/fetch-with-post-method-ignores-body/147758/3
https://community.cloudflare.com/t/how-to-post-with-a-body-as-readable-stream/211335
https://community.cloudflare.com/t/using-get-fetch-for-api-javascript-worker/98297
You have this code:
event.respondWith(eventHandler(event.request))
The event.respondWith() function needs to take a Response object as its parameter. However, your eventHandler() function does not return a Response. In some cases, the function does not return a result at all, and in other cases, it returns a string.
In cases where you don't want to modify the request/response, you can have eventHandler pass through the request to origin like so:
return fetch(request);
In cases where you have received a response from the origin, and you want to return it directly to the client unmodified, you should just return repsonse instead of return response.text().
In cases where you have created some new response text that you want to return, you need to wrap it in a Response, like:
return new Respnose(text, {headers: {"Content-Type": "text/plain"}});
I call a SOAP API from POSTMAN it is working fine. Now I want to use it with Node.js(nextjs).
This is how i am calling API and what I am getting.
How i will call this and get a json response?
Now i am calling like this-
const xml =
"<?xml version='1.0' encoding='utf-8'?><soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'><soap:Body><HourlyTransactions xmlns='https://secure.myterminals.com/ConfigStatusSyncService'><StartTime>2020-12-17 00:00</StartTime><EndTime>2020-12-18 00:00</EndTime><Login></Login><Password></Password></HourlyTransactions></soap:Body></soap:Envelope>";
let res = await fetch(
"https://secure.myterminals.com/ConfigStatusSyncService/DataQuery.asmx",
{
method: "POST",
headers: { "Content-Type": "text/xml" },
body: xml,
}
);
console.log(res);
I hope this can help I would use the easey-soap-request and here is an example.
import soapRequest from "easy-soap-request";
const url = "https://my-soap-server";
const sampleHeaders = {
"Content-Type": "text/xml;charset=UTF-8",
SOAPAction: "https://my-soap-action/something"
};
const xml = `<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>
<soap:Body>
<HourlyTransactions xmlns='https://secure.myterminals.com/ConfigStatusSyncService'>
<StartTime>2020-12-17 00:00</StartTime><EndTime>2020-12-18 00:00</EndTime><Login></Login><Password></Password></HourlyTransactions>
</soap:Body>
</soap:Envelope>`;
async function makeRequest() {
const { response } = await soapRequest({
url: url,
headers: sampleHeaders,
xml: xml,
timeout: 1000
});
const { headers, body, statusCode } = response;
console.log(headers);
console.log(body);
console.log(statusCode);
document.body.innerHTML = body;
}
makeRequest();
This is the example I found HERE
I would rather use easy-soap-request package.
Here's a working example:
const soapRequest = require('easy-soap-request');
const url = 'https://secure.myterminals.com/ConfigStatusSyncService/DataQuery.asmx';
const sampleHeaders = {
'Content-Type': 'text/xml',
// 'soapAction': '' //FILL_HERE If Needed
};
const xmlSoapEnvelope = "<?xml version='1.0' encoding='utf-8'?><soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'><soap:Body><HourlyTransactions xmlns='https://secure.myterminals.com/ConfigStatusSyncService'><StartTime>2020-12-17 00:00</StartTime><EndTime>2020-12-18 00:00</EndTime><Login></Login><Password></Password></HourlyTransactions></soap:Body></soap:Envelope>";
(async () => {
try {
const {
response
} = await soapRequest({
url: url,
headers: sampleHeaders,
xml: xmlSoapEnvelope,
timeout: 1000
});
const {
headers,
body,
statusCode
} = response;
console.log('soap headers:', headers);
console.log('soap body:', body);
}
catch(e) {
console.log("Error Due to: ", e)
}
})()
I'm learning nodejs and trying to make an API call. The API uses JWT to authenticate.
I created these functions to sign a token:
function token() {
const payload = {
iat: Math.floor(new Date() / 1000),
exp: Math.floor(new Date() / 1000) + 30,
sub: "api_key_jwt",
iss: "external",
jti: crypto.randomBytes(6).toString("hex")
};
return new Promise((resolve, reject) => {
jwt.sign(payload, privatekey, { algorithm: "RS256" }, function(
err,
token2
) {
if (err) reject(err);
else resolve(token2);
});
});
}
exports.genToken = async function() {
const header = {
"x-api-key": api
};
const data = {
kid: api,
jwt_token: await token()
};
async function authorization(req, res) {
try {
const auth = await rp({
url: authurl,
method: "POST",
headers: header,
body: data
});
res.send(auth.body);
} catch (error) {
res.send(404).send();
}
}
return {
"x-api-key": api,
Authorization: "Bearer " + authorization()
};
};
This works fine. Then I created a function to make the API call:
const token = require("./index").genToken;
const rp = require("request-promise");
exports.getOrderBook = function(res, error) {
const full_url = url + "order_book";
const auth = token();
rp({
url: full_url,
method: "GET",
headers: auth,
body: {
market: "btceur"
},
json: true
})
.then(function(response) {
res(response);
})
.catch(function(err) {
error(err);
});
};
And I call it using Express:
routes.get("/orderbook", async (req, res, next) => {
try {
const book = await orders.getOrderBook();
res.send(book);
} catch (error) {
next(error);
}
});
However, when I call my API, it shows an error in console:
TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of
type string or Buffer. Received type object.
I guess the error is something with the token generation, because if I console.log(auth) in the getOrderBook function, it shows Promise { <pending> }, so probably an object is being passed as the jwt token.
Is it really the problem? I tried a lot of different solutions that I found on internet, however the concept of Async/Await is new to me, and I'm having some troubles to figure it out.
Thanks a lot in advance guys!
Since getToken is an anync function, the return is wrapped in a Promise as well so you would need another anync/await:
exports.getOrderBook = async function() {
let response;
try {
const full_url = url + "order_book";
const auth = await token();
response = await rp({
url: full_url,
method: "GET",
headers: auth,
body: {
market: "btceur"
},
json: true
});
} catch (e) {
// handle error
throw e
// or console.error(e)
}
return response;
};
In this line as well Authorization: "Bearer " + authorization(), authorization is returning a promise
const bearer = await authorization()
return {
"x-api-key": api,
Authorization: "Bearer " + bearer
};
For error handling wrap entire thing in try..catch block
exports.genToken = async function() {
try {
const header = {
"x-api-key": api
};
const data = {
kid: api,
jwt_token: await token()
};
async function authorization(req, res) {
let auth;
try {
auth = await rp({
url: authurl,
method: "POST",
headers: header,
body: data
});
// res object not available
// res.send(auth.body);
} catch (error) {
// res object not available, better throw error and handle in your middleware
// res.send(404).send();
}
return auth
}
const bearer = await authorization()
} catch (e) {
// handle error
}
return {
"x-api-key": api,
Authorization: "Bearer " + bearer
};
}