POST-Anfrage mit einer einfachen Zeichenfolge im Body mit Alamofire

83

Wie ist es möglich, mit Alamofire in meiner iOS-App eine POST-Anfrage mit einer einfachen Zeichenfolge im HTTP-Body zu senden?

Standardmäßig benötigt Alamofire Parameter für eine Anfrage:

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

Diese Parameter enthalten Schlüssel-Wert-Paare. Ich möchte jedoch keine Anfrage mit einer Schlüsselwertzeichenfolge im HTTP-Body senden.

Ich meine so etwas:

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

Antworten:

88

Ihr Beispiel Alamofire.request(.POST, "http://mywebsite.com/post-request", parameters: ["foo": "bar"])enthält bereits den String "foo = bar" als Hauptteil. Aber wenn Sie wirklich Zeichenfolge mit benutzerdefiniertem Format wollen. Du kannst das:

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)
        }))

Hinweis: parameterssollte nicht seinnil

UPDATE (Alamofire 4.0, Swift 3.0):

In Alamofire 4.0 hat sich die API geändert. Für die benutzerdefinierte Codierung benötigen wir also einen Wert / ein Objekt, der dem ParameterEncodingProtokoll entspricht .

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: [:])
Silmaril
quelle
Dies funktioniert perfekt, nicht nur für einfache, sondern für alle Arten von JSON-Zeichenfolgen.
Sahil Kapoor
hat meinen Tag gerettet :) Danke (y)
ishhhh
1
@silmaril in meiner Situation Ich kann rohe Anfrage vom Backend nur erhalten, wenn ich PUT-Methode verwende. Könnten Sie mir bitte helfen, warum POST-Anfrage nichts sehen kann
AJ
1
.Custom ist in Alamofire 4 Swift 3 nicht mehr verfügbar, und ich kann die Alternative nicht finden, irgendwelche Hinweise?
Raheel Sadiq
@Silmaril Ich habe auch eine Frage gepostet, bitte beantworte diese, damit ich sie schließen kann: stackoverflow.com/questions/39573514/…
Raheel Sadiq
64

Du kannst das:

  1. Ich habe ein separates Alamofire-Anforderungsobjekt erstellt.
  2. Zeichenfolge in Daten konvertieren
  3. Geben Sie die Daten in httpBody ein

    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)
    
    }
    
afrodev
quelle
5
Dies sollte die akzeptierte Antwort sein. Es ist einfach, macht genau das, was benötigt wird, und ohne unnötige Erweiterungen oder Konvertierungen. Danke, Mann.
Seeküste von Tibet
2
PS Ich habe Ihre Antwort auf eine andere Frage "ausgeliehen" - stackoverflow.com/a/42411188/362305
Sea Coast of Tibet
2
Was ist Attendenzen, können Sie plz ein vollständigeres Snippet
posten
@SyraKozZ Egal, um welche Besucherzahlen es sich handelt, der einzige wichtige Punkt ist, dass pjson eine json-Zeichenfolge ist. Sie können dort eine beliebige JSON-Zeichenfolge einfügen.
Afrodev
13

Wenn Sie Alamofire verwenden, reicht es aus, den Typ in "URLEncoding.httpBody" zu codieren.

Damit können Sie Ihre Daten als Zeichenfolge im httpbody senden, obwohl Sie sie in Ihrem Code als json definiert haben.

Es hat bei mir funktioniert ..

AKTUALISIERT für

  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"]!)

        }

    })
Cemal BAYRI
quelle
1
Ich werde meine Antwort aktualisieren und den Code ein gebrauchtes schreiben, weil ich nicht finden konnte, wie man Code als Kommentar von hier schreibt. Entschuldigung für spät. @ Badr Filali
Cemal BAYRI
Vielen Dank
Badr Filali
1
Hat für mich funktioniert, aber mein Körper muss ein JSON sein, also habe ich die Codierung: URLEncoding.httpBody in encoding: JSONEncoding.default geändert und alles hat gut funktioniert.
Angelo Polotto
Ja @AngeloPolotto, danke für die Rekonstruktion :) Hier geht es um die Kodierung der Art des Dienstes. Kann abhängig von Ihrer Rest-API als URLEncoding oder JSONEncoding verwendet werden.
Cemal BAYRI
Danke für die Antwort. Das Problem ist jedoch, dass ich stattdessen eine Variable sende double quotes stringsund einen Fehlercode erhalte 400. Wie würde ich das lösen?
Viper
8

Ich habe die Antwort von @ Silmaril geändert, um den Manager von Alamofire zu erweitern. Diese Lösung verwendet EVReflection, um ein Objekt direkt zu serialisieren:

//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)
            })
        )
    }
}

Dann können Sie es so verwenden:

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

Wenn Sie eine Zeichenfolge als Rohkörper auf Anfrage veröffentlichen möchten

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)
        }))
JR
quelle
Hallo JITHINRAJ, ich habe hier eine Frage gepostet stackoverflow.com/questions/40385992/… Ich möchte eine XML-Body senden
Mike Vorisis
5

Ich habe es für Array aus Strings gemacht. Diese Lösung ist für die Zeichenfolge im Körper angepasst.

Der "native" Weg von 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!
    }
}

Und dann stellen Sie Ihre Anfrage mit:

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

Ich habe die Antwort von @afrodev als Referenz verwendet. In meinem Fall nehme ich Parameter zu meiner Funktion als Zeichenfolge, die auf Anfrage gebucht werden müssen. Also, hier ist der 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)
    }
}
GeoSD
quelle
Was genau bekommst du nicht?
GeoSD
3

Basierend auf der Antwort von Illya Krit

Einzelheiten

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

Lösung

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"
        }
    }
}

Verwendung

Alamofire.request(url, method: .post, parameters: nil, encoding: BodyStringEncoding(body: text), headers: headers).responseJSON { response in
     print(response)
}
Wassili Bodnarchuk
quelle
Спасибо вам большое!
15смаил Хасбулатов
2
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)
AndrewK
quelle
Was ist Mapper?
Ahmadreza
2

In meinem Fall, als ich Alamofire mit dem Inhaltstyp "Content-Type": "application / x-www-form-urlencoded" postete, musste ich die Codierung der Alampfire-Post-Anfrage ändern

von: JSONENCODING.DEFAULT bis: URLEncoding.httpBody

Hier:

let url = ServicesURls.register_token()
    let body = [
        "UserName": "Minus28",
        "grant_type": "password",
        "Password": "1a29fcd1-2adb-4eaa-9abf-b86607f87085",
         "DeviceNumber": "e9c156d2ab5421e5",
          "AppNotificationKey": "test-test-test",
        "RegistrationEmail": email,
        "RegistrationPassword": password,
        "RegistrationType": 2
        ] as [String : Any]


    Alamofire.request(url, method: .post, parameters: body, encoding: URLEncoding.httpBody , headers: setUpHeaders()).log().responseJSON { (response) in
IsPha
quelle
0
let parameters = ["foo": "bar"]
              
    // All three of these calls are equivalent
    AF.request("https://httpbin.org/post", method: .post, parameters: parameters)
    AF.request("https://httpbin.org/post", method: .post, parameters: parameters, encoder: URLEncodedFormParameterEncoder.default)
    AF.request("https://httpbin.org/post", method: .post, parameters: parameters, encoder: URLEncodedFormParameterEncoder(destination: .httpBody))
    
    
AbdelraZek
quelle
-3

Xcode 8.X, Swift 3.X.

Einfache Verwendung;

 let params:NSMutableDictionary? = ["foo": "bar"];
            let ulr =  NSURL(string:"http://mywebsite.com/post-request" as String)
            let request = NSMutableURLRequest(url: ulr! as URL)
            request.httpMethod = "POST"
            request.setValue("application/json", forHTTPHeaderField: "Content-Type")
            let data = try! JSONSerialization.data(withJSONObject: params!, options: JSONSerialization.WritingOptions.prettyPrinted)

            let json = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
            if let json = json {
                print(json)
            }
            request.httpBody = json!.data(using: String.Encoding.utf8.rawValue);


            Alamofire.request(request as! URLRequestConvertible)
                .responseJSON { response in
                    // do whatever you want here
                   print(response.request)  
                   print(response.response) 
                   print(response.data) 
                   print(response.result)

            }
SwiftDeveloper
quelle