Czy znak `+` w schemacie / hoście / ścieżce URL reprezentuje spację?

224

Wiem, że +ciąg zapytania w adresie URL reprezentuje spację. Czy tak jest również poza regionem ciągu zapytania? To znaczy, czy następujący adres URL:

http://a.com/a+b/c

faktycznie reprezentują:

http://a.com/a b/c

(a zatem należy je zakodować, jeśli powinno to być a +), czy też faktycznie reprezentuje a+b/c?

Francisco Ryan Tolmasky I
źródło
4
Zauważ, że w php urldecode dekoduje% 2b (zakodowany +) do spacji. Aby tego uniknąć rawurldecode. Mówię to tutaj w celach informacyjnych, ponieważ jest to wysoko oceniany wynik w wyszukiwaniu w Google „php url dekoduje przerwy na znak plus”.
danielson317
1
Możliwy duplikat Kiedy kodować spację na plus (+) lub% 20?
użytkownik

Odpowiedzi:

170
  • Oczekuje się, że kodowanie procentowe w sekcji ścieżki adresu URL zostanie zdekodowane, ale
  • wszelkie +znaki w komponencie ścieżki powinny być traktowane dosłownie.

Mówiąc wprost: +jest tylko znakiem specjalnym w komponencie zapytania.

Stobor
źródło
12
+1 Niestety, wiele „koderów / koderów URL” na wolności nie rozumie tego. Np. Sislands.com/coin70/week6/encoder.htm keyone.co.uk/tools-url-encoder.asp meyerweb.com/eric/tools/dencoder
leonbloy
11
@Stobor: potrzebne cytowanie.
bukzor
8
@Stobor Czy RFC kiedykolwiek stwierdził, że +znak jest interpretowany jako spacja w elemencie zapytania? Czy jest to po prostu zasada „z dziczy”?
Pacerier
44
@Pacerier i @bukzor: RFC 1738 (zmodyfikowany przez 2396 i 3986) definiuje komponent schemat ( http:), uprawnienie ( //server.example.com) i ścieżkę ( /myfile/mypage.htm) i nie definiuje żadnego specjalnego znaczenia dla +znaku. Specyfikacja HTML definiuje komponent zapytania jako mime type application / x-www-form-urlencoded, który jest zdefiniowany jako „zamień spacje +i inne znaki specjalne jak w RFC1738”. Więc nie jest to „z natury”, ale z przyjętego (nie RFC) standardu.
Stobor
2
Metoda .NET Server.UrlEncodebłędnie koduje spacje jako plusy również w części ścieżki, co narusza reguły HTTP.
Suncat2000
243

Możesz znaleźć ładną listę odpowiednich znaków zakodowanych w URL na W3Schools .

  • + staje się %2B
  • przestrzeń staje się %20
Niels R.
źródło
18
Zupełnie legalne jest, aby dosłowne znaki „+” pojawiały się w elemencie ścieżki w adresie URL.
Sam Stainsby
4
Aby uzyskać dosłowny znak +, który ma być odbierany przez zaplecze (lub przynajmniej PHP), musi być potrójnie zakodowany:%25252B
Parasol
11
Ta odpowiedź jest całkowicie nieistotna dla pytania.
Nisse Engström
22

Znaki spacji mogą być kodowane jako „+” tylko w jednym kontekście: pary klucz-wartość application / x-www-form-urlencoded.

RFC-1866 (specyfikacja HTML 2.0), pkt 8.2.1. akapit pierwszy mówi: „Nazwy i wartości pól formularza są znakami ucieczki: znaki spacji są zastępowane przez„ + ”, a następnie znaki specjalne są zastępowane”).

Oto przykład takiego ciągu w adresie URL, w którym RFC-1866 zezwala na kodowanie spacji jako plusów: „ http://example.com/over/there?name=foo+bar ”. Tak więc, tylko po znaku „?” Spacje można zastąpić plusami (w innych przypadkach spacje należy zakodować na% 20). Ten sposób kodowania danych formularza jest również podany w późniejszych specyfikacjach HTML, na przykład poszukaj odpowiednich akapitów na temat application / x-www-form-urlencoded w specyfikacji HTML 4.01 i tak dalej.

Ponieważ jednak trudno jest zawsze poprawnie określić kontekst, najlepszą praktyką jest, aby nigdy nie kodować spacji jako „+”. Lepiej jest kodować procentowo wszystkie znaki oprócz „niezarezerwowanych” zdefiniowanych w RFC-3986, str. 2.3. Oto przykład kodu ilustrujący, co należy zakodować. Jest podawany w języku programowania Delphi (pascal), ale bardzo łatwo jest zrozumieć, jak działa dla każdego programisty, niezależnie od posiadanego języka:

(* percent-encode all unreserved characters as defined in RFC-3986, p.2.3 *)
function UrlEncodeRfcA(const S: AnsiString): AnsiString;
const    
  HexCharArrA: array [0..15] of AnsiChar = '0123456789ABCDEF';
var
  I: Integer;
  c: AnsiChar;
begin
 // percent-encoding, see RFC-3986, p. 2.1
  Result := S;
  for I := Length(S) downto 1 do
  begin
    c := S[I];
    case c of
      'A' .. 'Z', 'a' .. 'z', // alpha
      '0' .. '9',             // digit
      '-', '.', '_', '~':;    // rest of unreserved characters as defined in the RFC-3986, p.2.3
      else
        begin
          Result[I] := '%';
          Insert('00', Result, I + 1);
          Result[I + 1] := HexCharArrA[(Byte(C) shr 4) and $F)];
          Result[I + 2] := HexCharArrA[Byte(C) and $F];
        end;
    end;
  end;
end;

function UrlEncodeRfcW(const S: UnicodeString): AnsiString;
begin
  Result := UrlEncodeRfcA(Utf8Encode(S));
end;
Maxim Masiutin
źródło
0

użyj funkcji encodeURIComponent do naprawy adresu URL, działa na przeglądarce i node.js

res.redirect("/signin?email="+encodeURIComponent("[email protected]"));


> encodeURIComponent("http://a.com/a+b/c")
'http%3A%2F%2Fa.com%2Fa%2Bb%2Fc'
Baryon Lee
źródło
1
To nie dotyczy pytania. Niepoprawnie koduje adresy URL za pomocą określonego języka (JavaScript) - w zależności od kontekstu prawdopodobnie nie chcesz kodować tam, gdzie potrzebujesz specjalnych (nie dosłownych) ukośników (/) i dwukropków (:), aby URL działał .
Gremio,
Dzięki, naprawdę mi pomogło!
qwsd
-2

Spróbuj poniżej:

<script type="text/javascript">

function resetPassword() {
   url: "submitForgotPassword.html?email="+fixEscape(Stringwith+char);
}
function fixEscape(str)
{
    return escape(str).replace( "+", "%2B" );
}
</script>
Facet z Jawy
źródło
2
To dziwne, że dwie osoby głosowały na tę odpowiedź. Dosłownie nie ma to nic wspólnego z pytaniem.
Andrew Barber,
1
Co powiesz na inne znaki * @ - _ +. /
Ravi
1
@AndrewBarber Dlaczego uważasz, że to nie ma znaczenia? + zmienia się w% 2B
The Java Guy
Jest to błędne z wielu powodów ... escapejest przestarzałe, zamiast tego należy użyć encodeURIlub w przypadku części zapytania encodeURIComponent. Również łańcuch parametrów powinien kodować zgodnie z w3c .
Christoph
-5

Zawsze będziesz kodować adresy URL.

Oto jak Ruby koduje twój adres URL:

irb(main):008:0> CGI.escape "a.com/a+b"
=> "a.com%2Fa%2Bb"
Lennart Koopmann
źródło
8
Nie jestem pewien, czy to prawda. Zgodnie z RFC2396 ( ietf.org/rfc/rfc2396.txt ) plusy nie są znakami zastrzeżonymi w ścieżce (segmentach) identyfikatora URI, tylko komponent zapytania. Wydaje się to sugerować, że nie muszą być one zakodowane w adresie URL, a zatem nie powinny być interpretowane jako spacje na ścieżce, tylko w zapytaniu.
tlrobinson
3
rfc 1738 traktuje plusy jak spacje. Wszystko zależy od tego, co jest realizowane przez funkcje kodowania / dekodowania. na przykład w php rawurlencode następuje po rfc 1738, a urlencode po rfc 2396.
Jonathan Fingland
1
Widzisz, teraz mam dodatkowe zamieszanie. W podanym powyżej przykładzie a.com% 2Fa% 2Bb nie jest tym, czego chcę, a przynajmniej będzie to a.com/a%2Bb. To jest rzeczywisty adres URL, z którym mam do czynienia, a nie adres URL przekazywany jako parametr w ciągu zapytania. Dla małego tła, które może pomóc wyjaśnić, Wyszukiwarka Mac OS X zwraca mi adresy URL systemów plików. Więc jeśli mam plik o nazwie „a? + B.txt”, zwraca coś, co wygląda jak „plik: //a%3F+b.txt”, NIE „plik: //a%3F%2B.txt” . Czy wyszukiwarka jest po prostu niepoprawna, czy też + przed ciągiem zapytania faktycznie jest plusem?
Francisco Ryan Tolmasky I
2
Jonathan: Czy jesteś pewien, że 1738 mówi, że + jest zastrzeżone? Widzę: safe = "$" | „-” | „_” | „.” | „+” bez zastrzeżeń = alfa | cyfra | bezpieczne | dodatkowo, a także: Zatem tylko znaki alfanumeryczne, znaki specjalne „$ -_. +! * '(),” oraz znaki zastrzeżone używane do ich zarezerwowanych celów mogą być użyte w postaci niezakodowanej w adresie URL.
tlrobinson
2
„Zawsze będziesz uciekać” wymaga więcej kwalifikacji, a odpowiedź i tak nie ma znaczenia.
błąd