16

http://localhost:9000/space testURL を Web ブラウザーのアドレス バーに入力すると、サーバーが呼び出されますhttp://localhost:9000/space%20testhttp://localhost:9000/specÁÉÍtestにもエンコードされhttp://localhost:9000/spec%C3%81%C3%89%C3%8Dtestます。

エンコードされた URL をアドレス バーに配置した場合 (つまりhttp://localhost:9000/space%20testhttp://localhost:9000/spec%C3%81%C3%89%C3%8Dtest)、それらは同じままです (二重にエンコードされることはありません)。

このエンコーディングを行う Java API またはライブラリはありますか? URL はユーザーからのものであるため、エンコードされているかどうかはわかりません。

(入力文字列を検索し、見つからない場合はエンコードするだけで十分ではないか%、またはこれが機能しない特別なケースはありますか?)

編集:

URLEncoder.encode("space%20test", "UTF-8")二重にエンコードspace%2520testされているため、これは私が望むものではありません。

編集2:

さらに、ブラウザは、 などhttp://localhost:9000/specÁÉ%C3%8Dtestの部分的にエンコードされた URL を二重エンコードせずに処理します。この場合、サーバーは次の URL を受け取ります: http://localhost:9000/spec%C3%81%C3%89%C3%8Dtest. のエンコード形式と同じです...specÁÉÍtest

4

5 に答える 5

12

すべての Web 開発者が URL エンコーディングについて知っておくべきこと

URL エンコーディングの説明

なぜ URL エンコーディングが必要なのですか?

The URL specification RFC 1738 specifies that only a small set of characters 
can be used in a URL. Those characters are:

A to Z (ABCDEFGHIJKLMNOPQRSTUVWXYZ)
a to z (abcdefghijklmnopqrstuvwxyz)
0 to 9 (0123456789)
$ (Dollar Sign)
- (Hyphen / Dash)
_ (Underscore)
. (Period)
+ (Plus sign)
! (Exclamation / Bang)
* (Asterisk / Star)
' (Single Quote)
( (Open Bracket)
) (Closing Bracket)

URL エンコーディングはどのように機能しますか?

All offending characters are replaced by a % and a two digit hexadecimal value 
that represents the character in the proper ISO character set. Here are a 
couple of examples:

$ (Dollar Sign) becomes %24
& (Ampersand) becomes %26
+ (Plus) becomes %2B
, (Comma) becomes %2C
: (Colon) becomes %3A
; (Semi-Colon) becomes %3B
= (Equals) becomes %3D
? (Question Mark) becomes %3F
@ (Commercial A / At) becomes %40

簡単な例:

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class TextHelper {
    private static ScriptEngine engine = new ScriptEngineManager()
        .getEngineByName("JavaScript");

/**
 * Encoding if need escaping %$&+,/:;=?@<>#%
 *
 * @param str should be encoded
 * @return encoded Result 
 */
public static String escapeJavascript(String str) {
    try {
        return engine.eval(String.format("escape(\"%s\")", 
            str.replaceAll("%20", " "))).toString()
                .replaceAll("%3A", ":")
                .replaceAll("%2F", "/")
                .replaceAll("%3B", ";")
                .replaceAll("%40", "@")
                .replaceAll("%3C", "<")
                .replaceAll("%3E", ">")
                .replaceAll("%3D", "=")
                .replaceAll("%26", "&")
                .replaceAll("%25", "%")
                .replaceAll("%24", "$")
                .replaceAll("%23", "#")
                .replaceAll("%2B", "+")
                .replaceAll("%2C", ",")
                .replaceAll("%3F", "?");
    } catch (ScriptException ex) {
        Logger.getLogger(TextHelper.class.getName())
            .log(Level.SEVERE, null, ex);
        return null;
    }
}
于 2013-08-21T16:28:46.567 に答える
8

Java を使用しますjava.net.URLEncoder#encode()

String page = "space test";
String ecodedURL = "http://localhost:9000/" + URLEncoder.encode(page, "UTF-8");

注: 完全な URL をエンコードすると、望ましくない状況が発生します。たとえばhttp://http%3A%2F%2F!

編集: URL を 2 回エンコードしないようにするには、URL に a が含まれているかどうかを確認します%。これは、エンコードに対してのみ有効です。しかし、ユーザーがエンコーディングを誤って台無しにした場合 (URL を部分的にのみエンコードしたり、%何かをエンコードするために使用せずに URL で a を使用したりするなど)、この方法を使用して行うことはあまりありません...

于 2013-01-16T12:03:53.900 に答える
4

最後に、Firefox と Chrome の動作を確認しました。両方のブラウザーで次の URL を使用し、netcat ( nc -l -p 9000)で HTTP 要求をキャプチャします。

http://localhost:9000/!"$%&'()*+,-./:;<=>?@[\]^_`{|}~

この URL には、 を除く ASCII 32 から 127 までのすべての文字が含まれています[0-9A-Za-z#]

キャプチャされたリクエストは、Firefox 18.0.1 では次のとおりです。

GET /!%22$%&%27()*+,-./:;%3C=%3E?@[\]^_%60{|}~%7F HTTP/1.1

クロムの場合:

GET /!%22$%&'()*+,-./:;%3C=%3E?@[\]^_`{|}~%7F HTTP/1.1

Firefox は Chrome より多くの文字をエンコードします。ここに表があります:

Char | Hex    | Dec     | Encoded by
-----------------------------------------
"    | %22    | 34      | Firefox, Chrome
'    | %27    | 39      | Firefox
<    | %3C    | 60      | Firefox, Chrome
>    | %3E    | 62      | Firefox, Chrome
`    | %60    | 96      | Firefox
     | %7F    | 127     | Firefox, Chrome

ソースツリーで似たようなことをするコードをいくつか見つけましたが、これらが実際に使用されているアルゴリズムであるかどうかはよくわかりません:

とにかく、ここに Java の概念実証コードがあります。

// does not handle "#"
public static String encode(final String input) {
    final StringBuilder result = new StringBuilder();
    for (final char c: input.toCharArray()) {
        if (shouldEncode(c)) {
            result.append(encodeChar(c));
        } else {
            result.append(c);
        }
    }
    return result.toString();
}

private static String encodeChar(final char c) {
    if (c == ' ') {
        return "%20"; // URLEncode.encode returns "+"
    }
    try {
        return URLEncoder.encode(String.valueOf(c), "UTF-8");
    } catch (final UnsupportedEncodingException e) {
        throw new IllegalStateException(e);
    }
}

private static boolean shouldEncode(final char c) {
    if (c <= 32 || c >= 127) {
        return true;
    }
    if (c == '"' || c == '<' || c == '>') {
        return true;
    }
    return false;
}

を使用しているため、文字だけでなくASCII文字もURLEncoder.encode扱います。ÁÉÍ

于 2013-11-03T15:53:11.647 に答える
2

これは Scala コード スニペットです。このエンコーダーは、URL 内の非 ASCII 文字と予約文字をエンコードします。また、操作はべき等であるため、URL は二重にエンコードされません。

import java.net.URL
import scala.util.parsing.combinator.RegexParsers

object IdempotentURLEncoder extends RegexParsers {
  override def skipWhitespace = false
  private def segment = rep(char)
  private def char = unreserved | escape | any ^^ { java.net.URLEncoder.encode(_, "UTF-8") }
  private def unreserved = """[A-Za-z0-9._~!$&'()*+,;=:@-]""".r
  private def escape = """%[A-Fa-f0-9]{2}""".r
  private def any = """.""".r
  private def encodeSegment(input: String): String = parseAll(segment, input).get.mkString
  private def encodeSearch(input: String): String = encodeSegment(input)
  def encode(url: String): String = {
    val u = new URL(url)
    val path = u.getPath.split("/").map(encodeSegment).mkString("/")
    val query = u.getQuery match {
      case null      => ""
      case q: String => "?" + encodeSearch(q)
    }
    val hash = u.getRef match {
      case null      => ""
      case h: String => "#" + encodeSegment(h)
    }
    s"${u.getProtocol}://${u.getAuthority}$path$query$hash"
  }
}

使用例(テストコード)

import org.scalatest.{ FunSuite, Matchers }

class IdempotentURLEncoderSpec extends FunSuite with Matchers {
  import IdempotentURLEncoder._

  test("Idempotent operation") {
    val url = "http://ja.wikipedia.org/wiki/文字"
    assert(encode(url) == encode(encode(url)))
    assert(encode(url) == encode(encode(encode(url))))
  }

  test("Segment encoding") {
    encode("http://ja.wikipedia.org/wiki/文字")
      .shouldBe("http://ja.wikipedia.org/wiki/%E6%96%87%E5%AD%97")
  }

  test("Query string encoding") {
    encode("http://qiita.com/search?utf8=✓&amp;sort=rel&q=開発&sort=rel")
      .shouldBe("http://qiita.com/search?utf8=%E2%9C%93&sort=rel&q=%E9%96%8B%E7%99%BA&sort=rel")
  }

  test("Hash encoding") {
    encode("https://www.google.co.jp/#q=文字")
      .shouldBe("https://www.google.co.jp/#q=文字")
  }

  test("Partial encoding") {
    encode("http://en.wiktionary.org/wiki/français")
      .shouldBe("http://en.wiktionary.org/wiki/fran%C3%A7ais")
  }

  test("Space is encoded as +") {
    encode("http://example.com/foo bar buz")
      .shouldBe("http://example.com/foo+bar+buz")
  }

  test("Multibyte domain names are not supported yet :(") {
    encode("http://日本語.jp")
      .shouldBe("http://日本語.jp")
  }
}

このコードはQiita のものです。

于 2014-12-25T03:00:20.907 に答える
-1

標準の Java API 自体が URL のエンコードとデコードを行います。

java.net.URI

クラスURLDecoderを試して、URLEncoder

インターネットを安全に通過できるようにテキストをエンコードするには:

import java.net.*;
...
try {
    encodedValue= URLEncoder.encode(rawValue, "UTF-8");
} catch (UnsupportedEncodingException uee) { }

そしてデコードするには:

try {
    decodedValue = URLDecoder.decode(rawValue, "UTF-8");
} catch (UnsupportedEncodingException uee) { }
于 2013-01-16T12:03:28.580 に答える