Botframework/Botbuilder-js - Send HTTP request - javascript

I created a JavaScript Bot using BotFramework and Botbuilder-js.
For this bot I use an adaptive dialog.
At some point in the dialog I need to send an HTTP-request.
For now, my HTTP-request Step looks like this:
new HttpRequest().configure({
resultProperty: new StringExpression("user.teamProfile.accessToken"),
url: new StringExpression('https://login.microsoftonline.com/myTenantId/oauth2/v2.0/token'),
method: HttpMethod.POST,
contentType: new StringExpression('application/x-www-form-urlencoded'),
headers: {
"Content-Type": new StringExpression("application/x-www-form-urlencoded")
},
body: new StringExpression("client_id: myClientId, scope: https://graph.microsoft.com/.default, client_secret: myclientSecret, grant_type: client_credentials"),
responseType: ResponsesTypes.Json
})
The bot in itself is working but when it tries to execute the HTTP-Request step, I get the following error message:
Error: TypeError: path.indexOf is not a function
Unfortunately, I don't get any more information. Can anyone help me ?
Best regards,
BufferOverflow

Since the HttpRequest-Step didn't work, I changed to a CodeAction.
Inside this CodeAction I then do my Http-Requests and work on the results (transforming them or saving them in a dialog variable).
A Code Snippet could look like the following:
new CodeAction(async (dc, options) => {
// Send your request
// options being the headers, body, etc.
const response = await this.fetch(url, options);
// Work on you result and if necessary, save it to a dialog variable
dc.state.setValue("user.yourPropertyName", value);
// Needed for the Bot to continue working
return await dc.endDialog();
})

Related

Unable to use the response gathered by Fetch API and use it in my code later

I'm trying to build a HTML, CSS, JS website and want to incorporate an API and use the response further in my website.
I've managed to make this API part work but I'm stuck with the final part.
What I've Achieved
Executing a JS function using FETCH that makes a POST Call with Auth Headers
Getting the response to show up inside my Chrome Developer Console.
What I'm trying to achieve
Use the Response (Web URL) that is being received by the POST API Call inside my
website as a variable. So when the user hits a button this response (URL) opens up in
a new tab.
In simple terms, I want the make use of the web url that shows up in the Chrome Console.
Here is the code I'm using
function initiateIDV(){
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Authorization", "Basic xxxxxxxxxxxxx");
var raw = JSON.stringify({
"customerInternalReference": "Will's App",
},
"userReference": "test-app",
"tokenLifetime": "10m"
});
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
fetch("https://[hidden]/api/v1/accounts", requestOptions)
.then(response => response.json())
.then(result => console.log(result.web.href))
.catch(error => console.log('error', error));
}
View From the Chrome Console of a Successful Response
I think there are 2 things to check first before make sure the value show in the Console.
Network request. Check in the Network panel to see if the network request call successful? If it's not fix the url or the API. Learn inspect network request
Log the result. Log the result object first to see if it contains .web.href. If it's not, fix the API.
I create a working example from your code. Run it and you will see result. I changed the API url to a demo url
function initiateIDV(){
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Authorization", "Basic xxxxxxxxxxxxx");
// changed body content
var raw = JSON.stringify({
title: 'foo',
body: 'bar',
userId: 1,
})
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
// changed url
fetch("https://jsonplaceholder.typicode.com/posts", requestOptions)
.then(response => response.json())
.then(result => console.log(result))
.catch(error => console.log('error', error));
}
initiateIDV();
Let me paraphrase your question. You want to:
make a POST request to an API
handle the API response in your JavaScript code
open a new tab in the user's browser, at the URL contained in the API response
And you are stuck at step 3.
What you are trying to achieve at step 3 is an effect (aka a side effect) on the user's browser.
Also, a minor remark about the terminology you used:
So when the user hits a button this response (URL) opens up in a new tab.
In your example the response is not a URL. You are calling response.json(), so the API response is JSON.
You are already performing a side effect at step 3: console.log(). A lot of stuff is a side effect. Basically everything that changes some kind of state. Printing something in the browser's console, showing an alert dialog, adding/removing CSS classes, adding/removing/altering DOM elements, are all side effects.
The side effect you want to achieve here is to open a new tab in the user's browser. In JS you can do it using this code:
window.open("https://stackoverflow.com/", '_blank').focus()
The state in your scenario is the fact that the browser currently has N tabs open, and after window.open() will have N+1 tabs open. And not only that. Opening a tab in Chrome might spawn a new operating system process (before the relationship was 1 tab => 1 process, but nowadays I don't think so, see here).

I can not send parameter using GET with jQuery to node js REST API [duplicate]

I have a React application where I am changing POST method to GET with the request body as it is. It works fine with POST request however when I change the method to GET, it gives me error-
message: "org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public
My Front End Code-
export const setData = (getData) => dispatch => {
axios({
method: 'GET',
url: 'http://localhost:8080/api',
headers: {
'Content-Type': 'application/json'
},
data: getData
})
.then (response => {
dispatch({
type: API_DATA,
payload: response.data
})
dispatch({
type: SET_SEARCH_LOADER,
payload: false
})
})
.catch(function(error) {
})
}
Can someone let me know what I am missing here. As per my understanding, http allows to have a request body for GET method.
As per my understanding, http allows to have a request body for GET method.
While this is technically true (although it may be more accurate to say that it just doesn't explicitly disallow it), it's a very odd thing to do, and most systems do not expect GET requests to have bodies.
Consequently, plenty of libraries will not handle this.
The documentation for Axois says:
// `data` is the data to be sent as the request body
// Only applicable for request methods 'PUT', 'POST', and 'PATCH'
Under the hood, if you run Axios client side in a web browser, it will use XMLHttpRequest. If you look at the specification for that it says:
client . send([body = null])
Initiates the request. The body argument provides the request body, if any, and is ignored if the request method is GET or HEAD.
If you want to send parameters with get request in axios, you should send parameters as params.
If you want to set "Content-type":"application/json" and send params with get request, you should also send an empty data object.
For example:
const AUTH_TOKEN = 'Bearer token'
const config = {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': AUTH_TOKEN,
},
data: {},
params: {
"post_id": 1
}
}
axios.get("http://localhost/api/v1/posts/", config)
This is not axios, the error origniates from the java backend you're talking to. The public field in your request body is missing.
If you just want to send the data as parameters (which would be odd), pass it using params instead of data (as shown here: https://github.com/axios/axios#example).
I personally don't think your API should support GET with a request body (talk to the devs and ask for documentation).

Linkedin webhooks event subscription not working

I've been stuck on this issue for some time now, I am trying to subscribe to Linkedin's webhook using ngrok for testing on localhost, and have been trying for some time now, i have tried using encode uri's as well but still running into error, I have verified that the APP_ID, profileId and organizationId i'm using are correct, but still i get the same error. I have also tried using the Restli protocol that linkedin suggests in their documentation but to no avail.
let url = `https://api.linkedin.com/v2/eventSubscriptions/(developerApplication:urn:li:developerApplication:${config.IN.APP_ID},user:urn:li:person:${profileId},entity:urn:li:organization:${organizationId},eventType:ORGANIZATION_SOCIAL_ACTION_NOTIFICATIONS)`;
return new Promise((resolve, reject) => {
request(
{
url,
method: 'PUT',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
// 'X-Restli-Protocol-Version': '2.0.0',
},
json: {
webhook: "https://url.ngrok.io/api/v1/webhook/linkedin/callback"
},
},
(err, response, body) => {
if (err) {
reject(err);
} else {
resolve(body);
}
},
);
});
I have been receiving this error constantly no matter what I try, I have tried sending the url like this:
https://api.linkedin.com/v2/eventSubscriptions/(developerApplication:urn:li:developerApplication:{${config.IN.APP_ID}},user:urn:li:person:{${profileId}},entity:urn:li:organization:{${organizationId}},eventType:ORGANIZATION_SOCIAL_ACTION_NOTIFICATIONS)
https://api.linkedin.com/v2/eventSubscriptions/${encodeURIComponent((developerApplication:urn:li:developerApplication:${config.IN.APP_ID},user:urn:li:person:${profileId},entity:urn:li:organization:${organizationId},eventType:ORGANIZATION_SOCIAL_ACTION_NOTIFICATIONS))
All I receive is this error
'{"serviceErrorCode":100,"message":"Unpermitted fields present in RESOURCE_KEY: Data Processing Exception while processing fields [/key]","status":403}'
Any help would be appreciated, I have been stuck on this for a while now.
The request seems to be OK , but the method should be GET (not PUT)
One thing is to check which ID are you using for application_id. The application ID is the one in the url - https://www.linkedin.com/developers/apps/<id from here>/settings
. You need to use and uncomment the header for Restli.
I'd say that your url needs to look like this, as this is from their original POSTMAN collection.
https://api.linkedin.com/v2/eventSubscriptions/(developerApplication:urn%3Ali%3AdeveloperApplication%3A{{application_id}},user:urn%3Ali%3Aperson%3A{{person_id}},entity:urn%3Ali%3Aorganization%3A{{organization_id}},eventType:ORGANIZATION_SOCIAL_ACTION_NOTIFICATIONS)
You can validate here, their full collection - https://www.postman.com/linkedin-developer-apis/workspace/e781b3ac-4101-4d60-8981-afcb4812623d/request/16069442-9d0bf046-ea81-4af0-9515-d07246a0ab39
LinkedIn webhooks does not support ngrok URIs

Javascript REST API with body in GET

I'm working in Javascript (frontend) and have a colleague working in the backend with NodeJS.
When calling a GET request, he asks me to put the data in the body, but I could not figure out how to do that. (If I use this code to a POST request, it works fine).
Could you tell me if this is possible and how to do it? He says that it is possible, but I've googled a lot and could not find the correct way to do that.
ERROR that I get: "Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body."
let URL = "http://localhost:3000/verifyUser";
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2NjJDMTRBNk";
fetch(URL, {
method: request,
mode: 'cors',
body: JSON.stringify({
user: 'Carlos6',
password: '543534543',
email: "algo6#gmail.com"
}),
headers: {
'Accept' : 'application/json',
'Content-type': 'application/json; charset=UTF-8',
'auth-token': token
}
}).then(function (response) {
if (response.ok) {
return response.json();
}
return Promise.reject(response);
}).then(function (data) {
console.log(data);
}).catch(function (error) {
console.warn('Something went wrong.', error);
});
You are using HTTP GET and sending a body.
If you want to send a body (JSON) you should use the PUT and POST.
The best will probably be to:
change your client code to method: "PUT"
change the server to access PUT request
If you want to know which one to chose look at this question:
( PUT vs. POST in REST)
If you wish to send a request with a body then you should make a POST-request and not a GET one. GET-request cannot have a body by its nature and primary goal.
All params of GET-request must be indicated in the URL itself only.

Unsupported grant type when getting OAuth token for Reddit API

I'm trying to get an OAuth token for the Reddit API following the Application Only OAuth instructions. My reddit app is an installed app, so for my grant_type I'm using https://oauth.reddit.com/grants/installed_client.
Currently I'm running a very short JS script to query the API and get a token:
const APP_ID = 'MY_APP_ID'
const DEVICE_ID = 'TRACKING_ID_20_TO_30_CHARS'
let form = new FormData()
form.append('grant_type', 'https://oauth.reddit.com/grants/installed_client')
form.append('device_id', DEVICE_ID)
fetch('https://www.reddit.com/api/v1/access_token', {
method: 'POST',
headers: new Headers({
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Basic ${btoa(`${APP_ID}:`)}`,
}),
body: form })
.then(handleResponse)
.then(function(data) {
console.log(data)
})
.catch(error => console.error(error))
function handleResponse(response) {
return response.json()
}
(Note: running the snippet as-is will give you a NetworkError because the APP_ID isn't a real one and I don't want to give mine out.)
The response I get is:
{
"error": "unsupported_grant_type"
}
When I try the same API request using a REST client I get back the expected response, so this makes me think that the problem is JavaScript-related. Since the grant_type matches what the instructions say I'm not really sure what to do with the error. I'm hoping someone else more experienced with OAuth will know what is going on here.
The problem was the use of the FormData object. In earlier stages of troubleshooting I found this answer on Reddit and decided to use it, but that didn't work for me.
It was submitting the data as multipart/form-data rather than application/x-www-form-urlencoded, which Reddit's OAuth server did not like. I wrote a helper function based on this answer which did the trick:
function urlEncode(data) {
let out = [];
for (let key in data) {
out.push(`${key}=${encodeURIComponent(data[key])}`);
}
return out.join('&')
}

Categories

Resources