web-dev-qa-db-fra.com

POST demande avec une simple ficelle dans le corps avec Alamofire

comment est-il possible d'envoyer une demande POST avec une simple chaîne dans le corps HTTP avec Alamofire dans mon application iOS?

Par défaut, Alamofire a besoin de paramètres pour une requête:

Alamofire.request(.POST, "http://mywebsite.com/post-request", parameters: ["foo": "bar"])

Ces paramètres contiennent des paires clé-valeur. Mais je ne veux pas envoyer de requête avec une chaîne clé-valeur dans le corps HTTP.

Je veux dire quelque chose comme ça:

Alamofire.request(.POST, "http://mywebsite.com/post-request", body: "myBodyString")
64
Karl

Votre exemple Alamofire.request(.POST, "http://mywebsite.com/post-request", parameters: ["foo": "bar"]) contient déjà la chaîne "foo = bar" en tant que corps ..____. Mais si vous voulez vraiment une chaîne au format personnalisé. Tu peux le faire:

Alamofire.request(.POST, "http://mywebsite.com/post-request", parameters: [:], encoding: .Custom({
            (convertible, params) in
            var mutableRequest = convertible.URLRequest.copy() as NSMutableURLRequest
            mutableRequest.HTTPBody = "myBodyString".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
            return (mutableRequest, nil)
        }))

Remarque: parameters ne devrait pas être nil

UPDATE (Alamofire 4.0, Swift 3.0):

Dans Alamofire 4.0, l'API a changé. Donc pour l'encodage personnalisé, nous avons besoin de valeur/objet conforme au protocole ParameterEncoding.

extension String: ParameterEncoding {

    public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
        var request = try urlRequest.asURLRequest()
        request.httpBody = data(using: .utf8, allowLossyConversion: false)
        return request
    }

}

Alamofire.request("http://mywebsite.com/post-request", method: .post, parameters: [:], encoding: "myBody", headers: [:])
77
Silmaril

Tu peux le faire:

  1. J'ai créé un objet Alamofire de requête séparée.
  2. Convertir une chaîne en données 
  3. Mettez dans httpBody les données

    var request = URLRequest(url: URL(string: url)!)
    request.httpMethod = HTTPMethod.post.rawValue
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    
    let pjson = attendences.toJSONString(prettyPrint: false)
    let data = (pjson?.data(using: .utf8))! as Data
    
    request.httpBody = data
    
    Alamofire.request(request).responseJSON { (response) in
    
    
        print(response)
    
    }
    
41
afrodev

Si vous utilisez Alamofire, il suffit de coder le type "URLEncoding.httpBody"

Avec cela, vous pouvez envoyer vos données sous forme de chaîne dans httpbody, bien que vous les ayez définies json dans votre code.

Cela a fonctionné pour moi ..

MISE À JOUR pour 

  var url = "http://..."
    let _headers : HTTPHeaders = ["Content-Type":"application/x-www-form-urlencoded"]
    let params : Parameters = ["grant_type":"password","username":"mail","password":"pass"]

    let url =  NSURL(string:"url" as String)

    request(url, method: .post, parameters: params, encoding: URLEncoding.httpBody , headers: _headers).responseJSON(completionHandler: {
        response in response

        let jsonResponse = response.result.value as! NSDictionary

        if jsonResponse["access_token"] != nil
        {
            access_token = String(describing: jsonResponse["accesstoken"]!)

        }

    })
9
Cemal BAYRI

J'ai modifié la réponse de @ Silmaril pour étendre le gestionnaire d'Alamofire. Cette solution utilise EVReflection pour sérialiser directement un objet:

//Extend Alamofire so it can do POSTs with a JSON body from passed object
extension Alamofire.Manager {
    public class func request(
        method: Alamofire.Method,
        _ URLString: URLStringConvertible,
          bodyObject: EVObject)
        -> Request
    {
        return Manager.sharedInstance.request(
            method,
            URLString,
            parameters: [:],
            encoding: .Custom({ (convertible, params) in
                let mutableRequest = convertible.URLRequest.copy() as! NSMutableURLRequest
                mutableRequest.HTTPBody = bodyObject.toJsonString().dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
                return (mutableRequest, nil)
            })
        )
    }
}

Ensuite, vous pouvez l'utiliser comme ceci: 

Alamofire.Manager.request(.POST, endpointUrlString, bodyObject: myObjectToPost)
8
raf

Si vous voulez poster une chaîne en tant que corps brut dans la demande

return Alamofire.request(.POST, "http://mywebsite.com/post-request" , parameters: [:], encoding: .Custom({
            (convertible, params) in
            let mutableRequest = convertible.URLRequest.copy() as! NSMutableURLRequest

            let data = ("myBodyString" as NSString).dataUsingEncoding(NSUTF8StringEncoding)
            mutableRequest.HTTPBody = data
            return (mutableRequest, nil)
        }))
5
J.R
func paramsFromJSON(json: String) -> [String : AnyObject]?
{
    let objectData: NSData = (json.dataUsingEncoding(NSUTF8StringEncoding))!
    var jsonDict: [ String : AnyObject]!
    do {
        jsonDict = try NSJSONSerialization.JSONObjectWithData(objectData, options: .MutableContainers) as! [ String : AnyObject]
        return jsonDict
    } catch {
        print("JSON serialization failed:  \(error)")
        return nil
    }
}

let json = Mapper().toJSONString(loginJSON, prettyPrint: false)

Alamofire.request(.POST, url + "/login", parameters: paramsFromJSON(json!), encoding: .JSON)
2
AndrewK

Je l'ai fait pour tableau de chaînes. Cette solution est ajustée pour la chaîne dans le corps.

Le chemin "natif" d'Alamofire 4: 

struct JSONStringArrayEncoding: ParameterEncoding {
    private let myString: String

    init(string: String) {
        self.myString = string
    }

    func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
        var urlRequest = urlRequest.urlRequest

        let data = myString.data(using: .utf8)!

        if urlRequest?.value(forHTTPHeaderField: "Content-Type") == nil {
            urlRequest?.setValue("application/json", forHTTPHeaderField: "Content-Type")
        }

        urlRequest?.httpBody = data

        return urlRequest!
    }
}

Et ensuite faites votre demande avec:

Alamofire.request("your url string", method: .post, parameters: [:], encoding: JSONStringArrayEncoding.init(string: "My string for body"), headers: [:])
2
Illya Krit

J'ai utilisé la réponse de @afrodev comme référence. Dans mon cas, je considère les paramètres de ma fonction comme des chaînes qui doivent être postées dans une requête. Alors, voici le code:

func defineOriginalLanguage(ofText: String) {
    let text =  ofText
    let stringURL = basicURL + "identify?version=2018-05-01"
    let url = URL(string: stringURL)

    var request = URLRequest(url: url!)
    request.httpMethod = HTTPMethod.post.rawValue
    request.setValue("text/plain", forHTTPHeaderField: "Content-Type")
    request.httpBody = text.data(using: .utf8)

    Alamofire.request(request)
        .responseJSON { response in
            print(response)
    }
}
1
Georgy Dyagilev

Basé sur la réponse de Illya Krit

Détails

  • Xcode version 10.2.1 (10E1001)
  • Swift 5
  • Alamofire 4.8.2

Solution

import Alamofire

struct BodyStringEncoding: ParameterEncoding {

    private let body: String

    init(body: String) { self.body = body }

    func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
        guard var urlRequest = urlRequest.urlRequest else { throw Errors.emptyURLRequest }
        guard let data = body.data(using: .utf8) else { throw Errors.encodingProblem }
        urlRequest.httpBody = data
        return urlRequest
    }
}

extension BodyStringEncoding {
    enum Errors: Error {
        case emptyURLRequest
        case encodingProblem
    }
}

extension BodyStringEncoding.Errors: LocalizedError {
    var errorDescription: String? {
        switch self {
            case .emptyURLRequest: return "Empty url request"
            case .encodingProblem: return "Encoding problem"
        }
    }
}

Usage

Alamofire.request(url, method: .post, parameters: nil, encoding: BodyStringEncoding(body: text), headers: headers).responseJSON { response in
     print(response)
}
0
Vasily Bodnarchuk