#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, хотя 🙂