I am building HTTP REST API and implementing CQRS, DDD, ES, and microservices concept for the API.
For example, I want to build API for ordering system. The order contains order status, customer data, employee data, cart items, shipping data. The order command service and order query service are using different code, different databases. and different ip / port.
Customer data consists of customer id, first name, last name, contact numbers, etc. Employee data like sales and staff consists of employee id, email, name, and role. Shipping data consists of shipping address, city, zipcode, shipping note, shipping method, and shipping cost. Cart items contains product id and qty. Customer data, product data, employee data, and shipping method data are produced from other services.
I have two questions when I want to developing it.
What should I do to develop HTTP REST API in a correct way?
Thank you.
I am building HTTP REST API and implementing CQRS, DDD, ES, and microservices concept for the API.
Cool. Keep firmly in your mind that the REST API part is part of your integration component; its purpose is to ensure that old clients can continue to take advantage of your services, even as the implementation of those services evolves.
Jim Webber, Domain-Driven Design for RESTful Systems
The web is not your domain, it's a document management system. All the HTTP verbs apply to the document management domain. URIs do NOT map onto domain objects - that violates encapsulation. Work (ex: issuing commands to the domain model) is a side effect of managing resources. In other words, the resources are part of the anti-corruption layer. You should expect to have many many more resources in your integration domain than you do business objects in your business domain.
When I build the POST method to create new order from sales / staff, what should be in a request payload?
Note the point above about "many more resources" -- you can provide as many different ways (protocols) to create a new order as you are willing to support.
From the point of view of microservices, placing an order probably touches on a number of different business capabilities. See Udi Dahan's writings on UI Composition Techniques, the same concerns have play in machine to machine interfaces.
So from the point of view of the web endpoint that ends up communicating the order with the service(s), the information that you need is going to depend on what the exposed endpoints need.
From the point of view of the client: part of the point of providing a REST API is that the integration resources can guide the client to construct the final submission. Think online shopping experience - Amazon doesn't ask you to type in a bunch of SKUs, or customer ids. You just submit a sequence of forms until you get to a screen that lets you make one last check of the data, and then you submit it if it looks right.
So one of the screens along the way could be something that helps the client figure out what the employee id should be (here's a search form, here's a list to choose from, etc).
When I build the POST / PUT method, should I return response code 200?
Generally speaking, 200 is fine. Unless you are anticipating clients that react cleverly to different forms of success, that will cover most of your cases.
202 Accepted is a finer grained status that's often used when processing is not going to be completed immediately. "Hi, we got your order. Here's a link you can use to check on progress."
For instance, if you were using an architecture where the REST api was going to simply write the order request into a queue for the microservice consumers to pick up, then 202 is conceptually accurate "we wrote it down, and the services will decide for themselves what to do about it".
user want to get the order data instantly.
Instantly isn't a latency that you are ever likely to meet, so you'll want an SLA that's a bit more forgiving.
I wouldn't expect that kind of a problem; after all, if your design is CQRS, you can have a denormalized representation of a lot of the data available in a hot cache. If that representation is independently addressable, and cacheable, you may be able to re-use a copy that's stored on the client.
But, how the backend API know that user wants to buy that product to an order? We receive the SKU as payload, don't we?
Not necessarily -- we receive something the REST API can use to calculate the SKU. It could be something else. But a SKU is fine: the main point from the perspective of the client is that the message formats didn't change; the main point from the perspective of the shopper is that she didn't have to care what was in the payload, because she had stable semantic cues to work from (ie: she was looking at the product name, but what the form submitted under the covers was the SKU).
What is the ideal way to map the HTTP verbs, URI, and domain objects?
Other way around: what's the right way to make your backend service look like a web site?
Ever use your web browser to configure a wireless router? How does that work -- a routers internals are nothing like a web site. There's no reason that the app that you use to ask questions on stack overflow should work as a router configuration tool. Yet it does, because the API on the router knows how to duck like a web site while at the same time sending the right instructions to the back end.
The REST client is only looking at the messages it receives; it doesn't know anything about domain objects; it only knows about representations of resources (think documents describing things).
The ideal way to map the HTTP verbs, and so on, it to pretend to be a dumb document store.