为什么使用httpwebrequest时,为什么在某些链接上遇到“(304)未修改”错误?
-
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
PS。在这里更新
仍然无法解决这个问题。基本上,我可以识别有问题的1个链接,并且似乎正常工作,第二次会出现错误,第三次好,第四次出现错误,第五次确定等等。代码中的某些内容。我尝试使用“使用”类型语句等来清理代码。
这是代码。如果有人可以发现为什么我第二次我浏览链接 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();
}
}
}
这是我看到的示例 - 第一个命中率很好,第二次有错误...
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也为您缓存Web数据。
解决方案: 力刷新。
按下刷新浏览器 Ctrl + F5 在Firefox或Chrome中也清除ISP缓存,而不仅仅是按下 F5
然后,您可以在浏览器中看到200个响应,而不是304 F12 开发人员工具网络选项卡。
另一个技巧是添加问号 ?
在请求页面的URL字符串的末尾:
http://localhost:52199/Customers/Create?
问号将确保浏览器刷新请求,而无需缓存任何以前的请求。
另外 视觉工作室 您可以将默认浏览器设置为 铬合金 在 隐身 在开发时避免缓存问题的模式,通过将Chrome添加为默认浏览器,请参见步骤(自图):
我认为您尚未安装这些功能。见下图。
几天前,我也遇到了这个问题。安装此功能后,我解决了它。如果您尚未安装此功能,请安装它。
安装过程:
- 去Android Studio
- 工具
- 安卓
- SDK Manager
- 外观和行为
- Android SDK