删除请求与有效载荷或表单数据会导致错误的请求

问题描述:

我建立一个RESTful Web服务与Java泽西2.17。客户端吧。我正在开发与ExtJS的5。

I am building a RESTful Web Service with Java Jersey 2.17. The Client for it. I am developing with ExtJS 5.

我在服务类

Main.java

Main.java

 public class Main
 {
    public static final String BASE_URI = "http://localhost:8080/app/rest/";
    public static HttpServer startServer() {
        final ResourceConfig rc = new ResourceConfig();

        rc.packages(true, "app");
        rc.register(ResponseCorsFilter.class);

        return GrizzlyHttpServerFactory.createHttpServer(URI.create(Main.BASE_URI), rc);
    }

    public static void main(final String[] args) throws IOException {
        final HttpServer server = Main.startServer();
        System.out.println(String.format("Jersey app started with WADL available at " + "%sapplication.wadl\nHit enter to stop it...",
                Main.BASE_URI));
        System.in.read();
        server.stop();
    }
}

UserRi.java

UserRi.java

@Path("/user")
public class UsersRi {
    @DELETE
    @Path("/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public String deleteUser(@PathParam("id") final String id) {
        final String res = "{\"success\":true,\"msg\":\"User " + id + " successfully deleted.\"}";
        return res;
    }
}

ResponseCorsFilter.java

ResponseCorsFilter.java

public class ResponseCorsFilter implements ContainerResponseFilter {

    @Override
    public void filter(final ContainerRequestContext req, final ContainerResponseContext contResp) {

        contResp.getHeaders().add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        contResp.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        contResp.getHeaders().add("Access-Control-Allow-Origin", "*");

        final String reqHead = req.getHeaderString("Access-Control-Request-Headers");
        if ((null != reqHead) && StringUtils.isNotBlank(reqHead)) {
            contResp.getHeaders().add("Access-Control-Request-Headers", reqHead);
        }

    }

}

目前,我坚持删除内容。在客户端上我得到一个小组的形式记录和调用的擦除功能。请求/响应正在寻找这样的:

At the moment I am stuck with deleting content. On the client I get the record from a form panel and calling the erase function. The Request/Response is looking like this:

General:
    Remote Address:127.0.0.1:8080
    Request URL:http://localhost:8080/app/rest/user/user4
    Request Method:DELETE
    Status Code:400 Bad Request

Response Headers
    Connection:close
    Content-Length:0
    Date:Tue, 14 Apr 2015 19:26:05 GMT

Request Headers
    Accept:*/*
    Accept-Encoding:gzip, deflate, sdch
    Accept-Language:de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
    Connection:keep-alive
    Content-Length:14
    Content-Type:application/json
    Host:localhost:8080
    Origin:http://localhost
    Referer:http://localhost/app/
    User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36
    X-Requested-With:XMLHttpRequest

Request Payload
    {"id":"user4"}

在控制台中我看到 XMLHtt prequest无法加载的http://本地主机:8080 / APP / REST /用户/ USER4。没有访问控制 - 允许 - 原产地标头的请求的资源present。原产地'的http:// localhost'的,因此没有允许访问。响应有HTTP状态code 400。

这也可重复执行与以下jQuery.ajax()调用: $.ajax({method:'DELETE',url:"http://localhost:8080/app/rest/user/user4",data:{"id":"user4"}})$c$c>

It is also reproduceable with following jQuery.ajax() call: $.ajax({method:'DELETE',url:"http://localhost:8080/app/rest/user/user4",data:{"id":"user4"}})

发送请求而没有表单数据或有效负载是工作

Sending the request without the form data or the payload is working.

有另一种方式来解决这个问题,而不在ExtJS的框架覆盖的东西?

Is there another way to solve this without overriding stuff in the ExtJS Framework?

问候
的Sören

Greetings
Sören

删除,以及 GET 请求不应该有一个有效载荷(实体主体)。我不知道这是指定的任何地方,但你可以看到讨论这里

DELETE, as well as GET requests should not have a payload (entity body). I don't know if this is specified anywhere, but you can see discussion here.

这是什么导致了 400错误的请求(将要发生的GET也)。摆脱它,它会工作。但无论如何,竟然没有一个需要发送的身体,你是唯一信息是 ID ,其中已经包含在URL路径。

That's what's causing the 400 Bad Request(will occur for GET also). Get rid of it, and it will work. But anyway there is not even a need to send that body, as you are, only information is the id, which is already included in the in the URL path.

如果这只是一个例子,你需要一起发送请求其他一些任意的信息,然后使用查询参数,例如:

If that's just an example, and you need to send some other arbitrary information along with the request, then use query params, e.g.

 /app/rest/user/user4?some=value1&other=value2&data=value3

 public String deleteUser(@PathParam("id") final String id,
                          @QueryParam("some") String some,
                          @QueryParam("other") String other,
                          @QueryParam("data") String data) {}

使用jQuery的,你可以做

With jQuery, you could do

var params = {
    some:"valeu1",
    other:"value2",
    data:"value3"
}

var encoded = $.param(params);
var url = baseUrl + "?" + encoded;
$.ajax({
    url: url,
    ...
})


更新

于是经过一番调查,这似乎是一个灰熊的问题。我已经与码头进行测试,并能正常工作。


UPDATE

So after some investigation, this seems to be a Grizzly problem. I've tested with Jetty, and it works fine.

请参阅类似的问题

  • 这里 - 最后的评论说,它是固定的,但我不能生产工作例如
  • 这里
  • Here - last comment says it's fixed, but I can't produce a working example
  • Here

因此​​,作为 @alexey 以下

您说的没错,灰熊在默认情况下不允许有效载荷的HTTP方法,为此,HTTP规范并没有明确指出。像HTTP GET,DELETE,HEAD。启动请不是方法应该叫; httpServer.getServerConfiguration()setAllowPayloadForUndefinedHttpMethods(真):但你可以通过调用切换的支持上。 > HttpServer的

You're right, Grizzly by default doesn't allow payload for HTTP methods, for which HTTP spec doesn't explicitly state that. Like HTTP GET, DELETE, HEAD. But you can switch the support on by calling: httpServer.getServerConfiguration().setAllowPayloadForUndefinedHttpMethods(true)‌​; Please not the method should be called before starting HttpServer

所以,解决将是像做

public static HttpServer createServer() {
    final ResourceConfig rc = new ResourceConfig();
    rc.packages(true, "app");
    rc.register(ResponseCorsFilter.class);

    HttpServer server = GrizzlyHttpServerFactory.createHttpServer(
                               URI.create(BASE_URI), rc, false);
    server.getServerConfiguration().setAllowPayloadForUndefinedHttpMethods(true);
    return server;
}

public static void main(String[] args) throws IOException {
    final HttpServer server = createServer();
    server.start();
    System.out.println(String.format("Jersey app started with WADL available at "
            + "%sapplication.wadl\nHit enter to stop it...", BASE_URI));
    System.in.read();
    server.stop();
}

测试,它按预期工作。

Tested and it works as expected.