I have been recently exploring the CloudKit and related frameworks. I got the communication with my app working, as well as with my website using CloudKitJS. Where I am struggling is the Server-to-Server communication (which I would need for exporting data from public database in csv.
I have tried Python package requests-cloudkit, which others were suggesting. I have created a Server-to-Server token, and have copied only the key between START and END line once creating the eckey.pem file. I then got this code:
from requests_cloudkit import CloudKitAuth
from restmapper import restmapper
import json
KEY_ID = '[my key ID from CK Dashboard]'
SECRET_FILE_KEY = 'eckey.pem'
AUTH = CloudKitAuth(KEY_ID, SECRET_FILE_KEY)
PARAMS = {
'query':{
'recordType': '[my record type]'
},
}
CloudKit = restmapper.RestMapper("https://api.apple-cloudkit.com/database/1/[my container]/development/")
cloudkit = CloudKit(auth=AUTH)
response = cloudkit.POST.public.records.query(json.dumps(PARAMS))
I am then getting the 401 Authentication failed response. I am stuck on this for days, so I would be grateful for any help or advice. 😊
Creating the server-to-server key is an important first step, but in order to make HTTP requests after that, you have to sign each request.
Look for the Authenticate Web Service Requests section near the bottom of this documentation page.
It's a little bit convoluted, but you have to carefully construct signed headers to include with each request you make. I'm not familiar with how to do it in Python, but here's how I do it in NodeJS which may help:
//Get the timestamp in a very specific format
let date = moment().utc().format('YYYY-MM-DD[T]HH:mm:ss[Z]')
//Construct the subpath
let endpoint = '/records/lookup'
let path = '/database/1/iCloud.*****/development/public'
let subpath = path+endpoint
//Get the key file
let privateKeyFile = fs.readFileSync('../../'+SECRET_FILE_KEY, 'utf8')
//Make a string out of your JSON query
let query = {
recordType: '[my record type]'
}
let requestBody = JSON.stringify(query)
//Hash the query
let bodyHash = crypto.createHash('sha256').update(requestBody, 'utf8').digest('base64')
//Assemble the components you just generated in a special format
//[Current date]:[Request body]:[Web service URL subpath]
let message = date+':'+bodyHash+':'+subpath
//Sign it
let signature = crypto.createSign('RSA-SHA256').update(message).sign(privateKeyFile, 'base64')
//Assemble your headers and include them in your HTTP request
let headers = {
'X-Apple-CloudKit-Request-KeyID': KEY_ID,
'X-Apple-CloudKit-Request-ISO8601Date': date,
'X-Apple-CloudKit-Request-SignatureV1': signature
}
This is a bit hairy at first, but I just put all this stuff in a function that I reuse whenever I need to make a request.
Apple's documentation has pretty much been abandoned and it's hard to find good help with CloudKit Web Services these days.
Related
im working in a personal project that needs new email in the start, and i want create a new email with python also i don't want run a complicate smtp server(I don't know much about that yet) i want do something like temp mail with api, i'd tried temp mail api but i got error i do something like this
import requests
url = "privatix-temp-mail-v1.p.rapidapi.com/request/mail/id/md5 of my temp mail"
req = request.get(url)
print(req)
but i got 401 status code that says your api key is invalid
then i go to rapidapi website and see examples there was a header for req so i put that to my code that was like:
import requests
url = "https://privatix-temp-mail-v1.p.rapidapi.com/request/mail/id/md5"
headers = {
'x-rapidapi-host': "privatix-temp-mail-v1.p.rapidapi.com",
'x-rapidapi-key': "that was a key"
}
req = request.get(url, headers=headers)
then i got this
{"message":"You are not subscribed to this API."}
now i get confused and i don't know what is problem if you know temp mail api or something liks this service or any suggest pls help me
In order to use any API from RapidAPI Hub, you need to subscribe to that particular API. It's pretty simple.
Go to the Pricing Page of this API and choose a plan according to your need. Click on the subscribe button and you will be good to go. However, the Basic plan is free but a soft limit is associated with it so it may ask for your card details.
The are any solutions to the problem but m not able to find the root cause and also to mention no of the solution is working in my case.
What I am trying to do is to upload a file to Django rest API from a angular Http Client Service.
I am taking up the input form the user passing to the service at the end I have declared a type specific for the type of model I am creating an object for but I am not getting the same error again and again.
I read some where that Django file uploader doesn't understand some char-set format but I still can't understand whats wrong with it.
var report = <CompleteReport> {
title:'heelo',
description:'sdfsdfs',
author: 'report',
article_upload_images: [uuid4(),],
presentation_upload_images: [uuid4(),],
report_article: article_object,
report_image: image_object,
report_podcast: podcast_object,
report_presentation: presentation_object,
report_video: video_object
};
let headers = new HttpHeaders({
'Accept': 'application/json'
});
let options = {headers: headers};
return this.http.post<any>(url, report, options)
I am very newbie with the Google DialogFlow, As I am exploring with the Api.ai. I got to know about the userEntity(V1) or SessionEntity(V2).
I have created the session entity using fulfilment with the below code:
import requests
REQUIRED_SCOPES = 'https://www.googleapis.com/auth/dialogflow'
access_token = generate_access_token()
url = 'https://dialogflow.googleapis.com/v2/'+ session_id +'/entityTypes'
headers = {'Authorization': 'Bearer '+ access_token,'Content-Type': 'application/json'}
entity_data = json.dumps({"entityOverrideMode": "ENTITY_OVERRIDE_MODE_OVERRIDE", "entities": [{"synonyms":["sugarcane", "sugar"],"value": "sweet"}], "value": str(session_id)+'fruit'})
response = requests.post(url,headers=headers,data=entity_data)
It creates the sessionEntity with success and also able to list the entity from the session.
It's working while I tried from the same page of console with TryMe-Intents.
But while I tried using simulator or mobile to pass some phrases for my Intent I am not getting the newly created entity to map with the matching phrases.
For Example, I want Sugarcane, at this point, I suppose to get sugarcane as mapped with the entity with the current session for followup intents.
But it was not happening, don't know if I am missing anything. Let me know if anything is wrong or missing.
Suggestions are always welcome.
Reference Links which I have referred to achieve:
https://cloud.google.com/dialogflow-enterprise/docs/reference/rest/v2/projects.agent.sessions.entityTypes/create
https://cloud.google.com/dialogflow-enterprise/docs/entities-session
I'm working on a Rails 4 / mongoid application which needs to expose APIs for other applications and scripts. I need to be able to update documents in one of the models through an API with Python 3 script. I'm a bit fresh with Python hence asking for help here.
I already found out how to query Rails APIs with Python 3 and urllib but struggling with updates. I was trying to go through Python 3.5 docs for urllib2 but struggling to apply this to my script.
What goes to data and how to add authentication token to headers, which in curl would look something like this
-H 'Authorization:Token token="xxxxxxxxxxxxxxxx"'
-X POST -d "name=A60E001&status=changed"
I would greatly appreciate if somebody explained how to, for example, update status based on name (name is not unique yet but will be). My biggest challenge is the Python side. Once I have the data in params on Rails side I think I can handle it. I think.
I included my model and update action from the controller below.
app/models/experiment.rb
class Experiment
include Mongoid::Document
include Mongoid::Timestamps
field :name, type: String
field :status, type:String
end
app/controllers/api/v1/experiments_controller.rb
module Api
module V1
class ExperimentsController < ActionController::Base
before_filter :restrict_access
...
def update
respond_to do |format|
if #expt_proc.update(expt_proc_params)
format.json { render :show, status: :ok, location: #expt_proc }
else
format.json { render json: #expt_proc.errors, status: :unprocessable_entity }
end
end
end
...
private
def restrict_access
authenticate_or_request_with_http_token do |token, options|
ApiKey.where(access_token: token).exists?
end
end
...
I figured out who to send a PATCH request with Python 3 and update the the record's status by name.
Thanks to this post found out about requests module. I used requests.patch to update the record and it works great.
python code
import requests
import json
url = 'http://0.0.0.0:3000/api/v1/update_expt_queue.json'
payload = {'expt_name' : 'myExperiment1', 'status' : 'finished' }
r = requests.patch(url, payload)
There are two problems remaining:
How to add headers to this request which would allow me to go through token based authentication. At the moment it's disabled. request.patch only takes 2 parameters, it doesn't take headers parameter.
How to access the JSON which is sent in response by Rails API.
I'm writing an application that utilizes Paypal's permissions API. I'm currently working on the sandbox. I get the verification code correctly but when I try to GetAccessToken, I get the error:
{"responseEnvelope":{"timestamp":"2013-09-03T08:32:16.580-07:00","ack":"Failure","correlationId":"3527b7033f20f","build":"2210301"},"error":[{"errorId":"560022","domain":"PLATFORM","subdomain":"Application","severity":"Error","category":"Application","message":"The X-PAYPAL-APPLICATION-ID header contains an invalid value","parameter":["X-PAYPAL-APPLICATION-ID"]}]}
I'm using the sandbox APP_ID and all the Verification code is also gotten dynamically. Here is my code fragment.
token = "AAAAAAAYaraTSVjvkUBT"
verification = "mgnnWDVfFmgAES0q371Hug"
headers2 = {
"X-PAYPAL-SECURITY-USERID": settings.USERNAME,
"X-PAYPAL-SECURITY-PASSWORD": settings.PASSWORD,
"X-PAYPAL-SECURITY-SIGNATURE": settings.SIGNATURE,
"X-PAYPAL-REQUEST-DATA-FORMAT": "JSON",
"X-PAYPAL-RESPONSE-DATA-FORMAT": "JSON",
"X-PAYPAL-APPLICATION-ID": "APP-80W284485P519543T",
}
url = "https://svcs.paypal.com/Permissions/GetAccessToken/?token=%s&verifier=%s" %(token, verification)
dat2 = {"requestEnvelope": {"errorLanguage":"en_US"}}
req2 = urllib2.Request(url, simplejson.dumps(dat2), headers2)
res2 = urllib2.urlopen(req2).read()
What I'm I doing wrong??
You cannot use the sandbox application id on the live environment. See https://developer.paypal.com/webapps/developer/docs/classic/lifecycle/goingLive/#register to learn how to obtain a live application id.
The endpoint should be https://svcs.sandbox.paypal.com as Siddick said above. The paypal API documentation is so inconsistent, the endpoint i had used previously had been used in a sandbox situation in the documentation.