How can I make a request that contains no headers fields? The requests are being sent to my own server implementation from scratch, which doesn't care about header fields. The request will at most contain only a post body. Let me know if I'm missing something logical.
Please don't tell me about ASIHTTPRequest. Thank you.
As I wanted to remove specific header on a NSMutableURLRequest, I've just found that calling setValue:forHTTPHeaderField: with a nil value actually removes it.
It's not documented by Apple, but it seems quite logical.
For me the code
[request addValue:#"" forHTTPHeaderField:#"User-Agent"];
only added an empty string instead of cleaning the User-Agent.
Instead, using setValue fixed it:
[request setValue:#"" forHTTPHeaderField:#"User-Agent"];
I found that for some of the header fields ("User-Agent" is one of them), setting the header value to nil using
[request addValue:nil forHTTPHeaderField:#"User-Agent"];
doesn't actually remove the header field, but rather sets it to a default value!
If you want to actually remove the content, it is enough setting the value to an empty string with
[request addValue:#"" forHTTPHeaderField:#"User-Agent"];
Why not just ignore them, if you control the server implementation?
Does [request setAllHTTPHeaderFields:[NSDictionary dictionary]] work?
If #2 didn't work, try making your own subclass that always returns an empty dictionary from the allHTTPHeaderFields method, and nil from the valueForHTTPHeaderField: method. But NSURLConnection might make a copy of your request, so you might have to override copyWithZone: also.
Related
I'm using AFNetworking 2.0 for a normal GET request and the parameter dictionary seems to be having no effect. I'm using the standard:
[manager GET:URLString parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {...
but my NSMutableDictionary (parameters) doesn't seem to have any effect on the URL sent in the GET request (GET requests don't have HTTP Bodies as far as I'm aware so they won't be there). So where are the parameters going? I know I could always amend the string, but the way in which I receive the parameters on an optional basis makes it far easier to just send in a dictionary. What's wrong, why isn't it working?
Thanks,
Mike
UPDATE: I'm setting the parameter like this: [parameters setValue:self.Object.ID forKey:#"Filter.Id"]; ID is a string. However, when I do [parameters valueForKey:#"Filter.Id"] I get a (null) in the NSLog. I'm going to mess around with it a little and see how it goes, but if you have any ideas why this is happening I'd appreciate it. Also, parameters is an NSMutableDictionary and is a property of the ViewController.
Was an issue with my NSMutableDictionary property. Changed it to a global variable and everything worked fine!
Thanks,Mike
I'm using an NSMutableURLRequest to perform a simple file upload from iOS5 to a custom server. When I send the request, I have it print out the length of bodyContents, which contains the body of the request. For the particular request I am working on, it will say that the length is 46784. I don't set the content-length, since I found out it was doing that automatically, but I pull the info anyway in case I need it later. The headers being received by the server say that the content-length is 46784. When I do a character count on the body at the server end, it tells me that the length of the body is 46788, 4 too many. I ran another request, again, the request had 4 more characters than what I sent.
At first, I thought it had to be on the server side, just because it didn't make any sense. So I sent a request from a test program that I know works to the server, and checked the length of the body it sent against the content-length header and they were identical.
What is the best way to deal with this? Should I manually set the content-length to 4+[bodyContents length]? I don't think that would be what I would want to do, just because I shouldn't have to add extra space for data I don't know that I want.
Here is the code that sends the request
-(void)send:(id)delegate
{
bodyContents = [bodyContents stringByAppendingFormat:#"--%#--",boundry];
NSInteger length = [bodyContents length];
NSLog(#"Length is %i",length);
[request setHTTPBody:[bodyContents dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:delegate];
if(connection)
{
NSLog(#"Connection good");
}
else
{
NSLog(#"Connection bad");
}
}
I set the content-type property of the request in the init method of the class.
Any ideas?
When you specify an encoding, the size of the contents can change... get the size after you set the HTTPBody and then see if that adjusts things up by four bytes automatically.
Alright. Hopefully this will be my last post about the download manager I am writing in Objective-C. Everything seems to work well except the pause/resume functionality. My issue is that when a download tries to continue from where it left off, it appends the data it receives to the file, but it still seems that it's trying to download the entire file. This results in a file that is larger than the original file is supposed to be. Here is the code I am using for downloading files. Am I doing something wrong?
-(void)start:(unsigned int)fromByte {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:DEFAULT_TIMEOUT];
// Define the bytes we wish to download.
NSString *range = [NSString stringWithFormat:#"bytes=%i-", fromByte];
[request setValue:range forHTTPHeaderField:#"Range"];
// Data should immediately start downloading after the connection is created.
self.urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:TRUE];
if (!self.urlConnection) {
#warning Handle error.
}
}
I see you are specifying the Range header in the request. First thing to check is whether the server is actually honoring the Range request, by checking the headers in the response object (which should be an NSHTTPURLResponse) in connection:didReceiveResponse: for a proper Content-Range.
I finally figured this out. It turns out that the 'getFilesizeInBytes' method I had was get the NSFileSize object from the file's attributes, but I was directly casting this to an int. This caused the number to be about 20 times larger than it should have been. I was able to fix this by using [#"" intValue]. Once this was fixed, the servers were able to give me the rest of the file starting with the correct byte. It seems that before my issue was not that the server wasn't honoring my request, but that it couldn't honor my request due to me requesting data that was well beyond the final byte of the file.
There's no support for pause/resume in NSURLConnection. You can emulate it by stopping the request, then issuing a request for the rest of the content with a Range header on resume. Some support from the HTTP server is required for that, and is not guaranteed.
Looks like lack of support at the server is what you're facing.
Most download managers, however, implement their own HTTP stack on top of sockets.
I've written a custom subclass of NSURLProtocol, however it seems that whenever I use the protocol to load a request in UIWebView it assumes the data is content-type "text/html". Is there a way to specify that this content is actually something else (For instance "text/plain" or "image/png")?
The content-type is actually carried by NSURLResponse, which you can modify by using the NSURLProtocolClient method URLProtocol:didReceiveResponse:cacheStoragePolicy: for instance, to set to text/plain
NSURLResponse *textResponse = [[NSURLResponse alloc] initWithURL:self.request.URL MIMEType:#"text/plain" expectedContentLength:100 textEncodingName:#"UTF-8"];
[self.client URLProtocol:self didReceiveResponse:textResponse cacheStoragePolicy:NSURLCacheStorageAllowedInMemoryOnly];
The content-type is carried by the NSMutableURLRequest.
[request setValue:#"image/png" forHTTPHeaderField:#"content-type"];
I'm trying to add a value to the header for a URL request.
Something like this works just fine:
[urlRequest addValue:#"gzip" forHTTPHeaderField:#"Accept-Encoding"];
But this doesn't even show up in the header:
NSString *authString = [[NSString alloc] initWithString:
[defaults objectForKey:#"auth"]];
[urlRequest addValue:authString forHTTPHeaderField:#"iphoneID"];
I'm completely stumped. The auth string is around 90 characters long. Is this a problem?
Edit:
Here's the code I'm trying:
NSString *authString = [[NSString alloc] initWithString:[defaults objectForKey:#"auth"]];
[urlRequest addValue:authString forHTTPHeaderField:#"iphoneid"];
[urlRequest addValue:#"gzip" forHTTPHeaderField:#"Accept-Encoding"];
I can see the Accept-Encoding header being sent through Wireshark, but iphoneid is nowhere to be found. It's just a string, 80-90 characters long.
Another Update:
So it seems that the problem isn't the field "iphoneid" but rather the authString I'm trying to pass into it. Other strings that I just create with the #"something" work fine, but the auth string that I pull from NSUserDefaults doesn't appear.
Suggestions on how to debug this?
The true problem.
The string I was pulling from NSUserDefaults already had a line ending. When set as a header, another \r\n is appended, which apparently isn't valid. Thus, the header wouldn't appear in any outgoing packets.
The fix:
Use this to trim off the characters before setting as a header value.
[yourString stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
Testing checklist:
Verify that you actually have a NSMutableURLRequest (and not a NSURLRequest) at this point. In particular, check your logs for an exception due to "unrecognized selector."
Verify that urlRequest is not nil.
Switch to setValue:forHTTPHeaderField: rather than addValue:forHTTPHeaderField:.
Swap the forHTTPHeaderField: value to #"Accept-Encoding" to see if the field is the problem
Swap #"gzip" for auth to see if the value is the problem.
You need Charles web proxy, to see what header values are really outbound and inbound. Then you can see if the problem is really in your code or some magic on the server discarding things.
There's a free trial, and after you install it if you hit record any traffic the simulator sends will go through the proxy. Very nice.
http://www.charlesproxy.com/