I'm developing microservise which receives HTTP POST requests and then redirects them to another destination point in order to receive response, handle it and hand it to another system.
My question is - how can I avoid deserealization while receiving these requests? The microservice don't handle incoming JSONs. From the performance point of view, it's better to avoid deserealization.
I heard I can use Nginx or Apache but how can I embed them into the microservice?
Is there any proven solution? Just don't want to invent a bicycle.
I don't know what is the technology stack you are using (programming language, framework.. etc) but I suppose that in all of them is a way to recieve incoming rest requests without need to deserialize the body.
For example in a java/spring scenario you can define in the corresponding controller method the body parameter as string and in this case there isn't any deserialization of the body, the method will recieve it as a plain string so you can forward it as is to the other service:
#PostMapping(value = "/path")
public ResponseEntity controllerMethod(#RequestBody String body) {
// your code here
}
Related
We are developing a REST service with Spring Boot and got stuck wondering if every error response should have the same JSON structure?
For error cases our service responds with a simple JSON format. For example, if a parameter is malformed we respond with HTTP status 400 and a JSON:
{
"errorCode": 05,
"message": "provided paramter XY is malformed"
}
The errorCode is our custom code id. One may argue whether this design is good or not, but it is simple and can be easily handled by the service consumer.
Now, Spring Boot creates some error responses automatically. For example, for a TypeMismatchException and response with HTTP status 400 is created. But of course, these automatically generated responses do not have the error format.
So... we have the situation that the service consumer does a prior not know for a HTTP status 400 whether it has the simple JSON error format in the body or not. Should we really overwrite all Spring Boot default exception handling to put our format in each response or should the service consumer swallow the bitter pill and identify if the simple JSON format is used or not?
It depends on the scale of your project. If your API is used by many applications you should go for the "catch everything and use the JSON format"-approach. Yes you would have more to do but when every other application in your company can use your standard way, they can save a lot of time.
In most of the projects where i was involved, we also had a "standard-way" to give our error-responses back (also JSON):
#RestControllerAdvice
public class GlobalResourceExceptionHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(GlobalResourceExceptionHandler.class);
// the class ValidationError contains the properties the json should contain.
#ExceptionHandler(Exception.class)
public List<ValidationError> exceptionHandler(Exception e, HttpServletResponse response) {
LOGGER.warn("Exception thrown in a resource", e);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return Collections.singletonList(new ValidationError(null, "unexpected exception"));
}
}
You can extend the class with more #ExceptionHandlers.
It turned out that this is a pretty good way because it is easy to implement (also for small applications) and it covers a lot. A lot means basically everything which had to do with a rest-request. Excluded from this was a resource-handler, which provided an angular-app and the security-layer.
UPDATE:
Conclusion: Catch everything when you have an api used by many applications. You should use the way shown above to start your error-handling in both cases (small or big app).
I have a rest api set up at api/books, and one can send a new book object there, and it will be added to the database. The guestion is, how can I correctly catch what is being POST'ed, so one can for example, validate what is being sent?
#RequestMapping(value="/api/books", method = RequestMethod.POST)
public String bookSavePost(#RequestBody Book book) {
bookRepository.save(book);
return "redirect:/api/books";
}
This works, as in it saves the book and I can catch what the user sends, but with this enabled, it overrides the default REST method, which doesn't allow one to actually view the api anymore. If I change this particular method to GET, it returns a string "redirect:/api/books", so it doesn't even redirect anything. Is there some way to actually redirect it to the rest api endpoint?
You can write your own reuquest Interceptor .
Spring provides HandlerInterceptor class :
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/HandlerInterceptor.html
Here is a quick sample how to do this:
https://www.baeldung.com/spring-mvc-handlerinterceptor
A redirect requires three two things to be successful: A HTTP code of 301 or 302 AND a location header that includes the endpoint to which you want the client to visit.
E.g., in the headers section you should have
location: '/correct/endpoint'
In Laravel we use routes to deal with HTTP requests from the browser.
We can route a request to a controller, do some logic and then return a response.
Now, we can send in variables encapsulated with braces {} and the response can be anything, so it seems to me that routing through a controller means that the the properties of the different request methods (POST, GET, PUT etc.) are lost.
For example I could send a POST request with URI example/{id} then put in my routes.php file
Route::post('example/{id}','SomeController#SomeAction');
Then I could do something in my controller with the variable $id and send a response.
On the other hand I could send a GET request with URI example/{id} and alter my route to
Route::get('example/{id}','SomeController#SomeAction');
The controller would give the same response.
So, am I right in thinking it does not really matter what request method is used?
Two parts of your question I can identify on a second read-through:
Request methods are not lost. You have access to them with $request->getMethod(). So a GET request will return GET. You also have the method isMethod('GET') available to you, which you could use to get a truthy value which would enable you to return a different kind of response depending on the request type.
With regards to the way you set up your URL, what HTTP verb you use does matter if you're creating a REST-ful web service.
I won't explain away what a REST-ful web service is (you can look it up), here is a couple of points from your example:
If you're getting some data, you ought to be doing a GET request. It is the verb to represent a read from a resource. If you had to send a lot of data - and your intention is to add data, you ought to POST it instead.
The URI should be meaningful in a way that best describes the resource you are manipulating.
Together with the HTTP verb, you can infer the implied action. So if you are POSTing to example/1, I might infer that (and this is a digression, actually) that you are attempting to update record 1 from an example resource. In reality, you would perhaps use the PUT verb (which handles update).
Behind the scenes, Laravel uses a POST request due to browser limitations but treats it as a PUT request server-side.
Of course request type does matter. When you want to hide some request data against user and dont show it in url for example:
?username="Admin"&nick="admin1" then u will use POST otherwise you can use GET. When you want get some data u will use GET but when you want to send some data then you should use POST instead.
I want to build a typical mvc app for CRUD of simple items, the api s should be RESTful. The catch here is, that i have a large pallete of items that needs to be initialized. On the server side those items are defined as java beans and the corresponding create form for the item is dynamically created from the field information(data type, validation constraints etc) harvested from the bean.
I am new to REST and just read up about how the urls should be nouns defining the resource and action specified by HTTP verb. In that perspective how to model something like
.../client/showForm?type=xyz from non RESTful way to RESTful one ?? My intention here is to tell the server to dynamically construct and send back a CREATE form for client of type xyz. The obvious problem with url i mentioned above is that it specifies action in the url which, from what i have read, makes it non RESTful.
When I think of REST, I think of resources. I think of data. In other words, I don't think of REST as being something that I would typically use to retrieve a form, which is a user interface component.
REST is an architectural style that is used to identify a resource on a server using a uniform resource identifier, or URI. Additionally, actions performed on those resources identified by the URI are determined based on the specific HTTP Method used in the request: GET, POST, PUT, DELETE, etc.
Thus, let's say you have a Client object. That client object might have the following properties:
Name
Location
AccountNumber
If I wanted to retrieve the data for a single client, I might use the following URI:
GET /client/xyz/ # xyx is the accountnumber used to identify the client.
I would use a GET method, since REST describes GET as being the method to use when retrieving data from the server.
The data could theoretically be returned in HTML, since REST is not a standard but more like a series of flexible guidelines; however, to really decouple my data from my user interface, I would choose to use something platform independent like JSON or XML to represent the data.
Next, when adding a client to the collection on the server, I would use the /client/ URI pattern, but I would use the HTTP Method POST, which is used when adding a resource to a collection on the server.
# Pass the data as JSON to the server and tell the server to add the client to the
# collection
POST /client/ {"accountnumber":"abc" , "Name" : "Jones" , "Location" : "Florida"}
If I were to modify an existing record on the server or replace it, I would most likely use the HTTP Method PUT, since REST guidelines say that PUT should be used if repeating the same operation repeatedly would not change the state of the server.
# Replace the client abc with a new resource
PUT /client/abc/ {"accountnumber":"abc" , "Name" : "Bob Jones" , "Location" : "Florida"}
The general idea behind REST is that it is used to identify a resource and then take action on that resource based on what HTTP Method is used.
If you insist on coupling your data with your view, one way accomplish this and retrieve the actual form, with the client data, could be to represent the form as a resource itself:
GET /client/abc/htmlform/
This URL would of course return your client data for client abc, but in an HTML form that would be rendered by the browser.
While my style of coding utilizes data transports such as JSON or XML to abstract and separate my data from my view, you could very well transport that data as HTML. However, the advantage of using JSON or XML is that your RESTful API becomes platform independent. If you ever expand your API to where other developers wish to consume it, they can do so, regardless of what specific platform or programming language they are using. In other words, the API could be used my PHP, Java, C#, Python, Ruby, or Perl developers.
In other words, any language or platform that can make HTTP requests and can send GET, POST, PUT, DELETE requests can be used to extend or build upon your API. This is the true advantage of REST.
For more information on setting up your controllers to use REST with Spring MVC, see this question. Additionally, check out the Spring MVC Documentation for more information.
Also, if you haven't checked out the Wikipedia article on REST, I strongly encourage you to do so. Finally, another good, classic read on REST is How I Explained REST To My Wife. Enjoy.
I have a RESTful URL that requires either the offset or the prefix request parameter (but not both).
GET /users?offset=0&count=20
GET /users?prefix=J&count=20
What's the best way to enforce this rule? Spring has the #RequestParam annotation with the 'required' property for optional parameters, but I want to enforce an "either-or" rule on these two parameters. I know I could do it in the code, but is there another way to do it?
Also, what's the proper way to handle "impractical" requests? Say I have 100 million users; the following request, although properly RESTful, is not something I want to support:
GET /users <-- Gets all 100 million users, crashes server and browser!
What should I send back?
You can create two methods and choose one of them with #RequestMapping's params attribute:
#RequestMapping(..., params = {"prefix", "!offset"})
public String usersWithPrefix(#RequestParam("prefix") ...) { ... }
#RequestMapping(..., params = {"offset", "!prefix"})
public String usersWithOffset(#RequestParam("offset") ...) { ... }
what's the proper way to handle "impractical" requests?
The lesser-practiced principles of REST include the requirement that resources be "discoverable". If you are asked for a complete list of 800 million users and you don't want to provide it, you might instead consider serving a page that describes in some way how to filter the collection: for example, an XForms document or HTML containing a FORM element with fields for offset/prefix/count, or a URI template with the appropriate parameters
Or you could just send a "413 Entity too large" error - edit: no you can't. Sorry, I misread the description of whath this code is for
If you decide to go down the route of just sending the first page, I think I would send it as an HTTP redirect to /users?offset=0&count=20 so that the client has a better idea they've not got the full collection (and if your response contains a link to access subsequent pages, even better)