Weird behavior with Restlet and GAE - google-app-engine

I have the following piece of code with Restlet in Google AppEngine from an Android client.
ClientResource clientResource = new ClientResource(RESTLET_TEST_URL);
ProductResource productResource = clientResource.wrap(ProductResource.class);
productResource.store(mProduct);
Status status = clientResource.getResponse().getStatus();
Toast.makeText(this, "Status: "+ status.getDescription(), Toast.LENGTH_SHORT).show();
clientResource.release();
The .store() method is analogous to a PUT request. The weird thing is, this works fine when I connect to the development server but on the actual AppEngine site, nothing happens. I just get Status: OK indicating that the request went through.
I can't troubleshoot cause I can only do that in the Dev Server and that is working fine.
Any ideas on what the problem may be or how to approach this ?
For reference, the code at the server end is :
if (product != null ) {
if (new DataStore().putToDataStore(product) ) {
log.warning("Product written to datastore");
} else {
log.warning("Product not found in datastore");
}
}
This is just a simple write to the datastore using Objectify.

Turns out this is a known issue. See here
The solution is to use clientResource.setEntityBuffering(true);. However, please note that this method is only available in the Release Candidate for Android Client and not in the stable release.

Related

SAD PANDA: TypeError: failed to fetch

​ === SAD PANDA ===
TypeError: Failed to fetch
=== SAD PANDA ===
While executing a flow cadence transaction in react.js, I got the above error.
My intention is when I click the minttoken button, this transaction has to execute so as to mint the NFT.
const mintToken = async() => {
console.log(form.name)
const encoded = await fcl.send([
fcl.proposer(fcl.currentUser().authorization),
fcl.payer(fcl.authz),
fcl.authorizations([fcl.authz]),
fcl.limit(50),
fcl.args([
fcl.arg(form.name,t.String),
fcl.arg(form.velocity,t.String),
fcl.arg(form.angle,t.String),
fcl.arg(form.rating,t.String),
fcl.arg(form.uri,t.String)
]),
fcl.transaction`
import commitContract from 0xf8d6e0586b0a20c7
transaction {
let receiverRef: &{commitContract.NFTReceiver}
let minterRef: &commitContract.NFTMinter
prepare(acct: AuthAccount) {
self.receiverRef = acct.getCapability<&{commitContract.NFTReceiver}>(/public/NFTReceiver)
.borrow()
?? panic("Could not borrow receiver reference")
self.minterRef = acct.borrow<&commitContract.NFTMinter>(from: /storage/NFTMinter)
?? panic("could not borrow minter reference")
}
execute {
let metadata : {String : String} = {
"name": name,
"swing_velocity": velocity,
"swing_angle": angle,
"rating": rating,
"uri": uri
}
let newNFT <- self.minterRef.mintNFT()
self.receiverRef.deposit(token: <-newNFT, metadata: metadata)
log("NFT Minted and deposited to Account 2's Collection")
}
}
`
]);
await fcl.decode(encoded);
}
this error being so useless is my fault, but I can explain what is happening here because it also only happens in a really specific situation.
Sad Panda error is a catch all error that happens when there is a catastrophic failure when fcl tries to resolve the signatures and it fails in a completely unexpected way. At the time of writing this it usually shows up when people are writing their own authorization functions so that was the first thing i looked at in your code example. Since you are using fcl.authz and fcl.currentUser().authorization (both of those are the same by the way) your situation here isnt because of a custom authorization function, which leads me to believe this is either a configuration issue (fcl.authz is having a hard time doing its job correctly) or what fcl is getting back from the wallet doesn't line up with what it is expecting internally (most likely because of an out of date version of fcl).
I have also seen this come up when the version of the sdk that fcl uses doesnt line up with the version of the sdk that is there (because some people have added #onflow/sdk as well as #onflow/fcl) so would also maybe check to make sure you only have fcl in your package.json and not the sdk as well (everything you should need from the sdk should be exposed from fcl directly, meaning you shouldnt need the sdk as a direct dependency of your application)
I would first recommend making sure you are using the latest version of fcl (your code should still all work), then i would make sure you are only using fcl and not inadvertently using an older version of the sdk. If you are still getting the same error after that could you create an issue on the github so we can dedicate some resources to helping sort this out (and make it so you and others dont see this cryptic error in future versions of fcl)

Cheerio not working as expected in a Google Cloud function

I have this piece of code :
const response = await request.get(
`https://www.youtube.com/watch?v=yURRmWtbTbo&sp=EgIQAQ%253D%253D`
);
const $ = cheerio.load(response, {
decodeEntities: false
});
console.log(
$(
".video-list-item.related-list-item.show-video-time.related-list-item-compact-video"
).html()
);
It works great on my local machine but if I execute this code in a cloud function, it returns null. I checked this is the exact same code, packages also have the same version. I'm not sure what's going on here. I also tried with axios...
What's even stranger is that it works well on both machines with a different youtube ID: I_izvAbhExY
EDIT:
Here is a diff check of the response from my local machine (to the left) and from the cloud function machine (to the right) :
https://www.diffchecker.com/dKaN5kBx
I don't see any class with "video-list-item" in the code on the right. Maybe that's the problem?
Some parts of the webpage are missing in the source code on the right. So the selector
$(
".video-list-item.related-list-item.show-video-time.related-list-item-compact-video"
)
will return null or undefined

cn1PostMessage is undefined on Android. PostMessage is not working

I created a webview (BrowserComponent) and added a listener:
BComp.addWebEventListener(BrowserComponent.onMessage, e->{
Display.getInstance().callSerially(()->{
Dialog.show("Message", (String)e.getSource(), "OK", null);
});
});
Then, in the JavaScript of the embedded website, I called cn1PostMessage and postMesage. This works well in the simulator! But when building the application, on Android, it does nothing (cn1PostMessage is undefined and postMessage is not received by the main program).
var msg = "test";
if(window.cn1PostMessage) {
window.cn1PostMessage(msg);
} else {
window.parent.postMessage(msg, '*');
// Tried: window.postMessage(msg, '*');
// Tried: window.top.postMessage(msg, '*');
}
What can I do?
Thanks!
I just tried building the BrowserComponentPostMessageSample, and it seemed to work fine on my Galaxy S8, Android 8.
If you're finding that window.cn1PostMessage is undefined, then either there was a javascript error in page load that prevented that callback from being installed, or your code is running before the CodenameOne initialization code has run.
I have just added support for the "android.webContentsDebuggingEnabled" display property, which will make the app's web views debuggable using Chrome's remote development tools. This will make it easier for your to track down such issues. See usage example:
Display.getInstance().setProperty("android.webContentsDebuggingEnabled", "true");
This will be available in Friday's update (Dec. 6/19).
In the mean time, I recommend starting with the BrowserComponentPostMessageSample and modifying it to suit your needs from there.
Alternatively, if you can post a test case to demonstrate the issue, I can look at it.

Spring + Angular / IE gets 403 on PUT (others don't)

I have a spring webapp with spring security(3.2.3, so no CSRF protection) and angular.
In a controller i have a method like this one to update the users pw:
#RequestMapping("/accountinfo/password", method = arrayOf(RequestMethod.PUT))
#ResponseBody
#Secured("ROLE_USER")
open fun updateOwnPassword(user: User, #RequestBody password: String) {
val editedUser = user
editedUser.password = encoder.encode(password)
userRepository.save(editedUser)
}
The request is done via angular Service:
function changeOwnPassword(newPassword) {
return $http
.put('accountinfo/password', newPassword)
.then(function (response) {
return response.data
});
}
This works fine in every browser i tested with. Except if using IE 11.0.35 in a Citrix environment (Works outside of it,but can't see any specific configuration).
In that case i get 403 on the Request. When i change the method to POST it works fine again. I could do that for every function where i got this problem of course, but that doesn't seem like a clean solution.
As far as my research goes, i think it's something wrong with the way the browser writes the Request, but that's were i can't find out what to do.
EDIT:
I compared the request headers of both IE 11.0.35 inside and outside of Citrix and they seem exactly the same. The only difference is that the working version uses DNT=1 and the non-working version as WOW64 in the User-Agent attributes?
UPDATE:
I found out that it happens with DELETE too
Found the problem: The client sends the Requests through an additional Proxy that doesn't like PUT and DELETE and just cuts the session cookies off of it. We are adressing that problem with putting the tokens in the header in the future.

Dart AppEngine Headers already sent when using Futures

I am using AppEngine and wrote a server application in Dart. Since the gcloud API is using Futures for pretty much everything, I make use of them as well. The problem however, once I start using Futures, a BadStateException is thrown. See the two examples below.
Working server
runAppEngine((HttpRequest request) {
request.response
..writeln('Hello world')
..statusCode = HttpStatus.OK
..close();
}, port: port);
Output:
Hello world
Not working server: Headers already sent
Future _asyncTask(HttpRequest request) {
return new Future(() {
request.response
..writeln('Hello world')
..statusCode = HttpStatus.OK; // causes BadStateException
}).catchError((e) {
request.response.writeln(e.toString());
}).whenComplete(() {
request.response.close();
});
}
runAppEngine((HttpRequest request) {
return _asyncTask(request);
}, port: port);
Output:
Hello world Bad state: HTTP headers were already sent.
I would like to use Futures but for some reasons, I just cannot get rid of the BadStateException. Can someone point me to what I am doing wrong?
Oh well, seems like I found the bug. I was looking for a fix to this problem all day and now that I ask here, I find the problem five minutes later.
Anyhow, I hope this answer helps people with the same problem.
The problem is that with writing to the response, headers are set implicitly. Hence, once you call writeln(String) you cannot set any headers afterwards anymore.
The reason, that there is no error logged in the first server code is, that there is simply no logic to log errors, but it is as wrong as the second one.
Here is the correct way of doing it:
Future _asyncTask(HttpRequest request) {
return new Future(() {
request.response
..statusCode = HttpStatus.OK
..writeln('Hello world');
}).catchError((e) {
request.response.writeln(e.toString());
}).whenComplete(() {
request.response.close();
});
}
runAppEngine((HttpRequest request) {
return _asyncTask(request);
}, port: port);
As you can see, the problem is fixed by sending the headers first.

Resources