Microsoft Graph add row into sharepoint excel file (The argument is invalid or missing or has an incorrect format) - sharepoint

So I am trying to add a row of data into an excel file via the microsoft graph API.
I was able to successfully set up the authentication and get tokens, read the excel file, etc.
I was also able to run the request to add a new row via Microsoft's graph explorer tool and it worked there perfectly, adding the row via postman and microsoft graph api worked fine.
https://developer.microsoft.com/en-us/graph/graph-explorer
Example request: https://graph.microsoft.com/v1.0/me/drive/items/${ItemId}/workbook/worksheets/Sheet1/tables/${tableId}/rows/add
This worked perfectly from postman and the graph explorer, but when I tried to do this from my localhost (react OR nodejs) it throws "The argument is invalid or missing or has an incorrect format"
Here is my code for the request
const accessToken = await Providers.globalProvider.getAccessToken({ scopes: ['User.Read', 'Files.ReadWrite'] })
const bearer = `Bearer ${accessToken}`;
let headers = new Headers();
headers.append("Authorization", bearer);
const options = {
method: "POST,
headers: headers,
body: {
"values": [
[
"column1", "column2", "column3"
]
]
}
};
const addResponse = await fetch(SHAREPOINT_URL, secondOptions);
And the error message I receive
{
"error": {
"code": "InvalidArgument",
"message": "The argument is invalid or missing or has an incorrect format.",
"innerError": {
"code": "invalidArgument",
"message": "The argument is invalid or missing or has an incorrect format.",
"date": "2023-02-16T12:53:56",
"request-id": "{request-id}",
"client-request-id": "{client-request-id}"
}
}
}

After some thought I realized the only difference between the postman POST request and my react one was the body object.
The answer was converting the javascript object body to a JSON.stringify(bodyObj). Kind of assumed it would automatically do that, but there it is!
let bodyObj = {
values: [
[
"1", "2", "3"
]
]
}
let options = {
method: "POST",
headers: headers,
body: JSON.stringify(bodyObj),
};

Your code looks good except the fact that you defined const options but in fetch you are passing secondOptions instead of options.
Try to use options
const addResponse = await fetch(SHAREPOINT_URL, options);

Related

response detail error:2,errMsg:post method api body check failed! Agora REST API

const Authorization = `Basic ${Buffer.from(`${config.CUSTOMERID}:${config.CUSTOMER_SECRET}`).toString("base64")}`;
const acquire = await axios.post(`https://api.agora.io/v1/apps/${config.agoraAppId}/cloud_recording/acquire`,{
cname: groupId,
uid: userId,
clientRequest: {
},
},
{ headers: { Authorization } }
);
Getting the following response when i call agora live streaming cloud recording from nodejs code using axios.
{
code: 2,
reason: 'response detail error:2,errMsg:post method api body check failed!'
}
This means you have been successfully Authorized but you are passing either wrong value or it is not defined in your body or URL.
Please check if any variable you are passing is undefined or contains wrong/incomplete value.
You should pass the header as an object with they Authorization key, in your case:
{
headers: {'Authorization': "Basic " + Authorization}
}

Discord.js send a webhook

Hi I have been experimenting with webhooks and I'm wondering how do you send a normal message(not embeded) through a webhook with a custom avatar and name
const user = message.mentions.users.first() || client.users.cache.get(args[0]);
let announcement = args.slice(1).join(" ");
if(!announcement) return message.channel.send(`lol say something`)
const wc = new WebhookClient('id', 'token')
const embed = new MessageEmbed()
.setTitle("").setColor('GREEN').setTimestamp().setDescription(announcement)
wc.send({
username : user.username,
avatarURL : user.displayAvatarURL({ dynamic : true }),
embeds : [embed]
})
}
```
If you wish to send Discord webhooks you need to make a POST API request to the webhook url.
For that you can basically use any module you want however in this example I'll use node-fetch. Simply install it in your console
npm install node-fetch
and then require it where you need to use it
const fetch = require('node-fetch');
Now that we have what we need to make it work lets create the API request.
For that we start with the params variable. Here you set all the things that make the webhook look like you want it to look. Note: I also included how to send embeds just in case. If you want to see all options check here.
var params = {
username: "Your name",
avatar_url: "",
content: "Some message you want to send",
embeds: [
{
"title": "Some title",
"color": 15258703,
"thumbnail": {
"url": "",
},
"fields": [
{
"name": "Your fields here",
"value": "Whatever you wish to send",
"inline": true
}
]
}
]
}
Now that we have the params we can create the actual POST request. For that you simply call the fetch function and provide the webhook url.
First you specify the method you want to use. By default the method is GET. Next make sure to set the headers to 'Content-type': 'application/json', otherwise you'll get an error. Lastly include the params from earlier in the body. We use JSON.stringify() here to make it work.
fetch('URL', {
method: "POST",
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify(params)
}).then(res => {
console.log(res);
})
At the end you have the option to catch any errors you might receive.

PUT API request returning JSON body error

Im trying to update a distribution list by sending a put request, when I run this code and test it in postman by giving it a JSON body I get this error in my node.js terminal stating SyntaxError: Unexpected end of JSON input ... any idea what I should change?
My PUT API request
app.put("/api/Dls/Add/:groupId" , (req, res) => {
const response = {
success: false
};
if (Authorized.myToken) {
response.success = true;
response.data = {};
var options = {
method: 'PUT',
url: 'https://SomeAPI.com/' + req.params.groupId,
headers:
{
Accept: 'application/json',
Authorization: 'Bearer' + ' ' + Authorized.myToken
},
body: JSON.stringify(req.body)
};
request(options, function (error, response, body){
if (error) {
console.log(error);
return;
}
const data = response.body;
const dls = JSON.parse(data)
return res.json(dls);
});
}
});
JSON body I'm passing through postman to test the API call
{
"groupId": "123456789",
"SomeField1": null,
"SomeField2": "xxxxxxxxx",
"SomeField3": true,
"SomeField4": "xxxxxxxxx",
"SomeField5": "xxxxxxxxx",
"SomeField6": [
"xxxxxxxxx"
],
"SomeField7": "xxxxxxxxx",
"SomeField8": "xxxxxxxxx",
"SomeField9": "xxxxxxxxx",
"SomeField10": "xxxxxxxxx",
"SomeField11": [],
"SomeField12": "xxxxxxxxx",
"SomeField13": null,
"SomeField14": false,
"SomeField15": ["xxxxxxxxx"]
}
Any feedback is appreciated!
If the JSON that you posted here is the real one that you pass via postman then, it is not the valid JSON as you have the same name properties. When I say valid it means you get something like this after posting to the endpoint.
{
"groupId": "123456789",
"SomeField": [
"xxxxxxxxx"
]
}
Request npm package is also deprecated so it is better to not use it and replace it with something like Axios. TBH I did not see any error in the code that causes the error that you mentioned, do you have access to the API to check the logs? Maybe something went wrong on the https://SomeAPI.com/ endpoint.
I figured out what the issue was, I needed to add the .end to the return statement
ex. return res.status(200).end()

Redirect URI from this request does not match one from the authorize request even though they're the same

So I am using ORY/Hydra to host an OAuth 2.0 Server and am in the process of building a sample client to demonstrate the flow. I call the /oauth2/auth endpoint with the redirect_uri in the query params, and I use simple-oauth2 to later call /oauth2/token to fetch the access tokens.
I can create a client through my API into the Hydra server and the response is a valid JSON with the one of the callback URL's being `http://localhost:3000/callback'
{
"id": "cbf09258-7f8e-4147-93c1-aa7e2e7b99b3",
"name": "Test App 1",
"clientId": "515e7876-881e-4f3a-b489-20ed7300c745",
"clientSecret": "deleted",
"clientSecretExpiresAt": 0,
"token":
"$2a$08$bWZMUf5wgEpOcoUjsJ5l/uS5LaTmqrC40FTnfegzelE69H8JAFrMW",
"callbackUrl": [
"127.0.0.1:3000",
"localhost:3000/callback",
"http://localhost:3000/callback"
],
"url": "",
"imageBanner": "",
"imageIcon": "",
"createdAt": "2019-02-04T19:14:22.193152Z",
"updatedAt": "2019-02-04T19:14:22.193152Z"
}
The flow starts at localhost:3000/callback as well and my jade file renders a link to call /oauth2/auth as follows
block content
h1 Whew
a(href="http://localhost:4444/oauth2/auth?client_id=" + clientid + "&scope=openid offline&response_type=code&redirect_uri=http://localhost:3000/callback&state=haardik123") Authorize
Finally, the handler includes code to call /oauth2/token if a code param is present in the query as follows: (callback.js)
const oauth2 = simpleOauthModule.create({
client: {
id: process.env.CLIENT_ID,
secret: process.env.CLIENT_SECRET,
},
auth: {
tokenHost: 'http://localhost:4444',
tokenPath: '/oauth2/token',
authorizePath: '/oauth2/auth',
},
});
// Authorization uri definition
const authorizationUri = oauth2.authorizationCode.authorizeURL({
redirect_uri: 'http://localhost:3000/callback',
scope: 'openid offline',
state: 'haardik123',
});
router.get('/', async function (req, res, next) {
var query = url.parse(req.url, true).query;
var clientid = process.env.CLIENT_ID;
var code = query.code;
const options = {
code,
};
if (code) {
try {
const result = await oauth2.authorizationCode.getToken(options);
console.log('The resulting token: ', result);
const token = oauth2.accessToken.create(result);
return res.status(200).json(token)
} catch(error) {
console.error('Access Token Error', error.message);
return res.status(500).json('Authentication failed');
}
}
res.render('callback', {
clientid: clientid
});
});
The flow goes normally until I get redirected back to localhost:3000/callback with a code in the query params but then it says Status 400: Bad request - Authentication Failed
Hydra logs show that
time="2019-02-04T19:16:05Z" level=info msg="started handling request" method=POST remote="172.29.0.1:35130" request=/oauth2/token
time="2019-02-04T19:16:05Z" level=error msg="An error occurred" description="The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed" error=invalid_request hint="The \"redirect_uri\" from this request does not match the one from the authorize request."
time="2019-02-04T19:16:05Z" level=info msg="completed handling request" measure#http://localhost:4444.latency=60183900 method=POST remote="172.29.0.1:35130" request=/oauth2/token status=400 text_status="Bad Request" took=60.1839ms
I'm not sure why the redirect_uri won't match as it seems like I did everything fine -- would love any insight on this, thanks!
This was solved by adding a redirect_uri to the options object being passed to oauth2.authorizationCode.getToken(options)
Changing the object to
const options = {
code,
redirect_uri: "http://localhost:3000/callback",
};
worked!

How do I properly send parameters and headers for swagger client get?

Currently checking out https://www.npmjs.com/package/swagger-client. The docs are a bit confusing to me.
I intend to hit a URL like www.mysite.com/topic/:topicName
I tried a few things like this:
const authHeaders = {
'X-Api-Key': 'mykey',
Authorization: `Bearer mytoken`,
};
const topic = await client.apis.Topic.getTopic({
headers: authHeaders,
parameters: {
topicName: 'myName'
}
});
I can't seem to figure the right way to send headers and fill in the variable from the swagger docs to form the URL. I'd seen examples where the headers are the first argument so I also had tried
const topic = await client.apis.Topic.getTopic(authHeaders, {
parameters: {
topicName: 'myName'
}
});
When I look at the docs for the word headers, they just talk about setting up the initial client. I figure making it send the auth headers every time is another good solution so I'm kind of looking for both ways (since either can make sense depending on the header).
Using the swagger-client is a little different that a regular http client because it follow exactly your swagger file, you will have to provide the parameters that your swagger spec describes.
for swagger client v3, this format works for me:
Swagger({
url: "www.example.org/swagger.json",
authorization: {
// This must be described in your swagger file, if not, will be ignored.
// See https://swagger.io/docs/specification/authentication/bearer-authentication/
bearerAuth: {type: 'apiKey', 'in': 'header', name: 'Authorization'}
}
}).then(client => {
client.apis.Topic.getTopic({
// The parameters need to be described in the swagger file, or will be ignored.
// Also make sure that the getTopic operation describes that uses the bearerAuth
// Or swagger-client will not send the Auth credentials.
topicName: "myName"
}).then(response => {
// Do magic.
})
});
The swagger portion for your getTopic operation should be similar to this:
{
"/rest/3/topic/{topicName}": {
"tags": ["topic"]
"operationId": "getTopic"
"get": {
"parameters": [
{
"name": "topicName", "in": "path", "required": true, "type": "string"
}
],
"security": { "basicAuth": "global" }
}
}
}

Resources