I am working in a iPhone project that uses restful web services. I need to send some tracking code or version number with every request sending from iPhone side. I am thinking of adding a header value into every request, by modifying a ASIHTTPRequest class.
Is there any method that ASIHTTPRequest providing to do this (without modifying framework files)?
If I need to modify ASIHTTPRequest class, what is the best place to modify it? (like buildRequestHeaders.. )
Thanks.
may be you can write a new class such as MyASIHttprequest and override the method requestwithURL
+ (MyASIHTTPrequest *) requestWithURL:url{
MyASIHTTPrequest *request;
if (request = [super requestWithUrl:url]){
[request addRequestHeader:#"" value:#""];
}
return request;
}
or you can write a method to add the header but maybe every time you new a asihttprequest, you should call this method to add header;
You can add headers by following method
ASIFormDataRequest *currentRequest = [ASIFormDataRequest requestWithURL:url];
[currentRequest addRequestHeader:#"" value:#""];
e.g.[currentRequest addRequestHeader:#"Content-Type" value:#"text/xml; charset=utf-8"];
Hope this helps.
If you are just starting by adding in ASIHTTPRequest and it is not embedded into your app yet then I recommend that you stop and switch to something else.
The creator of ASIHTTPRequest has discontinued development on the framework and even recommends in his blog post "Honestly, I think now is the time to start looking elsewhere." -Blog post
Also this was addressed in this question as well: Is it safe to still use ASIHTTPRequest?
I would personally recommend that you use NSURLConnection and send the data through the POST method.
Related
I am JSON newbie and can't find any material on how to simulate JSON payload request.
My ultimate goal is to be able to build an objective-c iOS app that will handle these request-response. I am aware of ASIHttprequest framework and the request-response mechanism it works around.
However right now I have a webservice api which expects various json payloads and also provides response in json format. Here is an example:
Example URL:
https://mywebServiceURL/api/ApiKey/user/create
The ContentType header = “application/json”.
Payload: The PUT payload is a JSON dictionary, containing the following keyvalue pairs:
email
screenName
User’s screen name.
password
passwordConfirm
phoneNumber (optional)
User’s phone number (optional)
picture A png file (64x64), encoded as a Base64 string (optional)
Now my questions:
1 - how do I simulate this normally (outside ios, just for the sake of testing)? I searched google but can't find exactly what I need, I got curl.exe but it gives me same as what a browser gives, like method not allowed etc. But that's not the only thing I want. I want to play with various requests, supply values and take the api for a ride for sometime before I know how it really works for PUT, GET, POST etc.
2 - what is the best way to incorporate such stuff into iOS? I already have ASIHttp for web requests and JSONKit for JSON handling included in my project.
I have done this kind of stuff but with xml responses, get requests. JSON I am working for the first time. Just a pointer to an example stuff like this would be a great help.
There are several Chrome extensions, such as Advanced REST client or REST Console, that you can use to simulate REST calls. These are very quick and easy to install into your browser and will allow you to construct requests and view the response.
I recommend using the open source iOS networking library AFNetworking. This library has built in support for REST calls and JSON parsing. It is very easy to get up and running, and is very powerful if you need more advanced features.
Hope this helps.
Jsut to add upon Andy's suggestions as I have used similar kind of things in one of my recent app.
Used Chrome extension Poster for testing REST calls.
Used ASIHttpRequest for handling async queries.
Sample code snippet
//dictionaryData contains the login user details
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:dictionaryData options:kNilOptions error:nil];
NSString *jsonString = [[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]autorelease];
//Handling ASI requests
ASIHTTPRequest* request = [ASIHTTPRequest requestWithURL:uri];
[request addRequestHeader:#"Content-Type" value:#"application/json"];
[request addRequestHeader:#"Accept" value:#"application/json"];
[request appendPostData:[jsonData dataUsingEncoding:NSUTF8StringEncoding]];
[request setRequestMethod:#"POST"];
[ASIHTTPRequest setDefaultTimeOutSeconds:30];
request.delegate = self;
[request startAsynchronous];
I am working on an upload code which will upload the file to the server, which is successfully working
now what I need as fallows:
started with an example-->suppose I have a file named file.txt, whose size is 30MB, when I read the contents of the file it will give me all the 30MB it contains. In the sendSynchronousRequest method I want to give request upto 10mb of data and aging calling the same thing unless it reaches at the last point of file. (in brief I want to use a loop to send the request part by part to the server
to solve the purpose i read form http://allseeing-i.com/ASIHTTPRequest/How-to-use and Included the ASIHTTPRequest in to my project after inclusion i want to do the same , that will accept a block of data (even via a POST) then append that block of data to a file. It seems to me that you need some kind of client side app that will take a file and break it up into chunks, then send it to your web service one chunk at a time.
My problems:
-how to sent a Post Request from ASIHTTPRequest with a chunk of data?
-do i need to change the PHP ?
Can any one post a piece of code for both php and ASIHTTPRequest so that i can take a reference from their.
Thank you guys for your continuos support .
If you use a form in the website, it would be easier to use ASIFormDataRequest instead of the standard ASIHTTPRequest. The specific details are here: Using ASIFormDataRequest
Essentially, you just create the form fields in the website and reference them when you create the request. If you have any text fields in your form you use the
[request setPostValue:#"Your value" forKey:#"form key"];
The file should be sent through the path using
[request setFile:#"filepath to needed file" forKey:#"form key"];
If you want you can also send it asynchronously and use the delegate methods for tracking the progress of the upload.
I hope this helps.
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:#"Ben" forKey:#"first_name"];
[request setPostValue:#"Copsey" forKey:#"last_name"];
[request setFile:#"/Users/ben/Desktop/ben.jpg" forKey:#"photo"];
From ASIHTTPRequest documentation
You can refer to the following link available on the stack overflow:
NSURLConnection to upload file asynchonrously?
In my iOS app, I'm using a UIWebView and a custom protocol (with my own NSURLProtocol implementation). I've been fairly careful about making sure that whenever I load a url, I load something like this into my UIWebView:
myprotocol://myserver/mypath
and in my NSURLProtocol implementation, I take a mutable copy of the NSURLRequest, convert the URL to http: and send that to my server.
Everything works for HTTP GET requests. The problem I encounter is with POST requests. It seems like the UIWebView doesn't properly encode the form data in the HTTPBody if the request uses my custom protocol.
One work-around, since I'm using HTTPS for my server requests, is that I register my protocol handler to intercept http: instead of myprotocol: and I can convert all calls to https: This other question, here, pointed me toward that solution:
But I'm wondering if there's any alternative and/or better way of accomplishing what I want.
Instead of trying to use POST requests, one work around is to continue using GET requests for myprotocol:// URLs, but transform them in your NSURLProtocol implementation to an http:// and POST request to your server using the request query string as the body of the POST.
The worry with using GET requests to send large amounts of data is that somewhere along the request chain, the request line might get truncated. This appears to not be a problem, however, with locally-implemented protocols.
I wrote a short Cordova test app to experiment and I found that I was able to send through a little over 1 MiB of data without trouble to the HTTP request echoing service http://http-echo.jgate.de/
Here is my startLoading implementation:
- (void)startLoading {
NSURL *url = [[self request] URL];
NSString *query = [url query];
// Create a copy of `url` without the query string.
url = [[[NSURL alloc] initWithScheme:#"http" host:#"http-echo.jgate.de" path:[url path]] autorelease];
NSMutableURLRequest *newRequest = [NSMutableURLRequest requestWithURL:url];
[newRequest setHTTPMethod:#"POST"];
[newRequest setAllHTTPHeaderFields:[[self request] allHTTPHeaderFields]];
[newRequest addValue:#"close" forHTTPHeaderField:#"Connection"];
[newRequest addValue:#"application/x-www-form-urlencoded;charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
[newRequest setHTTPBody:[query dataUsingEncoding:NSUTF8StringEncoding]];
urlConnection = [[NSURLConnection alloc] initWithRequest:newRequest delegate:self];
if (urlConnection) {
receivedData = [[NSMutableData data] retain];
}
}
I then implemented the NSURLConnection protocol methods to forward to the appropriate NSURLProtocolClient method, but building up the response data in the case of Transfer-Encoding:chunked (as is the case for responses from http://http-echo.jgate.de/).
Unfortunately it looks like that http: and https: scheme requests are handled slightly differently than other (including custom) schemes by Foundation Framework. Obviously HTTPBody and HTTPBodyStream calls on relevant NSURLRequest returns always nil for former ones. This is decided already prior call of [NSURLProtocol canInitWithRequest] therefore custom NSURLProtocol implementation has no way of influencing that (it is too late).
It seems that different NSURLRequest class is used for http: and https: than 'a default one'. Default GnuStep implementation of this class returns always nil from HTTPBody and HTTPBodyStream calls. Therefore particular implementations (e.g. one under PhoneGap, likely part of Foundation Framework) choose NSURLRequest-type of class based on scheme prior consulting that with NSURLProtocol. For custom schemes, you get NSURLRequest that returns nil for both HTTPBody and HTTPBodyStream which effectively disables use of POST method (and other methods with body) in custom URI scheme handler.
Maybe there is a way how to influence decision of which NSURLRequest class is actually used but it is currently unknown to me.
As a workaround, you can still use http: or https: scheme and decide in [NSURLProtocol canInitWithRequest] based on other criteria (e.g. host name).
I use ASIHttpRequest (v. 1.8-95) for Iphone and wanted to create a synchronous DELETE request together with some body data. I went this way:
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:nsUrl];
[request appendPostData:[#"some body params" dataUsingEncoding:NSUTF8StringEncoding]];
[request setRequestMethod:#"DELETE"];
[request startSynchronous];
Although I was confirmed on the client side via
NSLog(#"request: method:%#", request.requestMethod);
that the method was correctly set to "DELETE"
on the server side a "POST" request was received !
If I just omit
[request appendPostData: ..]
a correct DELETE is received on the server side)
So what's wrong with my request ?
Thanks for any solutions.
Regards
creator_11
Searching the asihttprequest group ( http://groups.google.com/group/asihttprequest/search?group=asihttprequest&q=delete&qt_g=Search+this+group ) turns up some relevant posts including a suggested workaround:
call buildPostBody on your request
after you've populated the body, but
before you set the request method.
HTTP verbs and usages can't just be mixed and matched. OK, they can, but you'd have to change the server to support your non-standard usage. DELETE should use the URI of the resource to be deleted, and thats it. No POST params, no attachment.
If really you want to send a little extra data along with the delete, you can set it in the headers of the request (addRequestHeader:value:), and server side pull that info out, but avoid that if you can. The reason is, the DELETE should be deleting one 'thing' referred to by it's URI. If the business logic of the server application says that delete should affect some other objects (eg cascading delete), the client application shouldn't know about that.
Can you explain what you're trying to POST while performing a DELETE, maybe I can offer an alternative solution.
The TBXML documentation is pretty small and the API didn't give me any hints as how I should define how to accept mime-type "application/xml" with TBXML, as I'm requesting data from a webservice that serves HTML as default but can serve XML if requested (and I need the XML).
Is there some way to do this with the API? Or is there a workaround? I didn't try any request processing with iOS SDK so far, so maybe there's an obvious answer I just don't see.
If you open TBXML source code, you'll see that initWithURL is defined as ...
- (id)initWithURL:(NSURL*)aURL {
self = [self initWithXMLString:[NSString stringWithContentsOfURL:aURL encoding:NSUTF8StringEncoding error:nil]];
... and there's no way how to say that you want to receive XML.
You should look at NSMutableURLRequest, NSURLConnection and download it by yourself. You can set HTTP header field Accept in NSMutableURLRequest and then you can use this request in NSURLConnection to download it.