Skip to content
This repository has been archived by the owner on Oct 22, 2019. It is now read-only.

add AMP Cache URL converter #511

Merged
merged 1 commit into from Dec 5, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion api/.gitignore

This file was deleted.

3 changes: 3 additions & 0 deletions api/app.yaml
Expand Up @@ -22,6 +22,9 @@ handlers:
- url: /img
static_dir: img
secure: always
- url: /scripts
static_dir: scripts
secure: always
- url: /third_party
static_dir: third_party
secure: always
Expand Down
81 changes: 81 additions & 0 deletions api/iframe/amp-url-converter.html
@@ -0,0 +1,81 @@
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
}
pre {
font-family: Menlo,Monaco,Consolas,"Courier New",monospace;
font-size: 14px;
overflow: auto;
margin: 0;
padding: 8px;
background-color: #ECEFF1;
overflow-x: auto;
min-height: 32px;
}
-webkit-scrollbar, pre::-webkit-scrollbar {
height: 8px;
width: 4px;
}
pre::-webkit-scrollbar-thumb {
background: rgba(0,0,0,.26);
}
a {
color: #37474f;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.error {
color: red;
}
.input-container {
display: flex;
}
.input-container .responsive {
flex: 1;
}
.input-container .fixed {
flex: 0;
margin: 0 0 0 16px;
}
.input-container div input {
font-size: 14px;
padding: 6px;
width: 100%;
}
.input-container div button {
font-size: 14px;
padding: 8px 16px;
white-space: nowrap;
}
.result-container {
padding: 16px 0 0 0;
}
</style>
</head>
<body>
<section class="input-container">
<div class="responsive">
<input id="input" type="text" />
</div>
<div class="fixed">
<button id="execute">Convert</button>
</div>
</section>
<section class="result-container">
<pre id="result"></pre>
</section>
<script src="https://cdn.ampproject.org/viewer/google/amp_url.js"></script>
<script src="/scripts/amp_url_converter.js"></script>
</body>
</html>
85 changes: 85 additions & 0 deletions api/scripts/amp_url_converter.js
@@ -0,0 +1,85 @@
/**
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

const DEFAULT_URL = "https://www.example.com/amp?param=value";
const AMP_CACHE_PREFIX = "https://cdn.ampproject.org/c/";

class AmpUrlConverter {

constructor(root, ampUrlFactory) {
this.inputView = root.getElementById('input');
this.resultView = root.getElementById('result');
this.ampUrlFactory = ampUrlFactory;
root.getElementById('execute')
.addEventListener("click", this.onClick.bind(this));
}

setInput(urlString) {
this.inputView.value = urlString;
this.convert(urlString);
}

convert(urlString) {
urlString = urlString.trim();
if (!urlString) {
this.showError('Empty input');
return;
}
try {
const ampUrl = this.ampUrlFactory.createAmpUrl(urlString);
const proxyUrl = ampUrl.getProxyUrl();
this.showResult('<a href="' + proxyUrl + '" target="_parent">' + proxyUrl + '</a>');
}catch(e) {
this.showError('Invalid URL');
}
}

showError(message) {
this.resultView.className = 'error';
this.resultView.innerHTML = message;
}

showResult(result) {
this.resultView.className = '';
this.resultView.innerHTML = result;
}

onClick() {
this.convert(this.inputView.value);
}

}

function getParameterByName(name, defaultValue) {
const url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
const regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) { return defaultValue; }
if (!results[2]) { return defaultValue; }
return decodeURIComponent(results[2].replace(/\+/g, " "));
}

const proxyUrlPrefix = 'https://cdn.ampproject.org';
const javascriptVersion = '5';
const useCurlsEncoding = true;
const ampUrlFactory =
new AmpUrlFactory(proxyUrlPrefix, javascriptVersion, useCurlsEncoding);

const converter = new AmpUrlConverter(document, ampUrlFactory);
const initialUrl = getParameterByName('url', 'https://www.example.com/amp?param=1');

converter.setInput(initialUrl);
62 changes: 51 additions & 11 deletions src/30_Advanced/Using_the_Google_AMP_Cache.html
Expand Up @@ -5,31 +5,67 @@
<!--
#### Introduction

The Google AMP Cache stores valid AMPs and provides a consistently fast access to AMPs.
The [Google AMP Cache](https://developers.google.com/amp/cache/overview) stores valid AMPs and provides a consistently fast access to AMPs. It is available for anyone to use.

<div class="card important">
This article describes the new AMP URL Cache format which will go live in Q1 2017. For the current format please refer to the [official documentation](https://developers.google.com/amp/cache/overview).
</div>
-->
<!-- -->
<!doctype html>
<html ⚡>
<head>
<meta charset="utf-8">
<script async src="https://cdn.ampproject.org/v0.js"></script>
<script async custom-element="amp-iframe" src="https://cdn.ampproject.org/v0/amp-iframe-0.1.js"></script>
<link rel="canonical" href="<%host%>/advanced/using_the_google_amp_cache/">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<style amp-custom>
.amp-iframe-container {
margin: 0;
padding: 16px;
}
.doc pre {
margin: 16px;
padding: 16px;
}
.doc pre code {
font-size: 14px;
}
@media (max-width: 700px) {
.amp-iframe-container, .doc pre {
margin: 16px 0;
}
}
.doc pre, .doc pre>code, code {
background-color: #ECEFF1;
}
</style>
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
</head>
<body>
<!--
#### AMP Cache URL Format

Loading your AMPs via the Google AMP Cache is easy. The AMP Cache URL is composed based on the source URL’s scheme (HTTP or HTTPS):
When possible, the Google AMP Cache will create a subdomain for each AMP document's domain by first converting it from [IDN (punycode)](https://en.wikipedia.org/wiki/Punycode) to UTF-8. The caches replaces every `-` (dash) with `--` (2 dashes) and replace every `.` (dot) with `-` (dash). For example, `pub.com` will map to `pub-com.cdn.ampproject.org`.

Here is AMP Cache URL for `https://ampbyexample.com/components/amp-img`:

<div class="amp-iframe-container"><amp-iframe height="88"
layout="fixed-height" sandbox="allow-scripts allow-same-origin allow-popups"
src="https://amp-by-example-api.appspot.com/iframe/amp-url-converter.html?url=https://ampbyexample.com/components/amp-img"><amp-img layout="fixed-height" height="88" src="https://ampbyexample.comm/img/pixel-white.png" placeholder></amp-img></amp-iframe></div>

* for HTTP prepend `cdn.ampproject.org/c/`. Example:
[https://cdn.ampproject.org/c/www.bbc.co.uk/news/amp/35838735](https://cdn.ampproject.org/c/www.bbc.co.uk/news/amp/35838735)
* for HTTPS prepend `cdn.ampproject.org/c/s`. Example: [https://cdn.ampproject.org/c/s/ampbyexample.com](https://cdn.ampproject.org/c/s/ampbyexample.com)
The converted AMP Cache URL consists of the following parts:

* `ampbyexample-com`: the publisher domain converted into a subdomain using the algorithm described above.
* `cdn.ampproject.org`: the AMP Cache domain.
* `c`: to indicate that it's an AMP document (there is also `i` for image and `r` for resources such as fonts).
* `s`: indicating that the AMP Cache fetches the content from the origin using TLS (secure HTTPS).
* `ampbyexample.com/components/amp-img`: the original URL excluding the scheme.

It is OK for URLs to include parameters in the query string, simply include these in the AMP Cache URL as well.

Example: [https://cdn.ampproject.org/c/s/ampbyexample.com/g?value=Hello%20World](https://cdn.ampproject.org/c/s/ampbyexample.com/g?value=Hello%20World)
Example: [https://ampbyexample-com.cdn.ampproject.org/ampbyexample.com/g?value=Hello%20World](https://ampbyexample-com.cdn.ampproject.org/ampbyexample.com/g?value=Hello%20World).

#### Redirect & Error Handling

Expand All @@ -41,33 +77,37 @@

```
$ curl -I https://ampbyexample.com/amp-img.html

HTTP/1.1 301 Moved Permanently
Location: https://ampbyexample.com/components/amp-img
Content-Type: text/html; charset=utf-8
Location: https://ampbyexample.com/components/amp-img/
...
```

Then the AMP Cache will return the content of the resolved redirect for the original URL.

Example: [https://cdn.ampproject.org/c/s/ampbyexample.com/amp-img.html](https://cdn.ampproject.org/c/s/ampbyexample.com/amp-img.html).
Example: [https://ampbyexample-com.cdn.ampproject.org/ampbyexample.com/amp-img.html](https://cdn.ampproject.org/c/s/ampbyexample.com/amp-img.html).
<p class="card important">**Important**: if you move the location of the AMP Files on your server, make sure to set up a redirect from the old location to the new one. </p>

**Not Found**

When a page is not found in the AMP Cache, it will show an error page and return a 404 status.

Example: [https://cdn.ampproject.org/c/s/ampbyexample.com/not-found](https://cdn.ampproject.org/c/s/ampbyexample.com/not-found).
Example: [https://ampbyexample-com.cdn.ampproject.org/ampbyexample.com/not-found](https://cdn.ampproject.org/c/s/ampbyexample.com/not-found)

**Invalid AMP**

When a page is invalid AMP, the AMP Cache will return a 404 status.

Example: [https://cdn.ampproject.org/c/s/ampbyexample.com/invalid_amp.html](https://cdn.ampproject.org/c/s/ampbyexample.com/invalid_amp.html).
Example: [https://ampbyexample-com.cdn.ampproject.org/ampbyexample.com/invalid_amp.html](https://cdn.ampproject.org/c/s/ampbyexample.com/invalid_amp.html)

**Server Errors**

If an URL returns a 5XX server errors, the AMP Cache will return a 404 status.

Example: [https://cdn.ampproject.org/c/s/ampbyexample.com/error](https://cdn.ampproject.org/c/s/ampbyexample.com/error).
Example: [https://ampbyexample-com.cdn.ampproject.org/ampbyexample.com/error](https://cdn.ampproject.org/c/s/ampbyexample.com/error)

<br>
-->
</body>
</html>
3 changes: 2 additions & 1 deletion templates/css/styles.css
Expand Up @@ -66,7 +66,8 @@ code, pre {
text-decoration: none;
}
.doc pre > code, .doc pre {
background-color: white;
padding: 0;
background-color: #f9f9f9;
}
.doc pre {
padding: 16px;
Expand Down