Reverse proxy inside OSX application - objective-c

Is there any reverse proxy that can be embedded within OSX application written in Objective-C? I need to develop application which is going to have reverse proxy embedded inside but not to use an external proxy server instance. Did someone used Nginx that way?

It's technically possible. I think your idea of using Nginx would work. Why did you call out Objective-C specifically? I don't see why you wouldn't use one written in plain C (there should be no problem with that). You might consider using a separate process space for the proxy, otherwise your app and the proxy might interfere with each other in ways you don't expect. (like calling exit(), handling signals, crashing, etc) Then you don't have to figure out how to recompile the proxy inside Xcode, etc - you just have a binary for it and you configure and run it.
The question is, why would you do it? Reverse proxies only make sense when you have a backing server farm to connect to. Do you just need an embedded web server to serve up pages to your application? Why not just use one directly? A reverse proxy would just complicate things.

It seems that there is no reverse proxy written in Objective-C :)
Solution I used is:
Download nginx source code
Configure using
./configure --sbin-path=/usr/local/nginx
--conf-path=/usr/local/nginx/nginx.conf --pid-path=/usr/local/nginx/nginx.pid --with-http_ssl_module --with-pcre=/usr/local/nginx/src/$PCRE_FILE/ --group=www --user=www --with-http_stub_status_module --with-http_gzip_static_module --prefix=/usr/local/nginx
copy binary into boundle
run binary using
NSTask *task = [[NSTask alloc] init];
NSPipe * out = [NSPipe pipe];
[task setStandardOutput:out];
[task setLaunchPath:[NSString stringWithFormat:#"%#/Library/run/nginx", appPath]];
[task setArguments:#[#"-c", [NSString stringWithFormat:#"%#/Library/conf/nginx/nginx.conf", appPath], #"-p", [NSString stringWithFormat:#"%#/Library/nginx", appPath]]];
[task launch];
[task waitUntilExit];
read = [out fileHandleForReading];
dataRead = [read readDataToEndOfFile];
stringRead = [[NSString alloc] initWithData:dataRead encoding:NSUTF8StringEncoding];
NSLog(#"output: %#", stringRead);

Related

Add commandline target in Xcode the ability to function as XPC server

I currently have target from type commandlined tool that run as daemon using a plist file under /Library/LaunchDaemons.
Now I need add it the functionality to receive XPC messages from another process that I have. This Macho file is standalone and runs under application bundle in Resources subfolder.
I added and implemented the following interface and called it from main method, but it's enough ?
#interface ServiceDelegate : NSObject <NSXPCListenerDelegate>
ServiceDelegate *delegate = [ServiceDelegate new];
NSXPCListener *listener = [[NSXPCListener alloc] initWithMachServiceName:#"com.macho.scanner"];
[listener resume];
[[NSRunLoop mainRunLoop] run];
The question is whether I can modify my command-line target and add an XPC server, or should I need to create new target from type XPC service, and run it as daemon ?
thanks
You should be able to add XPC server to your cmd target.
It would require two things:
Adding necessary code to run the server. I'm using C API for this, but Objective-C should be pretty the same. I would add to your code at least setting the delegate to the listener.
Declaring in the launch.plist that you want to have some mach service. It looks like:
<key>MachServices</key>
<dict>
<key>com.macho.scanner</key>
<true/>
</dict>
Also beware: your daemon runs under root namespace, and namespaces are like stack with the root on bottom. User apps could see your daemon mach endpoint and establish connection to it, but nor vice versa.

-1001 error when NSURLSession via httpproxy and /etc/hosts

I am trying to setup a http proxy server in my computer to simulate a virtual development environment.
To access the local url, I put the DNS info into computers' /etc/hosts.
Here is my test code:
NSURLSession *session = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString:#"http://someurl.local/bluh/bluh/path"];
NSURLSessionDataTask *dataTask =
[session dataTaskWithURL:url
completionHandler:^(NSData *data, NSURLResponse *response,
NSError *error) {
NSLog(#"data is %# error is %#", data, error);
}];
[dataTask resume];
My Experiments:
1. Browsers like safari or chrome can access both local web services and remote web services.
2. NSURLSession will response a NSURLErrorDomain Code=-1001 "The request timed out." when access local urls.
3. NSURLSession works correct if url not in /etc/hosts.
I also tried the NSURLConnection, same output as NSURLSession's.
so, is it means the NSURLConnection/NSURLSession and browsers use a different strategy to do the DNS?
how to deal or bypass this?
update
I build this environment for ios 7.0+.
Environment:
computer system: OS X 10.9.4 (13E28) which set up a proxy and have server in.
device system: iOS 7.1.2(11D257)
.local is treated as a special TLD on OS X, and I think iOS. I believe this is primarily because it's used as an indicator for Bonjour lookups. Try changing to a different TLD for your development domains. I use ".localhost"; I've seen others use ".dev". Both of those work as expected.
It looks from the linked article that you might have been running into the problem specifically because you were using x.local—a single label, which will be looked up via Bonjour instead of by DNS, so you might also find that x.y.local works, too, but personally I'd just avoid .local all together.

Using a certificate from Keychain in a Mac application

I am trying to build a mini-application to codesign one Mac OS X application with codesign utility and my developer certificate in keychain. To do that I use NSTask, like that :
[task setLaunchPath:#"/usr/bin/codesign"];
// ...
NSString *certificateName = #"\"3rd Party Mac Developer Application: Firstname Lastname\"";
NSString *appName = #"\"/path/to/My App.app\"";
NSArray *args = [NSArray arrayWithObjects:#"-s", certificateName, appName, nil];
// ...
[task launch];
I use a NSPipe to catch the output and I got this error message : no identity found...
But if I launch this command manually via Terminal, the application is well signed (so it's not a problem of certificate badly installed, etc).
I think issue comes because my application can't access the certificate in keychain (but me I can via Terminal).
Does someone already experienced this problem ?
Thanks in advance, Best.
You should not embed additional quotation marks in the arguments to NSTask:
NSString *certificateName = #"3rd Party Mac Developer Application: Firstname Lastname";
NSString *appName = #"/path/to/My App.app";
Spaces in the arguments are handled automatically, and do not require quotation marks.

NSMutableURLRequest cannot connect to local network

I am using AFNetworking to connect from an iOS v6.0 app to my local Cold Fusion 8 server, not on the same machine but on the same network and the connection times out. When I use an external public server it works fine.
I have tried the connection via IP address and it doesn't work.
I have tried an entry in the hosts file assigning a domain name to the IP address and this doesn't work either. Please see the error below.
I can however connect via a web browser just fine.
Also, the server side files are exactly the same. Versions of Cold Fusion are the same. The only difference that I can find are the public server is Win2003 with IIS6 and the local server is Windows7 with IIS7.
Any thoughts on why this would not work on a local network. Makes local development kind of difficult.
Here is the relevant code:
// load params
NSMutableDictionary *myParams = [[NSMutableDictionary alloc] init];
[myParams setValue:#"Hello" forKey:#"Parameter1"];
[myParams setValue:#"There" forKey:#"Parameter2"];
// Load the base URL into a URL object
// Changing this to an external public server works fine
NSURL *baseURL = [NSURL URLWithString:#"http://www.mylocalmachine.com/"];
// Create HTTP client and init with base url
AFHTTPClient *myHttpClient = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
// POST request to path with the parameters
NSMutableURLRequest *myRequest = [myHttpClient requestWithMethod:#"POST" path:#"myfile.cfm" parameters:myParams];
// Block response from the HTTP client request and pass it back to the calling object
AFJSONRequestOperation *myOperation = [AFJSONRequestOperation JSONRequestOperationWithRequest:myRequest
success:^(NSURLRequest *mySuccessRequest, NSHTTPURLResponse *mySuccessResponse, id mySuccessJSON)
{
// PROCESS THE SUCCESS RESPONSE;
}
failure:^(NSURLRequest *myFailureRequest, NSHTTPURLResponse *myFailureResponse, NSError *myFaliureError, id myFailureJSON)
{
// PROCESS THE FAILURE RESPONSE... AFTER 60 seconds the system will fallout to this block.
}];
// Create a queue object
NSOperationQueue *myQueue = [[NSOperationQueue alloc] init];
// Add the operation object to the queue
[myQueue addOperation:myOperation];
The following is the error I get print the myFailureError object
Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo=0x8481000 {NSErrorFailingURLStringKey=http://www.mylocalmachine.int/myfile.cfm, NSErrorFailingURLKey=http://www.mylocalmachine.int/myfile.cfm, NSLocalizedDescription=The request timed out., NSUnderlyingError=0x9189e20 "The request timed out."}
Update----
I believe I have narrowed the issue down to what I beleive to be an issue with the iPhone simulator accessing IIS 7. It will access previous versions of IIS on the same network using the same code no problem.
The problem may be in the iPhone Simulator's User-Agent. I have tried to find a way to change the iPhone Simulator's User-Agent or allow the User-Agent in IIS 7 but can not seem to figure it out. The User-Agent the iPhone Simulator 6 is presenting is (iPhone Simulator; ios 6.0; Scale/2.00).
Does anyone know how to either allow this User-Agent on IIS 7 or change the User-Agent in the iPhone simulator?
Has anyone else seen this issue?
Thanks in advance,
Ed
Update----
Hi Everyone
Ok so I figured out how to change the User-Agent and Content-Type using the NSMutableURLRequest. I changed these to match what the browser would send, FireFox browser, and tried again to no avail. I still believe there is an issue with the configuration of IIS 7.5 but I can not find it...
Thanks for anyones help!!!
Ed
please try to remove last 2 lines of code and write
remove this
NSOperationQueue *myQueue = [[NSOperationQueue alloc] init];
[myQueue addOperation:myOperation];
add this instead
[myoperation start];
and also write failure:nil before that ending square bracket(]) like
AFJSONRequestOperation *myOperation = [AFJSONRequestOperation JSONRequestOperationWithRequest:myRequest
success:^(NSURLRequest *mySuccessRequest, NSHTTPURLResponse *mySuccessResponse, id mySuccessJSON)
{
// PROCESS THE SUCCESS RESPONSE;
}
failure:^(NSURLRequest *myFailureRequest, NSHTTPURLResponse *myFailureResponse, NSError *myFaliureError, id myFailureJSON)
{
// PROCESS THE FAILURE RESPONSE... AFTER 60 seconds the system will fallout to this block.
}failure:nil];
let me know is it working or not...!!!!
Happy Coding!!!!!!
I have resolved this issue. I will post what the resolution was to hopefully help someone else with a similar issue.
Turns out the problem was AVG installed on the system that was running IIS 7. It was a difficult issue to determine because any other system could access the web server with out any problems. It was only specific with the iPhone simulator accessing the system running IIS7. Even Safari or FireFox running on the same Mac would work just fine. Now what within AVG was causing the problem... That is yet to be determined.
I truly hope this helps someone along the way!

NSURLConnection FTP file upload

I am trying to upload a PNG file on FTP server using the following code.
NSURL *ftpURL=[NSURL URLWithString:#"ftp://username:password#localhost"];
NSMutableURLRequest *urlRequest=[[NSMutableURLRequest alloc] initWithURL:ftpURL];
[urlRequest setHTTPMethod:#"POST"];
[postData appendData:[[NSString stringWithFormat:#"Content-Disposition: form-data; name=\"imageUrl\"; filename=\"dummy.png\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[#"Content-Type: image/png\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[#"Content-Transfer-Encoding: binary\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
UIImage *img=[UIImage imageNamed:#"a.png"];
NSMutableData *postData=[[NSMutableData alloc] init];
NSData *data=UIImagePNGRepresentation(img);
[postData appendData:data];
[urlRequest setHTTPBody:postData];
[[NSURLConnection alloc] initWithRequest:urlRequest delegate:self startImmediately:YES];
I don't receive any NSURL connection,like it has failed or ask for Authentication. Only, call back I receive is of
-(void) connectionDidFinishLoading:(NSURLConnection *)connection
I am not sure whether NSURLConnection supports ftp upload. I am not looking to implement it using CFFTPStream. Can any one correct me in my approach?
I've had good success with BlackRacoon.
Uploading file over FTP will require using FTP commands like STOR or APPE. And FTP commands are not possible using NSURLConnection because NSURLConnection does not provide any way to send FTP commands. To do that, you'll have to use CFFTPStream.
The SimpleFTPSample sample code shows this.
https://developer.apple.com/library/ios/#samplecode/SimpleFTPSample/
Specifically, it shows download (via NSURLConnection and CFFTPStream), upload, directory listing, and directory creation (all via CFFTPStream).
Note: CFFTPStream has no public API for deleting files , although it is possible to delete files using the deprecated, but still functional, CFURLDestroyResource.
There is currently no way to send arbitrary FTP commands via CFFTPStream. If you need to do that, you'll have to create (or acquire) your own FTP library.
Your are trying to use FTP and POST in one go, which won't work in almost any case.
FTP is a complete different protocoll, see for example http://www.faqs.org/rfcs/rfc959.html
It is somewhat more interactive, however many ftp server have a http wrapper which allows easy download, but upload will remain special. So if you want to use it, you should take a library or CFFTPStream.