Uploading a file using CURL to S3 AWS

This is a simple way to upload a file CURL. The type i am doing is an “IPA” file which is an Apple iTunes binary. You need to change the contentType to your liking. This script is awesome for backups and other devops needs.

Example of upload_s3.sh:

file=$1
bucket=YOUR_BUCKET
resource="/${bucket}/${file}"
contentType="application/x-itunes-ipa"
dateValue=`date -R`
stringToSign="PUT\n\n${contentType}\n${dateValue}\n${resource}"
s3Key=YOUR_KEY_HERE
s3Secret=YOUR_SECRET
echo "SENDING TO S3"
signature=`echo -en ${stringToSign} | openssl sha1 -hmac ${s3Secret} -binary | base64`
curl -vv -X PUT -T "${file}" \
  -H "Host: ${bucket}.s3.amazonaws.com" \
  -H "Date: ${dateValue}" \
  -H "Content-Type: ${contentType}" \
  -H "Authorization: AWS ${s3Key}:${signature}" \

https://${bucket}.s3.amazonaws.com/${file}

~                                             

To use:

sh upload_s3.sh yourfile.ipa

AWS Moving mysql to a new volume

Ugh. I am out of space on an old mysql box. Moving to a new volume on AWS is pretty easy here are my notes. The only real catch here is TO REMEMBER to add it to fstab.

Creating a new volume

1) Create a new volume on ec2
2) Attach this new volume to the instance you want through their GUI.  You can just click on a volume and click on attach to instance
3) ssh to the instance
4) fdisk /dev/xvdf
5)  mkfs.ext3 /dev/xvdf
6)  mount -t ext3 /dev/xvdf /disk
7)  vi /etc/fstab
8)  add /dev/xvdf       /disk   ext3    defaults,owner,errors=remount-ro 1      2
9) then fdisk -l to see your new hd, and df -H

Moving mysql to new position

1) rsync -vaC /var/lib/mysql/ /disk/mysql/
2) edit my.cnf and add:
   innodb_data_home_dir = /disk/ibdata
   log_bin                 = /disk/mysql-bin.log
3) mv /var/lib/mysql/ibdata /disk/ibdata/
4) service mysqld restart
5) then make sure mysql is running etc, and the slave is working

Using Ruby on Rails and AWS SNS to send APNS

SNS from AWS now offers a great way to send mobile APNS messages to your users. Sure you can blow away money with urban airship. The great part is that AWS can keep track of endpoints that fail, does a queue system for you and AWS gives great error messages back when a APNS fails. Before we would have to read in a stream from apple’s push notification servers to see if the message failed and deal with all the bizarre time outs. The cost with AWS SNS is really cheap as well.

Setting up a SNS app

To setup an app simply open up your p12 file and copy paste the two sections of your p12 file into these boxes below on AWS. You can open your p12 file by using just an editor like VI.

Screen Shot 2014-03-17 at 8.34.02 PM

Setting up SNS AWS

Create endpoints. Once you have an app setup with the correct p12 / pem file you can now create endpoints. An endpoint is a APNS token that can hold a value. We place the account_id into this value. In the image below you can see a User Data field. We add the account_id into that column.

Screen Shot 2014-03-17 at 8.27.05 PM

Code Time

First you want to get the AWS gem for ruby and install it. Once you have it installed you can try and setup an endpoint from the API. The code looks complicated but the only thing it is doing is getting an endpoint with the apns token passed from the mobile client.

arn = 'arn:aws:sns:us-east-1::app/APNS/.iOS.Production'
endpoint = AWS.sns.client.create_platform_endpoint :platform_application_arn => arn, :token => params[:apns_token from_mobile_device], :custom_user_data => user.id, :attributes => {}

Now you have an endpoint. With this you can message away.

out_message = {:m=>"Hi",:someotherdata=>"f19b9"}
apns_string[:aps] = {:alert => out_message, :sound => 'receive_message.wav', :badge => 1 }
aws_message = {:default => out_message,:APNS => apns_string.to_json}

AWS.sns.client.publish :message => aws_message.to_json, :target_arn => endpoint, :message_structure => 'json'

Cool parts of the AWS GUI.

You can publish / send an sms right there in the GUI. You can also see what tokens are enabled and disabled. Before you had to keep track of all these your self in a monster mySQL table.

Screen Shot 2014-03-17 at 8.56.41 PM

Loading files locally from a iOS webview

Ran into this issue yesterday. I am using a webView to develop a prototype in HTML5. The problem is that my webView accesses an external file index.html. If you try and file the standard file:// protocol you will get strange security issues and the files wont load. The solution is below, basically we had to use myapp:// protocol which is defined by the iOS app.

#---- Place this by your webview

[NSURLProtocol registerClass:[NSURLProtocolCustom class]];



#---- "NSURLProtocolCustom.h"

@interface NSURLProtocolCustom : NSURLProtocol
@end

#---- "NSURLProtocolCustom.m"

#import "NSURLProtocolCustom.h"

@implementation NSURLProtocolCustom

+ (BOOL)canInitWithRequest:(NSURLRequest*)theRequest
{
    if ([theRequest.URL.scheme caseInsensitiveCompare:@"myapp"] == NSOrderedSame) {
        return YES;
    }
    return NO;
}

+ (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)theRequest
{
    return theRequest;
}

- (void)startLoading
{
    NSURLResponse *response = [[NSURLResponse alloc] initWithURL:self.request.URL 
                                                        MIMEType:@"image/png" 
                                           expectedContentLength:-1 
                                                textEncodingName:nil];
  
    NSMutableString *FileName  = [[self.request.URL.absoluteString stringByReplacingOccurrencesOfString:@"myapp://" withString:@""] stringByReplacingOccurrencesOfString:@".png" withString:@""]; 
    NSString *imagePath = [[NSBundle mainBundle] pathForResource:FileName ofType:@"png"];  
    NSData *data = [NSData dataWithContentsOfFile:imagePath];
    
    NSLog(@"---- DATA URL"); 
    NSLog(imagePath); 
    
    [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
    [[self client] URLProtocol:self didLoadData:data];
    [[self client] URLProtocolDidFinishLoading:self];
}

- (void)stopLoading
{
    NSLog(@"request cancelled. stop loading the response, if possible");
}

@end

Detect ipad with standard CSS

It is possible to detect ipad users and simply over ride their css properties. Most of the examples from the internet tubes didn’t seem to work. These did:

.ui-page {
	min-height: 480px;
}

@media only screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:portrait) {

	.ui-page {
		min-height: 1024px !important;
	}
}

@media only screen and (min-device-width: 961px) and (max-device-width: 2048px) and (orientation:portrait) {
/** Ipad3 ***/ 
	.ui-page {
		min-height: 2048px !important;
	}
}