http request from Google App Engine - google-app-engine

I'm trying to make http requests from my Google App Engine webapp, and discovered I have to use URLConnection since it's the only whitelisted class. The corresponding Clojure library is clojure.contrib.http.agent, and my code is as follows:
(defroutes example
(GET "/" [] (http/string (http/http-agent "http://www.example.com")))
(route/not-found "Page not found"))
This works fine in my development environment- the browser displays the text for example.com. But when I test it out with Google's development app server:
phrygian:example wei$ dev_appserver.sh war
2010-09-28 14:53:36.120 java[43845:903] [Java CocoaComponent compatibility mode]: Enabled
...
INFO: The server is running at http://localhost:8080/
It just hangs when I load the page. No error, or anything. Any idea what might be going on?

http-agent creates threads so that might be why it does not work.
From the API documentation:
Creates (and immediately returns) an Agent representing an HTTP
request running in a new thread.
You could try http-connection, which is a wrapper around HttpURLConnection, so this should work.
Another alternative is to try clj-http. The API seems to be a bit more high-level, but it uses Apache HttpComponents which might be blacklisted.
I am guessing http.async.client is a definite no-go due to its strong asynchronous approach.

You might want to try appengine.urlfetch/fetch from appengine-clj (http://github.com/r0man/appengine-clj, also in clojars)

Related

AppEngine authentication through Node.js

I'm trying to write a VSCode extension where users could log into Google AppEngine with a google account, and I need to get their SACSID cookie to make appengine requests.
So I'm opening a browser window at
https://accounts.google.com/ServiceLogin?service=ah&passive=true&continue=https://appengine.google.com/_ah/conflogin%3Fcontinue%3Dhttp://localhost:3000/
(generated by google.appengine.api.users.create_login_url)
The user logs in and is redirected to my local webserver at
localhost:3000/_ah/conflogin/?state={state}
Now I try to forward the request to my AppEngine app (since it knows how to decode the state parameter), so I do a request to
https://my-app.appspot.com/_ah/conflogin/?state={state}
basically just replacing localhost with the actual app.
but it doesn't work, presumably because the domain is different. I assume this is on purpose, for security.
Is there any way I can make this work ?
Not ideal, but the only solution I've found is to have an endpoint on my GAE instance that does the redirection. Then I can set that as the continue url, when I'm starting the authentication process
https://accounts.google.com/ServiceLogin?service=ah&passive=true&continue=https://appengine.google.com/_ah/conflogin%3Fcontinue%3Dhttps://my-app.appspot.com/redirect?to=http://localhost:3000
I think you should center the attention on the protocols you are using, since it’s known that the cookie name is based on the http protocol (HTTP : ACSID, HTTPS:SACSID), and that’s the security perspective till this point for me.
Having the error you are facing now would be helpful to understand the problem better. Also, how are you performing the call to the API and the code you are using would be helpful too.

AppEnginePlatformWarning: urllib3 is using URLFetch on Google App Engine sandbox instead of sockets

I'm getting this error on app engine using flask to make a Slack bot. It happens whenever I send a POST request from Slackbot.
Unfortunately, the url provided in the error is a dead link. How do I go about using sockets instead of URLFetch?
/base/data/home/apps/[REDACTED]/lib/requests/packages/urllib3/contrib/appengine.py:115:
AppEnginePlatformWarning: urllib3 is using URLFetch on Google App
Engine sandbox instead of sockets. To use sockets directly instead of
URLFetch see https://urllib3.readthedocs.io/en/latest/contrib.html.
As detailed on Google's Sockets documentation, sockets can be used by setting the GAE_USE_SOCKETS_HTTPLIB environment variable. This feature seems to be available only on paid apps, and impacts billing.
Though the error you posted gets logged as an Error in App Engine, this thread suggests (see reply #8) that the error is actually meant as a warning, which the text "AppEnginePlatformWarning" seems to suggest anyway.
The comment block on the source page for appengine.py is also instructive.
You didn't post any information about your implementation, but on Google App Engine Standard edition, using URLFetch via the AppEngineManager should be just fine, though you will get the error.
You can use the following to silence this:
import warnings
import urllib3.contrib.appengine
warnings.filterwarnings('ignore', r'urllib3 is using URLFetch', urllib3.contrib.appengine.AppEnginePlatformWarning)
For me, turns out the presence of requests_toolbelt dependency in my project was the problem: it somehow forced the requests library to use urllib3, which requires URLFetch to be present, otherwise it raises an AppEnginePlatformError. As suggested in the app engine docs, monkey-patching Requests with requests_toolbelt forces the former to use URLFetch, which is no longer supported by GAE in a Python 3 runtime.
The solution was to remove requests_toolbelt from my requirements.txt file

Strange Behavior of $http/Ajax Calls on Windows Phone 8.1 App

I have been recently stuck into a strange issue, thrown by a Multi platform Hybrid App in Visual Studio App.. My Development Environment details are as follows :
Visual Studio 2013 Release 3
Cordova 4.0
Angularjs 1.4
Ionic 1.4
Nokia Lumia 1320 [Windows 8.1 OS]
I have a web app that will be interacting with the mobile app, deployed on a server machine that can be accessed both by an internal enterprise network, as well as from internet.
Now the problem is, when i am [the mobile device is] connected to the internal network, the $http call fails with a status code of 0. Internal dig down reveals that the actual returned status code is -1.
However, when i switch over to mobile data in the phone, the ajax call goes smooth and finishes successfully. Now, if i switch back to internal network, it again starts working perfectly. !!!!
The http call is quite simple and uses promise API... I also have some request interceptors.
Any explanations for this strange behavior, or more appropriately a solution for the same ??
After Scratching my head for over 2 days, i was finally able to conclude that it was my browser that was the culprit.
As i said, i was using Windows Phone 8.1, which uses Internet Explorer 11 as the default rendered. Also, My Web server was actually behind a Proxy Server [Apache HTTP].
Now, the Real problem was that the ajax call was returning response status code as 0. And the reason for that was that The Ajax Call was being suspended by The Apache HTTP Proxy Server, because of some tunneling issue. Please note that this was specifically happening with IE11 and Apache HTTP Server.
This was happening since I was using POST request on a HTTPS Based Proxy Server.
Now the solution is too non-technical, but that's what saved my life. In order to save your life from this issue, You must
1. Either convert your POST Request to GET Request
2. Or Before making a POST Request to the Server, make a GET Request to the same server.
In my case, i went with the second approach and it saved my life. Posting this as answer so that it saves someone else too.
You can refer to the following links for more details.
IE10/IE11 Abort Post Ajax Request After Clearing Cache with error “Network Error 0x2ef3”
Making XHR Request to HTTPS domains with WinJS

How to work with authentication in local Google App Engine tests written in Go?

I'm building a webapp in Go that requires authentication. I'd like to run local tests using appengine/aetest that validate the authentication behavior. However, I do not see any way to create an aetest.Context with a dummy user. Am I missing something?
I had a similar issue with Python sdk. The gist of the solution is to bypass authentication when tests run locally.
You should have access to the [web] app object at the the test setup time - create a user object and save it into the app (or wherever your get_current_user() method will check).
This will let you unit test all application functions except authentication itself. For the later part you can deploy your latest changes as unpublished google app version, then test authentication and if all works - publish the version.
I've discovered some header values that seem to do the trick. appengine/user/user_dev.go has the following:
X-AppEngine-Internal-User-Email
X-AppEngine-Internal-User-Federated-Identity
X-AppEngine-Internal-User-Federated-Provider
X-AppEngine-Internal-User-Id
X-AppEngine-Internal-User-Is-Admin
If I set those headers on the Context's Request when doing in-process tests, things seem to work as expected. If I set the headers on a request that I create separately, things are less successful, since the 'user.Current()' call consults the Context's Request.
These headers might work in a Python environment as well.

_ah/warmup requests coming with hosts prefixed with app version

I am using the warmup service to carry out precaching/etc. The request gets called with self.request.host being prefixed with a version of the app.
All other handler requests are coming with the expected host name for the app.
So if the app name is myapp - then all requests are called with self.request.host set to myapp.appspot.com, whereas for "_ah/warmup" call it is getting set to nnn.myapp.appspot.com.
My code is expecting the self.request.host to be always 'myapp.appspot.com'. Is this by design or am I missing something.
Thanks.
I think this is by design because the warmup service is for a specific version. All other requests are going straight to your main app URL, which is just "aliased" to whatever version happens to be the default version at the time.
By the way, it is documented that you can access all deployed versions of your app by prefixing the version number to the domain name, so you should be aware that any users could access any version if they know about this, and if you haven't taken countermeasures! So you should definitely support this - it's an official feature of App Engine.

Resources