no_file_data error when using Slack API upload - coffeescript

I'm getting this error {"ok":false,"error":"no_file_data"} when I try to call the slack API to upload. I already have the specified file in ./log.
robot.respond /upload (.*)/i, (res) ->
app_name = res.match[1]
request = require("request")
fs = require("fs")
channel_name = res.message.room
data = {
channels: channel_name,
filename: "#{app_name}.txt",
file: fs.createReadStream("./log/#{app_name}.txt"),
}
robot.http("https://slack.com/api/files.upload")
.headers(Authorization: 'Bearer slack-token', 'Content-Type': 'application/json')
.post(data) (err, httpRes, body) ->
if err
res.send "#{err}"
return
res.send "#{body}"

This does not work, because the API method files.upload does not support the content type application/json posts.
For your case you need to post as multipart/form-data, with one part containing the file data and one part containing the API parameters including the token.

Related

CORS error: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response

I'm trying to fetch an image resource that's part of a conversation message.
I've tried both FETCH as well as using AXIOS but I'm getting the same error message.
Here's an example of my FETCH request
const token = `${accountSid}:${authToken}`;
const encodedToken = Buffer.from(token).toString('base64');
let response = await fetch('https://mcs.us1.twilio.com/v1/Services/<SERVICE_SID>/Media/<MEDIA_SID>',
{
method:'GET',
headers: {
'Authorization': `Basic ${encodedToken}`,
}
});
let data = await response.json();
console.log(data);
And here's what Axios looked like
let config = {
method: 'get',
crossdomain: true,
url: 'https://mcs.us1.twilio.com/v1/Services/<SERVICE_SID>/Media/<MEDIA_SID>',
headers: {
'Authorization': `Basic ${encodedToken}`,
},
};
try {
const media = await axios(config);
console.dir(media);
} catch(err) {
console.error(err);
}
Both ways are NOT working.
After looking into it more, I found out that Chrome makes a pre-flight request and as part of that requests the allowed headers from the server.
The response that came back was this
as you can see, in the "Response Headers" I don't see the Access-Control-Allow-Headers which should have been set to Authorization
What am I missing here?
I have made sure that my id/password as well as the URL i'm using are fine. In fact, I've ran this request through POSTMAN on my local machine and that returned the results just fine. The issue is ONLY happening when I do it in my code and run it in the browser.
I figured it out.
I don't have to make an http call to get the URL. It can be retrieved by simply
media.getContentTemporaryUrl();

Google Storage REST get with axios

I want to get a list of images in a bucket using REST and axios.
ref: https://cloud.google.com/storage/docs/listing-objects#list-objects-json
The documentation gives this curl request
curl -X GET -H "Authorization: Bearer OAUTH2_TOKEN" \
"https://storage.googleapis.com/storage/v1/b/BUCKET_NAME/o"
reqConfig: this is a token I use in my REST firestore queries to authenticate the user. I'm using that same token for here. I'm guessing it's the problem but not sure how to fix it.
My result is consistently 404 for a bucket path that I know exists, using the URL from their docs. I should be getting a json list of the files in the bucket.
Error: Request failed with status code 404
Where am I going wrong?
export async function getCompanyStorage(context, apikey, companyId) {
const url = `https://storage.googleapis.com/storage/v1/b/uploads/${companyId}/o?key=${apikey}`;
const cookies = nookies.get(context);
const reqConfig = {
headers: new Headers({
Authorization: "Bearer " + cookies.token,
"Content-Type": "application/json",
}),
};
const result = axios
.get(url, { headers: { Authorization: `Bearer ${reqConfig}` } })
.then((res) => {
return res.data;
})
.catch((error) => {
console.error("error using axios", error);
});
}
Edit: a path to a bucket in the firebase console looks like this
gs://projectname.appspot.com/uploads/WhmDZyQdLVk7n0qR7aTg
I suggest reviewing the documentation you linked to. In particular:
OAUTH2_TOKEN is the access token you generated in Step 1.
BUCKET_NAME is the name of the bucket whose objects you want to list. For example, my-bucket.
You can use a prefix=PREFIX query string parameter to limit results to
objects that have the specified prefix.
Your URL does not contain the name of the bucket as required by the URL pattern. Use the unique name of the bucket where you see "BUCKET_NAME". It looks like, given your example, that it would be "projectname.appspot.com". BUCKET_NAME is not the path of the object within that bucket. If you want to list files under the "uploads" prefix, then you would use the prefix query string parameter to specify that, as documented in the last line of the quoted text.
You can use this function to create Get request with axios for Google Cloud Storage
export const UploadVideo = async (form_data, file, signedurl, asset_uuid) => {
let resultState = { state: '', data: {} };
console.log(signedurl)
/*
const xhr = new XMLHttpRequest();
xhr.open("PUT", signedurl);
xhr.setRequestHeader('Content-Type', "application/octet-stream");
xhr.send(file);
*/
let config = {
headers: {
'Content-Type': 'application/octet-stream',
},
};
await axios.get(signedurl, file, config).then(function (response) {
resultState.state = 'success';
}).catch(function (error) {
resultState.state = 'error';
resultState.data.message = error.message;
window.toastr.error(error.message);
console.log(error)
})
return resultState;
}

How to execute an HTTP Get with Params, RequestHeaders and RequestContent

I'm a couple of weeks into my Flutter journey. I have looked at a few tutorials on using a web service and returning data, but am unsure of a couple of things and how to apply to my web services.
I have completed my web app (written in Elevate Web Builder) and also my server side modules acting as my web services. Inside my web app I call the web service using a server request and the following parameters:
Params : Key and value pairs - used to pass authorization info
eg:
Params.Values['userid'] := 'test'
Params.Values['password'] := 'test-Password'
RequestHeaders - used to specify the content type
eg:
RequestHeaders.Values['Content-Type'] := 'text/plain'
RequestContent : Key and value pairs - used to send values to specify what to retrieve or what to save into the database
eg:
RequestContent.Values['webService'] := 'Get_StaffList'
RequestContent.Values['CompanyId'] := '123'
RequestContent.Values['OnlyActive'] := 'Y'
The Params are specified as URL parameters, but I'm not sure where I specify the RequestHeaders and RequestContent?
I have tried sending RequestHeaders and RequestContent as:
http.post('https://...', headers: {'Content-Type': 'text/plain',
'webService': 'Get_StaffList',
'CompanyId': '123',
'OnlyActive': 'Y'
});
but this didn't work. Any ideas how it should be sent in Flutter?
Thanks heaps,
Paul
Here is an example
String server = "http://localhost:8008";
userSearch(String accessToken, String searchTerm) async {
String url = server + "/_matrix/client/r0/user_directory/search";
Map<String, String> headers = {"content-type": "application/json", "authorization": "Bearer $accessToken"};
String body = jsonEncode({"search_term": searchTerm});
Response response = await post(url, headers: headers, body: body);
UserSearchObj users = UserSearchObj.fromJson(jsonDecode(response.body));
return users;
}
I just thought I'd let you know I got it working. I took what you suggested and looked at what the web service was receiving from the web app. Then modified the code in Flutter to send the data in the same format. This now works:
final response = await http.post(
Uri.encodeFull('http://mobileuser.pvapps.one:82/modules/rmo_daMLogin'),
headers: {'Content-Type': 'text/plain'},
body: 'rmoService=User_Login\n'
'UserId=fred\n'
'Password=abc123');
Thanks again for the help,
Paul

How do I add metadata to a file when uploading via a GCS signedUploadURL?

I'm using a signed URL (generated via the GCS PHP API) to upload a file to a bucket. I POST the signed URL, which returns a Location header which, in turn, I do a PUT of to do the actual upload. This basic upload process is working fine. Now, I need to pass some metadata (uploader name, uploader email, notes, etc.) along with the file.
According to the documentation, I add headers to the PUT request, of the form 'x-goog-meta-<name>': 'value', which are supposed to become the metadata. However, if I don't add them to the signed URL and the POST request, I get a spurious CORS error (No 'Access-Control-Allow-Origin' header is present on the requested resource).
The upload succeeds, and I can see in the Network tab of Chrome that these headers are getting added to the POST and PUT requests, but when the file hits the bucket, there is no metadata.
Here's my code, somewhat simplified:
var metadata, headers;
metadata =
{
'sender-name': "bob dobbs",
'sender-email': "bobdobbs#zynyz.com",
};
headers = { 'x-goog-resumable': 'start' };
for (var i in metadata)
{
headers['x-goog-meta-' + i] = metadata[i];
}
// Start the upload
$.ajax(
{
type: POST,
url: signed_upload_url,
success: on_init_success,
contentType: file.type,
headers: headers,
processData: false
});
// Do the actual upload
var on_init_success = function(result, status, xhr)
{
var loc;
loc = xhr.getResponseHeader('Location');
if (loc)
{
$.ajax(
{
type: 'PUT',
url: loc,
data: file,
contentType: file.type,
headers: headers,
processData: false
});
}
}

Error while generating access_token using Ebay 's REST API - Python requests

I'm trying to use the ebay REST-API for the first. I am simply trying to generate an access_token using the client credentials grant-request. I followed the instructions here https://developer.ebay.com/api-docs/static/oauth-client-credentials-grant.html
HTTP method: POST
URL (Sandbox): https://api.sandbox.ebay.com/identity/v1/oauth2/token
HTTP headers:
Content-Type = application/x-www-form-urlencoded
Authorization = Basic <B64-encoded_oauth_credentials>
Request body (wrapped for readability):
grant_type=client_credentials&
redirect_uri=<RuName-value>&
scope=https://api.ebay.com/oauth/api_scope
I'm getting this error: {'error': 'invalid_client', 'error_description': 'client authentication failed'} and my code looks like this:
path = 'https://api.sandbox.ebay.com/'
app_json = 'application/json'
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': base64.b64encode(b'Basic CLIENT_ID:CLIENT_SECRET')
}
payload = 'grant_type=client_credentials&redirect_uri=Searchez&scope=https://api.ebay.com/oauth/api_scope'
def get_oath_token():
url = 'https://api.sandbox.ebay.com/identity/v1/oauth2/token'
r = requests.post(url, headers=headers, data=payload)
print(r.json())
get_oath_token()
What do I have configured incorrectly? Thanks.
You're base64encoding "Basic " and shouldn't be.
The doc says just encode your Client ID + ":" + Client Secret, and leave the word "Basic" and the space that follows it alone.
In your code, i can see sandbox endpoint URI but in the request body scope, you have used production URL, instead of sandbox