how to get data from website through URL - javascript

i am trying to create an ios appplication which can data from website and can show me in an application.Is there any way though which i can get data from a website and show that data into my ios application?? please guide if something you have for me

Most sites expect a GET request.
Open a network connection to the server on port 80. Send the text "GET /rest_of_url" and read the text that comes back. It is up to you what you do with the response.
Try it with a simple raw terminal like putty to see how the server responds before going too deep coding.
Secure sites with https will take more work.

If I understand what you want, you can get datas from your URL with the following code
-(void) getDataWithCompletionHandler:(void(^ _Nonnull)(void))completion{
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setHTTPMethod:#"GET"];
[request setURL:[NSURL URLWithString:self.url]];
[self setRequestProperty:request];
[[[NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration] delegate:self delegateQueue:Nil] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable retour, NSError * _Nullable error) {
[self handleResponse:completion withDatas:data andTheHTTPResponse:retour];
}] resume];
}

Related

Node.js POST API and parsing of request body

being a Node newbie, I seem to be struggling with some very basic steps. Can someone point me in the right direction please?
Essentially, I'm trying to send an input from an iOS (Objective-C) client to a Node.js server, but somehow not able to parse the http message body. In fact the data being posted from the client is not even appearing in the request if I log the same in the POST API on the server. I can confirm the endpoints are correct since other logs are getting printed... Here's my iOS and Node code - seems to be pretty straightforward...
Appreciate your inputs...
iOS code:
- (IBAction)sendUsername:(id)sender
{
NSMutableURLRequest *postRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://MYURL:PORT/registerUser"]];
NSDictionary *sentData = [[NSDictionary alloc] initWithObjectsAndKeys:#"socool", #"username", nil];
NSError *theError = nil;
NSData *postData = [NSJSONSerialization dataWithJSONObject:sentData options:NSJSONWritingPrettyPrinted error:&theError];
[postRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[postRequest setHTTPMethod:#"POST"];
[postRequest setHTTPBody:postData];
// Have tried with both - initWithRequest and with sendSyncRequest - both dont show the req.body on the server...
// NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:postRequest delegate:self];
NSError *returnedError = nil;
NSURLResponse *urlResponse = [[NSURLResponse alloc] init];
NSData *dataResponse = [NSURLConnection sendSynchronousRequest:postRequest returningResponse:&urlResponse error:&returnedError];
}
Node.js code:
app.post('/registerUser', function(req, res) {
console.log("Request to register new user received"); // This gets printed successfully...
body = [];
body = Buffer.concat(body).toString();
console.log("Targeted output is: ", req.body.username); // req.body itself keeps coming as undefined.
});
It looks like you're using ExpressJS. If that's the case, prior to setting up your route with app.post, did you specify a bodyParser?
Take a look at this: http://expressjs.com/en/api.html
Specifically, the 'req.body' section.
Express relies upon a middleware that is going to intercept the request, parse it, and then fill req.body with it.

What Websocket library for a Node.js server works best with iOS clients?

On the iOS clients, I'm using SocketRocket by Square: https://github.com/square/SocketRocket
Everywhere I have looked, I have found comparisons of Websocket libraries based on web applications accessed from browser, or queried in a database, but nothing as yet for clients that are iOS smartphone apps.
The clients would connect to the remote server on request through the app (i.e. the connection isn't "always-on" or done through a mobile browser or proxy or GameCenter), and, once connected, be paired with other clients in a two-player "game" situation. Until a match ends, the connection would need to persist, and the server would be responsible for timing each user's turn and receiving & issuing commands from/to each user, sort of like a turn-based game except each turn has a server-managed time limit. After a match ends (generally 15-20 minutes), if a user doesn't want another match with another random opponent, then the connection would be closed and the user logged off; users that want to continue would then be matched with another user by the hosting server (running Node.js and the Websocket library).
Some of the options I have considered include
Socket.IO 1.0: http://socket.io/
Sockjs: https://github.com/sockjs
ws: https://github.com/einaros/ws
nodejs-websocket: https://www.npmjs.com/package/nodejs-websocket
but heard from https://medium.com/#denizozger/finding-the-right-node-js-websocket-implementation-b63bfca0539 that Socket.IO isn't optimal for heavy user traffic (and I'm anticipating more than 300 users requesting matches at any one point), and that Sockjs doesn't have some command query feature, but didn't quite find a conclusive answer in the context of smartphones or iOS devices -- not browsers -- either way, in any situation.
The question is what Node.js server Websocket library might play nicest or interface with the fewest stability/scalability/complexity concerns with the iOS clients running SocketRocket? The SocketRocket wiki itself isn't helpful as it uses a Python/Go-based server side test.
EDIT: Potentially helpful resource:
http://www.teehanlax.com/blog/how-to-socket-io-swift/
Only missing thing is a comparison or discussion of other potential websocket APIs, not just Socket.IO. But this is a start in that it seems to be working with the latest iOS, SocketRocket, and Socket.IO builds.
I like Sockjs because it is simple. Here is an implementation for SocketRocket --> Sockjs that works as proof of concept
NEED:
-SocketRocket (add libicucore.dylib, Security.framework and CFNetwork.framework to your project)
-Node.js
-Sockjs Server
SERVER:
var http = require('http'),
sockjs = require('sockjs'),
sockserver = sockjs.createServer(),
connections = [];
sockserver.on('connection', function(conn) {
console.log('Connected');
connections.push(conn);
conn.on('data', function(message) {
console.log('Message: ' + message);
// send the message to all clients
for (var i=0; i < connections.length; ++i) {
connections[i].write(message);
}
//
});
conn.on('close', function() {
connections.splice(connections.indexOf(conn), 1); // remove the connection
console.log('Disconnected');
});
});
var server = http.createServer();
sockserver.installHandlers(server, {prefix:'/sockserver'});
server.listen(3000, '0.0.0.0'); // http://localhost:3000/sockserver/websocket
CLIENT (ViewController.m):
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
{
SRWebSocket *myWebSocket;
__weak IBOutlet UILabel *connectionStatus;
__weak IBOutlet UITextView *myTextView;
}
- (void)viewDidLoad {
[super viewDidLoad];
connectionStatus.textColor = [UIColor redColor];
myWebSocket = [[SRWebSocket alloc] initWithURL:[[NSURL alloc] initWithString:#"http://localhost:3000/sockserver/websocket"]];
myWebSocket.delegate = self;
[myWebSocket open];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message{
myTextView.text = message;
NSLog(#"message: %#",message);
}
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean{
connectionStatus.text = #"Disconnected";
connectionStatus.textColor = [UIColor redColor];
}
- (void)webSocketDidOpen:(SRWebSocket *)webSocket{
connectionStatus.text = #"Connected";
connectionStatus.textColor = [UIColor greenColor];
}
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error{
}
#end
src: http://nunoferro.pt/?p=22

Pushwoosh phonegap plugin, retrieving device ID

I'm using the pushwoosh phonegap plugin for push notifications. After successful registration I need to store the device ID that the registration used in the "hwid" parameter so that I can target push notifications that I send with this same device ID. This works great on Android since it seems the phonegap device.uuid is the same ID that the pushwoosh plugin is sending to their servers. However, on ios the device.uuid returns a different ID than what is sent to pushwoosh. I can see from the Xcode console log the hwid that the plugin is sending to pushwoosh but cannot figure out where they are getting this ID from and how to access the same ID within phonegap.
EDIT: I was hoping the getRemoveNotificationStatus function would return this info but it actually returns less than the registerDevice callback.
UPDATE: Ok, from digging through their plugin code I see where they are constructing this ID that they send to their servers. Not sure why this ID isn't accessible through the phonegap plugin since this is the ID that I ultimately need to have in order to target a push notification to the specific device.
Their code:
(NSString *) uniqueDeviceIdentifier{
NSString *macaddress = [self macaddress];
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
NSString *stringToHash = [NSString stringWithFormat:#"%#%#",macaddress,bundleIdentifier];
NSString *uniqueIdentifier = [self stringFromMD5:stringToHash];
return uniqueIdentifier;
}
- (NSString *) uniqueGlobalDeviceIdentifier{
// >= iOS6 return identifierForVendor
UIDevice *device = [UIDevice currentDevice];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"6.1")) {
if ([device respondsToSelector:#selector(identifierForVendor)] && [NSUUID class]) {
NSUUID *uuid = [device identifierForVendor];
return [uuid UUIDString];
}
}
// Fallback on macaddress
NSString *macaddress = [self macaddress];
NSString *uniqueIdentifier = [self stringFromMD5:macaddress];
return uniqueIdentifier;
}
Are you sure that you need the hwid?
When I use the Pushwoosh Remote API to send push messages to individual devices I target using the "devices" tag and then just supply the deviceToken of the devices I wish to message.
The device token is easily accessible as it's part of the status-return from the plugin (status['deviceToken']).
As I posted here.
I found a work-around for anyone who needs this. Just open up the class "PWRequest.m" in xcode. Add the code below just under "[dict setObject:hwid forKey:#"hwid"];" in the NSMutableDictionary method.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"hwidfile2.txt"];
NSLog(#"From Echo Class File Path: %#", filePath);
NSString *str = hwid;
This will save a text file to your local app directory in which you can access from your Javascript code. For example, you can use this JS code to access and print the hwid to the console. Just call the 'readPwfile(filename)' function, passing in the name of your file as the function argument.
function readPWFile(fileName){
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem){
fileSystem.root.getFile(fileName, null, gotReadFileEntry, fail);
});
function gotReadFileEntry(fileEntry) {
fileEntry.file(gotFile, fail);
}
function gotFile(file){
//readDataUrl(file);
readAsText(file);
}
function readAsText(file) {
var reader = new FileReader();
reader.onloadend = function(evt) {
console.log('Reading file... hwig Result: '+evt.target.result);
};
reader.readAsText(file);
}
}

Issuing a synchronous HTTP GET request or invoking shell script in JavaScript from iOS UIAutomation

I am trying to use Apple's UIAutomation to write unit tests for an iOS Application that has a server-side component. In order to setup the test server in various states (as well as simulate two clients communicating through my server), I would like to issue HTTP get requests from within my javascript-based test.
Can anyone provide an example of how to either issue HTTP GET requests directly from within UIAutomation javascript tests, or how to invoke a shell script from within my UIAutomation javascript tests?
FWIW, most of the core objects made available by all browsers are missing within the UIAutomation runtime. Try to use XMLHTTPRequest for example and you will get an exception reporting that it cannot find the variable.
Thanks!
Folks,
I was able to work around this by sending HTTP requests to the iOS client to process and return the results in a UIAlertView. Note that all iOS code modifications are wrapped in #if DEBUG conditional compilation directives.
First, setup your client to send out notifications in the event of a device shake. Read this post for more information.
Next, in your iOS main app delegate add this code:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(deviceShakenShowDebug:)
name:#"DeviceShaken"
object:nil];
Then add a method that looks something like this:
- (void) deviceShakenShowDebug:(id)sender
{
if (!self.textFieldEnterDebugArgs)
{
self.textFieldEnterDebugArgs = [[[UITextField alloc] initWithFrame:CGRectMake(0, 0, 260.0, 25.0)] autorelease];
self.textFieldEnterDebugArgs.accessibilityLabel = #"AlertDebugArgsField";
self.textFieldEnterDebugArgs.isAccessibilityElement = YES;
[self.textFieldEnterDebugArgs setBackgroundColor:[UIColor whiteColor]];
[self.tabBarController.selectedViewController.view addSubview:self.textFieldEnterDebugArgs];
[self.tabBarController.selectedViewController.view bringSubviewToFront:self.textFieldEnterDebugArgs];
}
else
{
if ([self.textFieldEnterDebugArgs.text length] > 0)
{
if ([self.textFieldEnterDebugArgs.text hasPrefix:#"http://"])
{
[self doDebugHttpRequest:self.textFieldEnterDebugArgs.text];
}
}
}
}
- (void)requestDidFinishLoad:(TTURLRequest*)request
{
NSString *response = [[[NSString alloc] initWithData:((TTURLDataResponse*)request.response).data
encoding:NSUTF8StringEncoding] autorelease];
UIAlertView *resultAlert =
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Request Loaded",#"")
message:response
delegate:nil
cancelButtonTitle:NSLocalizedString(#"OK",#"")
otherButtonTitles:nil] autorelease];
resultAlert.accessibilityLabel = #"AlertDebugResult";
[resultAlert show];
}
This code will add a UITextField to the very top view controller after a shake, slapped right above any navigation bar or other UI element. UIAutomation, or you the user, can manually enter a URL into this UITextField. When you shake the device again, if the text begins with "http" it will issue an HTTP request in code (exercise for the reader to implement doDebugHttpRequest).
Then, in my UIAutomation JavaScript file, I have defined the following two functions:
function httpGet(url, delayInSec) {
if (!delayInSec) delay = 1;
var alertDebugResultSeen = false;
var httpResponseValue = null;
UIATarget.onAlert = function onAlert(alert) {
httpResponseValue = alert.staticTexts().toArray()[1].name();
alert.buttons()[0].tap();
alertDebugResultSeen = true;
}
var target = UIATarget.localTarget();
var application = target.frontMostApp();
target.shake(); // bring up the input field
application.mainWindow().textFields()["AlertDebugArgsField"].setValue(url);
target.shake(); // send back to be processed
target.delay(delayInSec);
assertTrue(alertDebugResultSeen);
return httpResponseValue;
}
function httpGetJSON(url, delayInSec) {
var response = httpGet(url, delayInSec);
return eval('(' + response + ')');
}
Now, in my javascript file, I can call
httpGet('http://localhost:3000/do_something')
and it will execute an HTTP request. If I want JSON data back from the server, I call
var jsonResponse = httpGetJSON('http://localhost:3000/do_something')
If I know it is going to be a long-running call, I call
var jsonResponse = httpGetJSON('http://localhost:3000/do_something', 10 /* timeout */)
I've been using this approach successfully now for several weeks.
Try performTaskWithPathArgumentsTimeout
UIATarget.host().performTaskWithPathArgumentsTimeout("/usr/bin/curl", "http://google.com", 30);
Just a small correction. The answer that suggests using UIATarget.host().performTaskWithPathArgumentsTimeout is an easy way to make a request on a URL in iOS 5.0+, but the syntax of the example is incorrect. Here is the correct way to make this call:
UIATarget.host().performTaskWithPathArgumentsTimeout("/usr/bin/curl", ["http://google.com"], 30);
The "[" around the "args" param is important, and the test will die with an exception similar to the following if you forget the brackets:
Error: -[__NSCFString count]: unrecognized selector sent to instance
Here is a fully working example that hits google.com and logs all the output:
var result = UIATarget.host().performTaskWithPathArgumentsTimeout("/usr/bin/curl", ["http://www.google.com"], 30);
UIALogger.logDebug("exitCode: " + result.exitCode);
UIALogger.logDebug("stdout: " + result.stdout);
UIALogger.logDebug("stderr: " + result.stderr);
+1 for creative use of "shake()". However, that's not an option for some projects, especially those that actually use the shake feature.
Think outside the box. Do the fetching with something else (Python, Ruby, node.js, bash+wget, etc). Then, you can use the pre-canned response and auto-generate the ui-test.js on the fly by including that dynamically generated json payload as the "sample data" into the test. Then you simply execute the test.
In my opinion, the test is the test, leave that alone. The test data you are using, if it's that dynamic, it ought to be separated from the test itself. By doing it this way of fetching / generating JSON, and referencing it from the test, you can update that JSON however often you like, either immediately right before every test, or on a set interval like when you know the server has been updated. I'm not sure you would want to generate it while the test is running, that seems like it would create problems. Taking it to the next level, you could get fancy and use functions that calculate what values ought to be based on other values, and expose them as "dynamic properties" of the data, rather than that math being inside the test, but at that point I think the discussion is more of an academic one rather than the practical one of how.
Apple has recently updated UIAutomation to include a new UIAHost element for performing a task on the Host that is running the instance of Instruments that is executing the tests.

Can I handle alert inside UIWebViewDelegate?

<script language="javascript">
alert("Hell! UIWebView!");
</script>
I can see the alert message inside my UIWebView but can I handle this situation?
Update:
I'm loading a web-page into my UIWebView:
- (void)login {
NSString *requestText = [[NSString alloc] initWithFormat: #"%#?user=%#&password=%#", DEFAULT_URL, user.name, user.password]; // YES, I'm using GET request to send password :)
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:requestText]];
[webView loadRequest:request];
}
The target page contain a JS. If user name or password is incorrect this JS show alert.
I have not any access to its sources.
I want to handle it inside my UIWebViewDelegate.
A better solution to this problem is to create a Category for UIWebView for the method
webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:
So that you can handle the alert event in any way that you'd like. I did this because I don't like the default behavior of UIWebView when it puts the filename of the source in the UIAlertView title. The Category looks something like this,
#interface UIWebView (JavaScriptAlert)
- (void)webView:(UIWebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame;
#end
#implementation UIWebView (JavaScriptAlert)
- (void)webView:(UIWebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame {
UIAlertView* dialogue = [[UIAlertView alloc] initWithTitle:nil message:message delegate:nil cancelButtonTitle:#"Okay" otherButtonTitles:nil];
[dialogue show];
[dialogue autorelease];
}
#end
This seems to do it:
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
JSContext *ctx = [webView valueForKeyPath:#"documentView.webView.mainFrame.javaScriptContext"];
ctx[#"window"][#"alert"] = ^(JSValue *message) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"JavaScript Alert" message:[message toString] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
};
}
Note: only tested on iOS 8.
If by "contain a flash" you mean the page you're loading into your web view has an Adobe Flash movie in it, you're out of luck, I'm afraid. Mobile Safari doesn't support Flash, and most likely never will.
In the general case, if you want JavaScript running in a web view to communicate with the native app hosting it, you can load fake URLs (for example: "myapp://alert?The+text+of+the+alert+goes+here."). That will trigger the webView:shouldStartLoadWithRequest:navigationType: delegate method. In that method, inspect the request, and if the URL being loaded is one of these internal communications, trigger the appropriate action in your app, and return NO.

Categories