System.Net.WebRequest ব্যবহার করার সময় কিছু HTTP শিরোনাম সেট করা যায় না


130

আমি যখন কোনও সামগ্রীতে একটি HTTP শিরোনাম কী / মান জোড় যুক্ত করার চেষ্টা করি তখন আমি WebRequestনিম্নলিখিত ব্যতিক্রমগুলি পাই:

এই শিরোনামটি যথাযথ সম্পত্তি ব্যবহার করে পরিবর্তন করতে হবে

আমি Headersযোগ () পদ্ধতিটি ব্যবহার করে সংগ্রহে নতুন মান যুক্ত করার চেষ্টা করেছি তবে এখনও আমি একই ব্যতিক্রম পাচ্ছি।

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

আমি এইচটিটিপিওয়েবরেউকস্টের কাছে ওয়েবরেক্সট অবজেক্টটি কাস্ট করে এবং এর মতো বৈশিষ্ট্যগুলি সেট করে এটিকে পেতে পারি httpWebReq.Referer ="http://stackoverflow.com", তবে এটি কেবল কয়েকটি মুখ্য শিরোনামের জন্য কাজ করে যা বৈশিষ্ট্যগুলির মাধ্যমে প্রকাশিত হয়।

আমি জানতে চাই যে রিমোট রিসোর্সের অনুরোধের সাথে শিরোনাম সংশোধন করার জন্য আরও সূক্ষ্ম শস্য নিয়ন্ত্রণ পাওয়ার কোনও উপায় আছে কিনা?

উত্তর:


182

আপনার যদি সংক্ষিপ্ত এবং প্রযুক্তিগত উত্তর প্রয়োজন হয় তবে উত্তরের শেষ অংশে ডানদিকে যান।

আপনি যদি আরও জানতে চান তবে এগুলি পড়ুন এবং আমি আশা করি আপনি উপভোগ করবেন ...


আমি আজও এই সমস্যার মুখোমুখি হয়েছি এবং আমি আজ যা আবিষ্কার করেছি তা হ'ল:

  1. উপরের উত্তরগুলি সত্য, যেমন:

    1.1 এটি আপনাকে বলছে যে আপনি যে শিরোনামটি যুক্ত করার চেষ্টা করছেন তা ইতিমধ্যে বিদ্যমান এবং আপনার আবার যুক্ত করার চেষ্টা না করে যথাযথ সম্পত্তি (সূচক, উদাহরণস্বরূপ) ব্যবহার করে এর মানটি পরিবর্তন করা উচিত।

    ১.২ যে কোনও সময় আপনি যখন একটি এর শিরোনাম পরিবর্তন করেন HttpWebRequest, আপনাকে যদি বস্তুর উপস্থিত থাকে তবে আপনাকে যথাযথ বৈশিষ্ট্যগুলি ব্যবহার করতে হবে।

নেতৃস্থানীয় নির্দেশিকাগুলির জন্য এবং জাভেনিমার ধন্যবাদ

  1. তবে, আমি যা জানতে পেরেছি , এবং তা ধাঁধার মধ্যে হারিয়ে যাওয়া অংশটি হ'ল:

    2.1 WebHeaderCollectionক্লাসটি সাধারণত অ্যাক্সেস করা হয় WebRequeste হিডর বা WebResponse.হিডার্স। কিছু সাধারণ শিরোনামগুলিকে সীমাবদ্ধ হিসাবে বিবেচনা করা হয় এবং এপিআই দ্বারা সরাসরি উন্মুক্ত করা হয় (যেমন বিষয়বস্তুর ধরণ) বা সিস্টেম দ্বারা সুরক্ষিত এবং পরিবর্তন করা যায় না।

সীমাবদ্ধ শিরোনামগুলি হ'ল:

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

সুতরাং, পরের বার আপনি যখন এই ব্যতিক্রমটির মুখোমুখি হয়েছিলেন এবং কীভাবে এটি সমাধান করবেন তা জানেন না, মনে রাখবেন কিছু সীমাবদ্ধ শিরোনাম রয়েছে এবং সমাধানটি হ'ল WebRequest/ HttpWebRequestশ্রেণীর থেকে সুস্পষ্টভাবে উপযুক্ত সম্পত্তি ব্যবহার করে তাদের মানগুলি সংশোধন করা ।


সম্পাদনা করুন: (দরকারী, মন্তব্যগুলি থেকে, ব্যবহারকারী কায়দো মন্তব্য করেছেন )

সমাধানটি শিরোনামটি ইতিমধ্যে উপস্থিত রয়েছে কিনা তা যাচাই করা হয় ( WebHeaderCollection.IsRestricted(key)অ্যাড কল করার আগে) সীমাবদ্ধ ( )


8
"উপযুক্ত সম্পত্তি ব্যবহার করে তাদের মানগুলি সংশোধন করুন"
এগুলি

76
এই উত্তরটি সমস্যার সমাধান না দিয়ে কেবল ব্যতিক্রম বার্তার পুনরাবৃত্তি করছে।
000

11
সমাধানটি শিরোনামটি ইতিমধ্যে উপস্থিত রয়েছে বা সীমাবদ্ধ রয়েছে কিনা তা পরীক্ষা করা হবে (ওয়েবহাইডারকলিকেশন Iসিসট্রিক্টেড (কী)) অ্যাড বলার আগে
কায়ডো

7
@ স্যাম পড়ুন বিভাগ 1.1 যা সমস্যা সমাধান করে। এর অর্থ আমরা যে সম্পত্তিটি যুক্ত করার চেষ্টা করছি তা Headers.Add()ইতিমধ্যে বিদ্যমান তাই আমাদের পরিবর্তে এটি পরিবর্তন করা উচিত।
জুনেদ কাদির

4
"আমি এই বিষয়টি উল্লেখ করা গুরুত্বপূর্ণ যে এই সীমাবদ্ধতাটি। নেট ফ্রেমওয়ার্কের একটি বৈশিষ্ট্য" - আমি বরং এই ধরণের বৈশিষ্ট্যটি না চাই।
হারবার্থ আমারাল

76

আমি একটি কাস্টম ওয়েব ক্লায়েন্টের সাথে এই সমস্যায় পড়েছি। আমি মনে করি এটি করার একাধিক উপায়ের কারণে লোকেরা বিভ্রান্ত হতে পারে। ব্যবহার করার সময় WebRequest.Create()আপনি একটিতে কাস্ট করতে পারেন HttpWebRequestএবং একটি শিরোনাম যুক্ত করতে বা সংশোধন করতে সম্পত্তিটি ব্যবহার করতে পারেন । একটি ব্যবহার করার সময় WebHeaderCollectionআপনি এটি ব্যবহার করতে পারেন .Add("referer","my_url")

প্রাক্তন ঘ

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();

1
প্রাক্তন 1 এই ব্যতিক্রমটি দিয়ে আমার সমস্যার সমাধান করেছে। সুতরাং আমি ক্লায়েন্টকে পরিবর্তন করেছি e হিডর ["রেফারার"] = ইউআরএল; ক্লায়েন্টকে। Heeers.Add ("রেফারার", url); এবং জিনিস কাজ করে। ধন্যবাদ।
000

2
এই উত্তরটিতে আপনি একটি ডেস্কটপে কাজ করছেন বলে একটি সুখী ধারণা রয়েছে সে সম্পর্কে সতর্ক হন। নেট রানটাইম এবং HTTP জিজ্ঞাসা করছেন। WebRequest.Create আপনি কী প্রোটোকল উপসর্গ ব্যবহার করেন তার উপর নির্ভর করে বিভিন্ন ধরণের বিভিন্ন বস্তু ফিরিয়ে দিতে পারে। এটি কাস্টমপ্রোটোকল হ্যান্ডলারের সাথে সম্পর্কিত যদি তাদের মধ্যে কেউ আগ্রহী হয় .. এবং ডাব্লুপি 7 বা সিলভারলাইটে অনুরোধ বাস্তবায়ন ক্লাসগুলিও কিছুটা আলাদা different শুধু এই সঙ্গে সাবধান।
কোয়েটজলকোটল

1
তবে আমি "গ্রহণ করুন" শিরোনামটি সংশোধন করতে পারি না। আমি কীভাবে এটি সংশোধন করতে পারি?
ব্যবহারকারী

প্রথম উদাহরণটি এখনও আমাকে একই ত্রুটি দিচ্ছে
মিড

29

পূর্ববর্তী সমস্ত উত্তর সমাধান সরবরাহ না করেই সমস্যার বর্ণনা দেয়। এখানে একটি এক্সটেনশন পদ্ধতি যা আপনার স্ট্রিং নামের মাধ্যমে কোনও শিরোনাম সেট করার অনুমতি দিয়ে সমস্যার সমাধান করে।

ব্যবহার

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>

অন্য উদাহরণ হ'ল এইচটিটিপি প্রক্সি যেখানে আপনাকে একটি অনুরোধে শিরোনাম নিতে হবে এবং সেগুলি প্রাপকের কাছে ফরোয়ার্ড করতে হবে।

এমন অনেকগুলি পরিস্থিতি রয়েছে যেখানে এর ব্যবহারিক ব্যবহার বা সম্পত্তি ব্যবহার সম্ভব নয়। ব্যবহারকারীর দ্বারা কোনও সম্পত্তি দিয়ে শিরোনাম সেট করতে বাধ্য করা একটি অত্যন্ত জটিল design ডিজাইনের কারণেই প্রতিফলন প্রয়োজন। উপরের দিকটি হ'ল প্রতিবিম্বটি বিমূর্তভাবে দূরে সরে গেছে, এটি এখনও দ্রুত (আমার পরীক্ষায় .001 সেকেন্ড), এবং একটি এক্সটেনশন পদ্ধতিটি স্বাভাবিক অনুভব করে।

মন্তব্য

শিরোনামের নামগুলি আরএফসি অনুসারে সংবেদনশীল, http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2


আমি এটি প্রক্সি-সংযোগের জন্য ব্যবহার করি, তবে এটি বলার পরে, হ্যাঁ আমি "প্রক্সি-সংযোগ" এর
কীটিটি

চতুর ঠিক করার জন্য আপনাকে ধন্যবাদ। আমি এই এক্সটেনশনে সমস্ত শিরোনাম সেট করতে দিয়েছি:static Dictionary<string, PropertyInfo> HeaderProperties = new Dictionary<string, PropertyInfo>(StringComparer.InvariantCultureIgnoreCase); static WebRequestExtensions() { // Get property info for restricted headers. Type type = typeof(HttpWebRequest); foreach (string header in Enum.GetNames(typeof(HttpRequestHeader))) { var property = type.GetProperty(header.ToString()); if (property != null) { HeaderProperties.Add(property.Name, property); } } }
সানক্যাট 2000

13

আমার কোডটি "স্বীকার করুন" শিরোনাম মানটি সেট করার চেষ্টা করার সময় আমার একই ব্যতিক্রম হয়েছিল:

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";

12

যে কোনও সময় আপনি যখন একটি এর শিরোনাম পরিবর্তন করছেন HttpWebRequest, আপনাকে অবশ্যই সেই বস্তুর উপর যথাযথ বৈশিষ্ট্যগুলি ব্যবহার করতে হবে, যদি সেগুলি উপস্থিত থাকে। আপনার যদি সমভূমি থাকে WebRequestতবে HttpWebRequestপ্রথমে এটি নিক্ষেপ করতে ভুলবেন না । তারপরে Referrerআপনার ক্ষেত্রে অ্যাক্সেস করা যেতে পারে ((HttpWebRequest)request).Referrer, সুতরাং আপনাকে সরাসরি শিরোনামটি পরিবর্তন করতে হবে না - কেবল সম্পত্তিটিকে সঠিক মান হিসাবে সেট করুন। ContentLength, ContentType, UserAgent, ইত্যাদি সব প্রয়োজন এই ভাবে সেট হওয়ার।

আইএমএইচও, এটি এমএস অংশে একটি সমস্যা Headers.Add()


7

ওয়েব রেকস্টটি বিমূর্ত (এবং যেহেতু কোনও উত্তরাধিকার সূত্রে প্রাপ্ত শ্রেণি অবশ্যই শিরোনামের সম্পত্তিটিকে ওভাররাইড করবে) .. আপনি কোন কংক্রিট ওয়েব-রিকোয়েস্ট ব্যবহার করছেন? অন্য কথায়, আপনি কীভাবে সেই ওয়েবরয়েস্ট অবজেক্টটি সাইন আপ করতে পারেন?

এহর .. শোকের উত্তর আমাকে বুঝতে পেরেছিল যে আপনি যে ত্রুটি বার্তাটি পেয়েছিলেন তা আসলে স্পট হয়েছে: এটি আপনাকে বলছে যে আপনি যে শিরোনামটি যুক্ত করার চেষ্টা করছেন তা ইতিমধ্যে বিদ্যমান এবং আপনার যথাযথ সম্পত্তি (সূচক, উদাহরণস্বরূপ) ব্যবহার করে এর মানটি পরিবর্তন করা উচিত ) পরিবর্তে এটি আবার যুক্ত করার চেষ্টা করুন। আপনি সম্ভবত এটিই খুঁজছিলেন।

WebRequest থেকে উত্তরাধিকার সূত্রে প্রাপ্ত অন্যান্য শ্রেণীর মধ্যে কিছু নির্দিষ্ট শিরোনাম মোড়ানো আরও ভাল বৈশিষ্ট্য থাকতে পারে; উদাহরণস্বরূপ এই পোস্টটি দেখুন ।


প্রকৃতপক্ষে WebRequest.Create (url) একটি ওয়েবআরকোয়েস্ট অবজেক্টের উদাহরণ তৈরি করে।
ইগাল তাবাচনিক

2

উপরের উত্তরগুলি সবই ঠিক আছে, তবে ইস্যুর সারমর্মটি হ'ল কিছু শিরোনাম একটি উপায়ে সেট করা হয়েছে, এবং অন্যরা অন্য উপায়ে সেট করেছেন। 'সীমাবদ্ধ শিরোনাম' তালিকার জন্য উপরে দেখুন। এগুলির জন্য, আপনি কেবল তাদের সম্পত্তি হিসাবে সেট করেছেন। অন্যদের জন্য, আপনি আসলে শিরোনাম যুক্ত করুন। এখানে দেখো.

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

    request.Accept = "application/json";

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

1

মূলত, না। এটি একটি HTTP শিরোনাম, সুতরাং এটিকে কাস্ট করা HttpWebRequestএবং সেট করা যুক্তিসঙ্গত .Referer(আপনি যেমন প্রশ্নটিতে নির্দেশ করেছেন):

HttpWebRequest req = ...
req.Referer = "your url";

1

দ্রষ্টব্য: এই সমাধানটি ওয়েবক্লিয়েন্টসকেটের পাশাপাশি এইচটিটিপিওব্রেকয়েস্ট বা অন্য কোনও শ্রেণীর সাথে কাজ করবে যা ওয়েব শোনার সাহায্যে শিরোলেখগুলির সাথে কাজ করে।

আপনি যদি ওয়েবহাইডারকলিকেশন.সি এর উত্স কোডটি দেখেন তবে আপনি দেখতে পাবেন যে সমস্ত পরিচিত শিরোলেখগুলির তথ্য রাখতে হিনফো ব্যবহৃত হয়:

private static readonly HeaderInfoTable HInfo = new HeaderInfoTable();

HeaderInfoTable ক্লাসটি দেখে আপনি খেয়াল করতে পারেন যে সমস্ত ডেটা হ্যাশ টেবিলের মধ্যে সঞ্চিত আছে

private static Hashtable HeaderHashTable;

তদ্ব্যতীত, HeaderInfoTable এর স্থিতিশীল কন্ট্রাক্টারে, আপনি দেখতে পাচ্ছেন যে সমস্ত পরিচিত শিরোলেখ HeaderInfo অ্যারে যুক্ত হয়েছে এবং তারপরে হ্যাশটেবলে অনুলিপি করা হয়েছে।

হেডারআইনফো ক্লাসে চূড়ান্ত চেহারা ক্ষেত্রগুলির নাম দেখায়।

internal class HeaderInfo {

    internal readonly bool IsRequestRestricted;
    internal readonly bool IsResponseRestricted;
    internal readonly HeaderParser Parser;

    //
    // Note that the HeaderName field is not always valid, and should not
    // be used after initialization. In particular, the HeaderInfo returned
    // for an unknown header will not have the correct header name.
    //

    internal readonly string HeaderName;
    internal readonly bool AllowMultiValues;
    ...
    }

সুতরাং, উপরোক্ত সমস্তগুলির সাথে, এখানে একটি কোড যা শিরোলেখযোগ্য টেবিল শ্রেণিতে স্ট্যাটিক হ্যাশটেবল সন্ধান করার জন্য প্রতিবিম্ব ব্যবহার করে এবং তারপরে হ্যাশ সারণীর অভ্যন্তরে প্রতিটি অনুরোধ-সীমাবদ্ধ শিরোলেখটিকে পরিবর্তনহীন করে তোলে

        // use reflection to remove IsRequestRestricted from headerInfo hash table
        Assembly a = typeof(HttpWebRequest).Assembly;
        foreach (FieldInfo f in a.GetType("System.Net.HeaderInfoTable").GetFields(BindingFlags.NonPublic | BindingFlags.Static))
        {
            if (f.Name == "HeaderHashTable")
            {
                Hashtable hashTable = f.GetValue(null) as Hashtable;
                foreach (string sKey in hashTable.Keys)
                {

                    object headerInfo = hashTable[sKey];
                    //Console.WriteLine(String.Format("{0}: {1}", sKey, hashTable[sKey]));
                    foreach (FieldInfo g in a.GetType("System.Net.HeaderInfo").GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
                    {

                        if (g.Name == "IsRequestRestricted")
                        {
                            bool b = (bool)g.GetValue(headerInfo);
                            if (b)
                            {
                                g.SetValue(headerInfo, false);
                                Console.WriteLine(sKey + "." + g.Name + " changed to false");
                            }

                        }
                    }

                }
            }
        } 

উজ্জ্বল! এই যখন ওয়েব সকেট সেট আপ এবং যার ফলে এই সমস্যা কাজ করছে এটা সম্ভব ব্যবহৃত অনুরোধ জন্য ঐ হেডার সেট করে তোলে github.com/dotnet/corefx/issues/26627
Øystein Kolsrud

এটি হওয়া উচিত কারণ তারা সকলেই হেডারগুলি ম্যানিপুলেট করতে ওয়েবহাইডার সংগ্রহটি ব্যবহার করে। আমি এটি কেবলমাত্র এইচটিটিপিওয়েবরেস্টে পরীক্ষা করেছি।
স্লিপার


0

আপনি কেবল নীচে দেখানো একটি HTTPWebRequest এ ওয়েবরকেষ্টটি কাস্ট করতে পারেন:

var request = (HttpWebRequest)WebRequest.Create(myUri);

এবং তারপরে শিরোনাম তালিকাটি কৌশলগত করার চেষ্টা করার পরিবর্তে এটি সরাসরি অনুরোধ সম্পত্তি অনুরোধে প্রয়োগ করুন e রেফারার:

request.Referer = "yourReferer";

এই বৈশিষ্ট্যগুলি অনুরোধের অবজেক্টে উপলব্ধ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.