2010-12-07 4 views
3

나는이 제목과 같은 제목 소리가 여러 번 언급되었습니다 알고 있습니다. 그러나 나는 특정한 경우에 고투하고 있으며, 나는 그것에 대해 매우 혼란 스럽다. 바라건대 노련한 C# '어쩌면 올바른 방향으로 나를 가리킬 수 있습니다.HttpWebRequest URL escapeing

RequestUri: {https://www.domain.com/service/tables/bucketname/tables/testtable/imports} 

그리고는 HttpWebRequest를 보이는이 두 %2F/ 변경되었습니다 : 나는 dataRequest을 간략한 때

string serviceURL = "https://www.domain.com/service/tables/bucketname%2Ftables%2Ftesttable/imports"; 
HttpWebRequest dataRequest = (HttpWebRequest)WebRequest.Create(serviceURL); 

지금, 내가 볼 :

나는 코드가 있습니다. 그러나 서버 은 요청한 URI가 을 포함하여 serviceURL이 쓰여진 것과 정확히 일치하도록이 필요합니다.

https://www.domain.com/service/tables/bucketname%2Ftables%2Ftesttable/imports 

많은 감사 :

URL을 호출 HttpWebRequest 클래스를 얻을 수있는 방법이 있습니까! 나는 그래서 공식 만들기 위해 -Brett

+0

체크 아웃이 질문, 답변에 해결 방법이있다 : http://stackoverflow.com/questions/781205/c-net-getting-a-url -with-an-url-encoded-slash –

+0

물론 그랬다. 여전히 동일합니다 : RequestUri : {https://www.domain.com/service/tables/bucketname/tables/testtable/imports} – Brett

+0

@ 카일, 감사합니다. 하지만 꽤 쉰 것처럼 보입니다. 더 좋은 방법이 있어야하는 것처럼 보입니다. PHP는이 문제를 처리합니다. – Brett

답변

-1
string serviceURL = Uri.EscapeUriString("https://www.domain.com/service/tables/bucketname%2Ftables%2Ftesttable/imports"); 
+0

올바른 트랙처럼 보이지만 % 2F를 % 252F (이스케이프 비율)로 만듭니다. – Brett

0

% 2F가 "/"로 이스케이프 처리되지 않는 한 문제가있는 한 해결 방법이 있습니다. 하나는 해킹을 포함하고 app.config 설정 인 .Net의 최신 버전입니다. 여기를 확인하십시오 : How to make System.Uri not to unescape %2f (slash) in path?

그러나 나는 '('및 ')'(% 28 및 % 29)과 같은 일부 특수 문자를 이스케이프 처리하지 못하도록 차단하는 방법을 알아 냈습니다. Uri 클래스가 WebRequest에 대해 부분적으로 이스케이프 처리되지 않은 경로를 제공하지 못하도록 막 다른 곳에서 발견 한 모든 설정 및 해킹을 시도했습니다. 이 솔루션은 이스케이프 처리되지 않은 % 2F가 행복하게 방지되지만 % 28 및 % 29는 사용할 수 없으며 대부분의 다른 문자는 특별히 이스케이프 처리됩니다.

WebRequest가 "Get/path HTTP/1.1"구문을 생성하기 위해 Uri 객체의 1 값을 요구하는 것처럼 보입니다. 다시 UriParser.GetComponents를 호출하는 Uri.PathAndQuery.

mediafire에서 다운로드하려면 % 28 및 % 29 문자가 포함되어 있습니다. .Net은 % 28 및 % 29을 (를) '('및 ')'로 변경하고 무한 리디렉션 루프를 계속 유지합니다. 리디렉션 (예외 : "너무 많은 자동 리디렉션이 시도되었습니다")

이렇게 붙어서 일부 문자의 이스케이프 방지 방법을 찾을 수없는 사용자를위한 솔루션입니다.

이 문제를 해결하기 위해 (.Net 4.6을 사용하여) 재정의하고 내 자신의 PathAndQuery를 제공하는 유일한 방법은 UriParser를 상속하고 해킹하는 방법입니다.

public sealed class MyUriParser : System.UriParser 
{ 
    private UriParser _originalParser; 
    private MethodInfo _getComponentsMethod; 

    public MyUriParser(UriParser originalParser) : base() 
    { 
     if (_originalParser == null) 
     { 
      _originalParser = originalParser; 

      _getComponentsMethod = typeof(UriParser).GetMethod("GetComponents", BindingFlags.NonPublic | BindingFlags.Instance); 
      if (_getComponentsMethod == null) 
      { 
       throw new MissingMethodException("UriParser", "GetComponents"); 
      } 
     } 
    } 

    private static Regex rx = new Regex(@"^(?<Scheme>[^:]+):(?://((?<User>[^@/]+)@)?(?<Host>[^@:/?#]+)(:(?<Port>\d+))?)?(?<Path>([^?#]*)?)?(\?(?<Query>[^#]*))?(#(?<Fragment>.*))?$",RegexOptions.Compiled | RegexOptions.ExplicitCapture | RegexOptions.Singleline); 
    private Match m = null; 

    protected override string GetComponents(Uri uri, UriComponents components, UriFormat format) 
    { 
     var original = (string)_getComponentsMethod.Invoke(_originalParser, BindingFlags.InvokeMethod, null, new object[] { uri, components, format }, null); 
     if (components == UriComponents.PathAndQuery) 
     { 
      var reg = rx.Match(uri.OriginalString); 
      var path = reg.Groups["Path"]?.Value; 
      var query = reg.Groups["Query"]?.Value; 
      if (path != null && query != null) return $"{path}?{query}"; 
      if (query == null) return $"{path}"; 
      return $"{path}"; 
     } 

     return original; 
    } 

} 

그리고 UriParser를이 UriParser로 바꾸어서 Uri 인스턴스에 해킹합니다.때문에 UriParser가 작동하는 방식에

public static Uri CreateUri(string url) 
    { 
     var uri = new Uri(url); 
     if (url.Contains("%28") || url.Contains("%29")) 
     { 
      var originalParser = ReflectionHelper.GetValueByReflection(uri, "m_Syntax") as UriParser; 
      var parser = new MyUriParser(originalParser); 
      ReflectionHelper.SetValueByReflection(parser, "m_Scheme", "http"); 
      ReflectionHelper.SetValueByReflection(parser, "m_Port", 80); 
      ReflectionHelper.SetValueByReflection(uri, "m_Syntax", parser); 
     } 
     return uri; 
    } 

, 그것은 일반적으로 자사의 포트와 구성표 이름 집합을 등록 할 필요가 있으므로이 두 값은 우리가 그것을 올바른 방법을 등록하지 않는 한 반사에 의해 설정되어야한다. 이미 "http"를 등록하는 방법을 찾지 못했습니다. ReflectionHelper는 내가 가지고있는 클래스 일 뿐이지 만 일반 리플렉션 코드로 신속하게 대체 될 수 있습니다.

는 다음과 같이 호출 :

HttpWebRequest dataRequest = (HttpWebRequest)WebRequest.Create(CreateUri(serviceURL));