Как установить связанный объект, используя HATEOAS?

Я не могу использовать успокоительный API со ссылками HATEOAS, сгенерированными из репозиториев Springboot.

Рассмотрим следующую модель:

public class Order {
  private UUID id;
  private String orderNumber;
  private Location location;
}

public class Location {
  private String street;
  private String town;
}

Просто для удобства чтения я исключил любой стандартный код, такой как геттеры, сеттеры и конструкторы.

После запуска сервиса я создал пустой Order, что я могу запросить как:

>curl http://localhost:8080/orders/1

Который возвращает:

{
  "orderNumber": "ON 0815", 
  "_links": {
    "self": {
      "href": "http://localhost:8080/orders/1"
    },
    "location": {
      "href": "http://localhost:8080/orders/1/location"
    }
  }
}

Теперь, если я позвоню curl http://localhost:8080/orders/1/location, это возвращает HTTP 404 - Not found Это разумно, потому что я еще этого не установил.

Затем я создаю Location установить через HTTP POST:

curl -XPOST http://localhost/8080/locations \
  -H 'Content-Type: application/json' \
  -d '{"street": "Bakerstreet 221B", "town": "London"}'

Служба отвечает:

{
  "street": "Bakerstreet 221B", 
  "town": "London",
  "_links": {
    "self": {
      "href": "http://localhost:8080/locations/1"
    }
  }
}

Теперь мы подошли к делу, я застрял на. Как мне связать Location к Order ? Ни одна из моих попыток не сработала. Буду благодарен за любой совет.

Пока что попробовал:

1. Поставить объект

>curl -XPUT http://localhost:8080/orders/1 \
  -H 'Content-Type: application/json' \
  -d '{"orderNumber": "ON 0815", "_links": {"self": {"href": "http://localhost:8080/orders/1"}, "location": {"href": "http://localhost:8080/orders/1/location"}}}'

2. ЗАПИШИТЕ объект

>curl -XPATCH http://localhost:8080/orders/1 \
  -H 'Content-Type: application/json' \
  -d '{"_links": {"self": {"href": "http://localhost:8080/orders/1"}, "location": {"href": "http://localhost:8080/orders/1/location"}}}'

3. ПОСТ на ссылку

>curl -XPOST http://localhost:8080/orders/1/location \
  -H 'Content-Type: application/json' \
  -d '{"street": "Bakerstreet 221B", "town": "London"}'

1 ответ

Решение

Резюме управления

>curl -XPUT http://localhost:8080/orders/1/location \
  -H "Content-Type: text/uri-list" \
  -d "http://localhost:8080/location/1"

Подробное описание

Если я называю вложенное местоположение URI с -I флаг и запрещенный метод, разрешенные методы перечислены.

>curl -I -XPOST http://localhost:8080/orders/1/location \
  -H 'Content-Type: application/json'

HTTP/1.1 405 
Allow: GET,PUT,PATCH,DELETE
Content-Length: 0
Date: Mon, 29 Oct 2018 08:59:19 GMT

Это означает PUT на этом URL должен быть действительным. Помещение этого URL с пустым телом приводит к:

>curl -XPUT http://localhost:8080/orders/1/location \
  -H 'Content-Type: application/json' \
  -d '{}'

{"cause":null,"message":"Must send only 1 link to update a property reference that isn't a List or a Map."}

После поиска этого сообщения я обнаружил, что мой Content-Type был неправ. Мне нужно использовать Content-Type: text/uri-list и добавьте URL-адрес местоположения, чтобы установить в качестве тела.

>curl -XPUT http://localhost:8080/orders/1/location \
  -H "Content-Type: text/uri-list" \
  -d "http://localhost:8080/location/1"
Другие вопросы по тегам