I'm using a firefox tool call "Poster" to check that my web service is working. When I POST the request I send a JSON object in the content to send (also call HTTP body data).
When I press the POST button the result is fine.
Now I want to do exactly the same with RestKit in objective-c:
NSString *squery = #"{\"Sort\":\"Relevance\",\"DaysToSearch\":0,\"WorkType\":\"\",\"PageSize\":20,\"LastRunCount\":0,\"IndustryCodes\":[\"\"],\"AccountId\":27,\"Experience\":\"\",\"GetResultCount\":0,\"Keywords\":\"iOS\",\"PageIndex\":0,\"DistanceFromLocation\":\"250\",\"SalaryType\":\"\",\"JobQueryId\":\"\",\"JobTitleCodes\":[\"\"]}";
RKObjectLoader *objectLoader = [[RKObjectManager sharedManager] objectLoaderWithResourcePath:url delegate:performJobQueryHandler];
objectLoader.method = RKRequestMethodPOST;
objectLoader.objectMapping = s.jobQueryDataMapper;
objectLoader.HTTPBody = [squery dataUsingEncoding:NSUTF8StringEncoding];
objectLoader.serializationMIMEType = RKMIMETypeJSON;
[objectLoader send];
As a result I get: "An non-fault exception is occured."
In the FireFox extension "Poster" if I use a different mine-type than "application/json", let say "application/x-www-form-urlencoded" I get the same error: "An non-fault exception is occured."
Is something wrong with objectLoader.serializationMIMEType = RKMIMETypeJSON; ???
Martin Magakian
Ok I think I find out.
I activated RestKit debug with
RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
And I get:
2012-02-14 11:55:48 [4048:207] T restkit.network:RKRequest.m:318 Prepared POST URLRequest '<NSMutableURLRequest http://servicestest.foo.com/jobservice/jobservice.svc/json/jobquery>'. HTTP Headers: {
Accept = "application/json";
"Content-Type" = "application/x-www-form-urlencoded";
}. HTTP Body: Sort=Relevance&DaysToSearch=0&WorkType=&SalaryType=&LastRunCount=0&IndustryCodes[]=&Experience=&AccountId=0&GetResultCount=0&PageIndex=0&DistanceFromLocation=250&PageSize=20&JobQueryId=&JobTitleCodes[]=.
So I think using RKObjectLoader object don't care about objectLoader.serializationMIMEType = RKMIMETypeJSON; because the Content-Type remain "Content-Type" = "application/x-www-form-urlencoded"; instead of "Content-Type" = "application/json";
Do you think it's a bug or the normal behavior ?
Related
I stuck with sending request with Akka HTTP singleRequest(). I'm trying to deal with Stripe API and it requires application/x-www-form-urlencoded content type for the incoming requests.
I tried to use following structure of HTTP request:
val authorization = Authorization(OAuth2BearerToken("some_token"))
Http().singleRequest(HttpRequest(
uri = Uri("https://api.stripe.com/v1/customers"),
method = HttpMethods.POST,
headers = List(authorization),
entity = FormData(Map("email" -> HttpEntity("test_1#email.com"))).toEntity(),
protocol = HttpProtocols.`HTTP/1.1`)
)
But in the Stripe logs I see following in the Parsed Request POST Body section:
(multipart form: 162)
So the question is how to set content type to application/x-www-form-urlencoded?
The problem was related to FormData type. In order to perform application/x-www-form-urlencoded request you need to use FromData from package akka.http.scaladsl.model
So here is working example:
Http().singleRequest(HttpRequest(
uri = Uri("https://api.stripe.com/v1/customers"),
method = HttpMethods.POST,
headers = List(authorization),
entity = akka.http.scaladsl.model.FormData(Map("email" -> "user#email.com")).toEntity(HttpCharsets.`UTF-8`),
protocol = HttpProtocols.`HTTP/1.1`)
)
I'm trying to set headers to HttpResponse
var response = HttpResponse()
val acrh = request.headers.filter(q => q.name() == "Access-Control-Request-Headers").head.value()
response = response.addHeader(`Access-Control-Allow-Headers`(acrh))
response = response.addHeader(`Access-Control-Request-Headers`(acrh))
In response I can see only "Access-Control-Allow-Headers", and I'm getting this error
"HTTP header 'Access-Control-Request-Headers' is not allowed in responses".
How can I solve this problem? I need to implement this for CORS.
I am trying to upload a file into OneDrive using its REST API. This is what I am trying to accomplish based on documentation available at OneDrive Rest API:
POST https://apis.live.net/v5.0/me/skydrive/files?access_token=ACCESS_TOKEN
Content-Type: multipart/form-data; boundary=A300x
--A300x
Content-Disposition: form-data; name="file"; filename="HelloWorld.txt"
Content-Type: application/octet-stream
Hello, World!
--A300x--
This is what I have:
Uri destination = new Uri(string.Format("https://apis.live.net/v5.0/{0}/files?", folder.ID));
BackgroundUploader uploader = new BackgroundUploader ();
uploader.SetRequestHeader("Authorization", "Bearer " + account.AccessToken);
uploader.SetRequestHeader("Content-Type", "multipart/form-data; boundary=\"foo_bar_baz\"");
List<BackgroundTransferContentPart> parts = new List<BackgroundTransferContentPart>();
BackgroundTransferContentPart metaDataPart = new BackgroundTransferContentPart();
metaDataPart.SetHeader("Content-Disposition", "form-data; name=\"file\";filename=\""+content.Name+"\"");
parts.Add(metaDataPart);
BackgroundTransferContentPart contentPart = new BackgroundTransferContentPart();
contentPart.SetHeader("Content-Type", content.ContentType);
// content is a StorageFile
contentPart.SetFile(content);
response.UploadOperation = await uploader.CreateUploadAsync(destination, parts, "form-data", "foo_bar_baz");
This line below causes an Access violation error and the Windows Store app crashes:
response.UploadOperation = await uploader.CreateUploadAsync(destination, parts, "form-data", "foo_bar_baz");
You are creating two BackgroundTransferContentPart and only adding the fist to your 'List'.
I think you only need one, something like this:
List<BackgroundTransferContentPart> parts = new List<BackgroundTransferContentPart>();
BackgroundTransferContentPart metaDataPart = new BackgroundTransferContentPart();
metaDataPart.SetHeader("Content-Disposition",
"form-data; name=\"file\";filename=\"" + content.Name + "\"");
metaDataPart.SetHeader("Content-Type", content.ContentType);
metaDataPart.SetFile(content);
parts.Add(metaDataPart);
UPDATE: Ok, the above code fixed the Access Violation issue. Why you are getting a 400 error is a mystery.
But another way to upload a file to OneDrive is using the PUT method:
Uri putUri = new Uri(string.Format("https://apis.live.net/v5.0/{0}/files/{1}",
"folder.a4fb14adbccd1917.A4FB14ADBCCD1917!32089",
content.Name));
BackgroundUploader uploader = new BackgroundUploader();
uploader.SetRequestHeader("Authorization", "Bearer " + accessToken);
uploader.Method = "PUT";
UploadOperation putOperation = uploader.CreateUpload(putUri, content);
await putOperation.StartAsync();
Have you tried PUT?
I am currently updating my app to .json from xml for Twitters new API v1.1. I currently have .json working and can log on, get me timelines, mentions, but when trying to get direct messages, lists, or user info it seems its looking for "cookies" but it is not stored.
This is the error message received by twitter when trying to make a simple GET user/show call:
Twitter request failed: 08AD12D3-0044-49AB-8D3D-4E61D8398550 with error:Error Domain=HTTP
Code=400 "The operation couldn’t be completed. (HTTP error 400.)" UserInfo=0xce90540
{response=<NSHTTPURLResponse: 0xce94bd0> { URL:
https://api.twitter.com/1.1/users/show.json?screen_name=FreeAppl3 } { status code: 400,
headers {
"Content-Encoding" = gzip;
"Content-Type" = "application/json; charset=utf-8";
Date = "Fri, 14 Jun 2013 09:25:40 UTC";
Server = tfe;
"Set-Cookie" = "guest_id=v1%3A137120194019582695; Domain=.twitter.com; Path=/;
Expires=Sun, 14-Jun-2015 09:25:40 UTC";
"Strict-Transport-Security" = "max-age=631138519";
"Transfer-Encoding" = Identity;
} }, body={"errors":[{"message":"Bad Authentication data","code":215}]}hjD4nzoeOUaTQ1Q%3D}
When I call [twitterEngine isAuthorized]; is returns YES and if I check for my access token string, I receive what was stored on initial login. I have searched and searched as to what is happening or how to fix the issues, but am simply stuck and any help would be greatly appreciated.
Twitter API - https://dev.twitter.com/docs/api/1.1/get/users/show
Twitter Error Codes - https://dev.twitter.com/docs/error-codes-responses
refer FHSTwitterEngine you can use newly FHSTwitterEngine and if you request this method without autenticating, the users status is removed... you need to send consumer key and token along with screen_name..
In FHSTwitterEngine
//get username pass to method. In Dictionary you can get all info
NSString *username = [[FHSTwitterEngine sharedEngine]loggedInUsername];
NSDictionary *data=[[FHSTwitterEngine sharedEngine]getUserProfile:username];
// method to get all user info
-(id)getUserProfile:(NSString *)username
{
if (username.length == 0) {
return getBadRequestError();
}
NSURL *baseURL = [NSURL URLWithString:url_users_show];
OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
OARequestParameter *usernameP = [OARequestParameter requestParameterWithName:#"screen_name" value:username];
NSArray *params = [NSArray arrayWithObjects:usernameP, nil];
id userShowReturn = [self sendGETRequest:request withParameters:params];
return userShowReturn;
}
I am using ASIHTTPRequest to contact an API the problem is that it is returning html instead of JSON and i have no idea why. Everything has been working great for weeks and i can't seem to figure out what has broken..
What's strange is doing exactly the same request with a browser or postie returns the correct JSON response, but when i do the request via ASIHTTPRequest these are the response headers i get:
"Cache-Control" = "private, max-age=0, must-revalidate";
Connection = "keep-alive";
"Content-Encoding" = gzip;
"Content-Type" = "text/html; charset=utf-8";
Date = "Tue, 05 Jul 2011 21:11:10 GMT";
Etag = "\"e467792713ac4124f055c1719f4ea6c2\"";
Server = "nginx/0.7.65";
Status = "200 OK";
"Transfer-Encoding" = Identity;
"X-Runtime" = 1;
And the html (which should be json)..
<div id="universal_meta" logged_in_user_id="removed" style="display:none"></div>
<div id="meta" screen="projects" logged_in_as="removed"></div>
<h1>9 projects with 50 open issues</h1>
<ul class="biglinks progressbars">
etc...
Here is the code used to do the request..
NSURL *url = [NSURL URLWithString:path];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
if(secure){
[request setUsername:self.username];
[request setPassword:self.password];
}
[request setDelegate:self];
[request setDidFinishSelector:#selector(requestDone:)];
[request setDidFailSelector:#selector(requestWentWrong:)];
[request setDownloadDestinationPath:destination];
[[self queue] addOperation:request]; //queue is an NSOperationQueue
I have triple checked all of the login details/url, everything is correct, i would really appreciate any help with this one as i am completely lost.
--
Update:
Lighthouse have acknowledged a bug regarding headers on their side. Waiting on a solution from them.
Did you check that the headers sent using your browser are also the same as when you send the request by code?
Especially did you try to add the "Accept" header to your request to define that you accept the json Content-Type?
[request addRequestHeader:#"Accept" value:#"application/json"];
Try using a tool like wireshark or charlesproxy to compare the working requests from your browser/postie, and compare them to the non-working requests from ASIHTTPRequest - once you spot what's different it should be easy to fix.
AliSoftware's suggestion is one of the most likely differences you'll see, but it's possible there are other things too.