Getting back nil from Google Translate using Swift and Alamofire - ios

I am trying to use Alamofire to use the Google Translate api.
Here is the code I am trying to use:
let textToTranslate = "你好"
let parameters = ["key":"MY_PRIVATE_IOS_APP_KEY","q":"\(textToTranslate)",
"source":"zh-CN","target":"en"]
Alamofire.request(.GET, "https://www.googleapis.com/language/translate/v2/languages", parameters:parameters)
.responseJSON
{ (_, _, JSON, _) -> Void in
let translatedText: String? = JSON?.valueForKeyPath("data") as String?
println(translatedText)
}
The console keeps printing nil.
Also, in the Google Translate API Usage Report it says I have "Client Errors".
This is the kind of output I get when I try this in the browser:
{
"data": {
"translations": [
{
"translatedText": "hello"
}
]
}
}
What am I missing or doing wrong?

The URL that you should GET is:
https://www.googleapis.com/language/translate/v2?parameters
On your code I see the URL:
https://www.googleapis.com/language/translate/v2/languages?parameters

Related

Xcode, The given data was not valid JSON, Can't read the JSON from API properly

Hello I am creating an app with Xcode and I am having the following problem, I created this API (if you enter the link you'll see the JSON data) https://proyecto-idts6.epizy.com/models/getCategorias.php
If you dont want to enter the link here is how this si how the structure of the JSON looks like:
{
"items":[
{
"categorie":"Fruits",
"id_categorie":"1"
},
{
"categorie":"Animals",
"id_categorie":"2"
},
{
"categorie":"Juices",
"id_categorie":"3"
},
{
"categorie":"Vegetables",
"id_categorie":"4"
},
{
"categorie":"Alcohol",
"id_categorie":"5"
},
{
"categorie":"Desserts",
"id_categorie":"6"
}
]
}
The problem I have is that when I try to decode the data from the API it cant't be decoded properly, I am trying to recreate the same code of this youtube video, but with my API: https://www.youtube.com/watch?v=sqo844saoC4
What I want basically is to print the categories and storage each of them in variables (because i'll need to move the variables between screens)
This is how my code looks like:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let url = "https://proyecto-idts6.epizy.com/models/getCategorias.php"
getData(from: url)
//Here is where i want to storage the variables from the JSON
}
private func getData(from url: String) {
let task = URLSession.shared.dataTask(with: URL(string: url)!, completionHandler: { data, response, error in
guard let data = data, error == nil else {
print("something went wrong")
return
}
do {
let result = try JSONDecoder().decode([ResultItem].self, from: data)
print(result)
}
catch {
print("failed to convert\(error)")
}
})
task.resume()
}
}
struct Response: Codable {
let items: [ResultItem]
}
struct ResultItem: Codable {
let categorie: String
}
My goal is to have variables for example like this: categorie1=("the category 1 called from the JSON"), categorie2=("the category 2 called from the JSON"), categorie3=("the category 3 called from the JSON"),...
The problem is not in the decoding but in the remote API.
Your endpoint (https://proyecto-idts6.epizy.com/models/getCategorias.php) instead of returning a JSON is returning the following HTML
<html><body><script type="text/javascript" src="/aes.js" ></script><script>function toNumbers(d){var e=[];d.replace(/(..)/g,function(d){e.push(parseInt(d,16))});return e}function toHex(){for(var d=[],d=1==arguments.length&&arguments[0].constructor==Array?arguments[0]:arguments,e="",f=0;f<d.length;f++)e+=(16>d[f]?"0":"")+d[f].toString(16);return e.toLowerCase()}var a=toNumbers("f655ba9d09a112d4968c63579db590b4"),b=toNumbers("98344c2eee86c3994890592585b49f80"),c=toNumbers("f5490e280a5e50f74932909856c3d3a3");document.cookie="__test="+toHex(slowAES.decrypt(c,2,a,b))+"; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/"; location.href="https://proyecto-idts6.epizy.com/models/getCategorias.php?i=1";</script><noscript>This site requires Javascript to work, please enable Javascript in your browser or use a browser with Javascript support</noscript></body></html>
So you are trying to decode that HTML content, which clearly leads to the error your reported
failed to convertdataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around line 1, column 0." UserInfo={NSDebugDescription=Invalid value around line 1, column 0., NSJSONSerializationErrorIndex=0})))

post request with body Alamofire

I am trying to post some data to the API, but I keep getting Response status code was unacceptable: 404 error message.. I have checked, the POST parameters and API Url are all correct, example request works on the postman but it is not working on Xcode..
my POST request Url is in this format: {{API}}/postData/Id/block.
my POST request function with Alamofire is as follows:
func postData(token: String, id: String, category: String, completion: #escaping(_ data: DataTobePost) -> Void) {
let header: HTTPHeaders = ["authorization": token]
let parameter: Parameters = [
"Id": id,
"category": category ]
Alamofire.request(API_Configurator.postData, method: .post, parameters: parameter, encoding: JSONEncoding.default, headers: header).validate().responseData(completionHandler: { response in
switch response.result {
case .success(let val):
do {
let data = try JSONDecoder().decode(DataTobePost.self, from: val)
completion(data)
}catch {
print("[DataTobePost Catch Error while decoding response: \(error.localizedDescription)]")
}
case .failure(let error):
print("[DataTobePost Failure Error : \(error.localizedDescription)]")
}
})
}
and the response is:
{
"success": true
}
where am i going wrong, can anyone help through this. (I am quite new to Alamofire)
There is no way to check what is wrong.
If you got the 404 error it means 2 things:
Code was written correctly(it compiles)
Requested page does not exist (404 error)
I think you need to check your API_Configurator.postData.
Usually, it's something simple like extra characters like "//", " ", "." etc.
Or the problem with API.
The best way to check API uses Postman

POST API call using APIGateway returns "Internal Server Error" in swift 4, but works everywhere else

I created a nodejs lambda function in AWS and exposed it using APIGateway with methods GET, PUT, POST, and DELETE (all setup with proxy). All methods have been tested and work in AWS using APIGateway, and then outside of AWS using Postman.
First, I called the GET method for the endpoint in my Swift 4 project, and it is successful.
BUT I have tried just about everything to call the POST method in swift and cannot get it to execute successfully. This is what I am currently trying after researching online:
let awsEndpoint: String = "https://host/path"
guard let awsURL = URL(string: awsEndpoint) else {
print("Error: cannot create URL")
return
}
var postUrlRequest = URLRequest(url: awsURL)
postUrlRequest.httpMethod = "POST"
postUrlRequest.addValue("John Doe", forHTTPHeaderField: "name")
postUrlRequest.addValue("imageurl.com", forHTTPHeaderField: "imageUrl")
URLSession.shared.dataTask(with: postUrlRequest) { data, response, error in
guard let data = data else { return }
do {
guard let receivedTodo = try JSONSerialization.jsonObject(with: data,
options: []) as? [String: Any] else {
print("Error")
return
}
} catch let err{
print(err)
}
}.resume()
The response I get is ["message":"Internal Server Error"]. When I look at the logs in CloudWatch they are not very descriptive. The error log for the post call is:
"Execution failed due to configuration error: Malformed Lambda proxy response"
After researching this issue aws suggests to format the response in a specific way and I have updated my nodejs lambda function to mimmic this.
case "POST":
pool.getConnection(function(err, connection) {
const groupName = event.headers.name;
const imageUrl = event.headers.imageUrl;
var group = {Name: groupName, ImageUrl: imageUrl, IsActive:true, Created:date, Updated:date};
var query = "INSERT INTO Groups SET ?";
connection.query(query,group, function (error, results, fields) {
var responseBody = {
"key3": "value3",
"key2": "value2",
"key1": "value1"
};
var response = {
"statusCode": 200,
"headers": {
"my_header": "my_value"
},
"body": JSON.stringify(responseBody),
"isBase64Encoded": true
};
if (error) callback(error);
else callback(null, response)
connection.release();
});
});
break;
Like I said previously, this works when testing everywhere except swift 4. My GET call works with swift 4, so I do not think it is an issue with allowing anything in the info.plist but I could be wrong. I have tried just about everything, but cannot seem to get past this error.
I fixed this issue myself. After allowing ALL log output in API Gateway for that endpoint, I found that somewhere along the way my headers were being converted to all lowercase.
'imageUrl' became 'imageurl'
It was throwing an error because in my lambda function, it could not find 'imageUrl'
I think this is a conversion that is happening in APIGateway because I have never come across this issue with swift.

Generate cURL output from Moya request?

I'm using Moya and need to print the cURL for a network request.
Usually, in Alamofire 4, I would do something like this:
let req = Alamofire.request(someURLRequestConvertible)
debugPrint(req) // will print cURL
My call site for Moya looks like this:
MyMoyaProvider.request(MyEndPoints.login(params)) { (result) in }
I've checked out the documentation for Moya, but I can't seem to get the results I'm looking for. I enabled the NetworkLoggingPlugin but still unsure how to print cURL for certain requests. Can someone help me find the proper way to print the Moya request's cURL to console?
If you initialize your NetworkLoggerPlugin, its cURL flag is set to false by default. Initializing it like NetworkLoggerPlugin(cURL: true), willSendRequest should print the cURL.
As per #BasThomas on GitHub: https://github.com/Moya/Moya/issues/1037#event-1027530791
For Moya 14.0.*
static fileprivate let provider = MoyaProvider<ApiService>(endpointClosure: { (target: ApiService) -> Endpoint in
let defaultEndpoint = MoyaProvider.defaultEndpointMapping(for: target)
switch target {
default:
let httpHeaderFields = ["Content-Type" : "application/json"]
return defaultEndpoint.adding(newHTTPHeaderFields: httpHeaderFields)
}
}, plugins: [
NetworkLoggerPlugin(configuration: .init(formatter: .init(), output: { (target, array) in
if let log = array.first {
print(log)
}
}, logOptions: .formatRequestAscURL))
])

Alamofire Get Request and JSON Response

I'm trying to use the Yoda API and send a request using the Alamofire Swift framework. I know that the API is correctly working, as I have tested the endpoint with my Mashape API key multiple times. I can also see that the requests are being sent (homepage of Mashape under my application). However my JSON response is always nil.
func handleRequest(words:String){
var saying = words.stringByReplacingOccurrencesOfString(" ", withString: "+");
saying = "?sentence=" + saying;
let url = NSURL(string: (baseURL+saying));
println(url);
var response:String;
Alamofire.Manager.sharedInstance.session.configuration.HTTPAdditionalHeaders = additionalHeaders;
Alamofire.request(.GET, url!).responseJSON { (_, _, JSON, _) in
println(JSON);
}
}
The words string can be "This is my first sentence" and it will automatically replace the spaces with "+" as per the API spec. Please Ignore the multiple println statements, they are just for debugging.
This is just proof of concept code, its purposely not doing much error checking and isn't pretty for that reason. If you have any suggestions I would appreciate them.
For some reason it's an issue I've too with the Alamofire request for JSON. It is the way I handle the JSON requests using Alamofire :
Alamofire.request(.GET, urlTo, parameters: nil, encoding: .URL).responseString(completionHandler: {
(request: NSURLRequest, response: NSHTTPURLResponse?, responseBody: String?, error: NSError?) -> Void in
// Convert the response to NSData to handle with SwiftyJSON
if let data = (responseBody as NSString).dataUsingEncoding(NSUTF8StringEncoding) {
let json = JSON(data: data)
println(json)
}
})
I strongly recommend you using SwiftyJSON to manage the JSON in a better and easy way, it's up to you.
I hope this help you.
Alamofire request have several method for handle response. Try to handle data response and convert it to String. Confirm that response JSON is normal.
Alamofire.request(.GET, url!).response { (_, _, data, error) in
let str = NSString(data: data, encoding: NSUTF8StringEncoding)
println(str)
println(error)
}
Also checkout error while parsing JSON data.

Resources