Żądanie POST z prostym ciągiem znaków w treści z Alamofire

84

Jak mogę wysłać żądanie POST z prostym ciągiem znaków w treści HTTP z Alamofire w mojej aplikacji na iOS?

Domyślnie Alamofire potrzebuje parametrów dla żądania:

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

Te parametry zawierają pary klucz-wartość. Ale nie chcę wysyłać żądania z ciągiem klucz-wartość w treści HTTP.

Mam na myśli coś takiego:

Alamofire.request(.POST, "http://mywebsite.com/post-request", body: "myBodyString")
Karl
źródło

Odpowiedzi:

88

Twój przykład Alamofire.request(.POST, "http://mywebsite.com/post-request", parameters: ["foo": "bar"])zawiera już ciąg „foo = bar” jako treść. Ale jeśli naprawdę chcesz napisać w niestandardowym formacie. Możesz to zrobić:

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

Uwaga: parametersnie powinnonil

AKTUALIZACJA (Alamofire 4.0, Swift 3.0):

W Alamofire 4.0 API uległo zmianie. Więc do niestandardowego kodowania potrzebujemy wartości / obiektu, który jest zgodny z ParameterEncodingprotokołem.

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
źródło
Działa to doskonale, nie tylko w przypadku prostych, ale wszystkich rodzajów ciągów mapowanych typu JSON.
Sahil Kapoor
uratował mój dzień :) Dzięki (y)
ishhhh
1
@silmaril w mojej sytuacji mogę uzyskać surowe żądanie z zaplecza tylko wtedy, gdy używam metody PUT, czy możesz mi pomóc, dlaczego żądanie POST nic nie widzi
AJ
1
.Custom nie jest już dostępny w Alamofire 4 Swift 3 i nie jestem w stanie znaleźć alternatywy, jakieś wskazówki?
Raheel Sadiq
@Silmaril Też opublikowałem pytanie, proszę odpowiedzieć, żebym mógł je zamknąć: stackoverflow.com/questions/39573514/…
Raheel Sadiq
64

Możesz to zrobić:

  1. Utworzyłem oddzielny obiekt żądania Alamofire.
  2. Konwertuj ciąg na dane
  3. Umieść dane w httpBody

    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
źródło
5
To powinna być akceptowana odpowiedź. Jest prosty, robi dokładnie to, co jest potrzebne, i bez zbędnych rozszerzeń czy konwersji. Dzięki.
Sea Coast of Tibet
2
PS „Pożyczyłem” Twoją odpowiedź na inne pytanie - stackoverflow.com/a/42411188/362305
Sea Coast of Tibet
2
co to jest frekwencja, czy możesz opublikować pełniejszy fragment
SyraKozZ
@SyraKozZ Nie ma znaczenia, jakie są frekwencje, jedyną myślą, która jest ważna, jest pjson, to ciąg json. Możesz tam umieścić dowolny ciąg json.
afrodev,
13

Jeśli używasz Alamofire, wystarczy zakodować typ na „URLEncoding.httpBody”

Dzięki temu możesz wysłać swoje dane jako ciąg w httpbody, mimo że zdefiniowałeś go jako json w swoim kodzie.

U mnie zadziałało ...

AKTUALIZACJA dla

  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
źródło
1
Zaktualizuję swoją odpowiedź i napiszę kod używany, ponieważ nie mogłem znaleźć tego, jak napisać kod jako komentarz stąd .. Przepraszam za spóźnienie. @ Badr Filali
Cemal BAYRI
Dzięki, świetnie
Badr Filali
1
Pracowało dla mnie, ale moje ciało musi być JSONem, więc zmieniłem kodowanie: URLEncoding.httpBody na encoding: JSONEncoding.default i wszystko działało dobrze.
Ângelo Polotto
Tak @AngeloPolotto dzięki za kontrubację :) Chodzi o typ kodowania usługi. Może być używany w zależności od twojego resztowego api jako URLEncoding lub JSONEncoding.
Cemal BAYRI
Dziękuję za Twoją odpowiedź. Ale problem, z którym się spotykam, polega na tym, że zamiast wysyłam zmienną double quotes stringsi otrzymuję kod błędu 400. Jak bym to rozwiązał?
viper
8

Zmodyfikowałem odpowiedź @ Silmaril, aby rozszerzyć Alamofire's Managera. To rozwiązanie używa EVReflection do bezpośredniego serializacji obiektu:

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

Następnie możesz go użyć w ten sposób:

Alamofire.Manager.request(.POST, endpointUrlString, bodyObject: myObjectToPost)
raf
źródło
5

Jeśli chcesz wysłać ciąg jako surową treść w żądaniu

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
źródło
Cześć JITHINRAJ Wysłałem pytanie tutaj stackoverflow.com/questions/40385992/ ... Chcę wysłać
treść
5

Zrobiłem to dla tablicy z ciągów. To rozwiązanie dostosowane do sznurka w body.

„Natywna” droga z 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!
    }
}

Następnie prześlij swoją prośbę za pomocą:

Alamofire.request("your url string", method: .post, parameters: [:], encoding: JSONStringArrayEncoding.init(string: "My string for body"), headers: [:])
Illya Krit
źródło
4

Użyłem odpowiedzi @afrodev jako odniesienia. W moim przypadku przyjmuję parametr do mojej funkcji jako ciąg znaków, który ma zostać przesłany w żądaniu. Oto kod:

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
źródło
Czego dokładnie nie dostajesz?
GeoSD
3

Na podstawie Illya Krit odpowiedź „s

Detale

  • Xcode w wersji 10.2.1 (10E1001)
  • Szybki 5
  • Alamofire 4.8.2

Rozwiązanie

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

Stosowanie

Alamofire.request(url, method: .post, parameters: nil, encoding: BodyStringEncoding(body: text), headers: headers).responseJSON { response in
     print(response)
}
Wasilij Bodnarczuk
źródło
Спасибо вам большое!
Исмаил Хасбулатов
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
źródło
Co to jest Mapper?
Ahmadreza,
2

Mój przypadek, wysyłając alamofire z typem treści: "Content-Type": "application / x-www-form-urlencoded", musiałem zmienić kodowanie żądania postu alampfire

od: JSONENCODING.DEFAULT do: URLEncoding.httpBody

tutaj:

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
źródło
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))
    
    
Mohamed AbdelraZek
źródło
-3

Xcode 8.X, Swift 3.X

Łatwe w użyciu;

 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
źródło