Tło (pytanie poniżej)
Szukałem tego w Google w tę iz powrotem, czytając RFC i pytania SO próbując to złamać, ale nadal nie mam gniazda.
Więc myślę, że po prostu głosujemy na „najlepszą” odpowiedź i to wszystko, prawda?
Zasadniczo sprowadza się to do tego.
3.4. Składnik zapytania
Składnik zapytania to ciąg informacji, które mają być zinterpretowane przez zasób.
query = *uric
W składniku zapytania znaki „;”, „/”, „?”, „:”, „@”, „&”, „=”, „+”, „,” I „$” są zarezerwowane.
Pierwszą rzeczą, która mnie zaskakuje, jest to, że * uric jest zdefiniowany w ten sposób
uric = reserved | unreserved | escaped
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
Jest to jednak nieco wyjaśnione w akapitach, takich jak
„Zarezerwowana” klasa składni powyżej odnosi się do tych znaków, które są dozwolone w obrębie URI, ale które mogą być niedozwolone w określonym składniku ogólnej składni URI; służą jako ograniczniki elementów opisanych w sekcji 3.
Znaki w zestawie „zarezerwowanym” nie są zarezerwowane we wszystkich kontekstach. Zestaw znaków faktycznie zarezerwowanych w ramach dowolnego składnika URI jest definiowany przez ten składnik. Ogólnie znak jest zarezerwowany, jeśli semantyka identyfikatora URI ulegnie zmianie, jeśli znak zostanie zastąpiony jego kodowaniem ze znakami ucieczki US-ASCII.
Ten ostatni fragment wydaje się nieco cofnięty, ale wyraźnie stwierdza, że zarezerwowany zestaw znaków zależy od kontekstu. Jednak 3.4 stwierdza, że wszystkie zastrzeżone znaki są zarezerwowane w komponencie zapytania, jednak jedyną rzeczą, która zmieniłaby tutaj semantykę, jest unikanie znaku zapytania (?), Ponieważ URI nie definiują pojęcia ciągu zapytania.
W tym momencie całkowicie zrezygnowałem z RFC, ale uznałem RFC 1738 za szczególnie interesujący.
Adres URL HTTP ma postać:
http://<host>:<port>/<path>?<searchpart>
W składnikach <path> i <searchpart>, „/”, „;”, „?” są zastrzeżone. Znak „/” może być użyty w HTTP do określenia struktury hierarchicznej.
Interpretuję to przynajmniej w odniesieniu do adresów URL HTTP, które RFC 1738 zastępuje RFC 2396. Ponieważ zapytanie URI nie ma pojęcia ciągu zapytania, również interpretacja zarezerwowanego tak naprawdę nie pozwala mi definiować ciągów zapytań, tak jak jestem przyzwyczajony już robię.
Pytanie
Wszystko zaczęło się, gdy chciałem przekazać listę numerów wraz z prośbą o inny zasób. Nie myślałem o tym zbyt wiele i po prostu przekazałem to jako wartości oddzielone przecinkami. Ku mojemu zdziwieniu udało się jednak uniknąć przecinka. page.html?q=1,2,3
Zakodowane zapytanie page.html?q=1%2C2%2C3
działa, ale jest brzydkie i nie spodziewałem się tego. Wtedy zacząłem przeglądać RFC.
Moje pierwsze pytanie brzmi po prostu, czy kodowanie przecinków jest naprawdę konieczne?
Moja odpowiedź, zgodnie z RFC 2396: tak, zgodnie z RFC 1738: nie
Później znalazłem powiązane posty dotyczące przekazywania list między wnioskami. Gdzie podejście CSV było gotowe jako złe. Pojawiło się to zamiast tego (nie widziałem tego wcześniej).
page.html?q=1;q=2;q=3
Moje drugie pytanie, czy to prawidłowy adres URL?
Moja odpowiedź, zgodnie z RFC 2396: nie, zgodnie z RFC 1738: nie (; jest zastrzeżone)
Nie mam żadnych problemów z przekazywaniem csv, o ile jest to liczba, ale tak, istnieje ryzyko konieczności kodowania i dekodowania wartości w tę iz powrotem, jeśli przecinek nagle jest potrzebny do czegoś innego. W każdym razie wypróbowałem ciąg zapytania ze średnikiem dwukropka w ASP.NET i wynik nie był tym, czego się spodziewałem.
Default.aspx?a=1;a=2&b=1&a=3
Request.QueryString["a"] = "1;a=2,3"
Request.QueryString["b"] = "1"
Nie widzę, jak bardzo różni się to od podejścia csv, ponieważ kiedy pytam o „a”, otrzymuję ciąg znaków z przecinkami. ASP.NET z pewnością nie jest implementacją referencyjną, ale jeszcze mnie nie zawiódł.
Ale co najważniejsze - moje trzecie pytanie - gdzie jest specyfikacja tego? i co byś zrobił lub czego nie zrobiłeś?
źródło
Odpowiedzi:
To, że znak jest zarezerwowany w ogólnym komponencie adresu URL, nie oznacza, że musi on zostać zmieniony, gdy pojawia się w komponencie lub w danych w komponencie. Znak musi być również zdefiniowany jako separator w składni ogólnej lub specyficznej dla schematu, a wygląd znaku musi znajdować się w danych.
Obecnym standardem dla ogólnych identyfikatorów URI jest RFC 3986 , który ma to do powiedzenia:
W związku z tym przecinki są wyraźnie dozwolone w ciągach zapytań i należy je stosować w danych tylko wtedy, gdy określone schematy definiują je jako separator. Schemat HTTP nie używa przecinka ani średnika jako separatora w ciągach zapytań, więc nie trzeba ich używać. To, czy przeglądarki przestrzegają tego standardu, to inna sprawa.
Używanie CSV powinno działać dobrze w przypadku danych ciągów, wystarczy przestrzegać standardowych konwencji CSV i albo cytować dane, albo wstawiać przecinki z ukośnikami odwrotnymi.
Jeśli chodzi o RFC 2396, zezwala również na stosowanie przecinków bez znaku zmiany znaczenia w ciągach zapytań HTTP:
Ponieważ przecinki nie mają zarezerwowanego celu w schemacie HTTP, nie muszą być używane w danych. Uwaga z § 2.3 o zastrzeżonych znakach to te, które zmieniają semantykę, gdy kodowane procentowo mają zastosowanie tylko ogólnie; znaki mogą być kodowane procentowo bez zmiany semantyki dla określonych schematów, a mimo to nadal mogą być zastrzeżone.
źródło
Aby odpowiedzieć na pytanie, co jest prawidłowe w ciągu zapytania, sprawdziłem, które znaki specjalne są zastępowane przez chrome podczas wysyłania żądania:
Uwaga: prawdopodobnie nie oznacza to, że nie powinieneś zmieniać znaczenia znaków, które nie zostały zastąpione podczas generowania identyfikatorów URI dla linków. Na przykład często zaleca się, aby nie używać
~
w identyfikatorach URI z powodu problemów ze zgodnością, ale nadal jest to prawidłowy znak.Innym przykładem może być znak plus, który jest prawidłowy, ale zwykle traktowany jako zakodowany pusty, gdy serwer odbiera go jako część żądania. Dlatego powinien być zakodowany, nawet jeśli jest ważny, gdy jego celem jest reprezentowanie plusa, a nie spacji.
Tak więc, aby odpowiedzieć, co powinno być zakodowane: nieprawidłowe znaki i znaki, które chcesz traktować dosłownie, ale mają specjalne znaczenie lub mogą powodować problemy po stronie serwera.
źródło
/programming/2366260/whats-valid-and-whats-not-in-a-uri-query?param=b#1;c#2
jest prawidłowym parametrem zapytania?#
nie może pojawić się wewnątrz części zapytania identyfikatora URI w obecnej postaci. Będziesz musiał zakodować go jako%23
, więc powinien być URI/programming/2366260/whats-valid-and-whats-not-in-a-uri-query?param=b%231;c%232
.Po prostu użyj
?q=1+2+3
Odpowiadam tutaj na czwarte pytanie :) które nie pytałem ale wszystko zaczęło się od: jak przekazać listę liczb a-la wartości rozdzielane przecinkami? Wydaje mi się, że najlepszym podejściem jest po prostu podanie ich rozdzielonych spacjami, gdzie spacje zostaną zakodowane w postaci adresu URL
+
. Działa świetnie, o ile wiesz, że wartości na liście nie zawierają spacji (coś, czego nie mają liczby).źródło
+
ma jeszcze większy sens w tym konkretnym przypadku, gdy szukałem przecinka.Tak.
;
Jest zarezerwowany, ale nie przez RFC. Kontekstem definiującym ten komponent jest definicjaapplication/x-www-form-urlencoded
typu mediów, która jest częścią standardu HTML (sekcja 17.13.4.1 ). W szczególności podstępna notatka ukryta w sekcji B.2.2 :Niestety wiele popularnych struktur skryptów po stronie serwera, w tym ASP.NET, nie obsługuje tego zastosowania.
źródło
?q=1;q=2;q=3
zapytanie jest poprawne, jest niejednoznaczne: niektóre frameworki po stronie serwera odczytują je w znaczeniu{ q: '1;q=2;q=3' }
, inne mogą to robić podobnie{ q: {'1', '2', '3'}}
.;
, co oznacza, że HTML4 i HTML5 są niespójne. Ugh, niebezpieczeństwa nienormatywnego języka w dokumencie specyfikacji ...{ q: 3 }
Chciałbym zauważyć, że
page.html?q=1&q=2&q=3
jest to również prawidłowy adres URL. Jest to całkowicie uzasadniony sposób wyrażania tablicy w ciągu zapytania. Technologia Twojego serwera określi, jak dokładnie to zostanie przedstawione.W klasycznym ASP sprawdzasz,
Response.QueryString("q").Count
a następnie używaszResponse.QueryString("q")(0)
(i (1) i (2)).Zauważ, że widziałeś to również w swoim ASP.NET (myślę, że nie było to zamierzone, ale spójrz):
Zauważ, że średnik jest ignorowany, więc tak
a
zdefiniowałeś dwa razy i otrzymałeś jego wartość dwukrotnie, oddzieloną przecinkiem. Użycie wszystkich znaków ampersandówDefault.aspx?a=1&a=2&b=1&a=3
da w wynikua
„1,2,3”. Ale jestem pewien, że istnieje metoda uzyskania każdego pojedynczego elementu, na wypadek, gdyby same elementy zawierały przecinki. Jest to po prostu domyślna właściwość nieindeksowanego QueryString, która łączy wartości podrzędne razem z separatorami przecinkowymi.źródło
Miałem ten sam problem. Adres URL, do którego nastąpiło hiperłącze, był adresem URL firmy zewnętrznej i oczekiwał listy parametrów
page.html?q=1,2,3
TYLKO w formacie oraz adresu URLpage.html?q=1%2C2%2C3
nie działał. Udało mi się to uruchomić za pomocą javascript. Może nie jest to najlepsze podejście, ale może sprawdzić tutaj rozwiązanie , jeśli komukolwiek pomoże.źródło
Jeśli wysyłasz ZAKODOWANE znaki do pliku FLASH / SWF , powinieneś KODOWAĆ znak dwukrotnie !! (z powodu parsera Flash)
źródło