I am creating a small application to test how GAE Channel API works. I think I have done all as it's described in the documentation but when I launch it, it shows an error in FireFox error log about syntax in the beginning and then another repeating error that an element wasn't found that.
Here is the first error info:
Source: http://127.0.0.1:8080/_ah/channel/dev?command=connect&channel=channel-773698929-185804764220139124118
Line 1, symbol 1
Here is the url where my javascript code tries to connect repeatedly and it raises the second error:
http://127.0.0.1:8080/_ah/channel/dev?command=poll&channel=channel-2071442473-185804764220139124118&client=1
I get the token through a JSON request with jQuery $.get. Then I run this code to get the token and open the channel. The error begins to show just when I run socket = channel.open(handler):
var response = JSON.parse(data);
var token = response.token.toString();
channel = new goog.appengine.Channel(token);
var handler = {
'onopen': onOpened,
'onmessage': onMessage,
'onerror': function() {
},
'onclose': function() {
}
};
socket = channel.open(handler);
Here is the server side code in Python to open the channel:
class OpenChannel(webapp.RequestHandler):
def get(self):
user = users.get_current_user()
token = channel.create_channel(user.user_id())
serialized = json.dumps({'token': token})
self.response.headers['Content-Type'] = "application/json"
self.response.out.write(serialized)
What's my error and what can I do? Thanks!
It seems that Channel API works on localhost different way than on GAE hosting. I uploaded it to the cloud and it works well now. Though it looks like it working fine on the local computer, it shows permanent JS error repeating in the error log.
You could try removing the handler argument and adding the handlers as methods of the socket object i.e. socket.onopen = function() {}; etc. That worked for me. But you are right. According to this, you should be able to get this working by using the handler argument. Hmm.
Related
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 currently using RASA and developed a working chatbot. One part of my project is to use a speech-to-text recognition, and I wrote a working code in Python that returns the text said by the user.
I want to use that text for RASA’s input, instead of writing like usual.
I saw there was something to do with the inputs channels, but I only saw input that are other webservices and couldn’t figure it out for using just a local script.
Thank you for any advice,
LM
You can try rasa REST API for this purpose. Make sure that you have action_endpoint url in endpoints.yml. Normally it is
url: "http://localhost:5055/webhook"
Then make sure your rasa bot is up and if htere are any custom actions, start that server as well.
After starting your webhook, you can simple call
http://localhost:5005/webhooks/rest/webhook
and in the payload you have to put below payload
messagePayload = {
sender: 'default',
message: 'Your message is here'
}
and finally add httpheader content type as application/json like below
'Content-Type': 'application/json'
Now your bot will work fine.
tldr;
If you are using request in your python for api calls, you can try below code.
import requests
API_ENDPOINT = "http://localhost:5005/webhooks/rest/webhook"
messagePayload = {
sender: 'default',
message: 'Your message is here'
}
r = requests.post(url = API_ENDPOINT, data = messagePayload)
How about just using Rest API that is already present in the library.
For this, you just need to fill the query parameter, which you can do with your script, rather than writing a custom Input Channel.
I am trying to setup push notifications using the django-push-notifications, I have copied most of the code from the example. I have a button that calls the enablePushNotifications() function:
export function enablePushNotifications() {
console.log("enabling push notifications...");
if (!'serviceWorker' in navigator){
console.log("Push notifications not supported");
return;
}
navigator.serviceWorker.ready.then(
(registration)=>{
registration.pushManager.subscribe({
userVisibleOnly: true
}).then(
(sub)=>{
console.log(sub);
let endpointParts = sub.endpoint.split("/");
let registration_id = endpointParts[endpointParts.length - 1];
let data = {
'browser': loadVersionBrowser(navigator.userAgent).name.toUpperCase(),
'p256dh': btoa(String.fromCharCode.apply(null, new Uint8Array(sub.getKey('p256dh')))),
'auth': btoa(String.fromCharCode.apply(null, new Uint8Array(sub.getKey('auth')))),
'registration_id': registration_id,
'endpoint': sub.endpoint,
};
request(
"/api/subscribe",
data
)
}
).catch(
(error)=>console.error(error)
)
}
)
}
When I open the networking tab I don't see anything strange about the passed properties or headers. Specifically the browser value is correct. The implementation for the /api/subscribe URL is as follows:
import push_notifications.models as pushmodels
def registerPush(request):
data = requestFormatting.get_data(
request
)
device = pushmodels.WebPushDevice(
name=request.user.username,
active=True,
user=request.user,
registration_id=data["registration_id"],
p256dh=data["p256dh"],
auth=data["auth"],
browser=data["browser"]
)
device.save()
device.send_message("hello")
Calling this function raises a PushError: Push failed: 401 Unauthorized. I have tested on both chrome and firefox, both give the same error. I specify my FCM_API_KEY in settings, nothing else. I do not currently use VAPID, though I plan to in the future. I have tried various variations of the code, but nothing seems to work. The documentation is unclear on how to actually initialize devices, and I only picked a WebPushDevice objects since it seems to contain similar attributes as the data provided in the example.
This is my first time trying to use web push, so a little help would be much appreciated!
I'm trying to wrap my head around the channel features of Google App Engine since they don't (easily) provide websockets.
My current situation is that I have a long work (file processing) that is being executed asynchronously via a worker.
This worker update the state of the file processing in the database at every lines in order to inform the customer.
From that current perspective, a F5 will indicate the evolution of the processing.
Now I'd like to implement a live update system. Of course I could do an XHR request every 5 seconds but a live connection seems better... introducing Channels since Websockets seems out of the possibilities.
From what I understood, I can channel.send_message to one client only, not to a "room". The issue here, is that the worker that process the file does not have any information which customer is currently connected (could be one, could be ten).
I could loop over all the customer and post to each client_id, suspecting that at least one of them will get the message, but this is awfully useless and too resourceful.
I was hoping there was a better way to achieve this ? Maybe a nice alternative to Google Channels feature without having to reconfigure my whole App Engine system (like for Websockets)?
One solution I can think of, which is not the absolute ideal but would be more suited, is to manage dedicated database tables (could also be implemented in Memcache) with :
A table that contains a list of rooms
A table that contains a list of client_id connected to the room
e.g. :
Rooms (id, name)
Clients (id, room_id, client_id)
Now, instead of posting to channel.send_message(client_id, Message), one would make a wrapper like this :
def send_to_room(room, message):
# Queries are SQLAlchemy like :
room = Rooms.query.filter(Rooms.name === room).first()
if not room:
raise Something
clients = Clients.query.filter(Rooms.room_id === room.id).all()
for client in clients:
channel.send_message(client.client_id, message)
And voilà, you have a Room like implementation in Google App Engine.
The drawback of this solution is to add two tables (or equivalent) in your database.
Does someone has better?
I am assuming that the long running task is being kicked off by the client.
So before you kick off the task make a ajax request from the client to a handler similar to this one. This handler has two things returned to the client. The token param which is used by the javascript api to create a channel, and a cid param which is used to determine which client created the channel.
from google.appengine.api import channel
#ae.route("/channel")
class CreateChannel(webapp2.RequestHandler):
def get(self):
cid = str(uuid.uuid4())
token = channel.create_channel(cid)
data = {
"cid":cid,
"token":token
}
self.response.write(json.dumps(data))
Now use the channel javascript api to create a new channel
https://cloud.google.com/appengine/docs/python/channel/javascript
var onClosed = function(resp){
console.log("channel closed");
};
var onOpened = function(resp){
console.log("channel created");
};
var onmessage = function(resp){
console.log("The client received a message from the backend task");
console.log(resp);
};
var channel_promise = $.ajax({
url: "/channel",
method: "GET"
});
channel_promise.then(function(resp){
//this channel id is important you need to get it to the backend process so it knows which client to send the message to.
var client_id = resp.data.cid;
var channel = new goog.appengine.Channel(resp.data.token);
handler = {
'onopen': $scope.onOpened,
'onmessage': $scope.onMessage,
'onerror': function () {
},
'onclose': function () {
alert("channel closed.")
}
};
socket = channel.open(handler);
//onOpened is the callback function to call after channel has been created
socket.onopen = onOpened;
//onClose is the callback function to call after channel has been closed
socket.onclose = onClosed;
//onmessage is the callback function to call when receiving messages from your task queue
socket.onmessage = onMessage;
});
Now we are all set up to listen for channel messages.
So when the user clicks the button we need to kickoff the backend task.
var letsDoSomeWorkOnClick = function(){
//make sure you pass the client id with every ajax request
$.ajax({
url: "/kickoff",
method: "POST",
params: {"cid":client_id}
});
}
Now the app engine handler to start the backend task queue. I use the deffered library to do this. https://cloud.google.com/appengine/articles/deferred
#ae.route("/kickoff")
KickOffHandler(webapp2.RequestHandler):
def post(self):
cid = self.request.get("cid")
req = {}
req['cid'] = cid
task = MyLongRunningTask()
deferred.defer(task.long_runner_1, req, _queue="my-queue")
example task:
class MyLongRunningTask:
def long_runner_1(self,req):
# do a whole bunch of stuff
channel.send_message(req["cid"], json.dumps({"test":"letting client know task is done"})
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.