When I try to HTTP PUT a SoundCloud playlist through the API, with a data structure: {"tracks": [{"id": 12345}, {"id": 45678}]}, the playlist doesn't get updated. The API returns a 200 response with what was in the playlist, completely ignoring the modifications.
What I think might be wrong
The SoundCloud API doesn't accept that format of data
Somehow the authorization is invalid, even though it's returning a 200
The code:
import requests
playlist_url = 'https://api.soundcloud.com/playlists/XXXXX?client_id=XXXXX'
like_url = 'https://api.soundcloud.com/users/XXXXX/favorites?client_id=XXXXX'
likes = requests.get(like_url)
likes_json = likes.json()
# oauth2_token = requests.post('https://api.soundcloud.com/oauth2/token', data=opts).json()
oauth2_token = 'XXXXX'
playlist = {'tracks': []}
for like in likes_json[::-1]:
track_id = like['id']
playlist['tracks'].append({'id': track_id})
resp = requests.put('https://api.soundcloud.com/playlists/XXXXX', json=playlist, params={
'oauth_token': oauth2_token,
'client_id': 'XXXXX',
'client_secret': 'XXXXX'
})
It turns out I was simply sending the wrong data structure. It should have been {'playlist': {'tracks': [{'id': 1234}, {'id': 4567}]}}.
https://stackoverflow.com/a/28847716/2350164
Related
previously same api was working fine but now it shows 502 bad gateway. Here is my api call:
def hit_dataprep_job(receipe_id):
print(receipe_id)
url = "https://api.clouddataprep.com/v4/jobGroups"
body = json.dumps({"wrangledDataset": {"id": receipe_id}})
headers = {"Content-Type": "application/json","Authorization": "Bearer "+str(key)}
response = requests.post(url, data=body, headers=headers)
print(response)
print(response.json())
if response.json()['reason'] == 'JobStarted':
print('started job successfully')
Output:
<Response [502]>
{'code': 13, 'message': 'BAD_GATEWAY', 'details': [{'#type': 'type.googleapis.com/google.rpc.DebugInfo', 'stackEntries': [], 'detail': 'application'}]}
this incident is now resolved. You can subscribe to https://status.trifacta.com/ for the latest update.
Join discussions and collaborations with Dataprep users in our Community, https://community.trifacta.com/s/.
How to configure flask app with flask-jwt-extended for which we need something like below.
AccessToken/Bearer must sent as a Header (and not cookie)
RefreshToken must sent as httpOnlyCookie for /api/refreshtoken path only
How to set two different token one in header and one in cookie? We are able to set either both as cookie or both as a header.
Any help?
Thanks
Raxit
I wanted to do the same while building a React + Flask single page application after days of headache trying to understand authorization and authentication as I am a beginner.
Anyways, I managed to do it this way:
In Flask, config:
app.config['JWT_TOKEN_LOCATION'] = ['headers', 'cookies']
app.config['JWT_REFRESH_COOKIE_PATH'] = '/auth/refresh'
And what I return in my login function:
resp = jsonify({'access_token': access_token})
set_refresh_cookies(resp, refresh_token)
return resp, 200
And in my refresh function:
# Refresh access token
#app.route('/auth/refresh', methods=['POST'])
#jwt_refresh_token_required
def refresh():
user = get_jwt_identity()
resp = {
'access_token': create_access_token(
identity={
'username': user['username'],
'role': user['role']
},
expires_delta=timedelta(seconds=600),
user_claims=user['role']
)
}
return jsonify(resp), 200
And on the front side, I collect the JSON access_token and set it in memory and use withCredentials to send the refresh_token with my API calls.
axios.defaults.withCredentials = true;
axios.defaults.headers.common['Authorization'] = `Bearer ${access_token}`;
more precisely:
.then(({ data: { access_token } }) => {
axiosHttp.defaults.headers.common['Authorization'] = `Bearer ${access_token}`;
return jwt_decode(access_token);
})
then I use the data from my decoded access_token in a React Context Component to authenticate access to pages depending on roles.
logout is simply setting to null my context and calling the api to unset the refresh cookie
#app.route('/auth/logout', methods=['DELETE'])
#jwt_required
def logout():
resp = jsonify({"msg": "Successfully logged out"})
unset_jwt_cookies(resp)
return resp, 200
it's quite simple in the end but it took me quite a while to figure out!
I'm trying to find users but it throws me an authentication error
import requests
from urllib.parse import urlencode
token = 'my-token'
graph_url = 'https://graph.facebook.com/v3.2/search?'
params = {
'q':'francisco',
'type':'user',
'method':'get',
'format':'json',
'access_token':token
}
url = graph_url+urlencode(params)
resp = requests.get(url)
print(resp.json())
error:
{'error': {'message': 'Unsupported operation', 'type': 'OAuthException', 'code': 100, 'fbtrace_id': 'Dao1UbelGkF'}}
It seems that something I'm not doing well or that searches are no longer allowed
https://developers.facebook.com/docs/graph-api/changelog/breaking-changes#search-4-4
Searching for users is not available anymore since 2018. It would not make any sense anyway, you would only be able to get users who authorized your App.
I have successfully implemented upload of an Object using multi-part Post request with Signature, Policy document GCS POST ...etc from the browser using XMLHttpRequest and angular $http .
But when I attach event listener on XMLHttpRequest upload to show a progress bar to the user, the browser sends a Options Method instead of POST. storage.googleapis.com returns 200 ok After that I was expecting a POST to be sent from the browser with the file but that did not happen. Without the upload listener the code works perfectly. Should I move to PUT ? any workaround
factory.uploadFileToUrlXHR = function(file,obj){
var deferred = $q.defer();
var fd = new FormData();
fd.append('key', obj.key);
fd.append('Content-Type',obj.contenttype)
fd.append('GoogleAccessId', obj.googleaccessId);
fd.append('policy', obj.policy);
fd.append('signature', obj.signature);
fd.append('file', file);
var XHR = new XMLHttpRequest();
XHR.addEventListener('load', function(event) {
// alert('Yeah! Data sent and response loaded.');
deferred.resolve(event);
});
XHR.upload.addEventListener("progress",function(evt){
if (evt.lengthComputable) {
$log.info("add upload event-listener" + evt.loaded + "/" + evt.total);
}
}, false);
// Define what happens in case of error
XHR.addEventListener('error', function(event) {
//alert('Oups! Something went wrong.');
deferred.resolve(event);
});
// Set up our request
XHR.open('POST', obj.uri);
// Send our FormData object; HTTP headers are set automatically
XHR.send(fd);
return deferred.promise;
}
I resolved the issue ,
When you use POST from the browser to upload a file to Google Cloud storage append the bucket name to the URL . In the below code obj.uri should be "https://storage.googleapis.com/bucketname
XHR.open('POST', obj.uri); and remove the bucket name from the key. Key should contain the object name.
fd.append('key', obj.key);
if you do not append the bucket name as part of the POST URL, the browser will send the Options request to https://storage.googleapis.com/. GCS will not be able to find the right CORS configuration. CORS configuration is mapped to the bucket Name.
Sample CORS configuration i had applied.
[
{
"origin": ["http://localhost:8282"],
"method": ["OPTIONS","PUT","POST","GET", "HEAD", "DELETE"],
"responseHeader": ["Content-Type"],
"maxAgeSeconds": 3600
}
]
I tried to add review comments by using this "set-review" api:
https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#set-review
I can get a json response from this interface, but nothing is changed.
I can't see any new comments from Gerrit web page.
Here is the example of my client side code:
url = '/changes/16148/revisions/1/review'
data = json.dumps({
'message': 'test',
'labels': {},
'comments': {
'tools/docpreview.py': [{
'line': 20,
'message': 'hehe',
}],
},
'notify': 'NONE'
})
pprint(rest.post(url, data=data))
And the response example(Private info was deleted).
This response looks like result of get-review api described here:
https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#get-review
{u'_number': 16148,
...
u'insertions': 20,
u'kind': u'gerritcodereview#change',
u'created': u'2014-11-05 16:23:08.849000000',
...
u'status': u'NEW',
u'subject': u'Add markdown preview.',
u'updated': u'2014-11-05 22:02:32.978000000'}
I struggled with getting this right for a while, finally, the following piece of code in Python works for me:
from requests.auth import HTTPBasicAuth
from pygerrit2.rest import GerritRestAPI
REST_AUTH = HTTPBasicAuth(MISC['auth_username'], MISC['auth_password'])
REST_CLIENT = GerritRestAPI(url=MISC['base_url'], auth=REST_AUTH)
query = "/changes/" + str(change_id) + "/revisions/" + str(cur_rev) + "/review"
REST_CLIENT.post(query, json={
"message": MISC['message'],
"reviewers": [{
"reviewer": MISC['reviewer_bot']
}]
})
# MISC is a dictionary
You should be authenticated, shouldn't you? Therefore your requests would have to go to /a/changes/