System.Net.WebRequest를 사용할 때 일부 HTTP 헤더를 설정할 수 없습니다 값을 추가하려고 시도 했지만 여전히

WebRequest객체 에 HTTP 헤더 키 / 값 쌍을 추가하려고 하면 다음 예외가 발생합니다.

이 헤더는 적절한 속성을 사용하여 수정해야합니다

HeadersAdd () 메서드를 사용하여 컬렉션에 새 값을 추가하려고 시도 했지만 여전히 동일한 예외가 발생합니다.

webRequest.Headers.Add(HttpRequestHeader.Referer, "http://stackoverflow.com");

WebRequest 객체를 HttpWebRequest로 캐스팅하고과 같은 속성을 설정 하여이 문제를 해결할 수 httpWebReq.Referer ="http://stackoverflow.com"있지만 속성을 통해 노출되는 소수의 헤더에서만 작동합니다.

원격 리소스에 대한 요청으로 헤더 수정을보다 세밀하게 제어 할 수있는 방법이 있는지 알고 싶습니다.



답변

짧은 기술 답변이 필요한 경우 답변의 마지막 섹션으로 바로 이동하십시오.

더 잘 알고 싶다면 모두 읽으십시오.


나는 오늘도이 문제에 대응했으며 오늘 내가 발견 한 것은 다음과 같습니다.

  1. 위의 답변은 다음과 같습니다.

    1.1 추가하려는 헤더가 이미 존재한다는 것을 알려주므로 다시 추가하지 않고 적절한 속성 (예 : 인덱서)을 사용하여 값을 수정해야합니다.

    1.2의 헤더를 변경할 때마다 HttpWebRequest객체 자체에 적절한 속성을 사용해야합니다 (있는 경우).

주요 지침에 대해 FOR와 Jvenema에게 감사드립니다 …

  1. 그러나 내가 찾은 것은 퍼즐에서 누락 된 부분 입니다.

    2.1 WebHeaderCollection클래스는 일반적으로 WebRequest.Headers 또는 WebResponse.Headers를 통해 액세스합니다 . 일부 공통 헤더는 제한적인 것으로 간주되며 API (예 : Content-Type)에 의해 직접 노출되거나 시스템에 의해 보호되며 변경할 수 없습니다.

제한된 헤더는 다음과 같습니다.

  • Accept
  • Connection
  • Content-Length
  • Content-Type
  • Date
  • Expect
  • Host
  • If-Modified-Since
  • Range
  • Referer
  • Transfer-Encoding
  • User-Agent
  • Proxy-Connection

따라서 다음에이 예외에 직면 할 때이 문제를 해결하는 방법을 모를 경우 제한된 헤더가 있음을 기억하십시오. 해결책은 WebRequest/ HttpWebRequest클래스 에서 명시 적으로 적절한 속성을 사용하여 값을 수정하는 것 입니다.


편집 : (유용한 의견, 사용자 Kaido의 의견 )

해결 방법은 WebHeaderCollection.IsRestricted(key)add를 호출하기 전에 헤더가 이미 존재하는지 또는 제한되어 있는지 확인하는 것입니다 ( ).


답변

사용자 정의 웹 클라이언트 에서이 문제가 발생했습니다. 여러 가지 방법으로 사람들이 혼란 스러울 수 있다고 생각합니다. 사용하는 경우 WebRequest.Create()당신은 캐스팅 할 수 있습니다 HttpWebRequest추가하거나 헤더를 수정하는 속성을 사용합니다. 를 WebHeaderCollection사용할 때을 사용할 수 있습니다 .Add("referer","my_url").

예 1

WebClient client = new WebClient();
client.Headers.Add("referer", "http://stackoverflow.com");
client.Headers.Add("user-agent", "Mozilla/5.0");

예 2

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Referer = "http://stackoverflow.com";
request.UserAgent = "Mozilla/5.0";
response = (HttpWebResponse)request.GetResponse();

답변

이전의 모든 답변은 솔루션을 제공하지 않고 문제를 설명합니다. 다음은 문자열 이름을 통해 헤더를 설정할 수있게하여 문제를 해결하는 확장 방법입니다.

용법

HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.SetRawHeader("content-type", "application/json");

확장 클래스

public static class HttpWebRequestExtensions
{
    static string[] RestrictedHeaders = new string[] {
            "Accept",
            "Connection",
            "Content-Length",
            "Content-Type",
            "Date",
            "Expect",
            "Host",
            "If-Modified-Since",
            "Keep-Alive",
            "Proxy-Connection",
            "Range",
            "Referer",
            "Transfer-Encoding",
            "User-Agent"
    };

    static Dictionary<string, PropertyInfo> HeaderProperties = new Dictionary<string, PropertyInfo>(StringComparer.OrdinalIgnoreCase);

    static HttpWebRequestExtensions()
    {
        Type type = typeof(HttpWebRequest);
        foreach (string header in RestrictedHeaders)
        {
            string propertyName = header.Replace("-", "");
            PropertyInfo headerProperty = type.GetProperty(propertyName);
            HeaderProperties[header] = headerProperty;
        }
    }

    public static void SetRawHeader(this HttpWebRequest request, string name, string value)
    {
        if (HeaderProperties.ContainsKey(name))
        {
            PropertyInfo property = HeaderProperties[name];
            if (property.PropertyType == typeof(DateTime))
                property.SetValue(request, DateTime.Parse(value), null);
            else if (property.PropertyType == typeof(bool))
                property.SetValue(request, Boolean.Parse(value), null);
            else if (property.PropertyType == typeof(long))
                property.SetValue(request, Int64.Parse(value), null);
            else
                property.SetValue(request, value, null);
        }
        else
        {
            request.Headers[name] = value;
        }
    }
}

시나리오

래퍼를 작성했으며 래퍼의 HttpWebRequest속성으로 13 개의 제한된 헤더를 모두 노출하고 싶지 않았습니다. 대신 나는 간단한을 사용하고 싶었다 Dictionary<string, string>.

또 다른 예는 요청에서 헤더를 가져 와서 수신자에게 전달해야하는 HTTP 프록시입니다.

실용적이지 않거나 속성을 사용할 수없는 다른 시나리오가 많이 있습니다. 사용자가 속성을 통해 헤더를 설정하도록하는 것은 매우 융통성이없는 디자인이므로 리플렉션이 필요합니다. 단점은 반사가 추상화되어 여전히 빠르며 (테스트에서 .001 초) 확장 방법이 자연 스럽습니다.

노트

RFC, http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2에 따라 헤더 이름은 대소 문자를 구분하지 않습니다 .


답변

내 코드가 “Accept”헤더 값을 다음과 같이 설정하려고 할 때 동일한 예외가 발생했습니다.

WebRequest request = WebRequest.Create("http://someServer:6405/biprws/logon/long");
request.Headers.Add("Accept", "application/json");

해결책은 이것을 다음과 같이 변경하는 것이 었습니다.

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://someServer:6405/biprws/logon/long");
request.Accept = "application/json";

답변

의 헤더를 변경할 때마다 HttpWebRequest객체 자체에 적절한 속성을 사용해야합니다 (있는 경우). 플레인 WebRequest이 있으면 HttpWebRequest처음 으로 캐스팅하십시오 . 그런 다음 Referrer을 통해 액세스 할 수 있으므로 ((HttpWebRequest)request).Referrer헤더를 직접 수정할 필요가 없습니다. 속성을 올바른 값으로 설정하십시오. ContentLength, ContentType, UserAgent, 등, 모든 필요는이 방법을 설정합니다.

IMHO, 이것은 MS 부분의 단점입니다 … 헤더를 통해 헤더를 설정 Headers.Add()하면 장면 뒤의 적절한 속성을 자동으로 호출해야합니다.


답변

WebRequest 는 추상적이며 상속되는 클래스는 Headers 속성을 재정의해야하므로 .. 어떤 구체적인 WebRequest를 사용하고 있습니까? 즉, WebRequest 객체를 어떻게 사용할 수 있습니까?

ehr .. mnour 응답으로 인해 오류 메시지가 실제로 발견되었음을 알 수 있습니다. 추가하려는 헤더가 이미 존재하고 적절한 속성 (예 : 인덱서)을 사용하여 값을 수정해야한다는 것을 알려줍니다 )를 다시 추가하는 대신 아마 당신이 찾고 있던 전부일 것입니다.

WebRequest에서 상속되는 다른 클래스는 특정 헤더를 래핑하는 더 나은 속성을 가질 수 있습니다. 예를 들어이 게시물 을 참조하십시오 .


답변

위의 답변은 모두 훌륭하지만 문제의 본질은 일부 헤더가 한 방향으로 설정되고 다른 헤더는 다른 방식으로 설정된다는 것입니다. ‘제한된 헤더’목록은 위를 참조하십시오. 이를 위해 속성으로 설정하면됩니다. 다른 사람들에게는 실제로 헤더를 추가합니다. 여기를 보아라.

    request.ContentType = "application/x-www-form-urlencoded";

    request.Accept = "application/json";

    request.Headers.Add(HttpRequestHeader.Authorization, "Basic " + info.clientId + ":" + info.clientSecret);