IT story

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

hot-time 2020. 4. 30. 07:36
반응형

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을 이해하지 못하는 프록시를 사용하도록 구성되었습니다.
  • 클라이언트는 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");

편집하다:

Okay, since that is not the problem, one way to tackle this is to use something like Fiddler or Wireshark to watch what is being sent to the web server from the browser successfully, then compare that to what is being sent from your code. If you are going to a normal port 80 from .Net, Fiddler will still capture this traffic.

There is probably some other hidden field on the form that the web server is expecting that you are not sending.


Solution from proxy side, I faced some problems in the SSL handshake process and I had to force my proxy server to send requests using HTTP/1.0 to solve the problem by setting this argument in the httpd.conf SetEnv force-proxy-request-1.0 1 SetEnv proxy-nokeepalive 1 after that I faced the 417 error as my clients application was using HTTP/1.1 and the proxy was forced to use HTTP/1.0, the problem was solved by setting this parameter in the httpd.conf on the proxy side RequestHeader unset Expect early without the need to change anything in the client side, hope this helps.


For Powershell it is

[System.Net.ServicePointManager]::Expect100Continue = $false

If you are using "HttpClient", and you don't want to use global configuration to affect all you program you can use:

 HttpClientHandler httpClientHandler = new HttpClientHandler();
 httpClient.DefaultRequestHeaders.ExpectContinue = false;

I you are using "WebClient" I think you can try to remove this header by calling:

 var client = new WebClient();
 client.Headers.Remove(HttpRequestHeader.Expect);

In my situation, this error seems to occur only if my client's computer has a strict firewall policy, which prevents my program from communicating with the web service.

So only solution I could find is to catch the error and inform user about changing the firewall settings manually.


The web.config approach works for InfoPath form services calls to IntApp web service enabled rules.

  <system.net>
    <defaultProxy />
    <settings> <!-- 20130323 bchauvin -->
        <servicePointManager expect100Continue="false" />
    </settings>
  </system.net>

참고URL : https://stackoverflow.com/questions/566437/http-post-returns-error-417-expectation-failed

반응형