% 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));
체크 아웃이 질문, 답변에 해결 방법이있다 : http://stackoverflow.com/questions/781205/c-net-getting-a-url -with-an-url-encoded-slash –
물론 그랬다. 여전히 동일합니다 : RequestUri : {https://www.domain.com/service/tables/bucketname/tables/testtable/imports} – Brett
@ 카일, 감사합니다. 하지만 꽤 쉰 것처럼 보입니다. 더 좋은 방법이 있어야하는 것처럼 보입니다. PHP는이 문제를 처리합니다. – Brett