I am having trouble with Siesta - an iOS REST Client Framework https://bustoutsolutions.github.io/siesta/.
Below is a simple example of a POST request to a REST API server, which fails with a "unsupported URL" error. Does anybody out there have any experience with Siesta and what could be wrong?
Siesta configuration & login server call
let api = Service(base: "http://myapidomain.net/rest")
enabledLogCategories = LogCategory.all
let parameters = ["username": "username", "password": "password"]
api.resource(url: "users/login").request(.POST, json: NSDictionary(dictionary: parameters)).success { data in
debugPrint("success logging in")
}.failure { error in
debugPrint("failed to log in")
}
Debug log
[Siesta:Configuration] Computing configuration for Siesta.Resource(users/login)[]
[Siesta:Configuration] Applying config 0 [Siesta default response transformers] to Siesta.Resource(users/login)[]
[Siesta:NetworkDetails] Request:
headers: (1)
Content-Type: application/json
[Siesta:Network] POST users/login
[Siesta:Network] – ← POST users/login
[Siesta:NetworkDetails] Raw response headers: –
[Siesta:NetworkDetails] Raw response body: 0 bytes
[Siesta:NetworkDetails] Response after transformer pipeline: (new data)
Failure
userMessage: "unsupported URL"
nsError: "unsupported URL"
"failed to log in"
The Service.resource(url:) method — the one with the parameter labeled url: — expects a complete URL. It looks like you want Service.resource(_:), which takes a path relative to the Service’s base URL.
Try:
api.resource("users/login")
Related
I have an api (nodejs) which saves my application data in MongoDB. But when I send the request, node throws an error which says that score is undefined
UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'score' of undefined
And when Xcode sends the request, the application works for about 30 seconds and then crashes and Xcode logs: "The request timed out."
this is my Swift code:
let parameters = ["score": scoreBoard]
print(parameters)
AF.request("http://localhost:4000/update/score", method: .post, parameters: parameters).responseDecodable(of: [jsonData].self) {response in
let json = JSON(response.data!)[0]["score"]
scoreBoard = json.rawString()!
}
The problem was with Node I didn't use a body parser. When I included a body-parser then it was able to retrieve the data from the body.
I'm working online with different people from different projects who take care of backend API webservice. Usually I don't have problems with sending and receiving JSON, but this time, I can't seem to be able to send JSON properly to the server.
Usually I use Alamofire to receive and send JSON message, and the usual call go like this:
let param = populateParamWithDictionary();
let url = "https://www.example.com";
Alamofire.request(.POST, url, parameters: param, headers: nil)
.responseJSON { response in {
// take care of response here
}
But this time, I got project which the backend programmer requires me to use OAuth v2. So, let's say I've develop a function which already take care of getting the access_token string. The function now become like this:
let param = populateParamWithDictionary();
let url = "https://www.example.com";
let headers : Dictionary<String, String> = [
"Content-Type":"application/json",
"Authorization":"Bearer \(access_token)"
];
Alamofire.request(.POST, url, parameters: param, headers: headers)
.responseJSON { response in {
// take care of response here
}
But instead of the result, I get 400 bad request error. I also even try this:
let param = populateParamWithDictionary();
let url = "https://www.example.com";
let headers : Dictionary<String, String> = [
"Content-Type":"application/json",
"Authorization":"Bearer \(access_token)"
];
Alamofire.request(.POST, url, parameters: param, encoding: ParameterEncoding.JSON, headers: headers)
.responseJSON { response in {
// take care of response here
}
But the result is even worse. This is what I get when I print the response.
FAILURE: Error Domain=NSURLErrorDomain Code=-1017 "cannot parse
response" UserInfo={NSUnderlyingError=0x7fbb505788f0 {Error
Domain=kCFErrorDomainCFNetwork Code=-1017 "(null)"
UserInfo={_kCFStreamErrorCodeKey=-1, _kCFStreamErrorDomainKey=4}},
NSErrorFailingURLStringKey=http://lfapp.learnflux.net/v1/me,
NSErrorFailingURLKey=http://lfapp.learnflux.net/v1/me,
_kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-1, NSLocalizedDescription=cannot parse response}
But the request works if I use REST client, by setting the headers to have the authentication and Content-Type, and have the parameters to be written as plain Content, e.g. in plain API in the body content.
How can I fix this?
EDIT: The part with the access token is already clear. The access token works. I can call an API successfully if the API doesn't requires any parameters (maybe because on the server, the code doesn't bother to even check or validate the body at all because it doesn't need anything from there, hence no error raised). The problem is when I make a request which needs any parameters.
The error you have is probably because of encoding: ParameterEncoding.JSON in the request. Try to change it to encoding: .URLEncodedInURL. If this doesn't help you, do add your parameters to the question and if you´re make a request to get the token do the following:
if let access_token = json["access_token"]!{
// Make the request here when you know that you have your token
}
So I'm sending a basic auth request to Bing Image Search to grab some image data, and it was working great, right until I updated to the latest version of Alamofire (1.3 -> 2.0.2), which I had to do because 1.3 wasn't even close to compatible with XCode 7.
Anyway, here is my code:
let credentials = ":\(Settings.bingApiKey)"
let plainText = credentials.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
let base64 = plainText!.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
manager = Alamofire.Manager.sharedInstance
manager!.session.configuration.HTTPAdditionalHeaders = [
"Authorization": "Basic \(base64)"
]
let url = NSURL(string: Settings.bingImageApi + "&Query=" + keyword + "&$top=15&$skip=" + String(skip))!
manager!
.request(.POST, url, parameters: nil, encoding: .JSON)
.responseJSON { request, response, result in
...
And I'm getting the error:
FAILURE: Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}
The authorization type you provided is not supported. Only Basic and OAuth are supported
I had the same issue while moving from Alamofire 1.x to 2.x.
One workaround I found (and that works), is to pass the headers when performing the request:
let headers = ["Authorization": "Basic \(base64)"]
Alamofire.request(.POST, url, parameters: nil, encoding: .JSON, headers: headers)
For more information you can take a look at the documentation.
please read here http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/
"App Transport Security (ATS) lets an app add a declaration to its Info.plist file that specifies the domains with which it needs secure communication. ATS prevents accidental disclosure, provides secure default behavior, and is easy to adopt. You should adopt ATS as soon as possible, regardless of whether you’re creating a new app or updating an existing one."
The first part of the error is due to you not receiving valid JSON in the response. You can use response, responseData or responseString to help debug.
The second part of the error is due to how you are setting the header. You cannot set an Authorization header after the session configuration has been created. You can either create your own session configuration and your own Manager, or you can pass the Authorization header in the request.
I am trying to use a custom java application of mine to upload videos to my youtube account via an access limited device like a Raspberry pi running as a server.
For this I am using the Google Oauth 2.0 for limited input device as a reference.
I followed the steps mentioned with my custom java application, Fiddler and curl, the surprise is as follows:
All of the calls worked right as mentioned by Google Oauth 2.0 for limited input device for curl.
But issues were observed with Fiddler and my custom java app for the following call:
When I am trying to get the access token from Google server (Step 4 from Google Oauth link) by posting similar request:
POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded
client_id=1084945748469-eg34imk572gdhu83gj5p0an9fut6urp5.apps.googleusercontent.com&
client_secret=hDBmMRhz7eJRsM9Z2q1oFBSem&
code=4/YMSlR3fSCC1NtUh073DuZKTJJ3ss&
grant_type=http://oauth.net/grant_type/device/1.0
but instead of getting the 'access_token' as response I am getting the following :
Status Code:400 Response: { "error" : "invalid_request",
"error_description" : "Required parameter is missing: grant_type" }
Note : With or without url encoding, my problem stays the same.
I am unable to understand what the issue is with my custom java app or with fiddler, Please help.
Following are my fiddler requests:
(One can get oauth credentials (client_id and client_secret) by following this)
Fiddler request:
(url encoded, obscured client secret)
POST HTTP/1.1
https://accounts.google.com/o/oauth2/token?client_id=308065994473-ur9dd7003ajs6mvr5s4kqnugr6j8tsf2.apps.googleusercontent.com&client_secret=XXXXXXXXXXXXXXX&code=4%2FWR-qiTquqB0e4-0LCy0-7rZ2kkE2&grant_type=http%3A%2F%2Foauth.net%2Fgrant_type%2Fdevice%2F1.0
Content-Type: application/x-www-form-urlencoded
(non url encoded, obscured client secret)
POST HTTP/1.1
https://accounts.google.com/o/oauth2/token?client_id=308065994473-ur9dd7003ajs6mvr5s4kqnugr6j8tsf2.apps.googleusercontent.com&client_secret=XXXXXXXXXXXXXX&code=4/WR-qiTquqB0e4-0LCy0-7rZ2kkE2&grant_type=http://oauth.net/grant_type/device/1.0
Java code project is available at (maven project, check the test case for the Oauth calls):
https://docs.google.com/file/d/0B8ltWBtPF-DVMDZFNHNMZXpCQlk
The parameters need to be added in the http post request body not in the url, Google documentation is confusing on this part.
public synchronized HttpResponse executePOST(HttpEntity httpEntity, String path) throws IOException {
if (!parameters.isEmpty()) {
httpPost.setEntity(new UrlEncodedFormEntity(parameters));
}
httpPost = new HttpPost(path);
logger.info(target.toHostString());
logger.info(httpPost.getURI().toString());
logger.info(httpPost.getRequestLine().toString());
for (Header header : headers) {
logger.info(header.getName() + ": " + header.getValue());
httpPost.addHeader(header);
}
httpResponse = httpClient.execute(target, httpPost);
return httpResponse;
}
How to add content-type to Twilio Response? I am getting 502 bad gateway error and the error says that it could be because of missing Content-Type. But I do see that the response has the Content-type. So what could be going wrong? I am also seeing the twilio reason is connection-time out! What does that mean? This is related to my earlier post at: An attempt to retrieve content from returned the HTTP status code 502. Please check the URL and try again
Response - The HTTP headers and body of your server's response to Twilio
Headers
Content-Type text/html
Transfer-Encoding chunked
X-Twilio-Reason connection timed out
Body
1
<html><head><title>502 Bad Gateway</title></head><body><h1>Bad Gateway</h1>An upstream server returned an invalid response.</body></html>
Can somebody help me to find out why twilio is giving error while accessing my API?
This is what I have in my controller:
public class TestController : ApiController
{
[HttpPost]
public HttpResponseMessage Post([FromBody]SmsRequest smsReq)
{
string smsReqUpper = smsReq.Body.ToUpper();
string testString = "TEST";
var response = new Twilio.TwiML.TwilioResponse();
if (smsReqUpper == testString)
{
response.Sms("Test Successful");
return Request.CreateResponse(HttpStatusCode.OK, response.Element);
}
else
{
string strBody = "Invalid Text Command. Please text the word TEST " ;
response.Sms(strBody);
return Request.CreateResponse(HttpStatusCode.OK, response.Element);
//return new TwiMLResult(response);
}
}
The Content-Type text/html bit refers to the 502 bad gateway response, not the actual response coming from your server. Add the "text/xml" content type to your request (I don't recognize the framework you are using) and you should be good to go.
To debug your response you can use curl -vvv [URL] until the Content-Type: text/xml part is present.