[C#] HTTP POST가 오류 : 417“예상 실패”를 반환합니다.

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 프록시 나던 이해하는 것이 무엇인가 보내는 최대 클라이언트 종료 ExpectHTTP를의 일환으로 헤더 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);