Skip to content

Cloudflare ad network example#6882

Merged
lannka merged 2 commits intoampproject:masterfrom
cloudflare:cloudflare/cf-ad-network
Jan 26, 2017
Merged

Cloudflare ad network example#6882
lannka merged 2 commits intoampproject:masterfrom
cloudflare:cloudflare/cf-ad-network

Conversation

@oliy
Copy link
Copy Markdown
Contributor

@oliy oliy commented Jan 5, 2017

For issue #6881

This adds example code for implementing an ad network that uses the Cloudflare A4A signing service.

Copy link
Copy Markdown
Contributor

@keithwrightbos keithwrightbos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to wait to review this until #6884 has been merged.

@dknecht
Copy link
Copy Markdown
Contributor

dknecht commented Jan 5, 2017

Can we still get them in same release?

@keithwrightbos
Copy link
Copy Markdown
Contributor

keithwrightbos commented Jan 5, 2017 via email

@oliy oliy force-pushed the cloudflare/cf-ad-network branch from 2a5aa26 to d2347d0 Compare January 5, 2017 17:53
export const a4aRegistry = map({
'adsense': adsenseIsA4AEnabled,
'doubleclick': doubleclickIsA4AEnabled,
'cloudflare': cloudflareIsA4AEnabled,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should only be enabled in dev mode, right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will be having some production demos so would like to keep enabled.

@oliy oliy force-pushed the cloudflare/cf-ad-network branch from d2347d0 to 026eae1 Compare January 5, 2017 19:44
@oliy
Copy link
Copy Markdown
Contributor Author

oliy commented Jan 5, 2017

I got the lint and type check errors out of the way, but I see a dist timeout. Is that an intermittent error?

@oliy oliy force-pushed the cloudflare/cf-ad-network branch from 026eae1 to a6ad0c1 Compare January 6, 2017 15:28
@keithwrightbos
Copy link
Copy Markdown
Contributor

I noticed that #6884 was closed. Are you planning to use this PR to include the triplelift A4A implementation? If so, can you address my review comments in the original PR?

@oliy
Copy link
Copy Markdown
Contributor Author

oliy commented Jan 9, 2017

I think I've addressed all your comments from the triple lift implementation. This won't include the triple lift implementation, but hopefully, it will inform them of changes necessary to have a clean submission. I'll be adding in tests this coming week.

import {dev} from '../../../src/log';


// Header that will contain Cloudflare generated signature
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct format for this comment would be as follows. Given that this can be private, please modify name to end in underscore.
`/**

  • Header that will contain Cloudflare generated signature.
  • @type {string}
  • @Private
    */
    const AMP_SIGNATURE_HEADER_ = 'X-AmpAdSignature';`

* @param {!Element} element
*/
/*
constructor(element) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted this file to serve as an example starting point for other implementations. Since many of them actually will need initialization, I've included most of the boilerplate here for guidance/convenience and given instructions to remove this in actual implementations. If you have a strong preference, I'm fine with removing this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this blocking the merge? If so, I will remove this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @keithwrightbos . let's remove. we can make the fake-impl as a template.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing.

// const rect = this.getIntersectionElementLayoutBox();
// can extract the layout size and be used to pass layout hints to the server.

// Be sure that this doesn't allow the generation of ANY url, since it could
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How/when do you plan to add checks?

* Extract creative and signature from a Cloudflare signed response.
*
* Note: Invalid A4A content will NOT have a signature, which will automatically
* cause the A4A processing to fall through to the 3p ad flow.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that lack of signature does not actually cause the 3p ad flow to be used where a xdomain iframe is created in which custom JS executes to generate an ad request. Instead, it will take the creative given and render it directly within a cross domain frame using either network cache (if Android) or safeframe (if iOS).

// check for an explicit attribute to enable A4A processing.
// This could be just true, if all ads from this network are A4A, or any
// other logic based upon configuration, client settings, etc.
return !!element.getAttribute('data-a4a');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could add check for src attribute existence

@oliy oliy force-pushed the cloudflare/cf-ad-network branch 3 times, most recently from 41689cc to a500b3d Compare January 21, 2017 02:25
@oliy
Copy link
Copy Markdown
Contributor Author

oliy commented Jan 21, 2017

I've added tests and made the most recently requested changes. Let me know if you'd like anything else. I'd like this to be a clean template for future implementers to start with to integrate Cloudflare ad signing.

@dknecht
Copy link
Copy Markdown
Contributor

dknecht commented Jan 21, 2017

cc / @keithwrightbos

@keithwrightbos
Copy link
Copy Markdown
Contributor

Can you explain why it is necessary to create a completely separate extension from the fake-impl? Why not just allow for fake-impl to extract its signing services via an element attribute?

@tdrl
Copy link
Copy Markdown

tdrl commented Jan 23, 2017

Sorry I'm late to this conversation. Just so I'm clear: Is Cloudflare providing an ad network service? Or only a signing service for other ad networks (e.g., TripleLift)?

// be sure that this only generates urls to valid hosts, since it could
// allow cookie leaks, etc.

return CLOUDFLARE_BASE_URL + this.element.getAttribute('src');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the 'src' attribute is publisher-controlled, is there a possibility for hostile content injection here? Would it be feasible to uriEncode the src?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added encoding.

@dknecht
Copy link
Copy Markdown
Contributor

dknecht commented Jan 23, 2017

@tdrl @keithwrightbos We are providing a signing service, but would like to be able to do a full working demo to help make educating potential users easier. We will use for PSA on our blog's amp content.

@keithwrightbos
Copy link
Copy Markdown
Contributor

And you feel that modifying fake as suggested would be insufficient? I'm concerned about making several extensions that will never actually be used. @jridgewell your thoughts?

@jridgewell
Copy link
Copy Markdown
Contributor

This is more a question for @lannka or @cramforce.

*/
var BBPromise = require('bluebird');
var app = require('express')();
var express = require('express');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is express used?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had worked around needing this, so this change is no longer needed. I'm removing it.

* @param {!Element} element
*/
/*
constructor(element) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @keithwrightbos . let's remove. we can make the fake-impl as a template.

@dknecht
Copy link
Copy Markdown
Contributor

dknecht commented Jan 23, 2017

I don't believe the fake-impl can be used in production.

@cramforce
Copy link
Copy Markdown
Member

I think having such demo code makes sense at this stage to help mature the content. Lets proceed with regular review.

@oliy oliy force-pushed the cloudflare/cf-ad-network branch 2 times, most recently from 5e123aa to 2b4316e Compare January 24, 2017 01:05
@dknecht
Copy link
Copy Markdown
Contributor

dknecht commented Jan 24, 2017

@keithwrightbos are we good to go? We are talking with @jasti about ways to remove in the future.


import {AmpAdNetworkCloudflareImpl} from '../amp-ad-network-cloudflare-impl';
import {
AmpAdUIHandler, // eslint-disable-line no-unused-vars
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

// be sure that this only generates urls to valid hosts, since it could
// allow cookie leaks, etc.

return CLOUDFLARE_BASE_URL + encodeURI(this.element.getAttribute('src'));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

encodeURIComponent

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to be encodeURI, since this is meant to be the continuation of the URL, to support path references, etc.

* @type {string}
* @private
*/
//const CLOUDFLARE_BASE_URL = 'http://www.mycloudflaredomain.com/_a4a';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we remove this and merge JsDoc into the other one?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

* @private
*/
const CLOUDFLARE_BASE_URL =
'/extensions/amp-ad-network-cloudflare-impl/0.1/data';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can use simple string like: /cloudflare/a4a-data

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This follows the pattern from the fake impl to locate test data, so this represents the path to the test data folder.

* Handle CORS headers
*/
app.use(cloudflareDir, function fakeCors(req, res, next) {
res.setHeader("Access-Control-Allow-Methods", "GET,OPTIONS");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we reuse the existing method assertCors?

/**
* Handle fake data
*/
app.get(cloudflareDir + '/*', function(req, res) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we reuse the existing code at line 543?

you do:

app.get([doubleclickPath, cloudflarePath], function(req, res) {
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is different, since it has different header handling than the fake one.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is X-AmpAdSignature the only difference ? we can add it to that method.

/**
* Handle CORS preflight
*/
app.options(cloudflareDir + '/*', function(req, res) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are we able to merge this into the previous CORS handler?

@oliy oliy force-pushed the cloudflare/cf-ad-network branch from 2b4316e to 7f695ab Compare January 25, 2017 00:55
@oliy
Copy link
Copy Markdown
Contributor Author

oliy commented Jan 25, 2017

The test failure only occurred after rebasing on master. I'm pretty sure we didn't do anything that would have changed that test result. Also, it looks like timing could affect the test results.

@cramforce
Copy link
Copy Markdown
Member

Restarted the test. You can always force-push a new git-sha to get a new run. Apologies for the flaky test.

assertCors(req, res, ['GET', 'OPTIONS'], ['X-AmpAdSignature']);

if (req.method=='OPTIONS') {
res.status(204);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: res.status(204).end()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@oliy oliy force-pushed the cloudflare/cf-ad-network branch from 7f695ab to 1a71d1e Compare January 25, 2017 19:14
@oliy oliy force-pushed the cloudflare/cf-ad-network branch from 1a71d1e to 6d41ed3 Compare January 25, 2017 23:22
@oliy
Copy link
Copy Markdown
Contributor Author

oliy commented Jan 25, 2017

@lannka I think I implemented all changes from your review.

@lannka lannka merged commit 298920c into ampproject:master Jan 26, 2017
jridgewell pushed a commit to jridgewell/amphtml that referenced this pull request Jan 31, 2017
* Local debug server changes to fake Cloudflare signing.

* Changes to support a new A4A ad network with Cloudflare Signing
mrjoro pushed a commit to mrjoro/amphtml that referenced this pull request Apr 28, 2017
* Local debug server changes to fake Cloudflare signing.

* Changes to support a new A4A ad network with Cloudflare Signing
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants