dvf/blockchain · error
$
Error message
$"{new HttpResponseMessage(HttpStatusCode.MethodNotAllowed)}" What it means
The /transactions/new route only accepts POST; any other HTTP method (typically GET) is rejected with a 405 MethodNotAllowed response. However, the handler stringifies an HttpResponseMessage object, so instead of a real HTTP 405 status the server returns 200 OK whose body is the object's ToString() dump (e.g. 'StatusCode: 405, ReasonPhrase: Method Not Allowed'). Clients expecting JSON fail to parse the body and standard HTTP error handling never fires.
Solutions
- Send the request with method POST and a JSON transaction body
- Fix the server to set the real status code on the HttpListenerResponse (response.StatusCode = 405) instead of interpolating an HttpResponseMessage into the returned string
- Add an 'Allow: POST' header to the 405 response so clients learn the supported method
- Ensure the client serializes Sender/Recipient/Amount as JSON, since a correct POST still needs a deserializable body
Example fix
// before
if (request.HttpMethod != HttpMethod.Post.Method)
return $"{new HttpResponseMessage(HttpStatusCode.MethodNotAllowed)}";
// after (server-side, respond with a real 405)
if (request.HttpMethod != HttpMethod.Post.Method)
{
response.StatusCode = (int)HttpStatusCode.MethodNotAllowed;
response.Headers["Allow"] = "POST";
return "Method Not Allowed: use POST for /transactions/new";
} Defensive patterns
Strategy: validation
Validate before calling
// client-side check before sending
using (var req = new HttpRequestMessage(HttpMethod.Post, "http://localhost:12345/transactions/new"))
{
req.Content = new StringContent(json, Encoding.UTF8, "application/json");
// send req; a 405 (or a 'StatusCode: 405' body) means the wrong method was used
} Type guard
static bool IsPostRequest(string method) =>
string.Equals(method, "POST", StringComparison.OrdinalIgnoreCase); Try / catch
try
{
var resp = await client.PostAsJsonAsync(url, trx);
if (resp.StatusCode == HttpStatusCode.MethodNotAllowed)
throw new InvalidOperationException("Use POST for /transactions/new");
}
catch (HttpRequestException ex)
{
// log/handle the failed request; do not retry with the same verb
} Prevention
- Always send POST with a JSON body to /transactions/new
- Never test POST-only endpoints by pasting the URL into a browser
- Check HTTP status codes, not the response body, when validating responses
- Document each route's expected verb next to its path in the server
When it happens
Trigger: Calling GET http://localhost:12345/transactions/new (or PUT/DELETE/HEAD) instead of POST with a JSON body like {"Amount":123,"Recipient":"ebeabf5cc1d54abdbca5a8fe9493b479","Sender":"31de2e0ef1cb4937830fcfd5d2b3b24f"}. Opening the URL in a browser or a client configured with the wrong method hits this branch.
Common situations: Testing the endpoint in a browser address bar (always GET); copying a GET-based REST call pattern to a POST-only route; client libraries defaulting to GET when no body is set; Postman collections or API docs with the wrong verb; proxies or health checkers issuing GET probes.
AI-assisted analysis of dvf/blockchain@68066d6482 (2026-09-13).
Data as JSON: /api/errors/d90e69b870d22dfc.
Report an issue: GitHub.
Appendix: source
Thrown at csharp/BlockChain/WebServer.cs:39
string json = "";
if (path.Contains("?"))
{
string[] parts = path.Split('?');
path = parts[0];
query = parts[1];
}
switch (path)
{
//GET: http://localhost:12345/mine
case "/mine":
return chain.Mine();
//POST: http://localhost:12345/transactions/new
//{ "Amount":123, "Recipient":"ebeabf5cc1d54abdbca5a8fe9493b479", "Sender":"31de2e0ef1cb4937830fcfd5d2b3b24f" }
case "/transactions/new":
if (request.HttpMethod != HttpMethod.Post.Method)
return $"{new HttpResponseMessage(HttpStatusCode.MethodNotAllowed)}";
json = new StreamReader(request.InputStream).ReadToEnd();
Transaction trx = JsonConvert.DeserializeObject<Transaction>(json);
int blockId = chain.CreateTransaction(trx.Sender, trx.Recipient, trx.Amount);
return $"Your transaction will be included in block {blockId}";
//GET: http://localhost:12345/chain
case "/chain":
return chain.GetFullChain();
//POST: http://localhost:12345/nodes/register
//{ "Urls": ["localhost:54321", "localhost:54345", "localhost:12321"] }
case "/nodes/register":
if (request.HttpMethod != HttpMethod.Post.Method)
return $"{new HttpResponseMessage(HttpStatusCode.MethodNotAllowed)}";
json = new StreamReader(request.InputStream).ReadToEnd();
var urlList = new { Urls = new string[0] };View on GitHub (pinned to 68066d6482)