AngularJS Protractor “App Already Bootstrapped” error

When attempting to run an End-to-End test in Protractor for a AngularJS web app with a non-angular login page I received the following error message:

UnknownError: Error Message => '[ng:btstrpd] App Already Bootstrapped with this Element '<html lang="en" data-ng-app=

The test took the same structure as below (NOTE: this is not the real test):

describe('Test a page', function() {
    var ptor;
 
    beforeEach(function() {
        ptor = protractor.getInstance();
 
        browser.driver.get(ptor.baseUrl + '/login');
 
        browser.driver.findElement(by.id('user_email')).sendKeys('test@example.com');
        browser.driver.findElement(by.id('user_password')).sendKeys('passpass');
 
        browser.driver.findElement(by.id('login')).click();
 
        browser.driver.wait(function() {
            return browser.driver.getCurrentUrl().then(function(url) {
                return (/\/#\/$/.test(url));
            });
        });
 
        browser.get('#/');
    });
 
    it('Should list some item on this page', function() {
        browser.get('#/page2');
 
        browser.findElements(by.css('.my-item')).then(function(results) {
            expect(results.length).toBeGreaterThan(0);
        });
 
    });
});

The Angular docs suggests the error is caused when bootstrapping the application in both the HTML and in the JS: http://docs.angularjs.org/error/ng:btstrpd. However I was not doing this.

I had added the line browser.get('#/'); to resolve an issue where Protractor was reporting:

Angular could not be found on the page

This appeared to be caused by Protractor not detecting Angular on a page it had been redirected too (i.e. from the non-angular login page to the Angular app page) so I added in the get() call to explicitly load an Angular page in, this however caused the double bootstrap issue.

It turned out this was due to having two browser.get() in one test run (in the beforeEach() and the it()). Replacing the one in the beforeEach() with the following solved the problem:

browser.driver.get('about:blank');

This clears the currently loaded page, so on the next get() call it starts again and doesn’t think the Angular app has already been bootstrapped. I couldn’t see a better way to do this in the docs, however let me know if you do know of a nicer way to solve this problem.

NSS error -8023 using AWS SDK for PHP

Please note this fix should also work on Fedora, CentOS and Redhat linux distros if you are seeing the NSS error -8023 when using CURL and PHP.

At work we came up against this odd error message from Amazon Web Services(AWS) SDK for PHP when using the SDK in a forked process on the AWS built AMI:

PHP Fatal error:  Uncaught exception 'cURL_Exception' with message 'cURL resource: Resource id #50; cURL error: SSL connect error (cURL error code 35). See http://curl.haxx.se/libcurl/c/libcurl-errors.html for an explanation of error codes.' in /usr/share/pear/AWSSDKforPHP/lib/requestcore/requestcore.class.php:829

Stack trace:
#0 /usr/share/pear/AWSSDKforPHP/sdk.class.php(1035): RequestCore->send_request()
#1 /usr/share/pear/AWSSDKforPHP/services/swf.class.php(1305): CFRuntime->authenticate('TerminateWorkfl...', Array)
#2 ....php(189): AmazonSWF->terminate_workflow_execution(Array)
#3 ....php(83): daemon->checkSWFExecutions()
#4 ....php(350): daemon->run()
#5 {main}
  thrown in /usr/share/pear/AWSSDKforPHP/lib/requestcore/requestcore.class.php on line 829

Now, cURL error 35 means “A problem occurred somewhere in the SSL/TLS handshake. You really want the error buffer and read the message there as it pinpoints the problem slightly more. Could be certificates (file formats, paths, permissions), passwords, and others.” which is a bit vague and didn’t really help. After setting the CURLOPT_VERBOSE flag in the AWS SDK for PHP we were able to see the real error message:

NSS error -8023

Continue reading

sdInteractiveChartPlugin as a stand-alone PHP Library

As promised a few times now I have finally got round to modifying the code slightly to remove any Symfony dependencies (Although there might still be some).

This download has been created using version 0.5.0 of the Symfony plugin. An example PHP page “example.php” has been added under the web directory to show the required JS scripts and a quick example of creating a chart using it. More details can be found here: http://www.symfony-project.org/plugins/sdInteractiveChartPlugin

Downloads:

sdInteractiveChart.zip

sdInteractiveChart.tar.gz

Bash Script to Create new virtual hosts on Nginx each under a different user

This script is a modified version of the original vhost creator script for nginx posted here (Actually it was a modified version of the original version of this script).

The script below will automatically create a new user on the system and adds the nginx user to the new users group. This allows FTP access to be given to the newly created user and the user will only have access to the their site and not to all vhosts running on your server, however as long as the users group has permission to access the files then nginx will still be able to serve them.

NOTE: This setup only helps lock down access to the vhost directories on a web server hosting only static sites, if CGI of any kind (i.e. PHP) is available then this will also need to be locked down so each user has access to a CGI process or set processes running as that user.

What does the script do:

  • Creates a new system user for the site
  • Creates a new vhost config file for nginx using a basic template
  • Creates a new directory for the site, within the new users home directory
  • Adds a simple index.html file to the new directory to show the site is working.
  • Makes sure the new nginx config syntax is correct before trying to reload nginx
  • Reloads Nginx to allow the new vhost to be detected

Reading User Data and Metadata on EC2

When creating a new Linux EC2 instance on AWS you’re able to pass extra data to the server to be used late in the boot sequence. This can be in the form of a simple bash script, or the URL(s) of a number of scripts. Or the data could simple by a list of parameters you need that instance to know. Full details on the sorts of things you can pass via the “User Data” parameter can be found on Ubuntu Website or details for the AWS build AMI can be found here. (Not all images can be passed User Data, but the standard ones by Amazon can be along with a range of community ones.)

Now if you pass a script or the URL to a script as User Data to your new instance then this will get run for you, and you don’t need to worry about it. However if you pass it a list of parameters (for example you may pass it the Endpoint URI for your RDS instance so the DB settings for your apps can be set up correctly) you need to know how to read the User Data. Along with reading the User Data you may also want to read in Metadata about your new instance, such as its AMI-ID or the public hostname of your instance. Reading the Metadata is done by querying a simple API:

The base URI of all the query’s is: http://169.254.169.254/

Continue reading

Nginx Configuration for Symfony

Recently when setting up a Symfony project on an Nginx powered server I found the Example configuration script found on the Nginx wiki for Symfony didn’t fully work as expected.

  1. If you added a slash to the end of the url when requesting backend.php or frontend_dev.php or similar caused the page not be found, even though under Apache this works fine and goes to the correct place. Which seemed to be caused by the script_name server param.
  2. GET parameters were not getting passed to Symfony. Caused by the arguments been removed during the try_files request.

So I modified the example config to produce the following, which as far as I can tell works exactly the same as the default .htaccess file does under Apache.

Continue reading

Automatically creating new virtual hosts with Nginx (Bash script)

NOTE: This script has been superseded by this one: Bash Script to Create new virtual hosts on Nginx each under a different user

Setting up virtual hosts on any sort of web server normally takes at least a few minutes and several commands (if you’re not running a control panel of some variety, and even then it normally takes a good number of clicks and checking boxes to get what you want). All of this can be quite annoying when you have to set up several of these a day.

So I put together a simple bash script to quickly provision the hosting for a new static site running on Nginx. The script was originally build for use on the Amazon AMI running on AWS. The script uses the sudo command as the password is not required for the default user on the AWS AMI, however if you are running as a non root user with access to the sudo command then you should be prompted for your password when running the script.

What does the script do:

  • Creates a new vhosts entry for nginx using a basic template
  • Creates a new directory for the new vhost and sets nginx as the owner
  • Adds a simple index.html file to the new directory to show the site is working.
  • Reloads Nginx to allow the new vhost to be picked up

zRSSFeed unable to load feeds with GET Parameters

zRSSFeed is a nice little RSS Reader for jQuery which uses Google’s Feeds API to parse the RSS Feed.

However if your RSS URL contains required GET variables you’ll find zRSSFeed will just display: “Feed could not be loaded.” – Or similar (if you’ve changed the default error message). There is however a really easy fix, although you will probably want to make the change in the non-minified version of the source and then re-minify. Change line 46 from:

var api = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&callback=?&q=" + url;

To:

var api = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&callback=?&q=" + encodeURIComponent(url);

This encodes the URL to allow it to be embedded as a GET parameter. (See MDN for more info…)

Edit:

Another thing I noticed with zRSSFeed is it won’t load the feed from Google over SSL if your site is using https. However this is easily fixed just modify the same line as above, from:

var api = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&callback=?&q=" + encodeURIComponent(url);

To:

var api = location.protocol + "//ajax.googleapis.com/ajax/services/feed/load?v=1.0&callback=?&q=" + encodeURIComponent(url);