1

I am building 2 REST microservices: ParentService and ChildService. I need to build endpoint to fetch all Child resources related to specific Parent, so I have these URI's as options:

  1. GET /parent/{parent_id}/child
  2. GET /child/parent/{parent_id}
  3. POST /child Body: {parentId: 123}

But neither seems to be proper solution:
  1. /parent prefix is reserved for ParentService. Also, fetching child resources in ParentService does not work b/c I need decoupled services.
  2. reverted hierarchy is contradicting intuition
  3. POST is reserved for creating resource

Is there any standard practice in REST to cover this case in Microservice architecture?

milosdju
  • 111
  • 1
  • 3

4 Answers4

5

Is there any standard practice in REST to cover this case in Microservice architecture?

No, because REST does not prescribe things such as reserving certain route parameters for certain microservices. REST does not contain any definition of microservices to begin with, let alone how multiple microservices should(n't) interact or how to share/separate routes.

You're succumbing to your own arbitrary rules here. None of this is technically impossible, you're just constantly bumping into the rules that you've set out for yourself. It's time to revise the rules and see if they actually make sense or if they are unnecessary blockers.

Something has got to give here. Points 2 and 3 do touch on REST principles, so I'd argue that your question implies that you don't want to budge on these as much as you would on point 1. And in my opinion, point 1 is the weakest link:

/parent prefix is reserved for ParentService.

Why? What are you achieving by prohibiting this? Because whatever it is that drove you to accept this as a rule, it is squarely at odds with the part of your brain that offered GET /parent/{parent_id}/child as a potential solution.

The key question you need to ask yourself here is what the purpose is of "route nesting" your microservices. What are you getting out of this?

Or, another way to phrase the same quandary: is the (sub)route structure owned by an individual microservice, or is the whole route structure owned by your ecosystem (i.e. collection of microservices?

I'm not telling you which answer is correct, but you need to pick a lane here and stick with it.

Either you agree that services owning their own route prefixes is necessary, and therefore you sign yourself up for your child service needing to have a route that is distinct from the parent route prefix; or you agree that it is not necessary and therefore allow yourself to have the "get child by parent ID" endpoint make itself indistinguishable (to an outside consumer) from actual parent-related endpoints.

Flater
  • 58,824
1

I usually start with the premise that:

GET /child
GET /parent

Return all children and parents respectively.

Then I can simply apply filters:

GET /child?parent_id=456
GET /parent?has_child=true
GET /parent?has_child_with_id=123
  1. Since a child likely has a parent_id attribute we can filter on it.
  2. Checks for any parents with at least one child.
  3. Looks for a parent with a child with a specific id.

I do this because, I often need to add additional filter criteria and it's just a case of appending all the filters I need:

GET /child?parent_id=456&active=true

The critical point is that both child and parent are individually addressable, probably using the paths:

/child/{id}
/parent/{id}

Hence I provide direct access to them at the top level - I would typically only use additional paths to:

  • Invoke an action: POST /child/123/go_clean_room
  • Or query part of the state which isn't directly addressable: GET /child/123/left_sock_color

PS: You probably also need to add pagination and API versioning (omitted above for clarity).

DavidT
  • 4,601
0

Is there any standard practice in REST to cover this case in Microservice architecture?

The common sense is to define a narative detailed formally by overview of RESTful API Description Languages wikipedia page

RESTful (representational state transfer) API (application programming interface) DLs (description languages) are formal languages designed to provide a structured description of a RESTful web API that is useful both to a human and for automated machine processing. API description languages are sometimes called interface description languages (IDLs). The structured description might be used to generate documentation for human programmers; such documentation may be easier to read than free-form documentation, since all documentation generated by the same tool follows the same formatting conventions. Additionally, the description language is usually precise enough to allow automated generation of various software artifacts, like libraries, to access the API from various programming languages, which takes the burden of manually creating them off the programmers.

... or by Clean URL wikipedia page

Clean URLs (also known as user-friendly URLs, pretty URLs, search engine-friendly URLs or RESTful URLs) are web addresses or Uniform Resource Locator (URLs) intended to improve the usability and accessibility of a website, web application, or web service by being immediately and intuitively meaningful to non-expert users. Such URL schemes tend to reflect the conceptual structure of a collection of information and decouple the user interface from a server's internal representation of information. Other reasons for using clean URLs include search engine optimization (SEO), conforming to the representational state transfer (REST) style of software architecture, and ensuring that individual web resources remain consistently at the same URL. This makes the World Wide Web a more stable and useful system, and allows more durable and reliable bookmarking of web resources.

It is common for a web service to have the response customisable according to request details. For the first option the URL GET /parent/{parent_id}?children=true should tell to the ParentService to respond just with the collection of children and it is just a technical detail to move from GET /parent/{parent_id}?children=true to GET /parent/{parent_id}/children.

Summed up the web services URI define a narative and requests to the same root URI could have the responses narrowed by including different details in the request URL.

0

One could also create another service.

  • Parent Service
  • Child Service
  • Descendent Service

Sample Service Methods

  • GET /parent/{parentId}
  • GET /child/{childId}
  • GET /descendent/{id}?level={n}

For the descendent service pass and Id (parent or child) and how deep to go.

For example:

GET /descendent/{parentId}?level=1

Would return all the children for that parent (id). If storing this hierarchically, would want to put a limit on how many levels to go down to avoid stack overflows with recursive queries.

Jon Raynor
  • 11,773