对于 Restful Web 服务,PUT 和 POST 获得 405 Method Not Allowed 错误

Posted

技术标签:

【中文标题】对于 Restful Web 服务,PUT 和 POST 获得 405 Method Not Allowed 错误【英文标题】:PUT and POST getting 405 Method Not Allowed Error for Restful Web Services 【发布时间】:2014-02-11 15:30:53 【问题描述】:

我正在尝试设置一个简单的 Restful Web 服务,它根据 Accept 标头返回 JSON 或 XML。我正在使用 Spring、Maven 和 WebLogic Server。我从这篇文章http://software.sawano.se/2012/03/combining-json-and-xml-in-restful-web.html 中举了一个例子,并试图改进它。 GET 和 DELETE 适用于 JSON 和 XML。但 PUT 和 POST 给出“405 Method Not Allowed”错误。我正在尝试使用 Chrome Extension Advanced Rest Client 对此进行测试。下面是响应头。

Status
405 Method Not Allowed Show explanation Loading time: 327

Request headers 
Accept: Application/json
Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36
Content-Type: application/x-www-form-urlencoded 
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8


Response headers 
Connection: close
Date: Tue, 11 Feb 2014 15:17:24 GMT 
Content-Length: 34 
Content-Type: text/html 
Allow: GET, DELETE 
X-Powered-By: Servlet/2.5 JSP/2.1
Raw
Parsed

我给出的请求正文如下:


id: 1
name: "manga"

我的控制器类如下图:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.HashSet;
import java.util.Set;

@Controller
@RequestMapping("/users")
public class RESTController 
Userlist obj2;
boolean flag=false;
private Logger logger = LoggerFactory.getLogger(getClass());

@RequestMapping(value = "/id",method = RequestMethod.GET)
@ResponseBody
public User getUser(@PathVariable int id, @RequestHeader("Accept") String acceptHeader) 
    User temp = new User();
    if(obj2==null)
    
        temp= new User(0, "Null");
    
    else   
        Set<User> set1= obj2.getUsers();
        for(User a:set1)
        
            if(id==a.getId()) temp=a;
        
      
    logger.trace("Serving resource for Accept header: ", acceptHeader);
    return temp;


@RequestMapping(value="",method = RequestMethod.GET)
@ResponseBody
public Userlist getUsers()
    if(flag==false)
    User new1=new User(1,"Rob");
    User new2=new User(2,"VAN");
    User new3=new User(3,"DAM");
    User new4=new User(4,"Helio");
 Set<User> obj1 =new HashSet<User>();
    obj1.add(new1);
    obj1.add(new2);
    obj1.add(new3);
    obj1.add(new4);
    obj2=new Userlist(obj1);
    flag=true;
    
    return obj2;


@RequestMapping(value="/id",method = RequestMethod.DELETE)
@ResponseStatus(HttpStatus.OK)
public void deleteUser(@PathVariable int id)
    Set<User> set1= obj2.getUsers();
   for(User a:set1)
    
        if(id==a.getId()) set1.remove(a);
     
    Userlist obj3=new Userlist(set1);
    obj2=obj3;
    //return obj3;


@RequestMapping(value="/id",method = RequestMethod.PUT, consumes = "Application/json")
@ResponseStatus(HttpStatus.OK)
public void updateUser(@PathVariable int id, @RequestBody User temp)
    System.out.println("Inside the put function");
        if(temp==null)System.out.println("This is a Null for PUT");
 

现在我在 PUT 中没有任何内容。

【问题讨论】:

Allow 响应仅显示“GET,DELETE”。这是服务器问题... 【参考方案1】:

注意响应中允许的方法

Connection: close
Date: Tue, 11 Feb 2014 15:17:24 GMT 
Content-Length: 34 
Content-Type: text/html 
Allow: GET, DELETE 
X-Powered-By: Servlet/2.5 JSP/2.1

它只接受 GET 和 DELETE。因此,您还需要调整服务器以启用 PUT 和 POST。

Allow: GET, DELETE

【讨论】:

正是我的问题。很好地检查响应中允许的方法:) 谢谢,这正是我需要的线索。 你说“调整服务器”是什么意思? @aNish 我同意 Vasanth K V 的观点:当你说“调整服务器”时,你到底是什么意思?我需要详细信息!【参考方案2】:

好吧,显然我不得不更改我的 PUT 调用函数 updateUser。我删除了@Consumes@RequestMapping,并在函数中添加了@ResponseBody。所以我的方法是这样的:

@RequestMapping(value="/id",method = RequestMethod.PUT)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public void updateUser(@PathVariable int id, @RequestBody User temp)
    Set<User> set1= obj2.getUsers();
    for(User a:set1)
    
        if(id==a.getId())
        
            set1.remove(a);
            a.setId(temp.getId());
            a.setName(temp.getName());
            set1.add(a);
        
    
    Userlist obj3=new Userlist(set1);
    obj2=obj3;

成功了!!!谢谢大家的回复。

【讨论】:

【参考方案3】:

我不确定我是否正确,但来自您发布的请求标头:

请求标头

接受:应用程序/json

来源:chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo

用户代理:Mozilla/5.0(Windows NT 6.1;WOW64)AppleWebKit/537.36(KHTML,如 Gecko)Chrome/29.0.1547.76 Safari/537.36

内容类型:application/x-www-form-urlencoded

接受编码:gzip,deflate,sdch 接受语言:en-US,en;q=0.8

您似乎没有将请求正文配置为 JSON 类型。

【讨论】:

【参考方案4】:

同样的事情发生在我身上, 如果你的代码是正确的,然后也给出 405 错误。由于某些授权问题导致此错误。 转到授权菜单并更改为“从父级继承身份验证”。

【讨论】:

【参考方案5】:

在我的情况下,表单(我无法修改)总是发送 POST。 在我的 Web 服务中,我尝试实现 GET 方法(由于缺乏文档,我希望两者都被允许)。

因此,它因“不允许”而失败,因为我这边没有 POST 类型的方法。

在我的 WS 方法上方将 @GET 更改为 @POST 解决了该问题。

【讨论】:

【参考方案6】:

问题是 nginx 服务器的静态文件请求禁止使用 POST 方法。这是解决方法:

# Pass 405 as 200 for requested address:

server 
listen       80;
server_name  localhost;

location / 
    root   html;
    index  index.html index.htm;


error_page  404     /404.html;
error_page  403     /403.html;

error_page  405     =200 $uri;

如果使用代理:

# If Nginx is like proxy for Apache:

error_page 405 =200 @405; 

location @405  
    root /htdocs; 
    proxy_pass http://localhost:8080; 

如果使用 FastCGI:

location ~\.php(.*) 
fastcgi_pass 127.0.0.1:9000;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
include /etc/nginx/fastcgi_params;

浏览器通常使用 GET,因此您可以使用ApiTester 等在线工具来测试您的请求。

来源

http://translate.google.com/translate?hl=&sl=ru&tl=en&u=https%3A%2F%2Fruhighload.com%2F%D0%9E%D1%88%D0%B8%D0%B1%D0%BA%D0%B0%20nginx%20405%20not%20allowed

【讨论】:

以上是关于对于 Restful Web 服务,PUT 和 POST 获得 405 Method Not Allowed 错误的主要内容,如果未能解决你的问题,请参考以下文章

如何在我的 Rails RESTful Web 服务中接受 PUT 和 DELETE 方法

使用 Jersey 和 Apache Tomcat 构建 RESTful Web 服务

IIS 7.5 + 为 RESTFul 服务启用 PUT 和 DELETE,无扩展

对于非 RESTful 的 HTTP Web 服务或对此类 Web 服务的调用是不是有标准术语?

RESTful 规范

(转)理解POST和PUT的区别,顺便提下RESTful