HTTP POST isteğinde parametreler nasıl gönderilir?


1475

Bir HTTP GET isteğinde, parametreler sorgu dizesi olarak gönderilir :

http://example.com/page ? parametre = değer & ayrıca = başka

Bir HTTP POST isteğinde, parametreler URI ile birlikte gönderilmez.

Değerler nerede? İstek başlığında mı? İstek gövdesinde? Nasıl görünüyor?

Yanıtlar:


1252

Değerler, istek gövdesinde, içerik türünün belirttiği biçimde gönderilir.

Genellikle içerik türü application/x-www-form-urlencoded, bu nedenle istek gövdesi sorgu dizesiyle aynı biçimi kullanır:

parameter=value&also=another

Formda bir dosya yükleme kullandığınızda, multipart/form-databunun yerine farklı bir biçime sahip olan kodlamayı kullanırsınız. Daha karmaşık, ancak genellikle neye benzediğini umursamanıza gerek yok, bu yüzden bir örnek göstermeyeceğim, ancak var olduğunu bilmek iyi olabilir.


25
Dosya yüklemelerinin farklı olduğunu unuttum (+ 1 / kabul edildi). Cevabınız yeterli, daha fazla bilgi varsa çok güzel olurdu multipart/form-data. Yine de ilgilenenler için burada bir soru var .
Camilo Martin

73
NOT : gövde, başlıktan yalnızca bir boş satırla ayrılır .
Gab 是 好人

2
HTTPBody'e ne yerleştirdiğimizi açıkladınız, ancak HTTPHeader'a ne yerleştiriyoruz / yazıyoruz? Hangi amaca hizmet ediyor?
Tatlım

4
@Honey: Bir gönderinin HTTP üstbilgisi bir get için bir tane gibi görünür, ancak GET yerine POST fiili ve isteğin içeriğe (gövdeye) sahip olduğu bir içerik türü değeri (ve isteğe bağlı bir içerik uzunluğu değeri) vardır. Her istek türünün bir başlığı vardır, bazı türlerin de bir gövdesi vardır.
Guffa

4
@KennethWorden Hayır, yöntemlerin hiçbiri JSON'u düzgün şekilde gönderemez. ancak, json dosyasını kodlanmış bir formda yükleyebilir multipart/form-dataveya istek oluşturma sorumluluğu application/json
sizdeyseniz

428

İçerik HTTP başlıklarının arkasına yerleştirilir. HTTP POST formatı, HTTP üstbilgilerini, ardından boş bir satır ve ardından istek gövdesini içermektir. POST değişkenleri gövdede anahtar / değer çiftleri olarak saklanır.

Bunu, aşağıda gösterilen bir HTTP Postasının ham içeriğinde görebilirsiniz:

POST /path/script.cgi HTTP/1.0
From: frog@jmarshall.com
User-Agent: HTTPTool/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 32

home=Cosby&favorite+flavor=flies

Bunu , tel üzerinden gönderilen ham HTTP isteğini ve yanıt yüklerini izlemek için kullanabileceğiniz Fiddler gibi bir araç kullanarak görebilirsiniz .


39
Yalnızca içerik türü ise application/x-www-form-urlencoded, her zaman böyle değildir.
Guffa

@ Camilo Martin .... [+1] büyük soru için & @ Joe Alfano .... [+1] büyük cevap için ....... şimdi POST isteği hakkında net bir fikrim var .... ancak bir görüntü anahtarla birlikte gelirse, veri bilgileri değer çifti ..... POST yapısı nasıl görünüyor?
Kasım'da Devrath

9
@Joe, Şimdi neden Fromorada bir başlığın olsun ki?
Pacerier

@Joe, Frombaşlığın rastgele eklenmesini seviyorum . IMO orada 418 HTTP durum kodu ile.
Tom Howard

kullanıcı ve şifre kimlik doğrulamasını nasıl eklersiniz?
m4l490n

376

Kısa cevap: POST isteklerinde, değerler isteğin "gövdesinde" gönderilir. Web formlarında, büyük olasılıkla bir medya türü application/x-www-form-urlencodedveya ile gönderilir multipart/form-data. Dil veya genellikle istekleri ile "Doğruyu ™" yapmak ve (gibi kolay kolay deşifre değerlere erişmenizi sağlamayı sap web istekleri için tasarlanmıştır çerçeveler Programlama $_REQUESTveya $_POSTPHP veya cgi.FieldStorage(), flask.request.formPython).


Şimdi biraz fark edelim, bu farkı anlamaya yardımcı olabilir;)

Arasındaki fark GETve POSTisteklerine büyük ölçüde semantik bulunmaktadır. Ayrıca farklı şekillerde kullanılırlar, bu da değerlerin nasıl aktarıldığındaki farkı açıklar.

GET ( ilgili RFC bölümü )

Bir GETistek yürütürken , sunucudan bir veya bir dizi varlık istersiniz. İstemcinin sonucu filtrelemesine izin vermek için URL'nin "sorgu dizesi" ni kullanabilir. Sorgu dizesi, öğesinden sonraki bölümdür ?. Bu, URI sözdiziminin bir parçasıdır .

Bu nedenle, uygulama kodunuzun ( isteği alan kısım) bakış açısından, bu değerlere erişmek için URI sorgu bölümünü incelemeniz gerekecektir.

Anahtarların ve değerlerin URI'nin bir parçası olduğunu unutmayın. Tarayıcılar URI uzunluğu için bir sınır getirebilir . HTTP standardı sınır olmadığını belirtir. Ama bu yazının yazıldığı anda, çoğu tarayıcı yok URI'ları (ı belirli değerleri yok) sınırlar. GETistekleri gerektiğini asla sunucuya yeni bilgi göndermek için kullanılabilir. Özellikle büyük belgeler değil. POSTVeya kullanmanız gereken yer burası PUT.

POST ( ilgili RFC bölümü )

Bir POSTistek yürütülürken , istemci gerçekte uzak ana bilgisayara yeni bir belge gönderiyor . Bu nedenle, bir sorgu dizesi (anlamsal olarak) mantıklı değildir. Bu yüzden uygulama kodunuzda bunlara erişemezsiniz.

POSTbiraz daha karmaşık (ve bir yol daha esnek):

Bir POST isteği alırken, her zaman bir "yararlı yük" veya HTTP terimleriyle bir ileti gövdesi beklemelisiniz . İleti gövdesi, standart (anlayabildiğim kadarıyla. Belki application / octet-stream?) Formatı olmadığı için oldukça işe yaramaz . Gövde biçimi Content-Typebaşlık tarafından tanımlanır . İle bir HTML FORMöğesi kullanıldığında method="POST", bu genellikle olur application/x-www-form-urlencoded. Dosya yüklemelerini kullanıyorsanız , çok yaygın olan başka bir tür de çoklu bölüm / form verisidir. Ama olabilir şey arasında değişen text/plainüzerinde, application/jsonhatta özel application/octet-stream.

Her durumda, uygulama tarafından işlenemeyen bir POSTistek yapılırsa, Content-Typebir 415durum kodu döndürmelidir .

Çoğu programlama dilleri (ve / veya web çerçeveler) de bir yol sunar / kodlamak gelen / en yaygın türlerinden (benzerine mesaj gövdesi application/x-www-form-urlencoded, multipart/form-dataya da application/json). Yani bu kolay. Özel türler potansiyel olarak biraz daha fazla çalışma gerektirir.

Örnek olarak standart bir HTML formu kodlu belge kullanarak, uygulama aşağıdaki adımları gerçekleştirmelidir:

  1. Content-TypeAlanı okuyun
  2. Değer desteklenen medya türlerinden biri değilse, 415durum koduyla bir yanıt döndürün
  3. aksi takdirde mesaj gövdesindeki değerleri deşifre edin.

Yine, PHP gibi diller veya diğer popüler diller için web çerçeveleri muhtemelen bunu sizin için halledecektir. Bunun istisnası 415hatadır. Hiçbir çerçeve, uygulamanızın hangi içerik türlerini desteklemeyi ve / veya desteklememeyi seçtiğini tahmin edemez. Bu size kalmış.

PUT ( ilgili RFC bölümü )

Bir PUTistek, bir istekle hemen hemen aynı şekilde ele alınır POST. En büyük fark, POSTsunucunun yeni bir kaynağın nasıl oluşturulacağına (ve eğer varsa) karar vermesine izin veren bir isteğin bulunmasıdır. Tarihsel olarak (artık kullanılmayan RFC2616'dan itibaren, talebin gönderildiği URI'nin "alt" (alt öğesi) olarak yeni bir kaynak oluşturmaktı).

PUTBuna karşılık bir talebin, kaynağı tam olarak bu URI'ye ve tam olarak bu içeriğe "yatırması" beklenir . Ne fazla ne az. Fikir müşteri "PUTting" önce tüm kaynağı oluşturmak için sorumlu olmasıdır. Sunucu , verilen URL'de olduğu gibi kabul etmelidir .

Sonuç olarak, POSTgenellikle varolan bir kaynağın yerini almak için bir istek kullanılmaz . Bir PUTistek yapmak hem oluşturabilir ve değiştirin.

Kenar notu

Ayrıca uzaktan kumandaya ek veri göndermek için kullanılabilecek " yol parametreleri " vardır, ancak çok nadirdir, burada çok fazla ayrıntıya girmeyeceğim. Ancak, referans olarak, RFC'den bir alıntı:

Hiyerarşik yollardaki nokta segmentlerinin yanı sıra, bir yol segmenti genel sözdizimi tarafından opak olarak kabul edilir. URI üreten uygulamalar genellikle şemaya özgü veya kayıttan çıkarılma özelliğine özgü alt bileşenleri sınırlandırmak için bir segmentte izin verilen ayrılmış karakterleri kullanır. Örneğin, noktalı virgül (";") ve eşittir ("=") ayrılmış karakterler genellikle bu segment için geçerli olan parametreleri ve parametre değerlerini sınırlamak için kullanılır. Virgül (",") ayrılmış karakteri genellikle benzer amaçlar için kullanılır. Örneğin, bir URI üreticisi "name" in 1.1 versiyonuna bir referansı belirtmek için "name; v = 1.1" gibi bir segment kullanabilir, diğeri ise bunu belirtmek için "name, 1.1" gibi bir segment kullanabilir. Parametre türleri şemaya özel anlambilim ile tanımlanabilir,


1
Gerçekten hafif bir teğet geçirmiş olabilirim. Cevabın üst kısmına netleştirmesi gereken bir "tl; dr" ekledim.
exhuma

Ben de şimdi RFC2616 (bir süredir kullanılmayan) yerine RFC7231 referans için düzenledi. Bu cevap için güncellenmiş bağlantılar dışında temel fark "PUT" bölümünde.
exhuma

Ben PUT idempotent olması gerekiyordu sonra POST farklı ele düşündüm? stackoverflow.com/questions/611906/…
rogerdpack

1
@rogerdpack Yanlış değilsiniz. Eğer ikinci paragrafı okursanız PUTbölümünde, bunu göreceksiniz olduğu İdempotent. POSTaksine - tanımı gereği - olamaz. POSTher zaman yeni bir kaynak oluşturur. PUTözdeş bir kaynak varsa, onun yerini alacaktır. Yani POST10 kez ararsanız , 10 kaynak yaratabilirsiniz. PUT10 kez ararsanız , sadece bir tane oluşturur (belki). senin sorunun cevabı bu mu?
exhuma

59

Doğrudan tarayıcı URL çubuğuna yazamazsınız.

Örneğin , POST verilerinin Internet'te Canlı HTTP Üstbilgileri ile nasıl gönderildiğini görebilirsiniz . Sonuç böyle bir şey olacak

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

Nerede söylüyor

Content-Length: 30
    username=zurfyx&pass=password

gönderi değerleri olacak.


2
Açıklama: Burada Content-Lengtholması gerekiyor 29mu? Bu ipin gerçek uzunluğu username=zurfyx&pass=password.
Hippo

@ Hippo orada olması gereken bir yeni satır karakteri miydi?
vikingsteve

@vikingsteve Ne demek istediğini anlıyorum. Bu yüzden sanırım İçeriğin sonunda her zaman yeni bir satır var.
Hippo

2
Üstbilgi, ekstra satırsonu ile vücuttan ayrılır
Mára Toner

24

Bir POST isteği varsayılan medya türüdür application/x-www-form-urlencoded. Bu, anahtar / değer çiftlerini kodlamak için kullanılan bir biçimdir. Anahtarlar kopyalanabilir. Her anahtar / değer çifti bir &karakterle ayrılır ve her anahtar kendi değerinden bir =karakterle ayrılır .

Örneğin:

Name: John Smith
Grade: 19

Şu şekilde kodlanır:

Name=John+Smith&Grade=19

Bu, HTTP üstbilgilerinden sonra istek gövdesine yerleştirilir.


1
HTTPBody'e ne yerleştirdiğimizi açıkladınız, ancak HTTPHeader'a ne yerleştiriyoruz / yazıyoruz?
Tatlım

Anahtarın yinelenebileceğini söylemiştiniz, o zaman böyle bir yinelemenin sonucu nedir? Sonuncusu otomatik olarak önceki değerlerin üzerine yazacak mı? Teşekkürler.
Jinghui Niu

@JinghuiNiu anahtar yineleniyorsa, bir dizi olarak ayrıştırılmalıdır. Bu çok geç ama başka birine yardımcı olabilir.
Hanash Yaslem

18

HTTP POST'larındaki form değerleri, sorgu gövdesiyle aynı biçimde istek gövdesinde gönderilir.

Daha fazla bilgi için teknik özelliklere bakın .


5
"Aynı biçim" biraz belirsiz. ?Örneğin bir ile mi başlıyorlar ?
Camilo Martin

7
@PeterWooster Evet, ancak bir örnek vermiyor. Bu bağlamda, "bak, sorunuzun yanıtını uygulamanın blogunda (bağlantı) " yazan bir yanıt gibidir .
Camilo Martin

36
@PeterWooster Gerekli değil, ancak bir şeyi unutduğunuzda, google'da, SO olan ilk bağlantıya gittiğinizde çok iyi ve sizi çiğnemeye göndermek yerine neye ihtiyacınız olduğunu açık, özlü bir örnek var. kapsamlı olsa bile, tazeleyiciler için uygun olmayabilir aşırı ayrıntılı özellikler. Bir düşünün: Bu sitedeki KG'lerin çoğu "spec / manual / API / etc (link) 'i okumak için kaybolabilir . Yararlı olur mu? Google'dan daha fazla değil.
Camilo Martin

2
Yalnızca içerik türü ise application/x-www-form-urlencoded, her zaman böyle değildir.
Guffa

3
GET sorgu dizesinin biçimi, application / x-www-form-urlencoded biçiminden farklıdır. Örneğin, boşluk farklı kodlanır (+% 20'ye karşı). Bu konuda cevap yanıltıcıdır.
UnclickableCharacter

18

Bazı web hizmetleri, istek verilerini ve meta verileri ayrı ayrı yerleştirmenizi gerektirir . Örneğin, uzak bir işlev, veriler bir HTTP gövdesinde yayınlanırken, imzalı meta veri dizesinin bir URI'ye dahil edilmesini bekleyebilir.

POST isteği anlamsal olarak şu şekilde görünebilir:

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

Bu yaklaşım mantıksal olarak QueryString ve Body-Post'u Content-Typebir web sunucusu için "ayrıştırma-talimatı" olan tek bir komut kullanarak birleştirir .

Lütfen not: HTTP / 1.1 olduğu sarılı ile #32solda ve birlikte (boşluk) #10sağda (Hat besleme).


Arasındaki fark /user/johnve /?user=johnmakul beklendiği gibi bunu alıp böylece, sadece bir semantik bir (gerçekten sorgu dizeleri özel muamelede bulunmaz HTTP) 'dir. Peki "soldaki boşlukla sarılmış" ile ne demek istiyorsun? HTTP yönteminden önce boşluk yok. Yazı gövdesi için boş satır mı demek istiyorsun?
Camilo Martin

Yukarıdaki kod arasında ...Ym04ve HTTP/1.1içinde bir boşluk (ASCII # 32) vardır . Yani bir QueryString fiil ve protokol sürümü arasında bulunur.
Arayüz Bilinmiyor

1
Notunuz, beklenmedik ve sürüme özgü bir şey gibi geliyor. Açıkçası orada bir yer var gibi görünüyor. Ayrıca satır besleme, unix gibi diğer satırlar için de geçerlidir.
Camilo Martin

1
Sadece kodda işaretleyemediğimi vurguladım. Çok açık görünebilir, ancak bazen değildir.
Arayüz Bilinmiyor

URI ve parametreleri isteklerde ?yaptığımız gibi ayırarak URL'nin bir parçası olarak sorgu parametrelerini geçirebileceğimiz doğrudur GET.
16:26

8

Her şeyden önce, GETvePOST

Get: Bu varsayılan HTTPsunucuya yapılır ve sonra gelen sunucu ve sorgu dizesi veri almak için kullanılan istek ?bir de URIeşsiz bir kaynak almak için kullanılır.

format bu

GET /someweb.asp?data=value HTTP/1.0

Burada data=valuegeçirilen sorgu dizesi değeri.

POST: Verileri sunucuya güvenli bir şekilde göndermek için kullanılır, böylece gereken her şey, bu bir POSTisteğin biçimidir

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

Neden GET üzerinden POST?

Gelen GETgenellikle sorgu dizesinde temel URL'ye eklenir sunucularına gönderilmeden değeri, şimdi bu 2 sonuçları vardır

  • GETİstekleri parametrelerle tarayıcı geçmişinde kaydedilir. Böylece şifreleriniz tarayıcı geçmişinde şifrelenmeden kalır. Bu, o günlerde Facebook için gerçek bir konuydu.
  • Genellikle sunucular a'nın ne kadar uzun URIolabileceği konusunda bir sınıra sahiptir . Çok fazla parametre gönderiliyorsa,414 Error - URI too long

Sonradan istek olması durumunda, alanlardaki verileriniz gövdeye eklenir. İstek parametrelerinin uzunluğu hesaplanır ve içerik uzunluğu için başlığa eklenir ve doğrudan URL'ye önemli bir veri eklenmez.

Sunuculara isteklerin nasıl yapıldığına ilişkin temel bilgileri görmek için Google Geliştirici Araçları'nın ağ bölümünü kullanabilirsiniz.

ve her zaman daha değerleri ekleyebilirsiniz Request Headersbeğendiniz Cache-Control, Origin, Accept.


4
Güvenlikle ilgili varsayımlar sadece HTTPSbağlantı bağlamında doğrudur , değil HTTP. HTTPSşifreler hem URL(Sorgu parametreleri de dahil olmak üzere), ve Request Bodyzaman HTTPşifreler / de korur. Açıklanan sorun, birçok tarayıcının URIs(dahil URLs) geçmiş veritabanlarında (genellikle şifrelenmemiş) sakladığı gerçeğinden kaynaklanmaktadır . Bu nedenle, hassas bir şey için yalnızca Request Body+ işaretini kullanın HTTPS.
Petru Zaharia

@PetruZaharia Açıklamanıza katılıyorum. Bunu düzenleme olarak da önerebilirsiniz ve kabul etmekten memnuniyet duyarız! :)
Zeeshan Adil
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.