1

I have a problem when trying to send a POST request. The sending method looks like this:

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

When running this I get the above error. Through Fiddler I can see that the request looks like:

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>

Now looking at this I suspected that it was due to the fact that the server does not accept POST messages. But some other reading suggests that the the URI http://blah/Request has been generated with a proxy and should be /Request so the line should read POST /Request HTTP/1.1

So what would be the common reason for this? And if it is a proxy problem, how is it sorted?

As asked below, I have created a new question for the more specific request. Changing absolute URI to relative in HTTP POST header

Community
  • 1
  • 1
anothershrubery
  • 20,461
  • 14
  • 53
  • 98

3 Answers3

1

There is nothing wrong with the POST request, so the problem must lie elsewhere.

There are a number of other places along the way that could be causing trouble:

  1. There could be a bad proxy between you and the server that is changing the HTTP method
  2. The server could be malfunctioning or simply no support POST

My guess, however, is that the server is doing more than just looking at the HTTP method and is instead giving you a 405 error in response to the RPC call that your XML payload is wrapping.

Some RPC servers will (erroneously) use HTTP status codes like this to indicate that the requested method cannot be executed, or that something else is wrong with the request that is of a permissions and security nature.

If the server is slightly better behaved (and you are lucky), it should be returning additional information in the response body that might indicate where the 405 error is coming from.

cdeszaq
  • 30,869
  • 25
  • 117
  • 173
  • Unfortunately the server is owned by a third party and I have no access to it to find out any more details. What would be your advised course of action? – anothershrubery Apr 05 '12 at 09:59
  • Also, I have been advised that the server accepts POST requests, but I am still unsure over this. – anothershrubery Apr 05 '12 at 10:08
  • 1
    Just because the _server_ accepts POST requests doesn't mean that the _software running on the server_ accepts your _particular_ post request. Since you have no access to the server, about the only thing you can do is strip your request down to as little as possible and slowly build it up. Start with an _empty_ POST and then build it up. If possible, ask the server controllers to provide you with an example of an HTTP request (including the full headers) that they know works. – cdeszaq Apr 05 '12 at 12:27
  • They have provided me with one, it is exactly the same as mine only the first line is `POST /Request HTTP/1.1` and not `POST http://blah/Request HTTP/1.1` – anothershrubery Apr 05 '12 at 12:34
  • As long as the Host header is correct, then you should be able to just use `POST /Request`. I'm not _particularly_ familiar with constructing that request in vb.net, but it shouldn't be too hard. – cdeszaq Apr 05 '12 at 12:39
  • I've been trying to get just the relative path but that's a bit I'm struggling with. – anothershrubery Apr 05 '12 at 12:57
  • So then ask _that_ as an SO question ;-) – cdeszaq Apr 05 '12 at 12:59
  • Don't like creating another question for a related question, if you know what I mean, but I will! – anothershrubery Apr 05 '12 at 13:57
  • I've marjed this as the answer as a bit of looking into the situation revealed that the third party company had actually given us an IP address which was wrong. Numerous times we asked them to confirm the Host and they said it was correct, but eventually found out it wasn't. The server was setup for our parent company, not us, so we eventually got the correct host and it works. – anothershrubery Apr 17 '12 at 08:32
  • Thanks for your answer, but unfortunately it didn't worked for me (I'm using IIS 7.5). After 2 days of research, the only working solution I found to avoid "405 Method Not Allowed" was to define the CORS headers in the `Application_BeginRequest` method, as mentioned in this answer http://stackoverflow.com/a/14631068/827168 – pomeh Oct 15 '14 at 08:43
0

Are you missing the Content-Type header required for a POST ? Read here for details. I assume it is mandatory.

AYK
  • 3,312
  • 1
  • 17
  • 30
0

Your POST appears to be completely invalid. POST data is supposed to be encoded (ie, as multipart/form-data) and use correct content-type (ie, application/x-www-form-urlencoded) with proper encoding and boundaries etc. You are just sending the server a lump of text and I'm not surprised it flips out.

I'm not 100% sure what VB is doing behind the scenes but this MSDN page suggests you need to set the content-type to a supported method and you probably need Content-Disposition: form-data in your headers as well. I found an example that does this and adds the MIME boundaries:

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

That example emulates a file field upload.

For a simpler version you can use request.ContentType = "application/x-www-form-urlencoded" with URL-encoded data like: Dim postData As String = "myURL=http%3A%2F%2Fexample.com%2Findex.php". Note that the format is key=value and the data must be URL-encoded first.

I'm not sure what exactly you need though because a lot depends on what the remote server actually expects for the form and field names. It also depends wether the server is actually following the relevant HTML standards and RFCs. Do you have a working HTML form to use as a guide for what the server expects?

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
SpliFF
  • 38,186
  • 16
  • 91
  • 120
  • Content-Type, and other headers, are not mandatory. As I have said before the POST request works when using the exact same request only with a relative URI not absolute. The problem being, I cannot get it to produce the relative URI. – anothershrubery Apr 11 '12 at 08:23
  • I just tried adding the Content-Type, to test your theory, and still getting same error. – anothershrubery Apr 11 '12 at 08:47
  • "As I have said before the POST request works when using the exact same request only with a relative URI not absolute" <- You said no such thing. What you actually said was they provided you an example which you assume works. It's not difficult to test that theory. Try bypassing VB altogether and use a tool like netcat: `cat example.txt | nc blah 80`. There's a win32 port of netcat and there's equivalent tools. The point is it's fast way to know if you're barking up the right tree because it will send exactly what you tell it to send. – SpliFF Apr 11 '12 at 13:18