Как параметры отправляются в HTTP-запрос POST?
В запросе HTTP GET параметры отправляются как строка запроса :
http://example.com/page?parameter=value&also=another
В запросе HTTP POST параметры не отправляются вместе с URI.
Где значения? В заголовке запроса? В теле запроса? Как это выглядит?
Ответы
Ответ 1
Значения отправляются в тело запроса в формате, указанном типом содержимого.
Обычно тип содержимого application/x-www-form-urlencoded
, поэтому тело запроса использует тот же формат, что и строка запроса:
parameter=value&also=another
Когда вы используете загрузку файла в форме, вместо этого вы используете кодировку multipart/form-data
, которая имеет другой формат. Это сложнее, но вам обычно не нужно заботиться о том, как это выглядит, поэтому я не буду показывать пример, но может быть полезно знать, что он существует.
Ответ 2
Содержимое помещается после заголовков HTTP. Формат HTTP POST должен состоять из заголовков HTTP, за которыми следует пустая строка, за которой следует тело запроса. Переменные POST хранятся в виде пар ключ-значение в теле.
Это можно увидеть в исходном содержимом HTTP-сообщения, показанного ниже:
POST /path/script.cgi HTTP/1.0
From: [email protected]
User-Agent: HTTPTool/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 32
home=Cosby&favorite+flavor=flies
Вы можете увидеть это с помощью инструмента, такого как Fiddler, который вы можете использовать для просмотра необработанных запросов HTTP-запроса и ответа, передаваемых по проводке.
Ответ 3
Короткий ответ: в POST-запросах, значения отправляются в "теге" запроса. С веб-формами они, скорее всего, отправляются с типом носителя application/x-www-form-urlencoded
или multipart/form-data
. Языки программирования или фреймворки, предназначенные для обработки веб-запросов, обычно выполняют "The Right Thing ™" с такими запросами и обеспечивают вам легкий доступ к легко декодированным значениям (например, $_REQUEST
или $_POST
в PHP или cgi.FieldStorage()
, flask.request.form
в Python).
Теперь отпустите немного, что может помочь понять разницу;)
Разница между запросами GET
и POST
в значительной степени семантична. Они также "используются" по-разному, что объясняет разницу в том, как передаются значения.
При выполнении запроса GET
вы запрашиваете сервер для одного или набор объектов. Чтобы клиент мог фильтровать результат, он может использовать так называемую "строку запроса" URL-адреса. Строка запроса - это часть после ?
. Это часть синтаксиса URI .
Итак, с точки зрения вашего кода приложения (части, которая получает запрос) вам нужно будет проверить часть запроса URI, чтобы получить доступ к этим значениям.
Обратите внимание, что ключи и значения являются частью URI. Браузеры могут налагать ограничение на длину URI. В стандарте HTTP указано, что ограничений нет. Но на момент написания этой статьи большинство браузеров ограничивают URI (у меня нет конкретных значений). GET
запросы никогда не должны использоваться для отправки новой информации на сервер. Особенно не крупные документы. Это где вы должны использовать POST
или PUT
.
При выполнении запроса POST
клиент фактически отправляет новый документ удаленному хосту. Таким образом, строка запроса не (семантически) имеет смысл. Вот почему у вас нет доступа к ним в вашем коде приложения.
POST
немного сложнее (и более гибким):
При получении запроса POST вы всегда должны ожидать "полезную нагрузку" или в терминах HTTP: тело сообщения. Тело сообщения само по себе довольно бесполезно, поскольку нет стандартного (насколько я могу судить. Может быть, application/octet-stream?) Формата. Формат тела определяется заголовком Content-Type
. При использовании элемента HTML FORM
с method="POST"
это обычно application/x-www-form-urlencoded
. Другим очень распространенным типом является multipart/form-data, если вы используете загрузку файлов. Но может быть что угодно: от text/plain
, более application/json
или даже пользовательского application/octet-stream
.
В любом случае, если запрос POST
выполняется с Content-Type
, который не может быть обработан приложением, он должен вернуть 415
статус-код.
Большинство языков программирования (и/или веб-фреймворки) предлагают способ де-кодирования тела сообщения от/до наиболее распространенных типов (например, application/x-www-form-urlencoded
, multipart/form-data
или application/json
). Так просто. Пользовательские типы требуют потенциально немного больше работы.
Используя стандартный HTML-документ, закодированный в качестве примера, приложение должно выполнить следующие шаги:
- Прочитайте поле
Content-Type
- Если значение не является одним из поддерживаемых типов носителей, затем верните ответ с кодом состояния
415
- иначе декодировать значения из тела сообщения.
Опять же, такие языки, как PHP, или веб-фреймворки для других популярных языков, вероятно, справятся с этим для вас. Исключением является ошибка 415
. Никакая структура не может предсказать, какие типы контента ваше приложение выбирает для поддержки и/или не поддержки. Это зависит от вас.
A PUT
запрос в значительной степени обрабатывается точно так же, как запрос POST
. Большая разница заключается в том, что запрос POST
должен позволить серверу решить, как (и если вообще) создать новый ресурс. Исторически (из теперь устаревшего RFC2616 он должен был создать новый ресурс как "подчиненный" (дочерний) URI, куда был отправлен запрос).
A PUT
запрос, напротив, должен "откладывать" ресурс именно в этом URI и именно с этим контентом. Не больше, не меньше. Идея заключается в том, что клиент несет ответственность за создание полного ресурса до "PUTting". Сервер должен принять его как есть на заданном URL.
Как следствие, запрос POST
обычно не используется для замены существующего ресурса. Запрос PUT
может создавать и заменять.
Side-Note
Также есть " параметры пути", которые могут использоваться для отправки дополнительных данных на пульт, но они настолько необычны, что я выиграл Здесь не слишком подробно. Но, для справки, вот отрывок из RFC:
Помимо точечных сегментов в иерархических путях рассматривается сегмент пути непрозрачный по обобщенному синтаксису. URI-приложения часто используют зарезервированные символы, разрешенные в сегменте для разграничения схемы или подкомпоненты, специфичные для разыменования. Например, точка с запятой ( ";" ) и equals ( "=" ) зарезервированные символы часто используются для разграничения параметров и значения параметров, применимые к этому сегменту. Запятая ( "," ) зарезервирована характер часто используется для аналогичных целей. Например, один производитель URI может использовать сегмент, такой как "name; v = 1.1", чтобы указать ссылку на версию 1.1 "name", тогда как другой может использовать сегмент, такой как "name, 1.1" to указывают на то же самое. Типы параметров могут определяться по схеме семантика, но в большинстве случаев синтаксис параметра специфичен для реализация алгоритма разыменования URI.
Ответ 4
Вы не можете ввести его прямо в строке URL браузера.
Вы можете увидеть, как данные POST отправляются в Интернете с помощью Live HTTP Headers.
Результат будет что-то вроде этого
http://127.0.0.1/pass.php
POST /pass.php HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://127.0.0.1/pass.php
Cookie: passx=87e8af376bc9d9bfec2c7c0193e6af70; PHPSESSID=l9hk7mfh0ppqecg8gialak6gt5
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
username=zurfyx&pass=password
Где он говорит
Content-Length: 30
username=zurfyx&pass=password
будут значениями post.
Ответ 5
Тип носителя по умолчанию в запросе POST application/x-www-form-urlencoded
. Это формат для кодирования пар ключ-значение. Ключи могут быть дублированы. Каждая пара ключ-значение разделяется символом &
, и каждый ключ отделяется от его значения символом =
.
Например:
Name: John Smith
Grade: 19
Записывается как:
Name=John+Smith&Grade=19
Это помещается в тело запроса после заголовков HTTP.
Ответ 6
Некоторые веб-службы требуют, чтобы вы размещали данные запроса и метаданные отдельно. Например, удаленная функция может ожидать, что подписанная строка метаданных будет включена в URI, а данные будут отправляться в HTTP-корпусе.
Запрос POST может семантически выглядеть следующим образом:
POST /?AuthId=YOURKEY&Action=WebServiceAction&Signature=rcLXfkPldrYm04 HTTP/1.1
Content-Type: text/tab-separated-values; charset=iso-8859-1
Content-Length: []
Host: webservices.domain.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: identity
User-Agent: Mozilla/3.0 (compatible; Indy Library)
name id
John G12N
Sarah J87M
Bob N33Y
Этот подход логически объединяет QueryString и Body-Post с помощью единственного Content-Type
, который является "инструкцией синтаксического анализа" для веб-сервера.
Обратите внимание: HTTP/1.1 заключен в #32
(пробел) слева и #10
(строка) справа.
Ответ 7
Значения форм в HTTP-POST-сообщениях отправляются в тело запроса в том же формате, что и запрос.
Для получения дополнительной информации см. spec.
Ответ 8
Прежде всего, давайте сделаем различие между GET
и POST
Get: Это запрос по умолчанию HTTP
, который делается на сервер и используется для получения данных с сервера, а строка запроса, которая следует после того, как ?
в URI
используется для получения уникального ресурса.
это формат
GET /someweb.asp?data=value HTTP/1.0
здесь data=value
- переданное значение строки запроса.
POST: Он используется для безопасной отправки данных на сервер, поэтому все, что нужно, это формат запроса POST
POST /somweb.aspHTTP/1.0
Host: localhost
Content-Type: application/x-www-form-urlencoded //you can put any format here
Content-Length: 11 //it depends
Name= somename
Почему POST более GET?
В GET
значение, отправляемое на серверы, обычно добавляется к базовому URL-адресу в строке запроса. Это позволяет взламывать ваши данные (это было проблемой в те дни, когда Facebook предоставлял свои учетные данные), поэтому POST
используется для отправки данных на сервер, который использовал Request Body
для отправки ваших данных на сервер, который является более безопасным, поскольку он скрывает ваши данные и получает данные из полей, вычисляет их длину и добавляет их к header
для content-length
, и никакие важные данные не добавляются непосредственно в URL
теперь, когда ваш запрос защищен, любые значения, отправляемые на сервер, могут быть отправлены в Request Body
, поскольку имя подразумевает, что оно будет содержать данные, которые пользователь хотел отправить (и оно отправлено в формате URL Encoded
), и Request Headers
обеспечит безопасность запроса, сравнивая значения в Request Body
с Request Headers
теперь вопрос безопасности не совсем верен только для HTTP, данные в теле не обязательно очень безопасны, если они не зашифрованы с использованием протокола HTTP.
Вы можете использовать сетевой раздел Инструментов Google для разработчиков, чтобы просмотреть основную информацию о том, как запросы поступают на серверы.
и вы всегда можете добавить больше значений в Request Headers
, например Cache-Control
, Origin
, Accept
.
Ответ 9
Чтобы добавить дополнительную информацию, ниже также поможет выяснить различия.
Я использовал Java в качестве HTTP-клиента, чтобы показать формирование запроса GET и POST. Комментарии для описания заявления.
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* HTTP GET and POST example
*
* @author iampayload
*
*/
public class GET_POST {
private final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.04";
// GET action URL, query string appended to the URL as ?stype=models
private final String urlGET = "https://www.servicesplus.sel.sony.com/PartsPLUSResults.aspx?stype=models";
// POST action URL
private final String urlPOST = "https://sg.campaign.samsung.com/smartacademy/controller/controller.php/getLocation";
// Post data or a payload
private String postDataBody = "state=West";
// Main class
public static void main(String[] args) throws Exception {
GET_POST http = new GET_POST();
System.out.println("Testing send HTTP GET request HTML output is below \n");
http.sendGET();
System.out.println(
"--------------------------------------------------------------------------------------------------------");
System.out.println("Testing send HTTP POST request HTML output is below \n");
http.sendPost();
}
// HTTP POST request
private void sendPost() throws Exception {
// POST example URL
URL obj = new URL(urlPOST);
// Send post request
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// Basic reuqest header to simulate a browser request
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
con.setRequestProperty("Upgrade-Insecure-Requests", "1");
con.setRequestProperty("Connection", "keep-alive");
con.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
// Payload
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
// POST data added to the request as a part of body
wr.writeBytes(postDataBody);
wr.flush();
wr.close();
// Reading the HTML output of the POST HTTP request
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
// HTTP GET request
private void sendGET() throws Exception {
URL obj = new URL(urlGET);
// Send post request
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// basic reuqest header to simulate a browser request
con.setRequestMethod("GET");
con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
con.setRequestProperty("Upgrade-Insecure-Requests", "1");
con.setRequestProperty("Connection", "keep-alive");
con.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
con.setRequestProperty("Accept-Encoding", "gzip, deflate, br");
con.setDoOutput(true);
// Reading the HTML output of the POST HTTP request
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
}