Отправка составного сообщения из iOS и чтение параметров в PHP $ _POST?

#php #objective-c #ios #post #nsurlrequest

#php #objective-c #iOS #Публикация #nsurlrequest

Вопрос:

Я пытаюсь отправить многострочное сообщение с iPhone / iPad в службу php, проблема в том, что по какой-то причине тип содержимого сообщения выглядит как application / x-www-form-urlenconded, (я узнал об этом с помощью Wireshark)

На самом деле это фрагмент захвата пакета Wireshark POST:

     **Content-Type: application/x-www-form-urlencodedrn**
    Content-Length: 324rn
        [Content length: 324]
    Connection: keep-alivern
    rn
    [Full request URI: http://my.server.com/mobile/tools/authentication]
Line-based text data: application/x-www-form-urlencoded
    --0xKhTmLbOuNdArYrn
    Content-Disposition: form-data; name="login"rn
    rn
    hello@hello.comrn
    --0xKhTmLbOuNdArYrn
    Content-Disposition: form-data; name="password"rn
    rn
    somepasswordrn
    --0xKhTmLbOuNdArYrn
    rn
    --0xKhTmLbOuNdArY--rn
  

Проблема в том, что на сервере я пытаюсь прочитать переменные login и password из этого POST-запроса, но это невозможно, поскольку я думаю, что php считает, что POST-запрос x-www-form-urlencoded , поэтому, если я настрою authentication.php , чтобы сделать:

 <?php
echo("<pre>")
print_r($_POST)
echo("</pre>")
?>
  

Я понимаю это:

 <pre>Arrayn
(n
    [--0xKhTmLbOuNdArYrn
Content-Disposition:_form-data;_name] => "login"rn
rn
hello@hello.comrn
--0xKhTmLbOuNdArYrn
Content-Disposition: form-data; name="password"rn
rn
somepasswordrn
--0xKhTmLbOuNdArYrn
rn
--0xKhTmLbOuNdArY--rn
n
)n
</pre>
  

Это явно нехорошо, поскольку, если я отправлю запрос, используя эту простую html-форму:

 <FORM action="http://my.server.com/mobile/tools/authentication.php" method="post">
   <P>
   <LABEL for="login">E-mail: </LABEL>
             <INPUT type="text" name="login"><BR>
   <LABEL for="password">pass: </LABEL>
             <INPUT type="text" name="password"><BR>
   <INPUT type="submit" value="Send"> <INPUT type="reset">
   </P>
</FORM>
  

Я получаю эту трассировку Wireshark, как и ожидалось, из формы:

     Content-Type: application/x-www-form-urlencodedrn
    Accept: text/html,application/xhtml xml,application/xml;q=0.9,*/*;q=0.8rn
    Accept-Encoding: gzip,deflate,sdchrn
    Accept-Language: en-US,en;q=0.8rn
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3rn
    Cookie: PHPSESSID=tpp10pbrdkkf5dg9qprlamfuu2rn
    rn
    [Full request URI: http://mymed2.sophia.inria.fr/mobile/tools/authentication.php]
Line-based text data: application/x-www-form-urlencoded
    login=hello@hello.comamp;password=somepassword
  

И этот текстовый вывод из print_r($_POST) authentication.php

 <pre>Arrayn
(n
    [login] => hello@hello.comn
    [password] => somepasswordn
)n
</pre>
  

Именно так я создаю запрос POST в Objective-C и Cocoa

 - (NSMutableURLRequest *) POSTRequestWithURL:(NSURL *)url andDataDictionary:(NSDictionary *) dictionary
{
    // Create a POST request
    NSMutableURLRequest *myMedRequest = [NSMutableURLRequest requestWithURL:url];
    [myMedRequest setHTTPMethod:@"POST"];

    // Add HTTP header info
    // Note: POST boundaries are described here: http://www.vivtek.com/rfc1867.html
    // and here http://www.w3.org/TR/html4/interact/forms.html
    NSString *POSTBoundary = [NSString stringWithString:@"0xKhTmLbOuNdArY"];
    [myMedRequest addValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@rn", POSTBoundary] forHTTPHeaderField:@"Content-Type"];

    // Add HTTP Body
    NSMutableData *POSTBody = [NSMutableData data];
    [POSTBody appendData:[[NSString stringWithFormat:@"--%@rn",POSTBoundary] dataUsingEncoding:NSUTF8StringEncoding]];

    // Add Key/Values to the Body
    NSEnumerator *enumerator = [dictionary keyEnumerator];
    NSString *key;

    while ((key = [enumerator nextObject])) {
        [POSTBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name="%@"rnrn", key] dataUsingEncoding:NSUTF8StringEncoding]];
        [POSTBody appendData:[[NSString stringWithFormat:@"%@", [dictionary objectForKey:key]] dataUsingEncoding:NSUTF8StringEncoding]];
        [POSTBody appendData:[[NSString stringWithFormat:@"rn--%@rn", POSTBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
    }

    // Add the closing -- to the POST Form
    [POSTBody appendData:[[NSString stringWithFormat:@"rn--%@--rn", POSTBoundary] dataUsingEncoding:NSUTF8StringEncoding]]; 

    // Add the body to the myMedRequest amp; return
    [myMedRequest setHTTPBody:POSTBody];
    return myMedRequest;
}
  

Как вы видите, вначале я делаю:

     [myMedRequest addValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@rn", POSTBoundary] forHTTPHeaderField:@"Content-Type"];
  

Но в предыдущих журналах трассировки Wireshark пакет POST просматривался как Content-Type: application / x-www-form-urlencoded, может быть, я делаю что-то еще неправильно?

Спасибо 🙂

РЕДАКТИРОВАТЬ: я хочу избегать внешних фреймворков, таких как ASIHTTPRequest, кстати, разработка ASIHTTPRequest была прекращена ведущим разработчиком, как указано здесь

Комментарии:

1. Единственное, о чем я могу думать: почему вы вручную пишете http-запрос? Разве не для этого предназначен API?

2. NSMutableURLRequest — это предоставленный «API», для этого есть несколько фреймворков, но я стараюсь избегать внешних фреймворков.

Ответ №1:

Хорошо, поскольку я не смог найти решение без внешних библиотек, я исправил свой код и открыл его с открытым исходным кодом, на случай, если кто-нибудь захочет его использовать.

Проблема в коде, который я опубликовал, заключалась в r n в строке

 [myMedRequest addValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@rn", POSTBoundary] forHTTPHeaderField:@"Content-Type"];
  

Удаление этого исправило все.

Надеюсь, это поможет кому-то еще 🙂

Комментарии:

1. Обновлено. Как поддерживает PUT / DELETE / PATCH тоже. 🙂

2. Спасибо! Я просто пробовал это. может ли он обрабатывать вложенный словарь? Я пытаюсь опубликовать изображение, состоящее из словаря «запись» на корневом уровне, затем описания, journal_id и изображения на вложенном уровне.

3. Не думайте так, вы могли бы открыть проблему на Github, хотя 🙂