405 - Метод запрещен HttpWebRequest

У меня проблема при попытке отправить POST запрос. Способ отправки выглядит так:

Public Sub SendXML(ByVal file As String)
    Dim reader As New StreamReader(file)
    Dim data As String = reader.ReadToEnd()
    reader.Close()
    Dim request As HttpWebRequest = WebRequest.Create("http://blah/Request")
    request.Method = "POST"

    System.Net.ServicePointManager.Expect100Continue = False

    Dim bytes As Byte() = System.Text.Encoding.ASCII.GetBytes(data)
    request.ContentLength = bytes.Length

    Dim oStreamOut As Stream = request.GetRequestStream()
    oStreamOut.Write(bytes, 0, bytes.Length)
    oStreamOut.Close()

    Dim response As HttpWebResponse = request.GetResponse()

End Sub

При запуске я получаю указанную выше ошибку. Через Fiddler я вижу, что запрос выглядит так:

POST http://blah/Request HTTP/1.1
Host: blah
Content-Length: 322
Proxy-Connection: Keep-Alive

<?xml version="1.0"?>
<Envelope>
<Header>
<UserID>uid</UserID>
<Password>pass</Password>
<SessionID />
<RequestType>GetDetails</RequestType>
<POSCompany>01</POSCompany>
<PackageType>DATA</PackageType>
<ActionType>READ</ActionType>
<SnoopUserID />
</Header>
<Body>
<MagicNumber>124</MagicNumber>
</Body>
</Envelope>

Теперь, глядя на это, я подозревал, что это произошло из-за того, что сервер не принимает POST сообщений. Но некоторые другие чтения предполагают, что URI http://blah/Request был сгенерирован с помощью прокси и должен быть /Request, поэтому строка должна читать POST /Request HTTP/1.1

Так какова общая причина этого? А если проблема с прокси, как это сортируется?

Как указано ниже, я создал новый вопрос для более конкретного запроса. Изменение абсолютного URI на относительный в заголовке HTTP POST


person anothershrubery    schedule 02.04.2012    source источник


Ответы (3)


В запросе POST нет ничего плохого, поэтому проблема должна быть в другом.

На этом пути есть ряд других мест, которые могут вызвать проблемы:

  1. Между вами и сервером, который меняет метод HTTP, может быть плохой прокси.
  2. Сервер может работать со сбоями или просто не поддерживать POST

Однако я предполагаю, что сервер делает больше, чем просто смотрит на метод HTTP, а вместо этого выдает вам ошибку 405 в ответ на вызов RPC, который обертывает ваша полезная нагрузка XML.

Некоторые серверы RPC будут (ошибочно) использовать такие коды состояния HTTP, чтобы указать, что запрошенный метод не может быть выполнен или что что-то еще не так с запросом, который имеет характер разрешений и безопасности.

Если сервер немного ведет себя лучше (и вам повезло), он должен возвращать дополнительную информацию в теле ответа, которая может указывать на источник ошибки 405.

person cdeszaq    schedule 04.04.2012
comment
К сожалению, сервер принадлежит третьей стороне, и у меня нет доступа к нему, чтобы узнать какие-либо подробности. Что бы вы посоветовали действовать? - person anothershrubery; 05.04.2012
comment
Кроме того, мне сообщили, что сервер принимает запросы POST, но я все еще не уверен в этом. - person anothershrubery; 05.04.2012
comment
Тот факт, что сервер принимает запросы POST, не означает, что программное обеспечение, работающее на сервере, принимает ваш конкретный почтовый запрос. Поскольку у вас нет доступа к серверу, единственное, что вы можете сделать, это сократить свой запрос до минимума и медленно его наращивать. Начните с пустого POST, а затем создайте его. Если возможно, попросите контроллеры сервера предоставить вам пример HTTP-запроса (включая полные заголовки), который, как они знают, работает. - person cdeszaq; 05.04.2012
comment
Они предоставили мне один, он точно такой же, как у меня, только первая строка POST /Request HTTP/1.1, а не POST http://blah/Request HTTP/1.1 - person anothershrubery; 05.04.2012
comment
Если заголовок Host правильный, вы можете просто использовать POST /Request. Я не особенно знаком с построением этого запроса в vb.net, но это не должно быть слишком сложно. - person cdeszaq; 05.04.2012
comment
Я пытался найти только относительный путь, но я немного борюсь с этим. - person anothershrubery; 05.04.2012
comment
Тогда задайте этот вопрос ТАК ;-) - person cdeszaq; 05.04.2012
comment
Не люблю создавать еще один вопрос для связанного вопроса, если вы понимаете, что я имею в виду, но я сделаю это! - person anothershrubery; 05.04.2012
comment
Я назвал это ответом, поскольку небольшое изучение ситуации показало, что сторонняя компания на самом деле дала нам неправильный IP-адрес. Много раз мы просили их подтвердить Хост, и они говорили, что это правильно, но в конце концов выяснилось, что это не так. Сервер был настроен для нашей материнской компании, а не для нас, поэтому мы в конечном итоге получили правильный хост, и он работает. - person anothershrubery; 17.04.2012
comment
Спасибо за ответ, но, к сожалению, у меня это не сработало (я использую IIS 7.5). После 2 дней исследований единственным рабочим решением, которое я нашел, чтобы избежать 405 Method Not Allowed, было определение заголовков CORS в методе Application_BeginRequest, как указано в этом ответе stackoverflow.com/a/14631068/827168 - person pomeh; 15.10.2014

Вам не хватает заголовка Content-Type, необходимого для POST? Подробнее читайте здесь. Я полагаю, это обязательно.

person AYK    schedule 11.04.2012

Ваш POST кажется полностью недействительным. Данные POST должны быть закодированы (например, как multipart / form-data) и использовать правильный тип содержимого (например, application / x-www-form-urlencoded) с правильной кодировкой и границами и т. Д. Вы просто отправляете серверу сообщение кусок текста, и я не удивлен, что он вылетает.

Я не уверен на 100%, что VB делает за кулисами, но эта страница MSDN предлагает вам установить тип содержимого для поддерживаемого метода, и вам, вероятно, также понадобится Content-Disposition: form-data в ваших заголовках. Я нашел пример , который делает это и добавляет границы MIME:

string FileData = "this is test file data\r\n"; // test data to send.
StringBuilder DataString = new StringBuilder();
DataString.Append(dataBoundary + "\r\n");
//This sends the viewstate info
DataString.Append("Content-Disposition: form-data; name=" + HiddenValue
+ "\r\n"
+ dataBoundary + "\r\n");
DataString.Append("Content-Disposition: form-data; name=" + "\"" +
"File1" +
"\"" +
"; filename=" + "\"" + "TestFile3.txt" + "\"" + "\r\n");
DataString.Append("Content-Type: text/plain\r\n\r\n");
DataString.Append(FileData);
DataString.Append(dataBoundary + "\r\n");
DataString.Append("Content-Disposition: form-data; name=" + "\"" +
"Submit1" +
"\"" + "\r\n\r\n" + "Upload\r\n" + dataBoundary + "--\r\n");

В этом примере имитируется загрузка поля файла.

Для более простой версии вы можете использовать request.ContentType = "application/x-www-form-urlencoded" с данными в кодировке URL, например: Dim postData As String = "myURL=http%3A%2F%2Fexample.com%2Findex.php". Обратите внимание, что это формат key=value, и данные должны быть сначала закодированы в URL-адресе.

Я не уверен, что именно вам нужно, потому что многое зависит от того, что удаленный сервер фактически ожидает от формы и имен полей. Это также зависит от того, действительно ли сервер следует соответствующим стандартам HTML и RFC. У вас есть рабочая HTML-форма, которую можно использовать в качестве руководства для того, что ожидает сервер?

person SpliFF    schedule 11.04.2012
comment
Content-Type и другие заголовки не являются обязательными. Как я уже сказал ранее, запрос POST работает при использовании того же самого запроса только с относительным URI, а не абсолютным. Проблема в том, что я не могу заставить его создать относительный URI. - person anothershrubery; 11.04.2012
comment
Я просто попытался добавить Content-Type, чтобы проверить вашу теорию, но все равно получаю ту же ошибку. - person anothershrubery; 11.04.2012
comment
Как я уже сказал, запрос POST работает при использовании того же самого запроса только с относительным URI, а не абсолютным ‹- Вы не сказали ничего подобного. На самом деле вы сказали, что они предоставили вам пример, который, по вашему мнению, работает. Проверить эту теорию несложно. Попробуйте полностью обойти VB и использовать такой инструмент, как netcat: cat example.txt | nc blah 80. Есть порт netcat для Win32 и аналогичные инструменты. Дело в том, что это быстрый способ узнать, правильное ли дерево вы лаете, потому что оно отправит именно то, что вы ему скажете. - person SpliFF; 11.04.2012