RxAlamofire post multipart data - swift3

How to send Multipart data with RxAlamofire
For instance in Alamofire
let URL = try! URLRequest(url: "http://example.com", method: .post)
Alamofire.upload(multipartFormData: { formData in
// multiaprt
}, with: URL, encodingCompletion: {(result: SessionManager.MultipartFormDataEncodingResult) in
})
How to get same behaviour/function with RxAlamofire?
Or An way of wrapping this function in an Observable?

You can easily wrap that function like this:
func wrapper() -> Observable<SomeResponseType> {
return Observable.create { observer in
let URL = try! URLRequest(url: "http://example.com", method: .post)
Alamofire.upload(
multipartFormData: { formData in
// multiaprt
},
with: URL,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
// convert response in something of SomeResponseType
// ...
observer.onNext(response)
observer.onCompleted()
}
case .failure(let encodingError):
observer.onError(encodingError)
}
})
return Disposables.create()
}
}

Related

Express Gateway: Not getting response body

I am not being able to get the response body that I need to store in the logs along with the request body. The only time I'm able to get the response body is when the request fails.
I've followed the blog post that solved my issue on getting the request body while using body-parser plugin - https://www.express-gateway.io/exploit-request-stream/.
const { PassThrough } = require("stream");
const jsonParser = require("express").json();
const urlEncodedParser = require("express").urlencoded({ extended: true });
module.exports = {
name: 'body-parser',
policy: actionParams => {
return (req, res, next) => {
req.egContext.requestStream = new PassThrough()
req.pipe(req.egContext.requestStream)
return jsonParser(req, res, () => urlEncodedParser(req, res, next))
}
}
};
When the request does work:
{ res: { statusCode: 400 },
req:
{ body: { a: 'b' },
headers:
{ ... } },
responseTime: 310 }
When it does not work:
{ res: { body: 'Bad gateway.', statusCode: 502 },
req:
{ body: { a: 'b' },
headers:
{ ... } },
responseTime: 1019 }
this code alone is not enough to get the response body. This will simply hook in the request body processing and make it available to EG in a parsed way. In case you want to hook in the response too, you will need to write an hook in the response object, once it's done.
You can find an example code here
I hope that helps!
V.

Alamofire post request return 404 in Swift

I am going to post a request via alamofire. I can post request with Postman. Response return true (201 code). However when I am try with Alamofire returns 404 code. What's wrong?
My codes:
let headers: HTTPHeaders = [
"Authorization": "Basic xxxxxxxxxxxx",
"content-type": "application/json"
]
let parameters:[String:Any] = [
"xxx":123,
"yyy":"test",
"zzz":"iphone"
]
Alamofire.request(myUrl, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: headers).responseJSON { response -> Void in
switch response.result {
case .success:
print(response.response?.statusCode)
break
case .failure(let error):
print(error)
}
}
Return this message :
success {
message = "No HTTP resource was found that matches the request URI 'https://xxxxx/PostErrorFeedBack'.";
}
Try this one hope it may help you !!
let headers = [
"Authorization": "Basic xxxxxxxxxxxx"
]
let parameters = [
]
Alamofire.request(.POST, "url", parameters: parameters, headers: headers, encoding: .JSON)
.validate(contentType: ["application/json"])
.responseJSON { response in
if response.response?.statusCode == 200 {
print("Success with JSON: \(response.result.value)")
}
else {
let error = response.result.value as! NSDictionary
let errorMessage = error.objectForKey("message") as! String
print(errorMessage)
failure(errorMessage)
}
}
you can try this method for using Alamofire as this worked for me.
let headers = [
"Accept": "application/json",
"Authorization" : "Authorization: Bearer ", //if any
"Cookie" : "Cookie" //if any
]
let parameterDict: NSDictionary = NSDictionary.init(objects: [nameTextField.text!, reportTextView.text!], forKeys: ["Name" as NSCopying,"Message" as NSCopying])
Alamofire.request("API",method: .post, parameters: parameterDict as? [String : AnyObject] , encoding:JSONEncoding.default, headers:headers) .responseJSON { response in switch response.result {
case .success(let JSON):
print("Success with JSON: \(JSON)")
let response = JSON as! NSDictionary
case .failure(let error):
print("Request failed with error: \(error)")
}
}

How to POST data for evaluation in middleware in loopback?

I want to use custom API to evaluate data which are posted by applications but remote methods are not accepted in middleware in loopback
module.exports = function () {
const http = require('https');
var request = require('request');
var { Lib } = require('Lib');
var lib = new Lib;
verification.checkID = function (ID, cb) {
cb(null, 'ID is :' + ID);
}
verification.remoteMethod('greet', {
accepts: {
arg: 'ID',
type: 'string'
},
returns: {
arg: 'OK',
type: 'string'
}
});
module.exports = function () {
const http = require('https');
var request = require('request');
var { Lib } = require('Lib');
var lib = new Lib;
verification.checkID = function (ID, cb) {
cb(null, 'ID is :' + ID);
}
verification.remoteMethod('greet', {
'http': { // add the verb here
'path': '/greet',
'verb': 'post'
},
accepts: {
arg: 'ID',
type: 'string'
},
returns: {
arg: 'OK',
type: 'string'
}
});
Update
module.exports = function(server) {
// Install a `/` route that returns server status
var router = server.loopback.Router();
router.get('/', server.loopback.status());
router.get('/ping', function(req, res) { // your middle ware function now you need to call the next() here
res.send('pong');
});
server.use(router);
};
To evaluate is something i am not getting please check this link too Intercepting error handling with loopback
Regarding to fallowing question How to make a simple API for post method?
I find my solution in fallowing way:
module.exports = function(server) {
const https = require('https');
var request = require('request');
return function verification(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
res.setHeader('Access-Control-Allow-Credentials', true);
var request;
var response;
var body = '';
// When a chunk of data arrives.
req.on('data', function (chunk) {
// Append it.
body += chunk;
});
// When finished with data.
req.on('end', function () {
// Show what just arrived if POST.
if (req.method === 'POST') {
console.log(body);
}
// Which method?
switch (req.method) {
case 'GET':
Verify url and respond with appropriate data.
handleGet(req, res);
Response has already been sent.
response = '';
break;
case 'POST':
// Verify JSON request and respond with stringified JSON response.
response = handlePost(body);
break;
default:
response = JSON.stringify({ 'error': 'Not A POST' });
break;
}
// Send the response if not empty.
if (response.length !== 0) {
res.write(response);
res.end();
}
// Paranoid clear of the 'body'. Seems to work without
// this, but I don't trust it...
body = '';
});
// If error.
req.on('error', function (err) {
res.write(JSON.stringify({ 'error': err.message }));
res.end();
});
//
};
function handlePost(body) {
var response = '';
var obj = JSON.parse(body);
// Error if no 'fcn' property.
if (obj['fcn'] === 'undefined') {
return JSON.stringify({ 'error': 'Request method missing' });
}
// Which function.
switch (obj['fcn']) {
// Calculate() requres 3 arguments.
case 'verification':
// Error if no arguments.
if ((obj['arg'] === 'undefined') || (obj['arg'].length !== 3)) {
response = JSON.stringify({ 'error': 'Arguments missing' });
break;
}
// Return with response from method.
response = verification(obj['arg']);
break;
default:
response = JSON.stringify({ 'error': 'Unknown function' });
break;
}
return response;
};
function verification(arg) {
var n1 = Number(arg[0]);
var n2 = Number(arg[1]);
var n3 = Number(arg[2]);
var result;
// Addem up.
result = n1 + n2 + n3;
// Return with JSON string.
return JSON.stringify({ 'result': result });
};
};

how to import FaceBook profile pictures from album using Swift

I am fetching the facebook profile picture like this
let params = ["height": 300, "width": 300, "redirect": false] as [String : Any]
let graphRequest = FBSDKGraphRequest(graphPath: "me/picture", parameters: params, httpMethod: "GET")
let connection = FBSDKGraphRequestConnection()
connection.add(graphRequest, completionHandler: { (connection, result, error) in
if error == nil {
print("profile pic ************\(result)")
}
})
connection.start()
Now I need to access the profile pictures from the ablum and set those in my collectionView . I tried to set the graphPath: "me/album/profile_picture" but no luck . Could anybody give me some hints please ?
You need to find the id of the "Profile Pictures" album and request the photos for that id.
Facebook.albums(user: "me").request({ albums in
albums.first(where: { ($0["name"] as? String) == "Profile Pictures" }).flatMap({
Facebook.photos(album: $0["id"] as! String).request({ photos in
print(photos)
})
})
})
I have made an enum below to make requesting graph api paths easier.
enum Facebook: Graphable {
case albums(user: String)
case photos(album: String)
var path: String {
switch self {
case let .albums(uid):
return "\(uid)/albums"
case let .photos(aid):
return "\(aid)/photos"
}
}
var method: String {
switch self {
case .albums, .photos:
return "GET"
}
}
var params: [String : Any] {
switch self {
case .albums:
return [:]
case .photos:
return [
"height": 300,
"width": 300,
"redirect": false
]
}
}
}
Here is the protocol and extension the enum must conform to.
protocol Graphable {
var path: String { get }
var method: String { get}
var params: [String : Any] { get }
}
extension Graphable {
typealias JSON = [String:Any]
func request(_ handler: #escaping ([JSON]!) -> (), failure: #escaping (Error) -> () = { print($0) }) {
let connection = FBSDKGraphRequestConnection()
let request = FBSDKGraphRequest(
graphPath: path,
parameters: params,
httpMethod: method
)
connection.add(request) {
_ = $0.1.map ({ handler(($0 as? JSON)?["data"] as? [JSON]) }) ??
$0.2.map ({ failure($0) })
}
connection.start()
}
}
I got my answer like this :
import FBSDKCoreKit
import SwiftyJSON
func getFBAlbumID() {
let graphRequest = FBSDKGraphRequest(graphPath: "me/albums", parameters: nil, httpMethod: "GET")
let connection = FBSDKGraphRequestConnection()
connection.add(graphRequest, completionHandler: { (connection, result, error) in
if error == nil
let dictionary = JSON(result)
// print("albums ID are **************\(dictionary)")
if let data = dictionary["data"].array {
print("data of profilePicture ******* \(data)")
if let dict = data.first(where: { ($0["name"].string ) == "Profile Pictures" }) {
let id = dict["id"].string
print("my desired id : ********* \(id)")
self.getFBAlbumPhoto(albumID: id!)
}
}
}
})
connection.start()
}
func getFBAlbumPhoto(albumID: String) {
let params = [ "height": 300, "width": 300, "redirect": false] as [String : Any]
let graphRequest = FBSDKGraphRequest(graphPath: "\(albumID)/photos?fields=source", parameters: params, httpMethod: "GET")
let connection = FBSDKGraphRequestConnection()
connection.add(graphRequest, completionHandler: { (connection, result, error) in
if error == nil {
//print(result)
let dictionary = JSON(result)
print("result are **************\(dictionary)")
}
})
connection.start()
}
Here I am grabbing the ID of the particular album I desire and then make another call to get the photos of that album. Here I am calling a function from inside another function. If someone can help me to write the code in more Swift way that would be helpful, like using closure. Thanks.

Alamofire 4.0, Swift 3 Post params not being passed

When I upgraded to latest everything (Alamo 4, Swift 3 and XC 8) the following stopped posting parameters and I dont have a clue why...
let params = ["stripeToken": token.tokenId,
"name": name,
"email": email
]
Alamofire.request(requestString, method: .post, parameters: params, encoding: JSONEncoding.default)
.responseJSON { (response) in
if response.result.value is NSNull {
return
}
I had a similar issue, I changed encoding from JSONEncoding.default to URLEncoding.httpbody or encoding: URLEncoding.default
Alamofire.request(URL, method: .post, parameters: params, encoding: URLEncoding.httpBody).responseJSON { response in
if let data = response.data {
let json = String(data: data, encoding: String.Encoding.utf8)
print("Response: \(json)")
}
}
I have the same issue and finally fixed it. URLEncoding.httpBody didn't work for me... but URLEncoding.default did.
So I changed JSONEncoding.default to URLEncoding.default.
It's now passing the parameters to the backend.
Alamofire.request(loginURL, method: .post, parameters: params, encoding: URLEncoding.default, headers: nil)
Everything works exactly as it should. Here's a quick example demonstrating that fact.
func testPostingJSON() {
let urlString = "https://httpbin.org/post"
let params: Parameters = [
"stripeToken": "token_id",
"name": "cnoon",
"email": "cnoon#alamofire.org"
]
let expectation = self.expectation(description: "should work")
Alamofire.request(urlString, method: .post, parameters: params, encoding: JSONEncoding.default)
.responseJSON { response in
if let json = response.result.value {
print("JSON: \(json)")
} else {
print("Did not receive json")
}
expectation.fulfill()
}
waitForExpectations(timeout: 5.0, handler: nil)
}
Hopefully that example helps you pinpoint the issue. Cheers. 🍻