1

Failed to load resource: the server responded with a status of 405.

I'm doing on online course from f-secure and Uni of Helsinki. I passed the test but I can't let me server accept delete request after @CrossOrigin(origins="/**"). The app is a simple task list where a form takes an input and creates a list element. The app also stores the input as objects in another page, /tasks. And when I want to delete them, /tasks won't let me. http.send in the html file gives me the error. How do I make the server accept my delete requests? Some interesting note; I get the same error no matter where I send the delete request. It might aswell be 4140i2t0efsk.org. Same error. CORS is enabled.

Chrome console error:

(index):112 DELETE http://localhost:8080/(random id) 405 () XHR failed loading: DELETE "http://localhost:8080/(same random id). 

TaskController.java

 package sec.controller; import java.util.ArrayList; import java.util.List; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import sec.domain.Task; @RestController @CrossOrigin(origins = "/**") @RequestMapping("/tasks") public class TaskController { private List<Task> tasks; public TaskController() { this.tasks = new ArrayList<>(); Task fixme = new Task(); fixme.setName("A random task."); this.tasks.add(fixme); } @RequestMapping(method = RequestMethod.GET) public List<Task> list() { return this.tasks; } @RequestMapping(method = RequestMethod.POST) public Task add(@RequestBody Task task) { this.tasks.add(task); return task; } @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) public Task delete(@PathVariable String id) { Task t = this.tasks.stream().filter(task -> task.getId().equals(id)).findFirst().get(); this.tasks.remove(t); return t; } }' 

tasks.html

 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head lang="en"> <meta charset="UTF-8" /> <title>Tasks</title> </head> <body> <h2>Tasks</h2> <a href="http://127.0.0.1:8080/tasks">Existing tasks</a> <!-- TODO: add the ability to list tasks --> <ul id="tasks"> </ul> <form> <input type="text" name="name" id="name"/> <input type="button" onclick="addTask()" value="Add!"/> </form> <!-- the javascript has been embedded to the same site --> <script th:inline="javascript"> var url = null; function loadTasks() { console.log("Requesting XML HTTP"); var http = new XMLHttpRequest(); http.onreadystatechange = function() { if (http.readyState == 4) { console.log("***READY"); if (http.status == 200) { console.log("***STATUS OK"); var response = JSON.parse(http.responseText); console.log("***RESPONSE ", response); // object console.log("***TYPE HTTP RESPONSE", typeof(http.response)); console.log("***TYPE RESPONSE", typeof(response)); console.log("***HTTP RESPONSE ", http.response); //string console.log("***FOR EACH..."); response.forEach(addTaskToList); }; } }; http.open("GET", "/tasks", true); http.send(null); } function addTask() { var name = document.querySelector("#name").value; if (!name) { return; } console.log("**NAME ",name, ); var http = new XMLHttpRequest(); http.open("POST", url, true); http.setRequestHeader("Content-type", "application/json"); var data = new Object(); data.name = name; http.onreadystatechange = function () { if (http.readyState === 4) { if (http.status === 200) { addTaskToList(JSON.parse(http.responseText)); } } }; http.send(JSON.stringify(data)); } function addTaskToList(task) { var liElement = document.createElement("li"); liElement.id = task.id; console.log("***Element id: ", task.id); console.log("***Element type:", typeof(liElement)); liElement.appendChild(document.createTextNode(task.name)); liElement.addEventListener("click", function(){removeTask(task.id);}); document.querySelector("#tasks").appendChild(liElement); } function removeTask(task_id) { console.log("***REMOVE TASK: ", task_id); document.getElementById(task_id).innerHTML = "Removing..."; document.getElementById(task_id).remove(); var http = new XMLHttpRequest(); http.open("DELETE", "/"+(String(task_id)), true); http.setRequestHeader("Content-type", "application/json"); http.onload = function() { tasks = JSON.parse(http.responseText); if (http.readState == 4) { if (http.status == 200) { console.table(tasks); } else { console.error(tasks); } } }; http.send(String(task_id)); //*** HERE IS THE ERROR *** } window.onload = function () { loadTasks(); }; </script> </body> </html> 

Task.java

package sec.domain; import java.util.UUID; public class Task { private String id; private String name; public Task() { this.id = UUID.randomUUID().toString(); } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } 

pom.xml

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>sec</groupId> <artifactId>S201.Tasks</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <properties> <java.version>1.8</java.version> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.1.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <!-- TMC --> <dependency> <groupId>fi.helsinki.cs.tmc</groupId> <artifactId>edu-test-utils</artifactId> <version>0.4.2</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> </configuration> </plugin> </plugins> </build> <repositories> <repository> <id>tmc</id> <name>TMC repo</name> <url>http://maven.testmycode.net/nexus/content/groups/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>tmc</id> <name>TMC repo</name> <url>http://maven.testmycode.net/nexus/content/groups/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository> </pluginRepositories> </project> 

3
  • You might consider using stackoverflow.com/posts/45563338/edit to edit/update your question and paste in the exact error message you’re seeing in your browser devtools console. Commented Aug 8, 2017 at 8:48
  • 1
    Your url should be http://localhost:8080/tasks/(random id) as your RequestMapping("/tasks") in your controller. Commented Aug 8, 2017 at 8:55
  • The thing is the URL doesn't matter. It's the same error no matter the URL I send the delete request to. Commented Aug 8, 2017 at 9:23

2 Answers 2

1
 @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) public Task delete(@PathVariable("id") String id) { Task t = this.tasks.stream().filter(task -> task.getId().equals(id)).findFirst().get(); this.tasks.remove(t); return t; } 

Try to add in method header ("id").

Btw, is there any WebSecurityConfig class? You could share it too.

Sign up to request clarification or add additional context in comments.

7 Comments

No there is only pom.xml and nbactions.xml. I'll try your solution. Can you also explain what I'm trying to do here? Because most of the code is basically a template. I only added to make the add and delete tasks work.
I have a feeling that value = "/{id}" is not corresponded by @PathVariable String id without specifying the name - ("id"). Tell me if this works.
I don't get why I get the same error, delete request denied, when I request to a totally random URL and have CORS enabled.
Could you please paste the URL you are using to call the API?
Sorry, I don't understand the question. I'm a beginner. Basically, the objects are displayed in localhost, 127.0.0.1:8080. The objects reside, in 127.0.0.1:8080/tasks. It is the ones I'm trying to delete. I've sent to request to both 127.0.0.1:8080/task and 127.0.0.1:8080/tasks/{id}. @Peter777
|
1

Solution

The problem was the mapping. As you can see in the code, I send my DELETE request to /{id}. Since the objects which I'm trying to delete reside in localhost:8080/tasks, I should've sent the DELETE request to /tasks/{id}.

Thank you for your help. It took me days to figure a simple problem out.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.