GAE go only serves paths on localhost not domain - google-app-engine

I am messing around with a small go app for google app engine locally using the appengine sdk.
I have a problem where a path different than root can only be served if I try to hit it using localhost, but not a domain name.
My setup is as follows.
home.mydomain.com points to my home ip adress
My home router forwards incoming tcp and udp on port 80 to my laptop on port 8080
My laptop is running Windows 10
My go version is go1.6 windows/amd64
My app.yaml:
application: tasks
version: 1
runtime: go
api_version: go1
handlers:
- url: /.*
script: _go_app
Minimum example code:
func init() {
fileHandler := http.FileServer(http.Dir("../frontend"))
http.HandleFunc("/loggedout", testHandler)
http.Handle("/", fileHandler)
log.Print(http.ListenAndServe(":8080", nil))
}
func testHandler(res http.ResponseWriter, req *http.Request){
panic("JUST NEED THIS TO WORK")
}
My symptoms is that if I access localhost:8080/ I get my website, and if I access localhost:8080/loggedout I get the expected panic.
If I access home.mydomain.com/ I get my website, however if I access home.mydomain.com/loggedout the connection just hangs, in chromes network tab it is listed as pending indefinitely.

As Greg pointed out, when I was using goapp I did not need to also call ListenAndServe.
To get goapp to listen for requests outside of localhost I also had to add --host "my laptops ip" to the command.

Related

Why app engine ignore PORT env variable in app.yaml

I am trying to migrate from Go 1.9 to Go 1.11. I copied the main function from the migration document
This is my app.yaml
runtime: go111
env: standard
instance_class: F1
handlers:
- url: /.*
script: auto
secure: always
redirect_http_response_code: '301'
- url: .*
script: auto
env_variables:
PORT: '443'
This is my main function
func main() {
http.HandleFunc("/demo", demoHandler)
port := os.Getenv("PORT")
if port == "" {
port = "443"
syslog.Printf("Defaulting to port %s", port)
}
syslog.Printf("Listening on port %s", port)
syslog.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
}
My application needs to run on port 443 with HTTPS. However, after deployment, the application doesn't respond. I checked the logs, and it says "Listening on port 8081". I don't understand why it takes 8081 instead of 443. Where is this 8081 from?
If I hardcode the main function to use port 443. It gives me this in the logs "App is listening on port 443, it should instead listen on the port defined by the PORT environment variable. As a consequence, nginx cannot be started. Performance may be degraded. Please listen on the port defined by the PORT environment variable."
What do I miss here?
The PORT environment variable will be set by the AppEngine platform, you do not have to set it in your app.yaml config file. In fact, you can't even override it.
See the list of environment variables set by the runtime.
So just use the PORT env var as you do in your Go code, but remove it from your app.yaml config. You just have to start a non-HTTPS web server, the platform will provide HTTPS support for you.

How do I access Fauxton on the Google AppEngine platform?

I am creating an offline-first app on Google App Engine, with PouchDB as my local DB, and CouchDB as my remote DB. I have enabled CouchDB on Google AppEngine, and tried to go to the following URL:
https://[my-app-id].appspot.com:5984/_utils/
When I do that, I get the following:
This site can’t be reached
The connection was reset.
Try:
Checking the connection
Checking the proxy and the firewall
Running Windows Network Diagnostics
ERR_CONNECTION_RESET
So I tried enabling https access in the firewall settings.
**Firewalls**
[ ] Allow HTTP traffic
[Y] Allow HTTPS traffic
Still getting the error above.
I searched the documentation but cannot find anything helpful about how to access Fauxton (or Futon) on Google AppEngine. (The instructions only tell you how to access Fauxton on your local machine.)
I have generated a private and public key and logged in to the server via command line.
I have also followed the instructions about configuring the firewall to allow remote access, and have given it to my PC only.
None of this has enabled me to access https://[my-app-id].appspot.com:5984/_utils/
How do I access Fauxton on the Google AppEngine platform?
Update: according to the development tools in my browser, my PouchDB application has successfully created a database to sync to, but it isn't on the server:
app.yaml file
application: [app-name]
version: 4
runtime: python27
api_version: 1
threadsafe: false
handlers:
- url: /
script: main.py
- url: /(favicon)\.ico$
static_files: \1.ico
upload: /(favicon)\.ico
application_readable: true
- url: /(package)\.json$
static_files: \1.json
upload: /(package)\.json
application_readable: true
# Serve images as static resources #
- url: /(.+\.(gif|png|jpg|json|ico))$
static_files: \1
upload: .+\.(gif|png|jpg|json|ico)$
application_readable: true
- url: /index.html
static_files: index.html
upload: index.html
- url: /licence.html
static_files: licence.html
upload: licence.html
- url: /privacy.html
static_files: privacy.html
upload: privacy.html
- url: /pouchnotes.manifest
static_files: pouchnotes.manifest
upload: pouchnotes.manifest
- url: /manifest.json
static_files: manifest.json
upload: manifest.json
# static directories #
- url: /img
static_dir: img
- url: /js
static_dir: js
- url: /css
static_dir: css
libraries:
- name: webapp2
version: "2.5.2"
EDIT: I posted this question in the Bitnami community forum (they provide CouchDB on Google App Engine)
FWIW, one of the references in your post points to Google Compute Engine (GCE), which is an IaaS, not a PaaS like Google App Engine (GAE), you might be looking at the wrong product.
The app.yaml file indicates you are using the standard environment, which doesn't offer ways to configure a listening port. And it also doesn't allow listening sockets. From Limitations and restrictions:
Although App Engine supports sockets, there are certain limitations
and behaviors you need to be aware of when using sockets :
You cannot create a listen socket; you can only create outbound sockets.
The GAE flexible environment might be an alternative as it drops many of the standard environment restrictions, but it's a significantly different solution (which I didn't use yet). The remainder of the answer assumes the flexible environment and it's based solely on the documentation.
Not 100% certain, but you might need to teach your app to listen to port 8080 instead. From Listen to port 8080:
The App Engine front end will route incoming requests to the
appropriate module on port 8080. You must be sure that your
application code is listening on 8080.
Unless you can use the forwarded ports network config (again, not 100% certain, I didn't use flex env). From Port forwarding:
Port forwarding allows for direct connections to the Docker container
on your instances. This traffic can travel over any protocol. Port
forwarding is intended to help with situations where you might need to
attach a debugger or profiler.
By default, incoming traffic from outside your network is not allowed
through the Google Cloud Platform firewalls. After you have
specified port forwarding in your app.yaml file, you must add a
firewall rule that allows traffic from the ports you want opened.
You can specify a firewall rule in the Networking Firewall Rules page
in the Google Cloud Platform Console or using gcloud
commands.
For example, if you want to forward TCP traffic from port 2222:
Modify the app.yaml to include:
entrypoint: gunicorn -b :$PORT -b :2222 main:app
In the network settings of your app.yaml, include:
network:
forwarded_ports:
- 2222/tcp
Specify a firewall rule in the Cloud Platform Console or using gcloud compute firewall-rules create to allow traffic from any
source (0.0.0.0/0) and from tcp:2222.
I'm getting some help with this from the Bitnami Community Forum.
Answers so far...
(1) set up the firewall rules - make sure you have a permanent IP address for this.
(2) set up SSH keys to access the server via command line
(3) sudo /opt/bitnami/couchdb/scripts/ctl.sh stop couchdb
(4) edit local.ini to point to 0.0.0.0 instead of 127.0.0.1 - but note that you will need to type cd /opt/bitnami/couchdb/etc/, press enter, and then sudo vi local.ini (rather than vi local.ini as the instructions suggest).
(5) Log in to the external IP address. (Log in as admin and prefix commands with sudo)
(NB: you don't need to run this in the GAE flexible environment)

Google App engine needs periodic restarting

I have a module that works fine when I push it to app engine. When it works it logs stuff nicely and the logs are accessible in the console logs viewer. But then after a while it just stops working and when I try to access any url give me 500 server errors with no info (it just says waiting 30 seconds might be a good idea). When this happens nothing gets logged for requests.
If I restart the module (by pushing my code to app engine) then it works for a little while again.
The module is running a Pyramid app and the configuration file looks a little something like:
application: my_app
module: my_module
version: dev
runtime: python27
api_version: 1
threadsafe: false
instance_class: B2
basic_scaling:
max_instances: 2
idle_timeout: 10m
handlers:
- url: /actions/.*
script: my_module.application
login: admin
- url: /.*
script: my_module.application
builtins:
- appstats: off
libraries:
- name: webob
version: latest
- name: setuptools
version: latest
includes:
- mapreduce/include.yaml
I think what is happening is that it's hitting the idle timeout and shutting down. I need requests to the module to turn it back on again. How do I do that?
Let me know if you need more info, I'm an app engine noob at this stage. Any help would be greatly appreciated.
When a module start, App Engine call the url /_ah/start. You mustn't handle this request.
In you my_module.application you need to add in the handler who match this request :
def get(self):
# Let module start
if "X-Appengine-Cron" in self.request.headers or "X-AppEngine-TaskName" in self.request.headers or "X-Appengine-Failfast" in self.request.headers:
return
Even if you hit the idle timeout, AppEngine will spin a new instance when new request is coming in.
Use Cloud Debugger to inspect the state of your application. The debugger makes it easier to view the application state and understand what happens after your app has been running for while.
Check the docs on startup state https://cloud.google.com/appengine/docs/python/modules/#Python_Instance_states
you current default handler /.* should be able deal with a /_ah/start if youe handler can gracefully deal with a 404.
Thats how I handle startups. Goes through the main handler which can deal with non existent url requests using the default pyramid not found.
I have a config.add_notfound_view(notfound) registered.

How to access local Cloud Endpoints API from mobile device

I want to access my Cloud Endpoints API hosted on my local dev machine from an Android app running on a mobile device I use for testing.
My device can access my dev machine by IP address. I passed --host=192.1.168.101 to the App Engine launcher so that my local App Engine instance binds to the IP address. Although I can access the App Engine instance from 192.168.1.101, I get a 404 when my app makes an API call.
I noticed that going to http://192.168.1.101:9080/_ah/api/explorer/ does not show my API; it redirects to https://developers.google.com/apis-explorer/#p/. If I use http://localhost:9080/_ah/api/explorer/ I'm able to see my API as intended. It seems that using an IP address as the host is not working with Cloud Endpoints.
I'd rather not root my device to change its /etc/hosts file. Changing that might not be a solution anyway, since I'm unable to bind my App Engine instance to a hostname other than localhost.
This is my app.yaml config:
application: my-server
version: 1
runtime: python27
threadsafe: true
api_version: 1
handlers:
# Endpoints handler
- url: /_ah/spi/.*
script: services.application
- url: /favicon\.ico
static_files: favicon.ico
upload: favicon\.ico
- url: .*
script: main.app
You bound to your specific IP, but as a reminder, you can also bind to 0.0.0.0 (all available IPs). This is handy if you're using the maven appengine plugin and don't want to update the pom.xml file whenever your IP changes.
Next, make sure you're on the same network and can connect between the machines. I typically use ConnectBot to test by opening a telnet session to the IP address and port you defined for running locally. This will ensure your firewall isn't causing an issue.
Finally, update your code by adjusting the root url for your API. That would look something like this if your IP address were 192.168.1.100 and port were 8080:
Helloworld.Builder helloWorld = new Helloworld.Builder(AppConstants.HTTP_TRANSPORT,
AppConstants.JSON_FACTORY, credential);
helloWorld.setRootUrl("http://192.168.1.100:8080/_ah/api/");
In your generated source code (usually the file named after your API name, such as Tictactoe.java), DEFAULT_ROOT_URL should be set to http://192.168.1.101:9080/_ah/api/. This URL isn't expected to provide anything useful if you load it in a browser. Rather, it's the base of the path to your API requests, e.g. http://192.168.1.101:9080/_ah/api/tictactoe/v1/board.
If you want to confirm your device is properly connecting to your local server (via your local network), load
http://192.168.1.101:9080/_ah/api/explorer/ from the device browser.
The problem had nothing to do with the IP address. I needed to include a path in my API method decorator:
#endpoints.method(HelloRequest, HelloResponse, name='helloworld', path='test', http_method='GET')
def helloworld(self, request):

Sending email from dev server with --smtp_host=smtp.gmail.com

In the answer to the question Error sending e-mail via SMTP server on App Engine development server there is a nice solution by Blixt:
"dev_appserver.py does not support TLS
which is required by Gmail. You can
enable it by adding a few lines in api/mail_stub.py:"
# After smtp.connect(self._smtp_host, self._smtp_port)
smtp.ehlo()
smtp.starttls()
smtp.ehlo()
But windows Vista would not let me change api/mail_stub.py
Is there another way to send mail from development server. Other options (Sendmail and ISP are not good for me). Thanks!
EDIT
I changed the api/mail_stub.py according to instructions here and I use the following command-line options:
dev_appserver.py
--smtp_host=smtp.gmail.com
--smtp_port=25
--smtp_user=xxxx#gmail.com
--smtp_password=gmail_pw
C:\Users\A\Desktop\repeater # path to root directory
But I get this error from Log Console:
***********************************************************
2010-11-18 10:24:37 Running command: "['C:\\Python26\\pythonw.exe',
'C:\\Program Files(x86)\\Google\\google_appengine\\dev_appserver.py',
'--admin_console_server=',
'--port=8080',
u'dev_appserver.py',
u'--smtp_host=smtp.gmail.com',
u'--smtp_port=25',
u'--smtp_user=xxxx#gmail.com',
u'--smtp_password=gmail_pw
C:\\Users\\A\\Desktop\\repeater',
'C:\\Users\\A\\Desktop\\repeater']"
Runs a development application server for an application.
dev_appserver.py [options] <application root>
Application root must be the path to the application to run in this server.
Must contain a valid app.yaml or app.yml file.
****************************************************
This is the app.yaml:
application: re-peater
version: 1
runtime: python
api_version: 1
handlers:
- url: /favicon.ico
static_files: static/images/favicon.ico
upload: static/images/favicon.ico
- url: /stylesheets
static_dir: stylesheets
- url: /.*
script: repeater.py
All this works without these command line options. Any suggestions why this is not working?
If you really, really need to send real email from the dev_appserver, you should set up your own mail relay on your machine, and point the SDK at that. I'm curious why it's so important to send real email, though - this is the development server, and you shouldn't be using it for anything other than development.
Change the file permissions so that you can change the api/mail_stub.py file.
This is no longer necessary
in /appengine/api/mail_stub.py
if self._allow_tls and smtp.has_extn ('STARTTLS'):
smtp.starttls ()
I am using appengine sdk version 1.9.15.

Resources