I'm not able in Google App Engine to download a file to the user's local Download folder. I think I've followed the instructions on how to do this. Here is the server code, in which the headers statement is supposed to make the response go to the user's Download folder. Instead, it is sent to the JavaScript function that made the GET request, the same behavior one gets with the headers statement commented out. And though I don't know what the difference is, self.response.out.write and self.response.write behave the same. In addition to get, I've also tried put, post, options, and delete, and all of them behave the same. I've run out of permutations to try.
# -*- coding: utf-8 -*-
import webapp2 as web
class ApiUser(web.RequestHandler):
def get(self, user): # fails with get, put, post, options, delete
source = 'a = 5'
self.response.headers['Content-Disposition'] = 'attachment; filename='+'test.py' # no effect
self.response.write(source) # same effect as self.response.out.write(source)
app = web.WSGIApplication([ (r'/api/user/([^/]+)', ApiUser) ], debug=True)
Here is the client code that makes the request:
$(function () {
"use strict";
function apiError(message) { console.log('ERROR', message) }
function apiGet(route, callback) {
$.ajax({
type: 'GET',
url: route,
//dataType: 'json', // SyntaxError: Unexpected token a in JSON at position 0
success: callback,
error: function (xhr, message, exc) {
apiError("API " + message + " getting " + url + ": " + exc)
}
})
}
$('#submit').click(function() {
var route = "api/user/"+'Testing'
apiGet(route, function(ret) {
console.log('callback', ret)
})
})
})
Here is the HTML file:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<a>JQuery Test Page</a><br>
<input id="submit" type="button" value="Submit"/>
<script type="text/javascript" language="javascript" src="lib/jquery/IDE/jquery.min.js"></script>
<script type="text/javascript" language="javascript" src="ide.js"></script>
</body>
</html>
Here is the yaml file:
application: helloworld
version: 1
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /
static_files: ide/index.html
upload: ide/index.html
- url: /ide.js
static_files: ide/ide.js
upload: ide/ide.js
- url: /lib
static_dir: lib
- url: /api/.*
script: api.app
- url: /favicon\.ico
static_files: static/images/favicon.ico
upload: static/images/favicon\.ico
The directory structure is this:
app.yaml
api.py
/ide (ide.js and index.html)
/lib (contains the jquery library)
The link to a solution didn't instantly answer my question but did lead eventually to the fact that all I needed to do in the JS file was to insert in apiGet(route, function(ret) the statement window.location = route. Thank you!
Related
I have my node sails project in Google App Engine in need to redirect http to https.
With google Docs, I need to add handlers with secure: always in app.yaml file to achieve secure redirection, But its not working for me.
My app.yaml
env: flex
runtime: nodejs
manual_scaling:
instances: 1
resources:
cpu: 2
memory_gb: 8
disk_size_gb: 200
handlers:
- url: /.*
script: auto
secure: always
redirect_http_response_code: 301
env_variables:
SQL_PASSWORD: "------"
SQL_DATABASE: "-----"
INSTANCE_CONNECTION_NAME: "-----"
Am I missing anything.
App Engine Flex does not support the option secure: always
That option is for App Engine Standard.
You will need to perform HTTP to HTTPS redirection in your webserver code.
Here is an example:
app.use(function(request, response){
if(!request.secure){
response.redirect("https://" + request.headers.host + request.url);
}
});
App Engine Flex does not support the option secure: always for App Engine Standard it supports.
With Sails created policies for redirection with reference John Hanley Answer
config/env/production.js
module.exports = {
...
......
.........
policies:{
'*': 'isHTTPS'
}
}
api/policies/isHTTPS.js
module.exports = function(req, res, next) {
var schema = req.headers['x-forwarded-proto'] || '';
if (schema === 'https') {
// if its a request from myweb.backend.appspot.com
if (req.headers.host !== 'myweb.com') {
res.redirect('https://' + 'myweb.com' + req.url);
} else {
next();
}
} else {
// Redirect to https.
res.redirect('https://' + ((req.headers.host !== 'myweb.com') ? 'myweb.com' : req.headers.host) + req.url);
}
};
I've got my redirect working correctly, the only problem is now all my style sheets are being served as text/html because it's being piped through core.index It only gives me the error for style sheets too not JS. How do I resolve this?
Error:
Resource interpreted as Stylesheet but transferred with MIME type text/html:
application.js
angular.module(ApplicationConfiguration.applicationModuleName).config(['$locationProvider',
function($locationProvider) {
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
$locationProvider.hashPrefix('!');
}
])
express.js
app.use(express.static(path.resolve('./public')));
// Globbing routing files
config.getGlobbedFiles('./app/routes/**/*.js').forEach(function(routePath) {
require(path.resolve(routePath))(app);
});
var core = require('../app/controllers/core.server.controller.js');
app.get('/*', core.index);
core.server.controller.js
exports.index = function(req, res) {
res.render('index', {
user: req.user || null,
request: req
});
};
core.client.routes.js
// Setting up route
angular.module('core').config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
// Redirect to home view when route not found
$urlRouterProvider.otherwise('/404');
$stateProvider
.state('admin', {
url: '/admin',
templateUrl: 'modules/core/views/home.client.admin.view.html',
});
}
]);
That would not be the correct way to serve static content - images, CSS and javascript files that run on the browser.
Take a look at this article
Basically, assuming that your directory structure is as follows:
-- public
|-- css
|-- img
`-- js
where public is the folder that contains all the sub folders for hosting stylesheets, images etc.
Then, in your nodejs code, where you have the var app = express() code, have the following code after it:
app.use(express.static('public'));
Thus, when the browser encounters a stylesheet declaration such as:
<link rel="stylesheet" href="css/style.css/>
it will make a request to /css/style.css and your express server will then correctly serve the stylesheet.
Have the code app.get("/*", core.index) at the end of all the above code to ensure that it is the last option that the server tries when attempting to match a request path to a request handler.
I include google's angularjs scripts but they don't seem to work with the app. If I open the html webpage directly with an internet browser it works fine.
The page is just a simple test with ng-model to see what you are typing and it doesn't print {{name}}
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
this is the app:
import os
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from google.appengine.ext.webapp import template
class MainHandler(webapp.RequestHandler):
def get (self, q):
if q is None:
q = 'index.html'
path = os.path.join (os.path.dirname (__file__), q)
self.response.headers ['Content-Type'] = 'text/html'
self.response.out.write (template.render (path, {}))
def main ():
application = webapp.WSGIApplication ([('/(.*html)?', MainHandler)], debug=True)
util.run_wsgi_app (application)
if __name__ == '__main__':
main ()
this is my app.yaml
application: sixth-tribute-676
version: 2
runtime: python27
api_version: 1
threadsafe: no
handlers:
- url: /(.*\.(gif|png|jpg|ico|js|css))
static_files: \1
upload: (.*\.(gif|png|jpg|ico|js|css))
- url: .*
script: main.py
The problem was that I was using template.render and {{name}} disappeared. I should serve the html without rendering it.
I am developing an app with AngularJS frontend + GAE backend (Python and Flask). I am having troubles to setting app.yaml for routing my API endpoints created with Flask-Restless extention. My app.yaml file looks like this:
application: myAppID
version: 1
runtime: python27
threadsafe: true
api_version: 1
handlers:
# handler 1
- url: /favicon\.ico
static_files: favicon.ico
upload: favicon\.ico
# handler 2
- url: /api/.*
script: main.app
# handler 3
- url: /test
script: main.app
# handler 4
- url: (.*)/
static_files: app\1/index.html
upload: app #this is the frontend folder for Angular
# handler 5
- url: (.*)
static_files: app\1
upload: app #this is the frontend folder for Angular
In Angular, the routes configuration looks like this:
App.config(['$stateProvider', '$locationProvider', '$urlRouterProvider', 'RouteHelpersProvider',
function ($stateProvider, $locationProvider, $urlRouterProvider, helper) {
'use strict';
$locationProvider.html5Mode(false);
// default route
$urlRouterProvider.otherwise('/app/dashboard');
// other routes ...
}]);
The main.py file looks like this:
from flask import Flask
import os
from werkzeug import debug
from flask import jsonify
from google.appengine.ext.webapp.util import run_wsgi_app
app = Flask('myApp')
if os.getenv('SERVER_SOFTWARE') and os.getenv('SERVER_SOFTWARE').startswith('Google App Engine/'):
app.debug = False
else:
app.debug = True
if app.debug:
app.wsgi_app = debug.DebuggedApplication(app.wsgi_app, True)
#app.route('/test')
def test():
return jsonify(test={"json": "test"})
import models
run_wsgi_app(app)
models is the file that contains Flask-SQLAlchemy models and Flask-Restless endpoints.
The Angular part loads correctly, for example this URL works fine:
A) http://localhost:8080/#/app/dashboard
But the GAE backend part responses with a 500 error for URLs like these:
B) http://localhost:8080/api/person
C) http://localhost:8080/test
If I remove the handler 4 and handler 5 then B and C URLs works fine but Angular frontend stop working.
What I'm doing wrong?
Im on the go, so writing from my phone isn't that fun...
Any way, what i did in my app is that i have only one handler that triggers the flask app.
In the flask app usually the / route will return the angular web app as a static file.
You need to configure your Flask app , that it will know about the statics (HTML, JS etc.) Folder.
EDITED:
app.yaml should look like this:
handlers:
- url: .* # This regex directs all routes to main.app
script: main.app
main.app is the flask app..
now lets see how to serve the angular app from the route '/'
from flask import Flask, render_template
app = Flask(__name__, static_folder='/templates') # This sets /templates to be the folder for all JS HTML CSS files
#app.route('/')
def wellcomePage():
return app.send_static_file('index.html')
angular routing configuration in your app.js file:
app.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: 'templates/views/home.html'
}).... Some More Routes..
Note that templateUrl: 'templates/...'
Please take a look at my app. I think it will help you understand what I'm trying to say here...
SE Hub at github
Ill edit this answer when i get to a freaking keyboard :)
Let me know if this helps.
Long time listener, first time caller.
I'm having some frustrating, seemingly inexplicable issues with Google App Engine, Jinja2, and CSS.
My templates are working, the functionality of my app works (users, blog posts, etc.), but the CSS file shows a big, fat 404 in my Chrome debugging tools and in my Google App Engine logs. Why isn't my /stylesheets/main.css loading?
Dear internet, I'd love to hear that this is just a typo. I'm sure that I'm just an idiot.
Here's my file directory:
stylesheets
main.css
templates
base.html
blog.html
front.html
login.html
newpost.html
signup.html
welcome.html
app.yaml
blogs.py
favicon.ico
index.yaml
main.py
users.py
utilities.py
Here's my YAML file:
application: hello-udacity-5681
version: 1
runtime: python27
api_version: 1
threadsafe: yes
handlers:
- url: /favicon\.ico
static_files: favicon.ico
upload: favicon\.ico
- url: /.*
script: main.app
- url: /stylesheets
static_dir: stylesheets
libraries:
- name: webapp2
version: "2.5.2"
- name: jinja2
version: latest
Here's my main.py:
import webapp2
import os
import jinja2
from google.appengine.ext import db
template_dir = os.path.join(os.path.dirname(__file__), 'templates')
jinja_env = jinja2.Environment(loader = jinja2.FileSystemLoader(template_dir), autoescape = True)
class Handler(webapp2.RequestHandler):
def write(self, *a, **kw):
self.response.out.write(*a, **kw)
def render_str(self, template, **params):
t = jinja_env.get_template(template)
return t.render(params)
def render(self, template, **kw):
self.write(self.render_str(template, **kw))
class MainHandler(Handler):
def render_front(self):
self.render("base.html")
def get(self):
self.render_front()
Here's my base.html:
<!DOCTYPE html>
<html>
<head>
<link type="text/css" rel="stylesheet" href="/stylesheets/main.css"/>
<title>Blog</title>
</head>
<body>
Blog
</body>
</html>
I ran my main.css through http://jigsaw.w3.org/css-validator/ without any issues, so I won't bore you with that.
Why am I still getting a 404 for my /stylesheets/main.css ?
Your app.yaml handler section should be like this
handlers:
- url: /favicon\.ico
static_files: favicon.ico
upload: favicon\.ico
- url: /stylesheets
static_dir: stylesheets
- url: /.*
script: main.app
In this case, the /stylesheets pattern will match before the /.* pattern will for the appropriate paths. For more information on URL mapping and other options you can specify in app.yaml, see the app.yaml reference.