Bir URI sorgusunda geçerli olan ve olmayan nedir?


101

Arka plan (soru daha aşağıda)

Bunu çözmeye çalışan RFC'leri ve SO sorularını ileri geri okudum, ancak hala jack'im yok.

Sanırım biz sadece "en iyi" cevaba oy veriyoruz ve bu kadar mı, yoksa?

Temelde buna indirgeniyor.

3.4. Sorgu Bileşeni

Sorgu bileşeni, kaynak tarafından yorumlanacak bir bilgi dizisidir.

query = *uric

Sorgu bileşeni içinde, ";", "/", "?", ":", "@", "&", "=", "+", "," Ve "$" karakterleri ayrılmıştır.

Beni şaşırtan ilk şey, * ürik'in böyle tanımlanması

uric = reserved | unreserved | escaped

reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","

Ancak bu, aşağıdaki gibi paragraflarla biraz açıklığa kavuşturulmuştur

Yukarıdaki "ayrılmış" sözdizimi sınıfı, bir URI içinde izin verilen, ancak genel URI sözdiziminin belirli bir bileşeni içinde izin verilmeyebilen karakterleri ifade eder; Bölüm 3'te açıklanan bileşenlerin sınırlayıcıları olarak kullanılırlar.

"Ayrılmış" kümedeki karakterler tüm bağlamlarda ayrılmaz. Herhangi bir URI bileşeni içinde gerçekten ayrılmış olan karakter kümesi, bu bileşen tarafından tanımlanır. Genel olarak, karakter, çıkış karakterli US-ASCII kodlaması ile değiştirilirse, URI'nin anlambilimi değişirse, bir karakter ayrılır.

Bu son alıntı biraz geriye doğru geliyor, ancak ayrılmış karakter kümesinin bağlama bağlı olduğunu açıkça belirtiyor. Yine de 3.4, tüm ayrılmış karakterlerin bir sorgu bileşeni içinde ayrıldığını belirtir, ancak buradaki anlamsallığı değiştirecek tek şey, URI'ler bir sorgu dizesi kavramını tanımlamadığından, soru işaretinden (?) Kaçmaktır.

Bu noktada RFC'lerden tamamen vazgeçtim ama RFC 1738'i özellikle ilginç buldum.

Bir HTTP URL'si şu biçimi alır:

http://<host>:<port>/<path>?<searchpart>

<path> ve <searchpart> bileşenleri içinde, "/", ";", "?" saklıdır. "/" Karakteri, hiyerarşik bir yapı belirlemek için HTTP içinde kullanılabilir.

Bunu en azından RFC 1738'in RFC 2396'nın yerini aldığı HTTP URL'leri ile ilgili olarak yorumluyorum. URI sorgusu bir sorgu dizesi kavramına sahip olmadığından, rezerve edilmişin yorumlanması da benim alıştığım gibi sorgu dizelerini tanımlamama gerçekten izin vermiyor şimdiye kadar yapıyor.

Soru

Bunların hepsi, başka bir kaynağın talebiyle birlikte bir sayılar listesini iletmek istediğimde başladı. Pek düşünmedim ve virgülle ayrılmış değerler olarak geçtim. Virgülün kaçmasına rağmen beni şaşırttı. page.html?q=1,2,3Kodlanan sorgu page.html?q=1%2C2%2C3işe yarıyor, ancak çirkin ve beklemiyordu. İşte o zaman RFC'lerden geçmeye başladım.

İlk sorum basitçe, virgül kodlamak gerçekten gerekli mi?

Cevabım, RFC 2396'ya göre: evet, RFC 1738'e göre: hayır

Daha sonra listelerin istekler arasında aktarılmasıyla ilgili gönderiler buldum. CSV yaklaşımının kötü olduğu yerde. Bunun yerine bu ortaya çıktı (bunu daha önce görmedim).

page.html?q=1;q=2;q=3

İkinci sorum, bu geçerli bir URL mi?

Cevabım, RFC 2396'ya göre: hayır, RFC 1738'e göre: hayır (; saklıdır)

Sayı olduğu sürece csv'yi geçmekle ilgili herhangi bir sorunum yok, ancak evet, virgül başka bir şey için aniden gerekliyse değerleri ileri geri kodlamak ve çözmek zorunda kalma riskiyle karşılaşıyorsunuz. Neyse, noktalı virgül sorgu dizesini ASP.NET ile denedim ve sonuç beklediğim gibi değildi.

Default.aspx?a=1;a=2&b=1&a=3

Request.QueryString["a"] = "1;a=2,3"
Request.QueryString["b"] = "1"

Bunun bir csv yaklaşımından ne kadar büyük farklılaştığını göremiyorum, çünkü "a" diye sorduğumda içinde virgül olan bir dizge alıyorum. ASP.NET kesinlikle bir referans uygulaması değil ama beni henüz yarı yolda bırakmadı.

Ama en önemlisi - üçüncü sorum - bunun spesifikasyonu nerede? ve sen ne yapardın yoksa yapmaz mısın?


RFC 2396 neredeyse 4 yıl sonra yayınlandığında, RFC 1738 nasıl RFC 2396'nın yerini alabilir?
Matthew Flaschen

1
URL'ler ve pratik olarak mantıklı olan şeyle ilgili olarak, benim yorumumdur. (geçersiz kılma muhtemelen doğru kelime değildir, çünkü RFC terminolojisinde kullanımdan kaldırılmış eski RFC'lerde kullanıldığından, RFC 1738, arama bölümüne bir sorgu dizesi koymanıza izin veren tek özellik bulunduğunda, tüm bunların kullanılmadığını hissetmez. URL)
John Leidegren

Yanıtlar:


70

Bir karakterin genel bir URL bileşeni içinde ayrılmış olması, bileşenin içinde veya bileşendeki verilerin içinde göründüğünde ondan kaçılması gerektiği anlamına gelmez. Karakter ayrıca genel veya şemaya özgü sözdizimi içinde bir sınırlayıcı olarak tanımlanmalıdır ve karakterin görünümü veri içinde olmalıdır.

Genel URI'ler için geçerli standart , şunu söyleyen RFC 3986'dır :

2.2. Ayrılmış Karakterler

URI'lar, "ayrılmış" kümedeki karakterlerle sınırlandırılmış bileşenleri ve alt bileşenleri içerir. Bu karakterler "ayrılmış" olarak adlandırılır çünkü bunlar genel sözdizimi tarafından, her şemaya özgü sözdizimi tarafından veya bir URI'nin referans alma algoritmasının uygulamaya özgü sözdizimi tarafından sınırlayıcılar olarak tanımlanabilirler (veya tanımlanmayabilirler). Bir URI bileşenine ilişkin veriler, ayrılmış bir karakterin sınırlayıcı olarak [vurgu eklendi] amacıyla çelişiyorsa, çakışan verilerin URI oluşturulmadan önce yüzde kodlanması gerekir.

   ayrılmış = gen-delims / sub-delims

   gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"

   alt sınırlamalar = "!" / "$" / "&" / "" "/" ("/") "
               / "*" / "+" / "," / ";" / "="

3.3. Yol Bileşeni

[...]
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
[...]

3.4 Sorgu Bileşeni

[...]
      sorgu = * (pchar / "/" / "?")

Bu nedenle, sorgu dizelerinde virgüllere açıkça izin verilir ve yalnızca belirli şemalar onu bir sınırlayıcı olarak tanımlıyorsa, verilerde kaçılması gerekir. HTTP şeması, sorgu dizelerinde sınırlayıcı olarak virgül veya noktalı virgül kullanmaz, bu nedenle bunların öncelenmesine gerek yoktur. Tarayıcıların bu standarda uyup uymadığı başka bir konudur.

CSV kullanmak dize verileri için iyi çalışmalıdır, sadece standart CSV kurallarını izlemeniz ve verileri alıntı yapmanız veya virgüllerden ters eğik çizgilerle kaçmanız gerekir.

RFC 2396'ya gelince, HTTP sorgu dizelerinde çıkış karaktersiz virgüllere de izin verir:

2.2. Ayrılmış Karakterler

Çoğu URI, belirli özel karakterlerden oluşan veya bunlarla sınırlandırılmış bileşenler içerir. Bu karakterler, URI bileşenindeki kullanımları ayrılmış amaçlarıyla sınırlı olduğundan "ayrılmış" olarak adlandırılır. Bir URI bileşenine ilişkin veriler ayrılmış amaç ile çelişiyorsa, URI oluşturmadan önce çakışan verilerden çıkış yapılmalıdır.

Virgüllerin HTTP şeması altında ayrılmış bir amacı olmadığından, verilerde öncelenmeleri gerekmez. Yüzde olarak kodlandığında semantiği değiştiren ayrılmış karakterlerle ilgili § 2.3'deki not yalnızca genel olarak geçerlidir; karakterler, belirli şemalar için anlambilim değiştirilmeden yüzde olarak kodlanabilir ve yine de rezerve edilebilir.


24

Sorgu dizesinde neyin geçerli olduğunu cevaplamak için, istek yaparken hangi özel karakterlerin Chrome ile değiştirildiğini kontrol ettim:

Space -> %20
! -> !
" -> %22
# -> removed, marks the end of the query string
% -> %
& -> &
' -> %27
( -> (
) -> )
* -> *
+ -> + (this usually means blank when received at the server, so encode if necessary)
, -> ,
- -> -
. -> .
/ -> /
: -> :
; -> ;
< -> %3C
= -> =
> -> %3E
? -> ?
@ -> @
[ -> [
\ -> \
] -> ]
^ -> ^
_ -> _
` -> `
{ -> {
| -> |
} -> }
~ -> ~

Extended ASCII (like °) -> Every character from this set is encoded

Not: Bu muhtemelen, bağlantılar için URI'ler oluşturduğunuzda değiştirilmeyen karakterlere çıkış yapmamanız gerektiği anlamına gelmez. Örneğin ~, uyumluluk sorunları nedeniyle genellikle URI'larda kullanılmaması önerilir , ancak yine de geçerli bir karakterdir.

Başka bir örnek, geçerli olan, ancak bir sunucu bunu bir isteğin parçası olarak aldığında genellikle boş olarak kodlanmış olarak değerlendirilen artı işaretidir. Bu nedenle, amacı bir uzayı değil, bir artıyı temsil etmek olduğunda, geçerli olsa bile kodlanmalıdır.

Neyin kodlanması gerektiğini cevaplamak için: Kelimenin tam anlamıyla ele almak istediğiniz, ancak özel bir anlamı olan veya sunucu tarafında sorunlara neden olabilecek geçersiz karakterler ve karakterler.


/programming/2366260/whats-valid-and-whats-not-in-a-uri-query?param=b#1;c#2geçerli bir sorgu parametresi?
Sumit Jain

@SumitJain Hayır, çünkü #bir URI'nin sorgu kısmında olduğu gibi görünemez. %23URI'nin olması için onu olarak kodlamanız gerekecek /programming/2366260/whats-valid-and-whats-not-in-a-uri-query?param=b%231;c%232.
Dai

10

Sadece kullan ?q=1+2+3

Burada sorulmayan, ancak şununla başlayan dördüncü bir soruyu yanıtlıyorum: virgülle ayrılmış değerler ile sayıların listesini nasıl geçirebilirim? Bana öyle geliyor ki en iyi yaklaşım onları boşluklarla ayrılmış olarak, boşlukların url-form-kodlanacağı yere geçirmek +. Listedeki değerlerin boşluk içermediğini bildiğiniz sürece harika çalışır (sayılar böyle değildir).


Bunun bir yorum olması gerekirken (soruyu cevaplamadığı için) teşekkür ederim. +virgül kullanmak istediğim özel durumda daha da mantıklı.
Gajus

6

page.html? q = 1; q = 2; q = 3

bu geçerli bir URL mi?

Evet. ;Ancak bir RFC tarafından, ayrılmıştır. Bu bileşeni tanımlayan bağlam application/x-www-form-urlencoded, HTML standardının bir parçası olan ortam türünün tanımıdır (bölüm 17.13.4.1 ). Özellikle, Bölüm B.2.2'de saklanan sinsi not :

HTTP sunucusu gerçekleştiricilerinin ve özellikle CGI uygulayıcılarının ";" kullanımını desteklemesini öneririz. yazarları bu şekilde "&" karakterlerinden kaçma zahmetinden kurtarmak için "&" yerine.

Ne yazık ki, ASP.NET dahil olmak üzere birçok popüler sunucu tarafı komut dosyası çerçevesi bu kullanımı desteklemez.


Dolayısıyla, ?q=1;q=2;q=3sorgu geçerliyken belirsizdir: Bazı sunucu tarafı çerçeveler bunu anlama gelecek şekilde okuyacaktır, bazıları ise { q: '1;q=2;q=3' }benzer şekilde yapabilir { q: {'1', '2', '3'}}.
Nas Banov

1
Evet. Daha da kötüsü, HTML5 artık ilgili dili içermiyor ;, yani HTML4 ve HTML5 tutarsız. Ugh, özel bir belgede normatif olmayan dilin tehlikeleri ...
bobince

@NasBanov Ve diğerleri (örneğin PHP) bunu şu şekilde yorumlayacak{ q: 3 }
Nicholas Shanks

1
@NicholasShanks - PHP söz konusu olduğunda, tüm bahisler kapalıdır! :)
Nas Banov

1

Bunun da page.html?q=1&q=2&q=3geçerli bir url olduğunu belirtmek isterim . Bu, sorgu dizesindeki bir diziyi ifade etmenin tamamen yasal bir yoludur. Sunucu teknolojiniz bunun tam olarak nasıl sunulacağını belirleyecektir.

Klasik ASP'de, işaretler Response.QueryString("q").Countve sonra Response.QueryString("q")(0)(ve (1) ve (2)) kullanırsınız.

Bunu ASP.NET'inizde de gördüğünüzü unutmayın (bunun amaçlanmadığını düşünüyorum, ancak bakın):

Default.aspx?a=1;a=2&b=1&a=3

Request.QueryString["a"] = "1;a=2,3"
Request.QueryString["b"] = "1"

Noktalı virgülün yok sayıldığına dikkat edin, bu nedenle aiki kez tanımladınız ve virgülle ayrılmış olarak değerini iki kez aldınız. Tüm ve işaretlerinin kullanılması "1,2,3" sonucunu Default.aspx?a=1&a=2&b=1&a=3verecektir a. Ancak, öğelerin kendilerinin virgül içermesi durumunda, her bir öğeyi elde etmenin bir yöntemi olduğundan eminim. Alt değerleri virgül ayırıcılarla birleştiren, dizine eklenmemiş QueryString'in varsayılan özelliğidir.


1

Ben de aynı sorunu yaşadım. Köprülü URL bir üçüncü taraf URL'siydi ve page.html?q=1,2,3YALNIZCA biçimdeki bir parametre listesi bekliyordu ve URL page.html?q=1%2C2%2C3çalışmadı. JavaScript kullanarak çalıştırmayı başardım. En iyi yaklaşım olmayabilir, ancak herhangi birine yardımcı olursa buradan çözüme göz atabilirsiniz .


-3

ENCODED karakterleri FLASH / SWF dosyasına gönderiyorsanız , karakteri iki kez ENCODE etmeniz gerekir !! (Flash ayrıştırıcı nedeniyle)

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.