Удалить запрос с полезной нагрузкой или данными формы вызывает плохой запрос
Я создаю веб-сервис RESTful с Java Jersey 2.17. Клиент для него. Я развиваюсь с ExtJS 5.
Мои занятия по службе
Главная.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.wadlnHit enter to stop it...",
Main.BASE_URI));
System.in.read();
server.stop();
}
}
Юзерри.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
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);
}
}
}
В данный момент я застрял с удалением контента. На клиенте я получаю запись из панели формы и вызываю функциюerase . Запрос / ответ выглядит следующим образом:
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"}
На консоли я вижу XMLHttpRequest cannot load http://localhost:8080/app/rest/user/user4. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. The response had HTTP status code 400.
Он также воспроизводится с помощью следующего jQuery.вызов ajax (): $.ajax({method:'DELETE',url:"http://localhost:8080/app/rest/user/user4",data:{"id":"user4"}})
Отправка запроса без данных формы или полезной нагрузки работает.
Есть ли другой способ решить эту проблему без переопределения материала в рамках ExtJS?
Приветствую
Серен
2 ответа:
DELETE
, а такжеGET
запросы не должны иметь полезной нагрузки (тело сущности). Я не знаю, указано ли это где-нибудь, но вы можете увидеть Обсуждение здесь.Вот что вызывает
400 Bad Request
(произойдет и для GET). Избавьтесь от него, и он будет работать. Но в любом случае нет даже необходимости отправлять это тело, как вы, только информация являетсяid
, которая уже включена в URL-путь.Если это только пример, и вам нужно отправить какой-то другой произвольную информацию вместе с запросом, затем используйте параметры запроса, например
/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 вы можете сделать
var params = { some:"valeu1", other:"value2", data:"value3" } var encoded = $.param(params); var url = baseUrl + "?" + encoded; $.ajax({ url: url, ... })
Обновление
Таким образом, после некоторого исследования, это кажется проблемой Гризли. Я проверил с Джетти, и он работает нормально.См. аналогичный вопрос
- здесь - последний комментарий говорит, что это исправлено, но я не могу привести рабочий пример
- здесь
Обновление 2
Так как @alexey указано в комментарии ниже
Вы правы, Grizzly по умолчанию не разрешает полезную нагрузку для HTTP-методов, для которых HTTP-спецификация явно не указывает это. Например, HTTP GET, DELETE, HEAD. Но вы можете включить поддержку, вызвав:
httpServer.getServerConfiguration().setAllowPayloadForUndefinedHttpMethods(true);
пожалуйста, не вызывайте метод перед запуском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(); }
Протестировано, и оно работает, как и ожидалось.
Используя
@Path
на уровне метода, вы переопределяете определенный@Path
на уровне класса.Если вы используете Apache Tomcat, используйте их CORS lib: Tomcat CORS filter. Таким образом, он чище и охватывает все исключения, а также.