Search

Binary Jam

Simon's blog, SharePoint, Arduino type things.

Tag

javascript

BrowserSync, gulp based script, handling middleware via Corp proxy

Phew that was a long title.  So what’s this about.

I live in a land of corporate proxies with giant .pac scripts, of https services and authenticated proxies.

It …makes….all….this….js….dev… HELL.

I use browser-sync as my local testing sever, its great,  I need it to handle requests to remote apis because of CORS and other security issues, until I can wrap a proxy around the remote system, even then its handy to have the ability to proxy the api calls via a node server (browser sync) for me.

This becomes an absolute bloody nightmare when you have an authenticated corporate proxy server.

None of the JS tools play nice,  there is no such thing as a centralised store for proxy settings, so you have to enter then in the .rc file of every tool, git, npm, bower, and now the custom middleware.  This is where windows got it right and Linux, well sucks.   Oh I wish that I still had ISA servers client transparent proxy.

So the example I have here is a gulp file, that configures browser-sync to run and to call into the middleware extension to handle proxying of api calls to my remote system and for that component to play nice with the corporate proxy.

You need the agent, I tried without it and failed miserably.

gulpfile.js

var gulp = require('gulp');
var browserSync = require('browser-sync').create();
var proxy = require('http-proxy-middleware');
var HttpsProxyAgent = require('https-proxy-agent');

var proxyServer = "http://localhost:8080";   //Cos Fiddler yeh!

var jsonPlaceholderProxy = proxy('/api/', {
    target: 'https://www.binaryjam.com',
    changeOrigin: true,
    logLevel: 'debug',
    secure: true,
    agent:new HttpsProxyAgent(proxyServer)
});

gulp.task('default', function () {
  browserSync.init({
    "port": 8000,
    injectChanges: true,
    "files": ["./src/**/*.{html,htm,css,js,json}"],
    "server": { "baseDir": "./src" },
    "middleware":jsonPlaceholderProxy
  });
});

 

 

 

 

 

 

 

 

 

Adventures in BrowserSync

I’m real new to browsersync and node development. So this has been a pretty steep learning curve, but I thought I’d document something I had to figure out as the documentation and guides on the web are hard to find or just missing.

For those who don’t know and are new to this javascript lark, browsersync is tool that runs under node to create a mini web server, but also it injects javascript into your pages and communicates to the server when the file watcher sees a change to a file.

The effect of this is you can configure it, then run this thing to point at the files in your directory that you are editing, it will fire up a browser and as soon as you save a file it will reload the page.  A real cool feature is called hot reloading, in certain circumstances and configuration it can detect you have changed say an image or css file and it will only change that item in the page, it uses JS to mangle it to the new version and won’t do a full page reload.

I’m using a modified version of browsersync called lite-server, by john papa, just because it was the one I came across first. I’ll be honest I’m not sure what lite-server gives me over browsersync native, it’s just where I started.  That said, you will spend a lot of time reading the browsersync docs not the lite-server page.

The main point of me writing this article was that as well as serving pages and auto reload, browsersync gives me the ability to handle API calls and proxy them to local files (possible another server but I’m not there yet).

In the framework I’m writing, to mimic the new SP framework (early days though) experience but on legacy stuff to deliver a sandbox WSP, the example code makes a call using SPServices library (this could be REST) that call as you may know has the path _vti_bin in it.  So my browsersync config has code in it (the config is javascript) that can intercept this and deliver my content instead.

Below is the bs-config.js file I wrote to achieve this.

The module.exports is the standard bit that configures bs with what files to the watch and how to configure the mini server

The special part is the middleware setting. I have set it so that the 2nd param points to my handleApi function call.  The reason I set the 2nd param (thats the “1:” bit) is that if you clear the 1st parameter then it no longer logs to the console the items its serving, which is handy.

As you can see the handleApiCall function is real simple, it detects the “_vti_bin” in the path and reads a file from a specific place and puts it out in the response stream along with the correct headers for xml.

This could be improved, lots, it could read the request object and parse it to determine what file to send back.

Of course someone has probably already done something like this, but I needed to do something quickly and there is enough to learn.

Saything that I will be looking into proxy-middleware a module for express/browsersync that will likely proxy to a real server not just my local files.

Alternatively https://www.npmjs.com/package/apimock-middleware.

You learn there are so many OS projects out there in npm land so its hard to find the right things.

// jshint node:true
function handleApiCall(req, res, next) {
    
    if (req.url.indexOf('_vti_bin') !== -1) {
        var fs = require("fs");
        fs.readFile("./WebComponents/.container/.mockapi/1.xml",function (err, data) {
            if (err) throw err;
            res.setHeader('Content-Type', 'text/xml');
            res.end(data.toString());
        });
     
    }
    else{
        next();
    }
}

module.exports = {
    'port': 8000,
    'files': [
        './WebComponents/src/**/*.*'
    ],
    'server': {
        'baseDir': './WebComponents/src',
        'middleware': {            2:handleApiCall        }
    }
};

Braindump:Adding CORS support to old SOAP Webservice

This has been a bit of a nightmare,  once you start you will find hundreds of stackexchange articles about this and the problems you will have.

So here are some key things.

Below IE11 ? (maybe 10)  CORS support was provided with the XDR object and this wasn’t automatically used in libraries like jQuery so your jQuery stuff wont work because IE doesnt use the proper XMLHttpRequest objects or what it has is borked.  Till now at least.     So IE11 right!.

There is some simple code you need in your .NET project.

This extract of System.webserver is needed (Dont just paste this you have to insert it into an existing section of your web.config.

This will allow ANYONE to connect. So go read up what each of these attribute do.
What they will do together is all get added to the HTTP headers returned to the server on all items, yes including your aspx pages, now feel free to work out how to restrict that, I had enough by this point and my site only has two things on it both needing this.

  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <!-- CORS Enabled -->
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
        <add name="Access-Control-Allow-Headers" value="origin, content-type, accept" />
        <add name="Access-Control-Allow-Credentials" value="true" />
        <add name="Access-Control-Max-Age" value="31536000" />
      </customHeaders>
    </httpProtocol>
</system.webServer>

Next you will need a global.asax  (not a global.aspx.cs like some guides refer to)

The function Application_BeginRequest is one of those that gets called as part of the request lifecycle.
What we are doing here is handling the case when you are doing a non-standard request which for SOAP services will actually be “text/xml;”

Having a non-standard request initiates part of the CORS protocol that does what they call a pre-flight request, to ask the server, “is this allowed or what?”, you are reponding with a A=OK matey.

protected void Application_BeginRequest(object sender, EventArgs e)
{
    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    {
        HttpContext.Current.Response.StatusCode = 200;
        HttpContext.Current.Response.End();
    }
}

Thats its.  That’s all you need to do server side to do this.

A matching client side request might look like this

$.ajax({
       url: serviceUrl,
       type: "POST",
       dataType: "xml",
       data: soapEnv,
       crossDomain: true,
       contentType: "text/xml; charset="utf-8"",
})

For me all this started working.  I did all my mappings, and pushed my array into knockout observables and Chrome was working brilliantly.

Then came IE. The pain, the endless searches.

Whilst debugging this I could see my “options” (preflight) request was being made and IE reported no headers returned.  Which was nonsense cos chrome was doing it and working.

I rewrote that C# code over and over with many alternatives.  Chatted to a nodejs bloke who showed me his code, which did exactly the same (well close enough).

That code works.

I saw articles that said that the website your connecting has to be in the Intranet security zone.  Bullshit! If that’s the case how can you connect to yahoo or any other CORS compliant service.

So the one to watch when your developing this stuff.   SELF CERT SSL.

If you have created a self cert and you browse to the service in IE and its got a RED un trusted cert and it will to begin with, this wont work.  The confusing part is the chrome doesnt care, and also IE issues and gets the OPTIONS http request, instead of throwing an error before hand, it shows a 200 status, but it has to issue a request to know its not secure, its why it doesnt show any headers in the network analysis I suspect because at that point it just goes “eeek” and stops.

So export your certificate, dont next next next it,  export it specifically to “trusted root” *  DO THAT AT YOUR OWN RISK, if your not sure dont do it and go buy a proper cert to get this working.

Close your browser and check it worked by navigating to the service endpoint in the browser, if its not red it worked, if it is go do it again, but right.

With all this done you ajax call from IE11 should work with CORS.

If it don’t well good luck :-).

 

List of JS Libraries I’m using / looking into

This is more of a note to myself so that I can remember the JavaScript libraries I’m interested in and what they do and maybe a related article.  These are mainly in dealing with SharePoint but could be anything really.  Not everything is compatible with everything else remember 🙂

 

KnockoutJs – Data binding library, works with jQuery, great for a true single page app, IE no routing just data binding.  Yes I know SPA’s pages are called views.

AngularJS – Proper SPA framework, there’s Durandal but I’?m not going there even though I love knockout.

BreezeJs

    – Linq Like queries, does need server side integration, not for local objects

Bootstrap – For that nice CSS layout grids and things.

Bootstrap UI – Directives for Angular using bootstrap

Angular Maps – Google maps directives for angular, something I’ve used already.

 

LinqJs – Linq for JavaScript, will work on JS objects, doesn’t do fetch for you

Js Loaders – http://requirejs.org/  and  http://labjs.com/

jQuery – Well how could I not mention it.

jQuery form validators

Sliders – http://slippry.com/ , http://bxslider.com/, http://workshop.rs/projects/coin-slider/

fontawesome – No idea, well something to do with a shed load of CSS icons, vectors (no IE7)

Charts – jqPlot, http://www.flotcharts.org/, hicharts

Spinner – svg/vml Spinner, easier than a gif ?

 

Stuff to investigate

 

Not a library but a list of handy SP2013 dev tools

Zimmergrens SP2013 Tools Page

CEWP – Making Use of Coin Slider II – SPServices Version

Part II of the blog posts now, adding a quick tweak to auto populate the images from an ImageLibrary.

In the last post we created all the elements needed for this next piece, if you have that working then great.

First a couple of things

Get the latest SPServices version be sure to match the versions correctly especially where jQuery 1.7 and SPServices versions are concerned, changes in jQuery caused some problems in peoples libraries.  Put that library in the place you like to store them (_layouts, portal root, site collection, doc lib which ever I stuck it in my SPFolder in the site collection)

Add a new field to your Image Library, a checkbox and call it active.

Paste this code (after you modify the include statements to point at the places you stored them).

 

I haven’t put any error trapping in this code or loading pictures or messages to say activate at least one image you idiot but you can and I would if this was going on a real site. You could extend this code to get descriptions from the image library and if there was one add it to the slider text.

 







<div id="gamesHolder" style="width:468px;height:280px;overflow-y:hidden;">
    <div id="games">
    </div>
</div>

jQuery(function($) {
 
    $().SPServices(
       {         
         operation: "GetListItems",         
         async: true,         
         listName: "ImageLibrary", 
         CAMLQuery : "1",        
         CAMLViewFields: "",         
         completefunc: function(data) 
           {
                var theMiddle="";
                $(data.responseXML).find("z\:row, row").each(function(){
                    var getimage= "/" + $(this).attr("ows_FileRef").substring( $(this).attr("ows_FileRef").indexOf("#") +1 );

                    theMiddle +='<a href="' + getimage + '" target="_blank"><img src="' + getimage + '" /></a>';

                });

                $(theMiddle).appendTo('#games');
                $('#games').coinslider({ hoverPause: false, height:246, width:618});

            }
       }
    ); 


});


CEWP – Making use of Coin Slider jQuery

This post is how to use a small jQuery library within a CEWP to provide sliders.

First some pre-reqs.

Download jQuery (latest) and Coin Slider jQuery plugin.

Place the jQuery library in a

Choose one.

  • SPFolder
  • _layouts
  • Document Library
  • Any old web you have access to

 

You need to choose a location, I prefer master pages and putting things in _Layout, but if you dont have access to the server then you could utilise SharePoint Designer to create a folder in a site collection, again here I prefer the top top top  level Site Collection so that anywhere I use this the same js files come from the same place and get cached.

Place the CoinSlider CSS and JS files either in the same location (not master page though) or perhaps in the local site collection you are about to create this content in.

In my Code example I have already a jQuery in my masterpage, so I dont load it again.  I put the other files in an SPFolder in the site collection call jQueryExtras, you can reference them  from where you put them.

 

Next you need an Image Library, just create one somewhere, ideally unique for the content you are to display, as later on I might get to publish the next article that loads the images using SPServices, but then I might not.

In this image library place the images you want to slide, these should ideally be “landscape” style better still CinemaScope style. Those long thin pictures just work better in sliders. All these images MUST be the same size.

I used images from another sliders content (the nivo slider which I struggled to get to work, it was just easier than trying to find content) you could use images from your own stock or the demo just remember to change the image sizes in the right places (css/js).

Now that you have your JS and CSS includes in your locations and your image library populated with images we can create a CEWP, so on the page you want this go create one and hit the EDIT Source Editor

 

Paste this lot in, it is important that you set the height and width in the javascript to match your images, if you don’t expect lots of formatting issues. I tried this on MOSS and in IE7+ it wornt work in IE6, which is a pain for me as I have to find another slider now.

 <link rel="stylesheet" href="/sites/SliderDemo/jQueryExtras/coin-slider-styles.css">
<script src="/sites/SliderDemo/jQueryExtras/coin-slider.min.js"></script>

<div id="gamesHolder">
    <div id="games">
       <a href="http://www.binaryjam.com/" target="_blank">
          <img alt="Wall-E" src="/sites/SliderDemo/SliderImages/walle.jpg"> 
          <span><b>Wall-E</b><br>A Film about a robot. </span>
       </a>
       <a href="http://www.binaryjam.com/" target="_blank">
          <img alt="Finding Nemo" src="/sites/SliderDemo/SliderImages/nemo.jpg"> 
       </a>
       <a href="http://www.binaryjam.com/" target="_blank">
           <img alt="Toy Story" src="/sites/SliderDemo/SliderImages/toystory.jpg"> </a>
       <a href="http://www.binaryjam.com/" target="_blank">
           <img alt="Up" src="/sites/SliderDemo/SliderImages/up.jpg"> </a>
    </div>
</div>
<script>jQuery(function($) {
	$('#games').coinslider({ hoverPause: false, height:246, width:618});
});
</script>

<!-- -->

<!- Force Stupid blog code window to be bigger -->

<!-- -->

Have fun

Blog at WordPress.com.

Up ↑