Coding

Using Node.js to redirect and proxy normal HTTP+WebSocket traffics based on hostnames

Usually I used to use a single server to host several developing or experimental projects. Thus I need a quick solution to forward different request to these services. I had tried to use nginx before. But now I have a easier way to do so.

  1. require modules

  2. config proxy(forward) and redirect mappings (hostname based)

    var proxyOptions = {
    router: {
    "api.testAppX.com" : 'localhost:2041',
    "dev.api.testAppX.com" : 'localhost:2042',
    "www.testAppY.com" : 'localhost:10520',
    "test.oldApps.com" : 'localhost:10520',
    'bc.ryanwu.co' : 'localhost:8888'
    }
    },
    redirectOptions = {
    'olddomain.com' : 'http://newdomain.com/',
    'www.olddomain.com' : 'http://newdomain.com/',
    'blog.olddomain.com' : 'http://newdomain.com/blog/'
    };

Best way of singleton in Objective-C

It’s very useful during iOS development

static GeneralData __strong *generalDataObject = nil;

@synthesize currentUser;

+(GeneralData *) getInstance
{
static dispatch_once_t pred;
dispatch_once(&pred, ^{
generalDataObject = [self new];
});
return generalDataObject;
}

Usage

  1. Add Data

    firstViewController.m
    #import "GeneralData.h";

    - (IBAction) passValueButton:(id)sender {
    {
    User *user = [User new];
    user.name = "Mary Jane";
    user.age = "21";
    [GeneralData sharedInstance].currentUser = user;
    }
  2. Read Data

    secondViewController.m
    #import "GeneralData.h";

    - (void)viewDidLoad
    {
    [super viewDidLoad];
    User *loggedInUser = [GeneralData sharedInstance].currentUser;
    NSLog(@"Name : %@", loggedInUser.name);
    NSLog(@"Age : %@", loggedInUser.age);

    }

Reference : StackOverflow

JavaScript number only lock

function(event) {
// Allow: backspace, delete, tab, escape, and enter
if ( event.keyCode == 46 ||
event.keyCode == 8 ||
event.keyCode == 9 ||
event.keyCode == 27 ||
event.keyCode == 13 ||
// Allow: Ctrl+A
(event.keyCode == 65 && event.ctrlKey === true) ||
// Allow: home, end, left, right
(event.keyCode >= 35 && event.keyCode <= 39)) {
// let it happen, don't do anything
return;
}
else {
// Ensure that it is a number and stop the keypress
if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) &&
(event.keyCode < 96 || event.keyCode > 105 )) {
event.preventDefault();
}
}
}

Make UILabel glow

You have to import QuartzCore

#import <QuartzCore/QuartzCore.h>

Then apply effect on your UILabel or titleLabel.

myLabel.layer.shadowOffset = CGSizeMake(0.0, 0.0);
myLabel.layer.shadowRadius = 20.0;
myLabel.layer.shadowOpacity = 0.5;
myLabel.layer.masksToBounds = NO;

Responsive Media Query Quick Reference

media-query

Just a reminder which helps me doing responsive design’s Media Query.

  • @media (max-width: 767px)
  • @media (max-width: 480px) 
  • @media (min-width: 768px) and (max-width: 979px)
  • @media (min-width: 980px)
  • @media (min-width: 1200px)

注意 :上面的順序是有意義的 更改順序會導致CSS被蓋掉

Get current location and city name

1. Add CoreLocation.framework to your project

2. Add CLLocationManagerDelegate to your viewController

3. Initialize CLLocationManager in viewDidLoad

4. Get current location in  the delegate method
- (void)locationManager:(CLLocationManager)managerdidUpdateLocations:(NSArray)locations;


5. Use CLGeocoder to reverseGeocodeLocation

Full Code here

在ViewController 之間傳值

在iOS的開發中,我們經常會使用ViewController來控制每一個畫面的行為,
剛開始的時候最常遇到的問題就是

“怎麼在兩個ViewController之間傳遞資訊”這篇文章中我列出了幾種常見的方法,提供給大家做參考。

1. 透過實體(Instance)傳遞資訊

我們都知道,每一個ViewController 的類別(Class),不管是用Storyboard還是Nib的方式,都要先初始化(alloc + init),然後再透過這些實體(Instance)物件做操作。所以,要在彼此之間傳遞資訊,必須要取得這些實體

如果傳遞的資訊比較簡單,或是傳遞資訊的動作只有一次的時候,透過物件的實體是比較簡單的方式

範例A: 透過 Nib 的方式,取得ViewController2 的實體,傳遞資訊,指定user的值

範例B:在StoryBoard中,透過Segue 取得的實體,傳遞資訊,指定user的值

**2.透過單例(Singleton)物件傳遞** 透過物件的實體來傳遞固然很方便,但是很多時候,資訊的共享並不只存在於兩個ViewController之間,例如這個應用程式的作者資訊、目前登入者的暫存資料等等,應該是在一個共通的地方,每個人都是去同一個地方存取共通的資訊。這時我們就可以透過Singleton的方式,讓資訊傳遞更簡單。
[![](http://3.bp.blogspot.com/-_ivnC4oFHjU/UGvy1U3Z79I/AAAAAAAACUM/3HjhOjMIaxg/s640/blog2.png)](http://3.bp.blogspot.com/-_ivnC4oFHjU/UGvy1U3Z79I/AAAAAAAACUM/3HjhOjMIaxg/s1600/blog2.png)
以下是範例程式碼

iOS Web 畫面閃爍問題 (CSS3)

在iOS (iPhone 4s/ iPad 2/iPod Touch) 上測試 Mobile Web的時候出現了閃爍問題
和Team member 花了一段時間發現一個很詭異的問題
狀況
1. 父節點(DIV)因為要做Transition使用了 **<span style="color: #666666;"> </span><span style="color: blue;">transform: translate3d(…)</span>**
<span style="font-family: Arial;">2\. 畫面處理完成後,觸動事件將子節點(DIV)的CSS改變** **</span><span style="color: blue; font-family: 'Courier New';">**left : *px**</span>

就在這個更改子節點的瞬間 iOS 的畫面一定會**<span style="color: red;">閃爍一下</span>** ``測試過了 iPad / iP4s / iPod Touch 都有這問題 但是Android 2.x 4.x 都沒有…

處理方式

原本以為是iOS 的 webkit 在處理特定 position 的 left 造成子節點重畫的問題,
後來想想覺得這 也太基本了吧 不太可能,經過嘗試以及搜尋,發現很多人都有類似問題。

像是StackOverflow 這篇 還有 這篇 他是改 CSS top 導致發生神秘的閃爍事件…

最後使用動態增加translatde3d 並且 reset 的 爛招 解法   

後來將以下的 css 指定給子節點 問題就解決了

transform: translate3d(0,0,0);
-webkit-transform: translate3d(0,0,0);

補充
回家後看到jsconsole/jsbin的作者 Remy Sharp 大大的影片

造成我畫面閃動的原因 應該是跟iOS的硬體加速有關

故需要Reset translate3d …..

真。他x的  上一次遇到這種神秘的問題 是面對高級瀏覽器 IE 6 …………… 

References
http://stackoverflow.com/questions/tagged/translate3d

Request Https resource in Java

This article is about how to request resource from an HTTPS resource. e.g. https://a.b.c.d/test-metadata.xml

We have to do following two things

  • Trust all certificates (PKIX path building failed)
  • Pass SSL handshake verification (javax SSLHandshakeException)
  • Pass basic (username/password) authentication (401, Authentication Required)
import java.io.*;
import java.net.*;
import java.security.cert.*;
import javax.net.ssl.*;

public class HttpsRequestClient {
private final String USERNAME = "ryanwu";
private final String PASSWORD = "mypwd";
private final String TESTURL = "https://a.b.c.d/test-metadata.xml";

public static void main(String[] args) {
HttpsRequestClient client = new HttpsRequestClient();
switch (args.length) {
case 0:
client.testURL();
break;
case 1:
client.testURL(args[0]);
case 3:
client.testURL(args[0], args[1], args[2]);
default:
client.testURL();
}

}

public void testURL() {
testURL(TESTURL, USERNAME, PASSWORD);
}

public void testURL(String url) {
testURL(url, USERNAME, PASSWORD);
}

public void testURL(String testURL, final String name, final String pwd) {

HttpsURLConnection testConnection = null;
try {
// Trust All HttpsCertificates
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[] { new AllPassTrustManager() }, null);

// Pass handshake verification
HostnameVerifier myHostnameVarifier = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
return true;
}
};

// Configuration
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(myHostnameVarifier);
Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(name, pwd.toCharArray());
}
});

testConnection = (HttpsURLConnection) new URL(testURL).openConnection();

printHttpsCertificates(testConnection);
printResponseContent(testConnection);

} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (testConnection != null)
testConnection.disconnect();
}

}

private static void printHttpsCertificates(HttpsURLConnection con) {
try {
System.out.println("-----Certificates-----");
System.out.println("Response Code : " + con.getResponseCode());
System.out.println("Cipher Suite : " + con.getCipherSuite());
System.out.println(System.getProperty("line.separator"));

Certificate[] certs = con.getServerCertificates();
System.out.println("Certificate Number : " + certs.length);
for (int i = 0; i < certs.length; i++) {
Certificate cert = certs[i];
System.out.println("No : " + i);
System.out.println("Cert Type : " + cert.getType());
System.out.println("Cert Hash Code : " + cert.hashCode());
System.out.println("Cert Public Key Algorithm : " + cert.getPublicKey().getAlgorithm());
System.out.println("Cert Public Key Format : " + cert.getPublicKey().getFormat());
System.out.println(System.getProperty("line.separator"));
}
} catch (SSLPeerUnverifiedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

private static void printResponseContent(HttpsURLConnection con) {
try {
System.out.println("-----Content-----");
BufferedReader br = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String input;
while ((input = br.readLine()) != null) {
System.out.println(input);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* A TrustManager which passes all certificates
*
* @see TrustManager
*/
private class AllPassTrustManager implements TrustManager, X509TrustManager {
public X509Certificate[] getAcceptedIssuers() {
return null;
}

public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
return;
}

public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
return;
}
}
}
````


With [HttpClient](http://hc.apache.org/httpcomponents-client-ga/index.html), the testURL method will become easier


````Java
public void testURL(String testURL, String name, String pwd) {
DefaultHttpClient httpclient = new DefaultHttpClient();
try {
// Trust all https certificates
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[] { new AllPassTrustManager() }, null);
// Use apache SSLSocketFactory
httpclient.getConnectionManager().getSchemeRegistry()
.register(new Scheme("https", 443, new SSLSocketFactory(sc)));
httpclient.getCredentialsProvider().setCredentials(
new AuthScope(AuthScope.ANY_HOST, 443),
new UsernamePasswordCredentials(name, pwd));
HttpGet httpget = new HttpGet(testURL);
ResponseHandler<String> handler = new ResponseHandler<String>() {
public String handleResponse(HttpResponse response)
throws ClientProtocolException, IOException {
System.out.println("Response Status : " + response.getStatusLine());
System.out.println("-----Content-----");
HttpEntity entity = response.getEntity();
if (entity != null) {
return EntityUtils.toString(entity);
} else {
return null;
}
}
};
System.out.println(httpclient.execute(httpget, handler));
} catch (Exception e) {
e.printStackTrace();
} finally {
httpclient.getConnectionManager().shutdown();
}
}