New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve fake ad network by providing working example, updating doc, a… #9295
Conversation
jonkeller
commented
May 12, 2017
- Provide a working example of fake ad network
- Document the use of fakesig="true"
- Fix bug in which, when fakesig="true" is used, it was expecting a file called something.json but which contained HTML, not JSON.
- Fix bug in which 2 network requests were issued for the fake creative
} | ||
// Prevent issueing a second network request to try to fetch | ||
// the same JSON again. | ||
this.experimentalNonAmpCreativeRenderMethod_ = XORIGIN_MODE.NAMEFRAME; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@keithwrightbos This isn't allowed since this.experimentalNonAmpCreativeRenderMethod_ is private. The reason I want to do this is so that on
amphtml/extensions/amp-a4a/0.1/amp-a4a.js
Line 1219 in 89320dc
const method = this.experimentalNonAmpCreativeRenderMethod_; |
So I would like to do an /OK/ to override this linter complaint. Or alternatively make a public setter for this, but that seems sketchy too. I figure you own this, per your comment on line 289 of the linked file. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Disregard - next commit is going to make this moot.
extensions/amp-a4a/0.1/amp-a4a.js
Outdated
if (getMode().localDev && this.element.getAttribute('type') == 'fake') { | ||
// Prevent issuing a second network request to try to fetch | ||
// the same JSON again. | ||
this.experimentalNonAmpCreativeRenderMethod_ = XORIGIN_MODE.NAMEFRAME; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can this be passed in by an attribute?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My original approach was to try to set it from AmpAdNetworkFakeImpl, but it's private to the parent class. I agree this is hacky, but I think any other approach would also be hacky. We could have AmpAdNetworkFakeImpl set some attribute, and then have the parent class say if (this.theAttribute) { this.experimentalNonAmpCreativeRenderMethod_ = theAttribute; } but I'm really bothered by doing any subclass-specific logic in the parent class...
extensions/amp-a4a/0.1/amp-a4a.js
Outdated
this.adUrl_ = this.getAdUrl(); | ||
this.adPromise_ = Promise.resolve(); | ||
return; | ||
if (getMode().localDev && this.element.getAttribute('type') == 'fake') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getMode().localDev
check is not needed. we already checked in amp-ad.js
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Happy to remove, but note that this check was here previously. Was trying to make as little change as possible...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's keep. I'd like to have 100% guarantee that this code is not in PROD binary.
// Gracefully handle the case in which the fake ad is still | ||
// formatted in JSON, which it almost certainly is, since | ||
// "gulp serve" won't serve an HTML file under /extensions | ||
const json = JSON.parse(deserialized); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering how does the production logic right now handle this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically the issue here is that normally it wants JSON like { "creative": ...html..., "signature": ... }
However if you use a fake ad, then it was just rendering everything it gets, so the ad would contain the JSON structure above, not just the html. But if you change to , then it doesn't work because gulp won't serve a .html file from extensions/. So the ugly workaround was to make a .json file which contained no JSON, only HTML. This fix just solves that, and affects only the fake ad network.
A real ad would come in the JSON format, but we would never be in AmpAdNetworkFakeImpl. extractCreativeAndSignature() in the first place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, should have made my question clearer. And this is mainly for my own learning. Let me know if any of my understanding went wrong:
- In fast fetch, runtime first requests a URL via XHR. It returns a JSON (AMP creative) or HTML (non-AMP creative)
- In case of non-AMP or invalid AMP, runtime creates an iframe and having the
src=
attribute pointing to the same URL (the cache frame rendering path). And we expect it to hit the browser cache to save a round trip. - In case of non-AMP, the HTML is perfectly rendered in the iframe. However, for the invalid AMP case, how do we deal with the cached JSON?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your understanding sounds correct to me. I'm not sure of the answer re: the invalid AMP caching question. I'd be happy to research that for you, or maybe Keith knows off the top of his head...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We parse the creative HTML out of the JSON in both cases. For non-AMP the creative portion only would be written into safeframe and rendered
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@keithwrightbos so you meant if the creative is AMP with a wrong signature, we'll always choose SafeFrame rendering method?
// Gracefully handle the case in which the fake ad is still | ||
// formatted in JSON, which it almost certainly is, since | ||
// "gulp serve" won't serve an HTML file under /extensions | ||
const json = JSON.parse(deserialized); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@keithwrightbos so you meant if the creative is AMP with a wrong signature, we'll always choose SafeFrame rendering method?
extensions/amp-a4a/0.1/amp-a4a.js
Outdated
if (getMode().localDev && this.element.getAttribute('type') == 'fake') { | ||
// Prevent issuing a second network request to try to fetch | ||
// the same JSON again. | ||
this.experimentalNonAmpCreativeRenderMethod_ = XORIGIN_MODE.NAMEFRAME; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see my other comment. I'm trying to see if we can avoid doing this test only logic. We are making the test widget behave differently than the prod widget, so we're not testing the true logic.
If this does not work, we might be hitting a bug?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the fake ad network should never be used in prod at all...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
of course it's not in prod.
my point is: why you have to have this logic in test to make it work? and why prod can work without it? how does prod prevent hitting the json cache?
overall, we want to avoid introducing test-only code in non-test. does it make sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see what you mean. This is due to the setting of "method" here:
amphtml/extensions/amp-a4a/0.1/amp-a4a.js
Line 611 in 49951ce
const method = fetchResponse.headers.get(RENDERING_TYPE_HEADER) || |
In prod, the HTTP header will be set. But when running locally, it isn't. Without explicitly setting it here, we hit the error on line 615 when testing locally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so i will suggest we change our local server to set the header, instead of putting extra logic into code to bypass this.
build-system/app.js
Outdated
@@ -755,16 +755,16 @@ app.use([cloudflareDataDir], function fakeCors(req, res, next) { | |||
*/ | |||
app.get([ fakeAdNetworkDataDir + '/*', cloudflareDataDir + '/*'], function(req, res) { | |||
var filePath = req.path; | |||
var unwrap = false; | |||
var unwrap = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lannka Re: your previous question, it turns out that the problem was here. This was implemented backwards. If the creative is a .json file, then it should be unwrapped (signature and HTML extracted), and if it's a .html file then that is not needed. It was done the opposite way. My other main change here is the line that sets the X-AmpAdRender header, which removes the need for the change to amp-a4a.js which you weren't a fan of. Now,
amphtml/extensions/amp-a4a/0.1/amp-a4a.js
Line 611 in 49951ce
const method = fetchResponse.headers.get(RENDERING_TYPE_HEADER) || |
…nd making the signature workaround not require using a .json file which contains HTML rather than JSON
filePath = pc.cwd() + filePath; | ||
fs.readFileAsync(filePath).then(file => { | ||
res.setHeader('X-AmpAdRender', 'nameframe'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Copying comment over from outdated code, with slight edits for clarity)
@lannka Re: your previous question, it turns out that the problem was here. "unwrap" was implemented backwards. If the creative is a .json file, then it should be unwrapped (signature and HTML extracted), and if it's a .html file then that is not needed (and the extension should NOT be stripped off). But "unwrap" was done the opposite way. My other main change here is the line that sets the X-AmpAdRender header, which removes the need for the change to amp-a4a.js which you weren't a fan of. Now,
amphtml/extensions/amp-a4a/0.1/amp-a4a.js
Line 611 in 49951ce
const method = fetchResponse.headers.get(RENDERING_TYPE_HEADER) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
much better. appreciate that.
filePath = pc.cwd() + filePath; | ||
fs.readFileAsync(filePath).then(file => { | ||
res.setHeader('X-AmpAdRender', 'nameframe'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
much better. appreciate that.
@@ -59,15 +59,24 @@ export class AmpAdNetworkFakeImpl extends AmpA4A { | |||
// and the signature is "FAKESIG". This mode is only allowed in | |||
// `localDev` and primarily used for A4A Envelope for testing. | |||
// See DEVELOPING.md for more info. | |||
const creative = this.transformCreativeLocalDev_(deserialized); | |||
let creative = this.transformCreativeLocalDev_(deserialized); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now i re-read the code. can we move the transformCreativeLocalDev_
logic to server side? so that we have a correct AMP ad format over the wire. ideally, this should be part of app.use('/a4a(|-3p)/'
middleware.
After that, we don't need this try-catch anymore, since we know the exact format over the wire.
again, more logic in this fake extension, the farther away we are from testing the real things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As it turns out, this change is no longer necessary - it is redundant due to the change in build-system/app.js. So I'll just remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did you try if it still works with the /a4a/xxx
style URL?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not familiar with what that is...can you give me an example or pointer to a doc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked at HEAD, and this does not currently seem to work. Unfortunately none of the team was aware of this URL format, so it's likely been broken for quite some time. If it's alright with you, I would suggest that we create a bug to fix that separately, since the current PR does not appear to be the one to have broken this functionality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good.
@@ -0,0 +1,24 @@ | |||
<!doctype html> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually, would you move this file to test/manual/fakeada4a.amp.html
, to sit together with test/manual/fakead3p.amp.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do customers know to look there? What is the intended difference between an example and a manual test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
example/
is for AMP page authors.
test/manual
is for us.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My preference would be to leave it in examples/ so that an AMP page author that wants to write a page and test including ads in it can use this. But it's up to you. Do you think this is valid/useful?
Thanks!
…On Sat, Jun 10, 2017 at 10:03 AM, keithwrightbos ***@***.***> wrote:
Merged #9295 <#9295>.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#9295 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ACV2B5psri9hXuwCvcVNm0UGGPnd4YHfks5sCqJFgaJpZM4NZdJP>
.
|