URL에 POST를 시도하면 다음 예외가 발생합니다.
원격 서버가 오류를 반환했습니다 : (417) 예상 실패.
샘플 코드는 다음과 같습니다.
var client = new WebClient();
var postData = new NameValueCollection();
postData.Add("postParamName", "postParamValue");
byte[] responseBytes = client.UploadValues("http://...", postData);
string response = Encoding.UTF8.GetString(responseBytes); // (417) Expectation Failed.
HttpWebRequest/HttpWebResponse
쌍을 사용 하거나 HttpClient
차이를 만들지 않습니다.
이 예외의 원인은 무엇입니까?
답변
이 정적 속성 을 false 로 설정하여 명시 적으로 요청하지 않는 한 System.Net.HttpWebRequest는 ‘HTTP 헤더 “예상 : 100- 계속”‘헤더를 모든 요청에 추가합니다 .
System.Net.ServicePointManager.Expect100Continue = false;
일부 서버는 해당 헤더를 질식시키고 현재보고있는 417 오류를 다시 보냅니다.
그 기회를 줘.
답변
또 다른 방법 –
다음 행을 애플리케이션 구성 파일 구성 섹션에 추가하십시오.
<system.net>
<settings>
<servicePointManager expect100Continue="false" />
</settings>
</system.net>
답변
런타임시 다음과 같은 상황 및 오류가 기본 마법사에서 생성 된 SOAP 웹 서비스 프록시 (WCF System.ServiceModel
스택 의 경우 100 %가 아님)에서도 발생할 수 있습니다 .
- 최종 사용자 컴퓨터가 인터넷 설정에서 HTTP 1.1을 이해하지 못하는 프록시를 사용하도록 구성되었습니다.
- (일반적으로는 A HTTP 1.0 프록시 나던 이해하는 것이 무엇인가 보내는 최대 클라이언트 종료
Expect
HTTP를의 일환으로 헤더POST
또는PUT
인해 두 부분으로 요청을 전송하는 표준 프로토콜 규칙에 요청 비고에 덮여 여기에 )
… 417을 산출합니다.
다른 답변에서 다루었 듯이, 특정 문제가 Expect
헤더로 인해 문제가 발생하는 것이라면을 통해 두 부분으로 구성된 PUT / POST 전송의 상대적으로 전역 전환하여 특정 문제를 해결할 수 있습니다 System.Net.ServicePointManager.Expect100Continue
.
그러나 이것은 완전한 근본적인 문제를 해결하지는 않습니다. 스택은 여전히 KeepAlives 등과 같은 HTTP 1.1 관련 사항을 사용하고있을 수 있습니다 (많은 경우에 다른 답변이 주요 사례를 다루지 만).
그러나 실제 문제는 자동 생성 코드는 모든 사람들이 이것을 이해하면서 HTTP 1.1 기능을 맹목적으로 사용하는 것이 좋다고 가정한다는 것입니다. 특정 웹 서비스 프록시에 대해이 가정을 중지하기 위해이 게시물에 표시된대로 대체되는 파생 프록시 클래스를 작성 HttpWebRequest.ProtocolVersion
하여 기본 1.1 에서 기본 기본 대체를 변경할 수 있습니다 .protected override WebRequest GetWebRequest(Uri uri)
public class MyNotAssumingHttp11ProxiesAndServersProxy : MyWS
{
protected override WebRequest GetWebRequest(Uri uri)
{
HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(uri);
request.ProtocolVersion = HttpVersion.Version10;
return request;
}
}
( MyWS
웹 참조 추가 마법사가 표시되는 프록시가 있습니다.)
업데이트 : 프로덕션에서 사용하는 impl이 있습니다.
class ProxyFriendlyXXXWs : BasicHttpBinding_IXXX
{
public ProxyFriendlyXXXWs( Uri destination )
{
Url = destination.ToString();
this.IfProxiedUrlAddProxyOverriddenWithDefaultCredentials();
}
// Make it squirm through proxies that don't understand (or are misconfigured) to only understand HTTP 1.0 without yielding HTTP 417s
protected override WebRequest GetWebRequest( Uri uri )
{
var request = (HttpWebRequest)base.GetWebRequest( uri );
request.ProtocolVersion = HttpVersion.Version10;
return request;
}
}
static class SoapHttpClientProtocolRealWorldProxyTraversalExtensions
{
// OOTB, .NET 1-4 do not submit credentials to proxies.
// This avoids having to document how to 'just override a setting on your default proxy in your app.config' (or machine.config!)
public static void IfProxiedUrlAddProxyOverriddenWithDefaultCredentials( this SoapHttpClientProtocol that )
{
Uri destination = new Uri( that.Url );
Uri proxiedAddress = WebRequest.DefaultWebProxy.GetProxy( destination );
if ( !destination.Equals( proxiedAddress ) )
that.Proxy = new WebProxy( proxiedAddress ) { UseDefaultCredentials = true };
}
}
답변
에뮬레이션하려는 양식에 사용자 이름과 비밀번호라는 두 개의 필드가 있습니까?
그렇다면이 줄 :
postData.Add("username", "password");
정확하지 않습니다.
다음과 같은 두 줄이 필요합니다.
postData.Add("username", "Moose");
postData.Add("password", "NotMoosespasswordreally");
편집하다:
자, 이것이 문제가 아니기 때문에 이것을 해결하는 한 가지 방법은 Fiddler 또는 Wireshark와 같은 것을 사용하여 브라우저에서 웹 서버로 전송되는 것을보고 코드에서 전송 된 것과 비교하는 것입니다. .Net에서 일반 포트 80으로 이동하는 경우 Fiddler는 여전히이 트래픽을 캡처합니다.
웹 서버가 보내지 않을 것으로 예상되는 양식에 다른 숨겨진 필드가있을 수 있습니다.
답변
프록시 측의 해결책으로 SSL 핸드 셰이크 프로세스에서 몇 가지 문제에 직면했으며 프록시 서버가 HTTP / 1.0을 사용하여 요청을 보내서 문제를 해결하기 위해 httpd.conf 에서이 인수를 설정 SetEnv force-proxy-request-1.0 1
SetEnv proxy-nokeepalive 1
하여 417 오류에 직면 한 후 내 클라이언트 응용 프로그램이 HTTP / 1.1을 사용하고 프록시가 HTTP / 1.0을 사용하도록 강요 RequestHeader unset Expect early
했지만 클라이언트 측에서 아무것도 변경할 필요없이 프록시 측의 httpd.conf 에서이 매개 변수를 설정하여 문제가 해결되었습니다. .
답변
Powershell의 경우
[System.Net.ServicePointManager]::Expect100Continue = $false
답변
” HttpClient “를 사용 중이고 전역 구성을 사용하여 모든 프로그램에 영향을 미치지 않으려면 다음을 사용할 수 있습니다.
HttpClientHandler httpClientHandler = new HttpClientHandler();
httpClient.DefaultRequestHeaders.ExpectContinue = false;
” WebClient “를 사용하고 있습니다. 다음을 호출하여이 헤더를 제거 할 수 있다고 생각합니다.
var client = new WebClient();
client.Headers.Remove(HttpRequestHeader.Expect);