4

I would like to serve static files depending on the query parameter. More specificly I would like to serve prerendered snapshots for search engine optimalization. The pages are hosted on Google Appengine, so I'm using app.yaml to define these urls.

handlers:
# Consider anything matching a dot static content.
- url: /(.*\..*)$
  static_files: dist/\1
  upload: dist/(.*\..*)$

# Serve snapshots for seo
- url: /?_escaped_fragment_=(.*)
  static_files: dist/snapshots/\1
  upload: dist/(.*)$

# Otherwise let Angular handle it.
- url: /(.*)
  static_files: dist/index.html
  upload: dist/index.html

However, when I fetch a url with the query parameter _escaped_fragment_, the last url handler is triggered. Is it possible to define query params in urls? If so, what am I doing wrong?

Remco Haszing
  • 5,879
  • 3
  • 33
  • 69
  • what is the url you're trying to fetch? – marcadian Feb 25 '14 at 21:00
  • Any url googlebot would fetch. For example I have `/support` defined, so googlebot would fetch `/?_escaped_fragment_=support`. It is an AngularJS site, so `/?_escaped_fragment_=support` should fetch a prerendered html file in order to index it. – Remco Haszing Feb 25 '14 at 21:51
  • The workaround is create a handler which either returns dist/index.html (when _escape_fragment_ isn't in the query string) else returns snapshop html for the given _escape_fragment_. I don't know how much additional cost is involved with serving it this way. – Rob Curtis Feb 26 '14 at 08:22

2 Answers2

4

I'm happy to be proven wrong, but I'm pretty sure that query parameters aren't considered when dispatching via app.yaml.

Dave W. Smith
  • 21,640
  • 4
  • 33
  • 38
0

I had the exact same problem. It is kind of lame that App Engine hasn't added the ability to dispatch on static query parameters... Anyway.

import webapp2, urllib, logging, json, os

dp = os.path.dirname(os.path.realpath(__file__))
fp = os.path.join(dp, "resources", 'index.html')
w = open(fp, 'r').read()

class Fragment(webapp2.RequestHandler):
  def get(self, pathname):
    if '_escaped_fragment_' in self.request.arguments():
      CODE_GOES_HERE_FOR_BUILDING_YOUR_FRAGMENT_RESPONSE
    else:
      self.response.write(w)

application = webapp2.WSGIApplication(
    [('/(.*)', Fragment)],
  debug=True)

This code basically guesses whether you are dispatching on the _escaped_fragment_ query parameter and modifies the output accordingly. I have no idea how much less (if any) performant this is than being able to just leave index.html in the static_files: handlers in app.yaml.

Stephen Cagle
  • 12,627
  • 14
  • 49
  • 83
  • I had built something similar back when I still had the problem. Nowadays Google indexes the JavaScript rendered pages, making the `_escaped_fragment_` responses less important. (Still useful for other search engines though.) – Remco Haszing Dec 29 '14 at 12:56
  • Good point. I unfortunately still have a dynamic site where the majority of content does not show up unless you use javascripting UI elements, so the _escaped_fragment_ thing is still useful in my particular case. But yes, I agree, if the majority of your content shows up on initial javascript render, then google probably handles that just fine. – Stephen Cagle Dec 29 '14 at 16:54