programing

응용 프로그램/x-www-form-urlencoded를 사용한 POST 요청

yellowcard 2023. 3. 16. 21:17
반응형

응용 프로그램/x-www-form-urlencoded를 사용한 POST 요청

백엔드 개발자는 POST 요청 시 다음과 같은 지시를 내렸습니다.

  1. 경로: {url}/{app_name/{controller}/{action}
  2. 컨트롤러와 액션은 작은 캡으로 해야 합니다.
  3. API 테스트 링크: http:******************
  4. 요청은 POST Method를 사용해야 합니다.
  5. 매개 변수는 요청 컨텐츠 본문(FormUrlEncodedContent)을 통해 전달되어야 합니다.
  6. 매개 변수는 json 형식이어야 합니다.
  7. 파라미터는 키에 민감합니다.

프로토콜에서 5번을 사용한 경험이 없어서 코드를 검색하여 종료했습니다.

-(id)initWithURLString:(NSString *)URLString withHTTPMEthod:(NSString *)method withHTTPBody:(NSDictionary *)body {

    _URLString = URLString;
    HTTPMethod = method;
    HTTPBody = body;

    //set error message
    errorMessage = @"Can't connect to server at this moment. Try again later";
    errorTitle = @"Connection Error";

    return  self;
}


-(void)fireConnectionRequest {

    NSOperationQueue *mainQueue = [[NSOperationQueue alloc] init];
    [mainQueue setMaxConcurrentOperationCount:5];

    NSError *error = Nil;

    NSURL *url = [NSURL URLWithString:_URLString];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];

    NSData *sendData = [NSJSONSerialization dataWithJSONObject:HTTPBody options:NSJSONWritingPrettyPrinted error:&error];
    [request setHTTPMethod:@"POST"];

    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];

    [request setHTTPBody: sendData];
    [NSURLConnection connectionWithRequest:request delegate:self];

    NSString *jsonString = [[NSString alloc]initWithData:sendData encoding:NSUTF8StringEncoding];


    //fire URL connectiion request
    [NSURLConnection sendAsynchronousRequest:request queue:mainQueue completionHandler:^(NSURLResponse *response, NSData *responseData, NSError *error) {

        //get the return message and transform to dictionary
        NSString *data = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
        returnMessage = [NSJSONSerialization JSONObjectWithData: [data dataUsingEncoding:NSUTF8StringEncoding]
                                                        options: NSJSONReadingMutableContainers
                                                          error:&error];


        //check return message
        if (!error) {
            [delegate returnMessageForTag:self.tag];

        }
        else {
            [delegate returnErrorMessageForTag:self.tag];
        }

    }];

}

JSON으로 포맷된 사전을 전달했습니다. 그는 제가 올바른 데이터를 전달할 수 있었다는 것에 동의했습니다.그리고 API에 접속할 수 있었지만, 등록 데이터를 송신하려고 하면 항상 "FAILED"가 반환됩니다.연결에는 문제가 없지만 데이터 전송에 실패했습니다.

같은 API를 사용하는 안드로이드 개발자는 문제없지만 iOS에 익숙하지 않아 도움을 주지 못했습니다.

제가 무엇을 빠뜨리고 있나요?

이 코드와 같이 시도합니다.

목표 C

NSString *post =[NSString stringWithFormat:@"AgencyId=1&UserId=1&Type=1&Date=%@&Time=%@&Coords=%@&Image=h32979`7~U@)01123737373773&SeverityLevel=2",strDateLocal,strDateTime,dict];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:@"%d",[postData length]];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://google/places"]]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];
NSError *error;
NSURLResponse *response;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *str=[[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];

스위프트 2.2

var post = "AgencyId=1&UserId=1&Type=1&Date=\(strDateLocal)&Time=\(strDateTime)&Coords=\(dict)&Image=h32979`7~U@)01123737373773&SeverityLevel=2"
var postData = post.dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: true)!
var postLength = "\(postData.length)"
var request = NSMutableURLRequest()
request.URL = NSURL(string: "http://google/places")!
request.HTTPMethod = "POST"
request.setValue(postLength, forHTTPHeaderField: "Content-Length")
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.HTTPBody = postData
NSError * error
NSURLResponse * response
var urlData = try! NSURLConnection.sendSynchronousRequest(request, returningResponse: response)!
var str = String(data: urlData, encoding: NSUTF8StringEncoding)

Swift 3.0

let jsonData = try? JSONSerialization.data(withJSONObject: kParameters)
    let url: URL = URL(string: "Add Your API URL HERE")!
    print(url)
    var request: URLRequest = URLRequest(url: url)
    request.httpMethod = "POST"
    request.httpBody = jsonData
    request.setValue(Constant.UserDefaults.object(forKey: "Authorization") as! String?, forHTTPHeaderField: "Authorization")
    request.setValue(Constant.kAppContentType, forHTTPHeaderField: "Content-Type")
    request.setValue(Constant.UserAgentFormat(), forHTTPHeaderField: "User-Agent")

    let task = URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in

        if data != nil {

            do {
                let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! NSDictionary
                print(json)
            } catch let error as NSError {
                print(error)
            }
        } else {
            let emptyDict = NSDictionary()
        }
    })
    task.resume()

스위프트 4

let headers = [
            "Content-Type": "application/x-www-form-urlencoded"
        ]

    let postData = NSMutableData(data: "UserID=351".data(using: String.Encoding.utf8)!)
    let request = NSMutableURLRequest(url: NSURL(string: "Add Your URL Here")! as URL,
                                      cachePolicy: .useProtocolCachePolicy,
                                      timeoutInterval: 10.0)
    request.httpMethod = "POST"
    request.allHTTPHeaderFields = headers
    request.httpBody = postData as Data

    let session = URLSession.shared
    let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
        if (error != nil) {
            print(error!)
        } else {
            let httpResponse = response as? HTTPURLResponse
            print(httpResponse!)

            do {
                let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments)
                print(json)
            } catch {
                print(error)
            }

        }
    })

    dataTask.resume()

알라모파이어

Alamofire.request("Add Your URL Here",method: .post, parameters: ["CategoryId": "15"])
        .validate(contentType: ["application/x-www-form-urlencoded"])
        .responseJSON { (response) in

            print(response.result.value)

    }

이 코드가 당신에게 도움이 되길 바랍니다.

스위프트 4

let params = ["password":873311,"username":"jadon","client_id":"a793fb82-c978-11e9-a32f-2a2ae2dbcce4"]
let jsonString = params.reduce("") { "\($0)\($1.0)=\($1.1)&" }.dropLast()
let jsonData = jsonString.data(using: .utf8, allowLossyConversion: false)!
urlRequest.addValue("application/x-www-form-urlencoded", forHTTPHeaderField:"Content-Type")
urlRequest.httpBody  = jsonData 

@fatihyildizan

당신의 답변에 직접 코멘트를 달기에는 충분한 평판이 없기 때문에 이 답변이 필요합니다.

스위프트 1.2

let myParams = "username=user1&password=12345"
let postData = myParams.dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: true)
let postLength = String(format: "%d", postData!.length)

var myRequest = NSMutableURLRequest(URL: self.url)
myRequest.HTTPMethod = "POST"
myRequest.setValue(postLength, forHTTPHeaderField: "Content-Length")
myRequest.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
myRequest.HTTPBody = postData

var response: AutoreleasingUnsafeMutablePointer<NSURLResponse?> = nil

위의 코드는 제 경우 정상적으로 작동합니다.

Swift는 URL-%-encoding 기능을 제공하지만 첫 번째 코멘트에서 @nolanw가 지적한 것과 완전히 일치하는 것은 아닙니다.첫 번째 질문의 스텝5에서는 키와 값의 페어가 어떤 구조에서 확립되면 간단하고 간단한 부호화 대체 방법(Swift 4.2)을 다음에 나타냅니다.

var urlParser = URLComponents()
urlParser.queryItems = [
    URLQueryItem(name: "name", value: "Tim Tebow"),
    URLQueryItem(name: "desc", value: "Gators' QB")
]
let httpBodyString = urlParser.percentEncodedQuery

Xcode 플레이그라운드에 붙여넣고 추가한다.print(httpBodyString!)출력에는 다음이 표시됩니다.

name=Tim%20Tebow&desc=Gators'%20QB

참고: 이것은 기본 폼 값의 백분율 인코딩 세트(즉, 이진 데이터나 멀티 파트가 아님)에 대한 것입니다.

이 버전에서는 파라미터의 인코딩과 공백의 '+' 치환을 처리합니다.

extension String {
    static let formUrlencodedAllowedCharacters =
        CharacterSet(charactersIn: "0123456789" +
            "abcdefghijklmnopqrstuvwxyz" +
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
            "-._* ")

    public func formUrlencoded() -> String {
        let encoded = addingPercentEncoding(withAllowedCharacters: String.formUrlencodedAllowedCharacters)
        return encoded?.replacingOccurrences(of: " ", with: "+") ?? ""
    }
}

class HTTPUtils {
    public class func formUrlencode(_ values: [String: String]) -> String {
        return values.map { key, value in
            return "\(key.formUrlencoded())=\(value.formUrlencoded())"
        }.joined(separator: "&")
    }
}

let headers = [
    "content-type": "application/x-www-form-urlencoded; charset=utf-8"
]

let body = HTTPUtils.formUrlencode([
    "field": "value"
])

var request = try URLRequest(url: url, method: .post, headers: headers)
request.httpBody = body.data(using: .utf8)

URLSession.shared.dataTask(with: request, completionHandler: { ... }).resume()

Swift 3에서 jsonData =를 사용해 보시겠습니까?JSON Serialization.data(JSONObject: kParameters 사용)가 제대로 작동하지 않아 Alamo Fire 솔루션을 복사해야 했습니다.

let body2 = ["username": "au@gmail.com",
        "password": "111",
        "client_secret":"7E",
        "grant_type":"password"]

let data : Data = query(body2).data(using: .utf8, allowLossyConversion: false)!
var request : URLRequest = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField:"Content-Type");
request.setValue(NSLocalizedString("lang", comment: ""), forHTTPHeaderField:"Accept-Language");
request.httpBody = data 

do {...}

}

public func queryComponents(fromKey key: String, value: Any) -> [(String, String)] {
        var components: [(String, String)] = []

        if let dictionary = value as? [String: Any] {
            for (nestedKey, value) in dictionary {
                components += queryComponents(fromKey: "\(key)[\(nestedKey)]", value: value)
            }
        } else if let array = value as? [Any] {
            for value in array {
                components += queryComponents(fromKey: "\(key)[]", value: value)
            }
        } else if let value = value as? NSNumber {
            if value.isBool {
                components.append((escape(key), escape((value.boolValue ? "1" : "0"))))
            } else {
                components.append((escape(key), escape("\(value)")))
            }
        } else if let bool = value as? Bool {
            components.append((escape(key), escape((bool ? "1" : "0"))))
        } else {
            components.append((escape(key), escape("\(value)")))
        }

        return components
    }


    public func escape(_ string: String) -> String {
        let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
        let subDelimitersToEncode = "!$&'()*+,;="

        var allowedCharacterSet = CharacterSet.urlQueryAllowed
        allowedCharacterSet.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")

        var escaped = ""

        if #available(iOS 8.3, *) {
            escaped = string.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? string
        } else {
            let batchSize = 50
            var index = string.startIndex

            while index != string.endIndex {
                let startIndex = index
                let endIndex = string.index(index, offsetBy: batchSize, limitedBy: string.endIndex) ?? string.endIndex
                let range = startIndex..<endIndex

                let substring = string.substring(with: range)

                escaped += substring.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? substring

                index = endIndex
            }
        }
        return escaped
    }

그리고 한 가지 확장:

extension NSNumber {
fileprivate var isBool: Bool { return CFBooleanGetTypeID() == CFGetTypeID(self) }}

이건 일시적이야 더 나은 해결책이 될 거야

도움이 됐으면 좋겠는데...

스위프트 4.2

    func percentEscapeString(_ string: String) -> String {
            var characterSet = CharacterSet.alphanumerics
            characterSet.insert(charactersIn: "-._* ")
            return string
              .addingPercentEncoding(withAllowedCharacters: characterSet)!
              .replacingOccurrences(of: " ", with: " ")
              .replacingOccurrences(of: " ", with: " ", options: [], range: nil)
              .replacingOccurrences(of: "\"", with: "", options: NSString.CompareOptions.literal, range:nil)
          }
//    Set encoded values to Dict values you can decode keys if required
    dictData.forEach { (key, value) in
              if let val = value as? String {
                dictData[key] = self.percentEscapeString(val)
              } else {
                dictData[key] = value
              }
            }

이것은 나에게 효과가 있었고, 이것은 소스 https://gist.github.com/HomerJSimpson/80c95f0424b8e9718a40의 링크입니다.

이 코드를 swift로 변환할 수 있습니까? 이미 시도했지만 처리할 수 없었습니다.이 코드 블록이 도움이 될지도 몰라감사해요.

    let myParams:NSString = "username=user1&password=12345"
    let myParamsNSData:NSData = NSData(base64EncodedString: myParams, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)!
    let myParamsLength:NSString = NSString(UTF8String: myParamsNSData.length)
    let myRequest: NSMutableURLRequest = NSURL(fileURLWithPath: self.url)
    myRequest.HTTPMethod = "POST"
    myRequest.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    myRequest.HTTPBody = myParamsNSData
    var data2: NSData!
    var error2: NSError!

사전 매개 변수를 문자열로 구문 분석:

-(NSData *)encodeParameters:(NSDictionary *)parameters {

NSMutableArray *list = [NSMutableArray new];

for (NSString *key in [parameters allKeys]) {
    id obj = [parameters objectForKey:key];
    NSString *path = [NSString stringWithFormat:@"%@=%@", key, obj];
    [list addObject:path];
}

return [[list componentsJoinedByString:@"&"] dataUsingEncoding:NSUTF8StringEncoding];

}

사용방법:

[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:[self encodeParameters:parameters]];

Swift 5에서 다음 코드가 오늘 작동하도록 테스트되었습니다.

let url = URL(string: "https://something")
var request = URLRequest(url: url!)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let post = "parameter1=abc&parameter2=abc"
let postData = post.data(using: String.Encoding.ascii, allowLossyConversion: true)!
request.httpBody = postData
let params:[String: Any]
if "application/x-www-form-urlencoded" {
let bodyData = params.stringFromHttpParameters()
self.request.httpBody = bodyData.data(using: String.Encoding.utf8)}
if "application/json"{
  do {
    self.request.httpBody = try JSONSerialization.data(withJSONObject: params, options: JSONSerialization.WritingOptions())
  } catch {
    print("bad things happened")
  }
}

확장 사전

func stringFromHttpParameters() -> String {
let parameterArray = self.map { (key, value) -> String in let percentEscapedKey = (key as!String).stringByAddingPercentEncodingForURLQueryValue()!

let percentEscapedValue = (value as! String).stringByAddingPercentEncodingForURLQueryValue()!}
return "\(percentEscapedKey)=\(percentEscapedValue)"}
return parameterArray.joined(separator: "&")}

언급URL : https://stackoverflow.com/questions/22063959/post-request-using-application-x-www-form-urlencoded

반응형