لماذا أحصل على خطأ "(304) غير معدّل" في بعض الروابط عند استخدام httpwebrequest؟
-
25-09-2019 - |
سؤال
أي أفكار لماذا في بعض الروابط التي أحاول الوصول إليها باستخدام httpwebrequest ، أحصل على "أن الخادم البعيد أعاد خطأ: (304) لم يتم تعديله." في الكود؟
الرمز الذي أستخدمه هو من منشور جيف هنا (يبدو أن الصفحة قد اختفت ، انظر أرشيف نسخة في آلة Wayback).
لاحظ أن مفهوم الكود هو خادم وكيل بسيط ، لذلك أشير إلى متصفحي في قطعة الكود التي تعمل محليًا ، والتي تحصل على طلب المتصفحات الخاص بي ، ثم يتم وضعه على ذلك عن طريق إنشاء httpwebrequest جديد ، كما سترى في الرمز. إنه يعمل بشكل رائع لمعظم المواقع/الروابط ، ولكن بالنسبة لبعض هذا الخطأ يأتي. سترى جزء مفتاح واحد في الكود هو المكان الذي يبدو فيه نسخ إعدادات رأس HTTP من طلب المتصفح إلى طلبه إلى الموقع ، ويقوم بنسخ في سمات الرأس. لست متأكداً مما إذا كانت المشكلة تتعلق بكيفية تحاكي هذا الجانب من الطلب ومن ثم ما يحدث مع عودة النتيجة؟
case "If-Modified-Since":
request.IfModifiedSince = DateTime.Parse(listenerContext.Request.Headers[key]);
break;
أحصل على المشكلة على سبيل المثال من http://en.wikipedia.org/wiki/main_page
ملاحظة. تحديث هنا
ما زلت لا أستطيع العمل هذا. في الأساس ، يمكنني تحديد رابط واحد له مشكلة ، ويبدو أنه يعمل بشكل جيد ، المرة الثانية التي يحصل فيها على الخطأ ، الوقت الثالث على ما يرام ، المرة الرابعة تحصل على الخطأ ، المرة الخامسة على ما يرام. شيء ما في الكود. لقد حاولت تنظيف الكود قليلاً باستخدام عبارات النوع "باستخدام" وما إلى ذلك.
ها هو الرمز. إذا كان بإمكان أي شخص تحديد سبب كل مرة أتصفح فيها رابط مثل http://newsimg.bbc.co.uk/css/screen/1_0_16/nol/v4/story.css (بدءًا من المرة الثانية ، وليس الأول) عبر رمز الوكيل هذا ، أحصل على الخطأ الذي أحب أن أسمعه.
class Program
{
static void Main(string[] args)
{
Proxy p = new Proxy(8080);
Thread proxythread = new Thread(new ThreadStart(p.Start));
proxythread.Start();
Console.WriteLine("Proxy Started. Press Any Key To Stop...");
Console.ReadKey();
p.Stop();
}
}
public class Proxy
{
private HttpListener _listener;
private int _port;
public Proxy(int port)
{
int defaultport = 8080;
// Setup Thread Pool
System.Threading.ThreadPool.SetMaxThreads(50, 1000);
System.Threading.ThreadPool.SetMinThreads(50, 50);
// Sanitize Port Number
if (port < 1024 || port > 65535)
port = defaultport;
// Create HttpListener Prefix
string prefix = string.Format("http://*:{0}/", port);
_port = port;
// Create HttpListener
_listener = new HttpListener();
_listener.Prefixes.Add(prefix);
}
public void Start()
{
_listener.Start();
while (true)
{
HttpListenerContext request = null;
try
{
request = _listener.GetContext();
// Statistics (by Greg)
int availThreads = -1;
int compPortThreads = -1;
ThreadPool.GetAvailableThreads(out availThreads, out compPortThreads);
log("INFO", request.Request.Url.ToString(), "START - [" + availThreads + "]");
ThreadPool.QueueUserWorkItem(ProcessRequest, request);
}
catch (HttpListenerException ex)
{
log("ERROR", "NA", "INFO: HttpListenerException - " + ex.Message);
break;
}
catch (InvalidOperationException ex)
{
log("ERROR", "NA", "INFO: InvalidOperationException - " + ex.Message);
break;
}
}
}
public void Stop()
{
_listener.Stop();
}
private void log(string sev, string uri, string message)
{
Console.Out.WriteLine(Process.GetCurrentProcess().Id + " - " + sev + " (" + uri + "): " + message);
}
private void ProcessRequest(object _listenerContext)
{
#region local variables
HttpWebRequest psRequest; // Request to send to remote web server
HttpWebResponse psResponse; // Response from remote web server
List<byte> requestBody = new List<byte>(); // Byte array to hold the request's body
List<byte> responseBody = new List<byte>(); // Byte array to hold the response's body
byte[] buffer;
string uri = "";
#endregion
var listenerContext = (HttpListenerContext)_listenerContext;
uri = listenerContext.Request.Url.ToString().Replace(string.Format(":{0}", _port), "");
// Create Interent Request
HttpWebRequest internetRequest = (HttpWebRequest)WebRequest.Create(uri);
#region Build Request Up
internetRequest.Method = listenerContext.Request.HttpMethod;
internetRequest.ProtocolVersion = listenerContext.Request.ProtocolVersion;
internetRequest.UserAgent = listenerContext.Request.UserAgent;
foreach (string key in listenerContext.Request.Headers.AllKeys)
{
try
{
switch (key)
{
case "Proxy-Connection":
case "Connection":
internetRequest.KeepAlive = (listenerContext.Request.Headers[key].ToLower() == "keep-alive") ? true : false;
break;
case "Content-Length":
internetRequest.ContentLength = listenerContext.Request.ContentLength64;
break;
case "Content-Type":
internetRequest.ContentType = listenerContext.Request.ContentType;
break;
case "Accept":
internetRequest.Accept = listenerContext.Request.Headers[key];
break;
case "Host":
break;
case "Referer":
internetRequest.Referer = listenerContext.Request.Headers[key];
break;
case "If-Modified-Since":
internetRequest.IfModifiedSince = DateTime.Parse(listenerContext.Request.Headers[key]);
break;
default:
internetRequest.Headers.Add(key, listenerContext.Request.Headers[key]);
break;
}
}
catch (Exception ex)
{
Console.WriteLine("Error settup up psRequest object. Error = " + ex.Message + "\n" + ex.StackTrace);
}
}
#endregion
#region Copy content into request
buffer = new byte[1024];
using (Stream instream = listenerContext.Request.InputStream)
{
int incount = instream.Read(buffer, 0, buffer.Length);
while (incount > 0)
{
internetRequest.GetRequestStream().Write(buffer, 0, incount);
incount = instream.Read(buffer, 0, buffer.Length);
}
}
#endregion
// Get Internet Response
HttpWebResponse internetResponse = null;
try
{
using (internetResponse = (HttpWebResponse)internetRequest.GetResponse())
{
#region Configure Local Response Header Keys
foreach (string key in internetResponse.Headers.Keys)
{
try
{
switch (key)
{
case "Transfer-Encoding":
listenerContext.Response.SendChunked = (internetResponse.Headers[key].ToLower() == "chunked") ? true : false;
break;
case "Content-Length":
listenerContext.Response.ContentLength64 = internetResponse.ContentLength;
break;
case "Content-Type":
listenerContext.Response.ContentType = internetResponse.Headers[key];
break;
case "Keep-Alive":
listenerContext.Response.KeepAlive = true;
break;
default:
listenerContext.Response.Headers.Add(key, internetResponse.Headers[key]);
break;
}
}
catch (Exception ex)
{
log("ERROR", uri, "Error settup up listenerContext.Response objects. Error = " + ex.Message + "\n" + ex.StackTrace);
}
}
#endregion
try
{
// Transfer the body data from Internet Response to Internal Response
buffer = new byte[1024];
using (Stream inputStream = internetResponse.GetResponseStream())
{
int outcount = inputStream.Read(buffer, 0, buffer.Length);
while (outcount > 0)
{
listenerContext.Response.OutputStream.Write(buffer, 0, outcount);
outcount = inputStream.Read(buffer, 0, buffer.Length);
}
}
}
catch (Exception ex)
{
log("ERROR", uri, "Could not obtain response from URI: " + ex.Message);
}
finally
{
listenerContext.Response.OutputStream.Close();
}
}
}
catch (Exception ex)
{
//if (ex is InvalidOperationException ||
// ex is ProtocolViolationException ||
// ex is WebException)
//{
// log(uri, "Could not successfully get response: " + ex.GetType() + " - " + ex.Message);
// listenerContext.Response.Close();
// return;
//}
//else { throw; }
log("ERROR", uri, "Could not successfully get response: " + ex.GetType() + " - " + ex.Message);
listenerContext.Response.Close();
}
}
}
وهنا مثال على ما أراه - أول ضربة جيدة ، 2nd لديها خطأ ...
Proxy Started. Press Any Key To Stop...
2080 - INFO (http://newsimg.bbc.co.uk:8080/css/screen/1_0_16/nol/v4/story.css): START - [50]
2080 - INFO (http://newsimg.bbc.co.uk:8080/css/screen/1_0_16/nol/v4/story.css): START - [50]
2080 - ERROR (http://newsimg.bbc.co.uk/css/screen/1_0_16/nol/v4/story.css): Could not successfully get response: System.Net.WebException - The remote server returned an error: (304) Not Modified.
المحلول
أولاً ، هذا ليس خطأ. ال 3xx
يدل على إعادة التوجيه. الأخطاء الحقيقية 4xx
(خطأ العميل) و 5xx
(خطأ في الخادم).
إذا حصل العميل على ملف 304 Not Modified
, ، عندها تقع على عاتق العميل مسؤولية عرض إعادة الاستعادة المعنية من ذاكرة التخزين المؤقت الخاصة بها. بشكل عام ، لا ينبغي أن يقلق الوكيل بشأن هذا. إنه مجرد رسول.
نصائح أخرى
هذا هو السلوك المقصود.
عند تقديم طلب HTTP ، يقوم الخادم عادة بإرجاع التعليمات البرمجية 200 OK
. إذا قمت بتعيين If-Modified-Since
, ، قد يعود الخادم 304 Not modified
(والاستجابة لن تحتوي على المحتوى). من المفترض أن يكون هذا هو جديلة أن الصفحة لم يتم تعديلها.
ال لقد قرر مؤلفو الفصل بحماقة الذي - التي 304
يجب أن تعامل كخطأ ورمي استثناء. الآن عليك التنظيف من خلال اللحاق بالاستثناء في كل مرة تحاول استخدامها If-Modified-Since
.
مجرد الضغط F5 لا يعمل دائما.
لماذا ا؟
لأن ISP الخاص بك يقوم أيضًا بتخزين بيانات الويب لك.
المحلول: القوة تحديث.
إجبار تحديث متصفحك بالضغط كنترول + F5 في Firefox أو Chrome لمسح ذاكرة التخزين المؤقت ISP أيضًا ، بدلاً من الضغط فقط F5
يمكنك بعد ذلك رؤية 200 استجابة بدلاً من 304 في المتصفح F12 علامة تبويب شبكة أدوات المطور.
خدعة أخرى هي إضافة علامة استفهام ?
في نهاية سلسلة عنوان URL للصفحة المطلوبة:
http://localhost:52199/Customers/Create?
ستضمن علامة الاستفهام أن المتصفح ينشط الطلب دون تخزين أي طلبات سابقة.
بالإضافة إلى ذلك استوديو مرئي يمكنك تعيين المستعرض الافتراضي ل كروم في التخفي وضع لتجنب مشكلات ذاكرة التخزين المؤقت أثناء التطوير ، عن طريق إضافة Chrome في وضع التخفي كمتصفح افتراضي ، راجع الخطوات (الموضحة ذاتيًا):
أعتقد أنك لم تقم بتثبيت هذه الميزات. انظر أدناه في الصورة.
كما عانيت من هذه المشكلة قبل بضعة أيام. بعد تثبيت هذه الميزة ثم قمت بحلها. إذا لم تكن قد قمت بتثبيت هذه الميزة ثم قمت بتثبيتها.
عملية التثبيت:
- انتقل إلى Android Studio
- أدوات
- ذكري المظهر
- مدير SDK
- المظهر والسلوك
- أندرويد سك