Skip to content
This repository has been archived by the owner on Jun 10, 2020. It is now read-only.

Allow Option to Include JavaScript from a Seperate File #120

Closed
RehanSaeed opened this issue Nov 11, 2015 · 16 comments
Closed

Allow Option to Include JavaScript from a Seperate File #120

RehanSaeed opened this issue Nov 11, 2015 · 16 comments

Comments

@RehanSaeed
Copy link
Contributor

For those using the Content-Security-Policy (CSP) HTTP header, including inline JavaScript is not allowed. Would it be possible for Microsoft to create and use a CDN which returns the client side JavaScript? The instrumentation key could be included in the query string portion of the URL. So something like this:

<script src="https://application-insights.com?key=[INSTRUMENTATION KEY]"></script>
@SergeyKanzhelev
Copy link
Contributor

You can host it in your own domain as mentioned in this blog post. Hosting it on CDN wouldn't work as desired - see explanation of it here: Specifically this

... this script is working in application domain so it can subscribe on onerror callback and get a full error stack. Due to security restrictions browser will not give you the full error stack if you subscribe on onerror callback from the script downloaded from the different domain. It also takes cookies from application domain so they can be used for user/session tracking.

@RehanSaeed
Copy link
Contributor Author

So you can have a separate file, as long as it's in the same domain. I suppose you could also use the script hash or nonce to get inline scripts working with CSP securely. Either way is not great but worth it to get app insights working.

@SergeyKanzhelev
Copy link
Contributor

In aspnet5 it's very easy to implement. Something like pseudocode:

app.Use((reaquest, next) => { if (request.Url.Contains("ai.0.js") ) request.Response.Write(new httpclient.DownloadStringAsync("from "//az416426.vo.msecnd.net/scripts/a/ai.0.js"");})

and than just reference ai.0.js from the app's domain

@SergeyKanzhelev
Copy link
Contributor

BTW, thanks for reporting the issue and using Application Insights!

@RehanSaeed
Copy link
Contributor Author

Even better you can read the instrumentation key from config.json in your gulpfile.js file, then use gulp-replace to inject the key into the app insights JavaScript file.

I intend to add an app insights feature implemented as above to ASP.Net MVC Boilerplate this weekend.

@SergeyKanzhelev
Copy link
Contributor

Cool. Send me a link

BTW, in my example pseudo code I should have been using class JavaScriptSnippet instead of downloading script from CDN =)

@RehanSaeed
Copy link
Contributor Author

Will do. The basic idea is:

var replace = require("gulp-replace"),    // String replace (https://www.npmjs.com/package/gulp-replace/)
var config = require("./config.json");    // Read the config.json file into the config variable.

gulp.task('insert-application-insights-key', function(){
  gulp.src(['scripts/application-insights.js'])
    .pipe(replace('[ApplicationInsightsInstrumentationKey]', config.ApplicationInsights.InstrumentationKey))
    .pipe(gulp.dest('wwwroot/js/application-insights.js'));
});

The application-insights.js file under the scripts folder should look like this:

var appInsights=window.appInsights||function(config){
    function s(config){t[config]=function(){var i=arguments;t.queue.push(function(){t[config].apply(t,i)})}}var t={config:config},r=document,f=window,e="script",o=r.createElement(e),i,u;for(o.src=config.url||"//az416426.vo.msecnd.net/scripts/a/ai.0.js",r.getElementsByTagName(e)[0].parentNode.appendChild(o),t.cookie=r.cookie,t.queue=[],i=["Event","Exception","Metric","PageView","Trace"];i.length;)s("track"+i.pop());return config.disableExceptionTracking||(i="onerror",s("_"+i),u=f[i],f[i]=function(config,r,f,e,o){var s=u&&u(config,r,f,e,o);return s!==!0&&t["_"+i](config,r,f,e,o),s}),t
}({
    instrumentationKey:"[ApplicationInsightsInstrumentationKey]"
});

window.appInsights=appInsights;
appInsights.trackPageView();

@SergeyKanzhelev
Copy link
Contributor

Consider using this package to get snippet from if possible.

nuget install Microsoft.ApplicationInsights.JavaScript -Pre -OutputDirectory "c:\temp\nugets"
cd c:\temp\nugets
cd .\Microsoft.ApplicationInsights.JavaScript.0.15.0-build58334\tools\
cat .\prefix.html

@RehanSaeed
Copy link
Contributor Author

That package has a prefix.html file with the script snippet in it. Is that what you mean? If so, being a .html file, it's not very easy to consume from Gulp. I would have to strip out the <script> tags.

It would be nice to have a NuGet package that I can take the .js from, rather than having to keep it up to date myself. Could this package be updated to include this?

@SergeyKanzhelev
Copy link
Contributor

Feel free to send PR for our NuGet. NuGet definition is here: https://github.com/Microsoft/ApplicationInsights-JS/blob/master/JavaScript/NuGet.JavaScript/Package.nuspec

@RehanSaeed
Copy link
Contributor Author

I don't mind raising a PR. Comments added to your new issue.

@RehanSaeed
Copy link
Contributor Author

@SergeyKanzhelev I've updated the ASP.NET MVC Boilerplate project template. You can now create a new project and enable Application Insights by selecting the feature below:

applicationinsights

It uses the gulp-replace method I explained above, so you can now try it out. I have taken a copy of your script and created an application-insights.js file but ideally this would be in Bower.

@RehanSaeed
Copy link
Contributor Author

FYI, I spotted an applicationinsights-js bower package with the snippet.js file in it. You can now use that file in ASP.NET Core.

@RehanSaeed
Copy link
Contributor Author

@SergeyKanzhelev In your early message you mentioned that hosting the app insights snippet on a CDN would not work but if I add the crossorigin attribute to enable reporting of errors from third party scripts (See https://raygun.com/blog/2015/05/fixing-script-errors/), then would this not work?

@RehanSaeed RehanSaeed reopened this Nov 27, 2016
@SergeyKanzhelev
Copy link
Contributor

@RehanSaeed I think this would work. However we still want Application Insights API to work before scripts loaded. Like "appInsights.trackTrace()". So you can report that something happened during the loading time. So we still want a snippet to be part of a page and it's easier to include onerror handler there. However I believe you the solution you proposing is a nice one for the certain customers who needs speed and knows what they are doing in terms of telemetry reporting. If you will manage it to work - I think it can make a nice blog post or documentation page.

@RehanSaeed
Copy link
Contributor Author

Talking of a blog post, I wrote 'Making Application Insights Fast and Secure'.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants