Почему я получаю «(304) не модифицировал« Ошибка по некоторым ссылкам при использовании httpwebrequest?
-
25-09-2019 - |
Вопрос
Любые идеи, почему по некоторым ссылкам, которые я пытаюсь получить доступ к использованию httpwebrequest, я получаю сообщение «Удаленный сервер вернул ошибку: (304) не модифицирован». в коде?
Код, который я использую, от Джефф пост здесь (страница, похоже, исчезла, см. Архив скопированной на пуфике).
Примечание. Концепция кода является простым прокси-сервером, поэтому я указываю на мой браузер в этом локально запущенном кусочке кода, который получает мой запрос браузеров, а затем прокси его, создавая новый httpwebrequest, как вы увидите в код. Он отлично работает для большинства сайтов / ссылок, но для некоторой этой ошибки возникает. Вы увидите, что один ключ в коде - это то, где кажется, что скопируйте настройки заголовка HTTP из запроса на браузер к его запросу на сайт, и он копирует в атрибутах заголовка. Не уверен, что проблема - это что-то делать с тем, как она имитирует этот аспект запроса, а затем, что происходит, когда результат возвращается?
case "If-Modified-Since":
request.IfModifiedSince = DateTime.Parse(listenerContext.Request.Headers[key]);
break;
Я получаю проблему, например из http://en.wikipedia.org/wiki/main_page.
Придавать Обновить здесь
До сих пор не могу это работать. По сути, я могу определить 1 ссылку, которая имеет проблему, и, похоже, работает нормально, 2-й раз это получает ошибку, 3-й раз в порядке, 4-й раз получает ошибку, 5 раз в порядке и т. Д., Как будто есть какое-то состояние, не получаемое не очищенное или что-то в коде. Я попытался убрать код немного, используя «Использование» типовых выписок и т. Д.
Вот код. Если кто-то может заметить, почему каждый 2-й раз я просматриваю ссылку, как http://newsimg.bbc.co.uk/css/screen/1_0_16/nol/v4/story.css. (Начиная с 2-го времени, не первый) через этот прокси-код, я получаю ошибку, я бы слышал.
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();
}
}
}
И вот пример того, что я вижу - первый хит хороший, 2-й имеет ошибку ...
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 также кэширует веб-данные для вас.
Решение: Сила обновления.
Сила обновить ваш браузер нажатием Ctrl. + F5. в Firefox или Chrome, чтобы очистить провалочный кеш тоже вместо просто нажатия F5.
Затем вы можете увидеть 200 ответ вместо 304 в браузере F12. Вкладка «Инструменты разработчика».
Еще один трюк - добавить знак вопроса ?
В конце строки URL запрошенной страницы:
http://localhost:52199/Customers/Create?
Марк вопроса обеспечит, чтобы браузер обновит запрос без кэширования любых предыдущих запросов.
Дополнительно в Visual Studio Вы можете установить браузер по умолчанию на Хром в Инкогнито Режим, чтобы избежать проблем кэша при разработке, добавив Chrome в режиме Incognito в качестве браузера по умолчанию, см. Шаги (я иллюстрируемые):
Я думаю, что вы не установили эти функции. Смотрите ниже на картинке.
Я также страдал от этой проблемы несколько дней назад. После установки этой функции я решил ее. Если вы не установили эту функцию, то установил ее.
Процесс установки:
- Перейти к андроидной студии
- Инструменты
- Андроид
- Менеджер SDK
- Внешний вид и поведение
- Android SDK