Node.js + request json format - node.js

I'm working with the spotify web api to build a Node.js app. One of the functions provided by the api allows you to play a specific track/album/playlist through the spotify player, here's the Start/Resume a User's Playback documentation.
However, when I send the put request, the song I chose doesn't start, it only continues playing the current song. I was hoping that it was my bad formatting of the json string to send, and not spotify's api not working?
Here's my code:
request({
method: 'PUT',
uri: 'https://api.spotify.com/v1/me/player/play',
headers:{
Authorization: 'Bearer ' + access_token
},
data:{
"context_uri": "spotify:user:spotify:playlist:37i9dQZF1DX0s5kDXi1oC5",
"offset": {
"position": 0
}
},
json: true
}, function (error, response, body) {
err = error;
});
I don't get any errors, as the api is doing it's job, I guess it just doesn't get the "context_uri" that I'm trying to give to it. I've also tried multiple different links for the context_uri that are valid.
So if you've looked at the documentation, I guess my question is should the context_uri be inside the "data" array, is that why it's not being seen?
Really appreciate the help, been trying to figure this out for days.

To confirm:
'context_uri': 'spotify:user:spotify:playlist:37i9dQZF1DX0s5kDXi1oC5',
'offset': {
'position': 0
}
works as expected for me. It begins playing Justin Timberlake - My Love.
So the problem is elsewhere. Things to consider:
The 'active' device hasn't recently been active / playing?
You're not catching an exception somewhere else?

Related

AWS Api Gateway response mapping regex not working

I'm trying to do a mapping from AWS lambda function response using regex.
This is my regex:
.*statusCode”:406.*
As you can see - I am trying for it to take a specific mapping from the following response:
{
"statusCode": 406,
"body": "{\"aerocrs\":{\"success\":false,\"error_type\":\"request\",\"details\":{\"detail\":\"Incorrect reqyest \",\"errorCode\":4}}}",
"headers": {
"x-powered-by": "Express",
"content-type": "application/json; charset=utf-8",
"content-length": "116",
"etag": "W/\"74-Zzo6HU1M1kKkLM9KGtX0jJdePQY\"",
"date": "Thu, 28 Nov 2019 16:03:05 GMT",
"connection": "close"
},
"isBase64Encoded": false
}
However, I always get to the default mapping.
When I change the mapping to .*.*, it gets to the correct one, which makes sense, but for some reason this regex isn't working.
Do you have any idea?
Thanks!
I managed to find the issue!
Thanks to this great person.
Long story short. AWS Api Gateway is SUPER picky and annoying regarding the error regex. This means, that is looking for a specific structure. Something of this sort:
{
"errorType": "string",
"errorMessage": "{\"body\":{\"success\":false,\"error_type\":\"request\",\"details\":{\"errorCode\":4}}}",
"trace": []
}
So the .*.* does work because it is valid for everything, but even a single letter, like .*s.* is causing an issue.
What you need to fix is in your lambda function.
In my case - I was using nodeJS function, and aws-serverless-express.
The aws-serverless-express is super easy as it works perfectly with express. However, I was using:
awsServerlessExpress.proxy(server, event, context);
Which was enough to return the response ok, but not enough to work with the API gateway's annoying regex.
Instead, I changed it to this:
awsServerlessExpress.proxy(server, event, context, 'CALLBACK', function(param1, response){
if (response.statusCode == 200) {
//Success
context.done(response.body);
}
else {
//Fail
context.fail(response.body);
}
});
And it worked like a charm. Now I took the response body and return it as success / fail. Then it will work with the format that the lambda function knows how to use.
I hope this will help other people not waste 6 hours on this!
looks like the output has a space before 406. what happens if you add that space to your regex?
--Edited to add: I use this site all the time (with redacted stuff, naturally) - https://regex101.com/

postman POST request doesn't work in nodejs (accessing 3rd party API)

I've been playing around with some web scraping but I've run into an issue I can't figure out; Using a nodejs server (on my local computer) I cannot get passed a permission error barring me from accessing the data. What is confusing to me most is that using the chrome extension "Postman" I don't run into the permission errors, but using the code generated by postman, I do (as well as fiddling with variations of my own scratch code).
Do I have to be using a live server? Do I need to include some extra items in the headers that aren't being put there by Postman? Is there some layer of security around the API that for some reason Postman has access do that a local machine doesnt?
Any light that can be shed would be of use. Note that there is no public documentation of the SmithsFoodAndDrug API (that I can find), so there aren't necessarily APIKeys that are going to be used. But the fact that Postman can access the information makes me think I should be able to on a node server without any special authentication set up.
In Summary:
I'm looking at SmithsFoodAndDrug product information, and found the API where they are grabbing information from.
I figured out the headers needed in order to get local price information on products (on top of the json body format for the POST request)
Using postman I can generate the POST request and retrieve the desired API results
Using nodejs (and the code generated by postman to replicate the request) with both 'request' module and standard 'http' module request module I receive permission errors from the server.
Details: (assume gathering data on honeycrisp apples (0000000003283) with division-id of 706 and store-id of 00144)
http://www.smithsfoodanddrug.com/products/api/products/details
Headers are 'division-id' and 'store-id'. Body is in format of {"upcs":["XXX"],"filterBadProducts":false} where XXX is the specific product code.
Here are the Request Headers in postman. Here are the Request Body settings in postman. The following is a portion of the json response (which is what I want).
{"products": [
{
"brandName": null,
"clickListItem": true,
"countryOfOrigin": "Check store for country of origin details",
"customerFacingSize": "price $2.49/lb",
...
"calculatedPromoPrice": "2.49",
"calculatedRegularPrice": "2.99",
"calculatedReferencePrice": null,
"displayTemplate": "YellowTag",
"division": "706",
"minimumAdvertisedPrice": null,
"orderBy": "Unit",
"regularNFor": "1",
"referenceNFor": "1",
"referencePrice": null,
"store": "00144",
"endDate": "2018-09-19T00:00:00",
"priceNormal": "2.55",
"priceSale": "2.12",
"promoDescription": "About $2.12 for each",
"promoType": null,
...
"upc": "0000000003283",
...
}
],
"coupons": {},
"departments": [],
"priceHasError": false,
"totalCount": 1 }
When using the code given by postman to replicate the request, I get the error saying 'You don't have permission to access "http://www.smithsfoodanddrug.com/products/api/products/details" on this server.
Reference #18.1f3de93f.1536955806.1989a2b1.' .
// Code given by postman
var request = require("request");
var options = { method: 'POST',
url: 'http://www.smithsfoodanddrug.com/products/api/products/details',
headers:
{ 'postman-token': 'ad9638c1-1ea5-1afc-925e-fe753b342f91',
'cache-control': 'no-cache',
'store-id': '00144',
'division-id': '706',
'content-type': 'application/json' },
body: { upcs: [ '0000000003283' ], filterBadProducts: false },
json: true };
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
change headers
headers:
{
'store-id': '00144',
'division-id': '706'
//'content-type': 'application/json'
}

Getting JSON Data into image format

I have this GET request I built to call Google APIS dot com to get an image of a house at a given address. It's all working fine. In Postman it displays the image from the body of the request. All good!
I converted the code to NodeJS REQUEST. Put that code into my project. It all works though the data returned is all �����JFIF������ like this in the BODY returned.
Can you point me to some resources or can you tell me in NODEJS how I get that into a Image type variable. I want to then display it using JSON code into Messenger Bot. I have the JSON code to send a IMAGE type back to Messenger - I just need to get the results of the GET above into a format in NODEJS that will work - like a PNG or JPG format.
This is the code I used from Postman CODE:
var options = { method: 'GET',
url: 'https://maps.googleapis.com/maps/api/streetview',
qs:
{ size: '450x450',
location: 'N108W15303%20Bel%20Aire%20Ln%2053022',
fov: '90',
heading: '235',
pitch: '10',
key: 'xxx' },
headers:
{ 'Postman-Token': 'xxx',
'Cache-Control': 'no-cache',
Accept: 'application/json' } };
requestGoogle(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The BODY var is is all ����JFIF��C
It displays great in the Postman App. so you are somehow converting it to display it - what I am looking for.
Any help would be appreciated - or direct me to a resource that can help that would be great.

Stripe module issues at Parse

I am developing a project which integrates Stripe + Parse for iOS. It uses web hooks and Cloud code via node js. Currently i am in need of implementing a couple of functions:
cancel user subscription with flag atPeriodEnd;
subscribe cancelled customer once again (named multiple subscriptions via Stripe docs).
As for the first one: I'm sending a request as follows in Parse's API -
Stripe.Customers.cancelSubscription(request.params.customerID, 1, null)
but the second parameter, i.e. atPeriodEnd remains 0 when i receive Stripe's response and my webhook catches request for cancelling user immediately. Also i have checked Stripe's dashboard to see parameters that i pass and it says 'No query parameters'. Hope you can help me with this one out.
Second one: as i mentioned earlier user needs to have ability to subscribe once again after cancellation. That means that i already have a valid customer saved at Stripe and all i need is to 'attach' to him a new subscription. There is a method for this at Stripe docs:
stripe.customers.createSubscription("cus_00000000000", { plan: "planName" }, function(err, subscription) {
});
But i can't find similar to this in Parse's API. Hope you can help with this one out.
Sorry if there are some mistakes or misunderstandings for you - feel free to ask, i will answer as much clear as i can. Thanks!
Here is a workaround to #1 - make an http call directly to the stripe endpoint using Parse.Cloud.httpRequest. (I agree that Stripe.Customers.cancelSubscription in the Parse cloud module does not seem to be working)
Parse.Cloud.define("cancel", function(request, response) {
var user = request.user;
var customerStripeId = user.get("stripeId");
var key = "<stripe_api_key>"
var url = "https://api.stripe.com/v1/customers/" + customerStripeId + "/subscription"
Parse.Cloud.httpRequest({
method: 'DELETE',
params: { at_period_end: true, key: key },
url: url,
success: function() {
response.success()
},
error: function(httpResponse) {
console.error('Delete failed with response code ' + httpResponse.status);
response.failure()
}
});
});

Google+ insert moment with nodejs client

Has anyone been able to get the google-api-nodejs-client to successfully insert a moment?
Whatever I try, I get a generic 400 "Invalid value" error but am unable to narrow down the invalid value because the API Explorer doesn't work either.
Would it be because of the missing data-requestvisibleactions parameter? I'm using passport.js's require('passport-google-oauth').OAuth2Strategy for handling oauth access, and that part is working fine, but I have no idea how to incorporate requestvisibleactions into the oauth request flow since this is definitely not originating from a clientside form.
Here's a snippet of what I'm trying to do (using the latest version of googleapis, v1.0.2):
var google = require('googleapis')
var auth = new google.auth.OAuth2()
auth.setCredentials({
'access_token': user.token
})
google.plus('v1').moments.insert({
collection: 'vault',
userId: 'me',
debug: true,
resource: {
type: "http://schemas.google.com/AddActivity",
target: {
type: "http://schema.org/CreativeWork",
url: "...omitted...",
image: "...omitted...",
description: "test",
name: "test"
}
},
auth: auth
}, function (err, response) {
if (err) {
console.error(err)
res.send(err.code, err)
} else {
console.log(response)
res.send(200)
}
})
ref 1 (out-of-date w.r.t. an older version of googleapis)
ref 2 (client-side, where the use of data-requestvisibleactions is more obvious)
As you speculated, you need the request_visible_actions parameter as part of the URL calling the oauth endpoint.
It looks like the current version of passport-google-oauth doesn't support this parameter. Judging by several of the open issues and pull requests, it isn't clear that the author will respond to requests to add it either. You have two possible options:
Switch to using the OAuth support that is included in google-api-nodejs-client
Patch the passport-google-oauth code. (And possibly submit a pull request in the hopes it will be useful to someone else.)
I don't use passport.js or the passport module in question, so I can't test this, but based on the github repository, I think you can insert the following in lib/passport-google-oauth/oauth2.js after line 136 and before the return statement:
if (options.requestVisibleActions) {
// Space separated list of allowed app actions
// as documented at:
// https://developers.google.com/+/web/app-activities/#writing_an_app_activity_using_the_google_apis_client_libraries
// https://developers.google.com/+/api/moment-types/
params['request_visible_actions'] = options.requestVisibleActions;
}

Resources