How to change which resources answers a request from Servlet Filter? - redirect

I have a ServletFilter (which happens to be a GuiceShiroFilter) that processes incoming web requests before they go to a Jersey 1.x Resource.
However, in some situations (namely when Shiro finds that the request is not authenticated), I want to change which Jersey resource answers my request, without the resource that otherwise would have answered even being able to respond.
Here's what I have (in my Shiro AuthenticatingFilter.onLoginFailure()):
ServletRequest request = ...;
RequestDispatcher disp = request.getRequestDispatcher("/resource/that/always/responsds/with/a/403");
try {
disp.forward(request, response);
} catch (ServletException | IOException e) {
e.printStackTrace();
}
// this is needed to prevent the woud-be resource from responding as well
return false;
The problem of this server-side redirect is that not returning false will invoke both my resource for "/resource/that/always/responsds/with/a/403" and the original would-be response, and in the best case the response body contains both responses concatenated.
Is there a way to modify an existing instance of (Http)ServletRequest from a Filter such that later on, only the redirected-to resource can answer?

I dug into the issue a little bit and I realized that there is little I can do here, given that I don't control how the filter chain is processed further.
In a generic Filter, the implementer can wrap the current ServletRequest (in doFilter() in a HttpServletRequestWrapper implementation. This wrapper can then override the request URI. However, this requires that the implementer has control over how the filter chain is continued (which is where the wrapped request can be fed back into the execution path), but this is not the case in my situation, where Shiro controls that.
With Shiro, the filter chain continuation is controlled in AdviceFilter.doFilterInternal(), many layers above my own AuthenticatingFilter implementation.
So for now, my best bet is to do what I already described above: Invoke another resource - free from filters - by using a RequestDispatcher and stop the filter chain by returning false at the end of my AuthenticatingFilter's onLoginFailure()

Related

REST URL for transforming one resource into another resource

I am struggling to come with proper REST URL for converting one resource into another. The API method does not do any CRUD operations but instead transform/convert one resource into another type of resource.
I have 2 resources Workunit and Document. I have 3 operations on these two resources
1> trasform Workunit into Document
2> sync Workunit into Document (different logic than transform)
3> transform Document into Workunit
and i have the following urls
[POST] api/v1/workunits/transform
[POST] api/v1/workunits/sync
[POST] api/v1/documents/transform
problem here is action is a part of REST URL
any suggestions?
problem here is action is a part of REST URL
That's not a problem - clients don't depend on the URL for semantics, so you can use any spelling you like; api/v1/4dc233fa-c77c-49d7-b7d6-296ffeb89612 is perfectly satisfactory.
It's analogous to having a verb as a variable name -- it may not be in keeping with your local coding standards, but the compiler doesn't care. So too is it with your URL and the general purpose components that use it.
Choosing a good identifier is like choosing a good name; it requires having a clear understanding of what the thing is. In the case of URI/URL, the thing being identified is a resource, which is to say something that is described by a document. GET/POST/PUT/DELETE and so on are all requests that we do something interesting with the underlying document.
So the usual pattern might be to POST a transform message to the workunit resource, or to POST a transform message to the Document resource, or to POST a sync message to the workunit resource.
Hmm, that last one sounds backwards; if the workunit is unchanged, and the Document is changed by the sync, then you would probably send a sync message to the Document resource.
So if I have /api/v1/documents/1, and I need to sync it, then I would normally use POST /api/v1/documents/1, with the sync semantics described in the message body (on the web, that would usually be an application/x-www-form-urlencoded representation of the sync message).
But it could just as easily be a message that says "Sync documents/1 with workitem/2" that I POST to the todo list for the synchronizer.
We are just putting documents politely into the server's in-tray, so that it can do useful work. The in-tray can have whatever label you want.
It is fine with given situation.
Nevertheless, if I am getting you right it may be a good idea to create two different controllers.
It's up to you but think of changing structure a little bit:
Separate the logic of Transformation and Sync into two different controllers, so you can avoid URL issue.
TransformationController
[Route("api/v1/transformation-controller/")]
TransformationController : ControllerBase
{
[HttpPost("workunits")]
public Task<Response> TransformWorkunits()
{
//logic
}
[HttpPost("documents")]
public Task<Response> TransformDocuments()
{
//logic
}
}
SynchronizationController
[Route("api/v1/synchronization-controller/")]
TransformationController : ControllerBase
{
[HttpPost("workunits")]
public Task<Response> SyncWorkunits()
{
//logic
}
}
So the URLs will be:
[POST] api/v1/transformation-controller/workunits
[POST] api/v1/synchronization-controller/workunits
[POST] api/v1/transformation-controller/documents
So this is a way to avoid verbs and fit REST rules.
If there will be more objects to transform/sync from and into, then you'll have to improve this approach.

What is the correct status code to return for a successful PUT operation performed by a RESTful API?

In Visual Studio 2017, when creating a new controller for a .Net Core 2.1 Web API, and using the "Add Scaffold - API Controller with actions, using Entity Framework" wizard, the generated controller code returns a NoContent() for the PUT action, and a CreatedAtAction() for the POST action.
// POST: api/Items
[HttpPost]
public async Task<IActionResult> PostItem([FromBody] Item item)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
_context.Item.Add(item);
await _context.SaveChangesAsync();
return CreatedAtAction("GetItem", new { id = item.Id }, item);
}
// PUT: api/Items/5
[HttpPut("{id}")]
public async Task<IActionResult> PutItem([FromRoute] int id, [FromBody] Item item)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
if (id != item.Id)
return BadRequest();
_context.Entry(item).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ItemExists(id))
return NotFound();
else
throw;
}
return NoContent();
}
I completely agree with the return value for the POST action. But regarding the PUT action returning a NoContent() with an empty body, is this "best practice" for RESTful APIs? I mean, I understand that it is returning a NoContent() status code because the body is empty, but would it not make more sense if it returned an Ok() to signal that everything went fine? It seems a bit ambiguous as to whether the action succeeded or not when receiving a NoContent() status code. Or is it more correct to return NoContent(), to let the consuming app know that it should ignore the body, and assume that, because no error code was returned, everything went fine?
Just wondering what RESTful best practice dictates in this situation...
Returning no content status still falls within the 2xx status code range which all indicate successful processing of the request. Returning 200 would now be just a matter of choice rather than what best practice dictates in this situation.
Reference Learn REST: A RESTful Tutorial - Using HTTP Methods for RESTful Services
PUT is most-often utilized for update capabilities, PUT-ing to a
known resource URI with the request body containing the newly-updated
representation of the original resource.
However, PUT can also be used to create a resource in the case where
the resource ID is chosen by the client instead of by the server. In
other words, if the PUT is to a URI that contains the value of a
non-existent resource ID. Again, the request body contains a resource
representation. Many feel this is convoluted and confusing.
Consequently, this method of creation should be used sparingly, if at
all.
Alternatively, use POST to create new resources and provide the
client-defined ID in the body representation—presumably to a URI that
doesn't include the ID of the resource (see POST below).
On successful update, return 200 (or 204 if not returning any content
in the body) from a PUT. If using PUT for create, return HTTP status
201 on successful creation. A body in the response is
optional—providing one consumes more bandwidth. It is not necessary to
return a link via a Location header in the creation case since the
client already set the resource ID.
PUT is not a safe operation, in that it modifies (or creates) state on
the server, but it is idempotent. In other words, if you create or
update a resource using PUT and then make that same call again, the
resource is still there and still has the same state as it did with
the first call.
If, for instance, calling PUT on a resource increments a counter
within the resource, the call is no longer idempotent. Sometimes that
happens and it may be enough to document that the call is not
idempotent. However, it's recommended to keep PUT requests idempotent.
It is strongly recommended to use POST for non-idempotent requests.

Controller return type and httpStatus best practice and production/consumption on method in REST WS

I commence in REST and I have some questions:
What type must the controller return? Typically, I'm asking if my Rest #Controller must return Item object as it is or encapsulate it in ResponseEntity in order to specify http-status-code.
What http status code to use in a GET method on a particular item ("/items/2") if the given item does not exists: HttpMediaStatus.OK(200) and null return or HttpStatus.NO_CONTENT(204) and null return ?
Second part: I saw it was possible to specify #Produces and #Consumes on WS method but what the use of that? My application and my methods work so, why specify MediaType.APPLICATION_JSON_VALUE? Doesn't Spring/SpringBoot automatically convert Item or ResponseEntity into json?
Context: using Spring Boot, hibernate, REST webservice.
Thank you.
Many questions in one, I'll provide short answers with a bunch of link to relevant articles and the reference documentation.
What type must the controller return?
Depends on your annotation and the RESTful-ness of your service. There are three annotations you can use for controllers: #Controller, #RestController and #RepositoryRestController.
Controller is the base annotation to mark your class as a controller. The return type of the controller endpoint methods can be many things, I invite you to read this dedicated post to get a grasp of it.
When developing a pure-REST service, you will focus on using RestController and RepositoryRestController.
RestControlleris Controller + ResponseBody. It binds the return value of the endpoint method to the web response body:
#RestController
public ItemController {
#RequestMapping("/items/{id}")
public Item getItem(#PathVariable("id") String id) {
Item item = ...
return item;
}
}
With this, when you hit http:/.../api/items/foo, Spring does its magic, automatically converting the item to a ResponseEntity with a relevant 40X status code and some default HTTP headers.
At some point, you will need more control over the status code and headers, while still benefiting from Spring Data REST's settings. That's when you will use RepositoryRestController with a ResponseEntity<Item> as return type, see the example the Spring Data REST reference.
What http status code to use in a GET method on a particular item if the given item does not exists?
Bluntly said: use HttpStatus.NOT_FOUND. You're looking for a resource that does not exist, there's something wrong.
That being said, it is completely up to you to decide how to handle missing resources in your project. If your workflow justifies it, a missing resource could be something completely acceptable that indeed returns a 20X response, though you may expect users of your API to get confused if you haven't warned them or provided some documentation (we are creatures of habits and conventions). But I'd still start with a 404 status code.
(...) #Produces and #Consumes on WS method but what the use of that? My application and my methods work so, why specify MediaType.APPLICATION_JSON_VALUE? Doesn't Spring/SpringBoot automatically convert Item or ResponseEntity into json?
#Consumes and #Produces are respectively matched against content-type and accept headers from the request. It's a mean of restricting the input accepted and the output provided by your endpoint method.
Since we're talking about a REST service, communications between clients of the API and the service are expected to be JSON-formatted. Thanks to Spring HATEOAS, the answer are actually formatted with the application/hal+json content-type.
In that scenario, you can indeed not bother with those two annotations. You will need them if you develop a service that accepts different content-types (application/text, application/json, application/xml...) and provides, for instance, HTML views to users of your website and JSON or XML response to automated clients of your service.
For real life examples:
Facebook provides the Graph API for applications to read to/write from its graph, while users happily (?) surf on web pages
Google does the same with the Google Maps API

Should a RESFTful Web API return the modified entity on an Update operation (Put)?

I'm creating a new Web API and I'm having a doubt regarding the Update operation (it's a basic CRUD). Should I return a DTO with the updated entity data? I want my API to be RESTful.
have a read here
https://www.rfc-editor.org/rfc/rfc7231
it says and I quote:
For a state-changing request like PUT (Section 4.3.4) or POST
(Section 4.3.3), it implies that the server's response contains the
new representation of that resource, thereby distinguishing it from
representations that might only report about the action (e.g., "It
worked!"). This allows authoring applications to update their
local copies without the need for a subsequent GET request.
However, you do not need to be too fixed on this, return a 201 for example when you create something is perfectly OK as well and you probably want to add the the unique identifier of the created resource.
For updates, a 200 would be ok as well. 204 can be acceptable as well as already mentioned.
The bottom line is ... return only the data you need, if you need to see the whole updated object then return it. If you don't then don't do it. Keep in mind that some objects can be quite big and have a whole object graph below them, there's no point sending too much data down the wire.
I guess the most important thing is to choose one way of doing things and then be consistent and use the same thing everywhere
First of all, returning a DTO has nothing to do with RESTful.
It's true that DTO is a pattern created with the purpose of transferring data to remote interfaces (and web services can be a good fit for this pattern).
However using DTOs won't make your application more or less RESTful. Your application can use DTOs to have more control over the data exposed in the REST API. Just that.
If your update operation relies on the PUT HTTP method (which is designed to replace the state of a resource with a new representation), you may want to return 200 or 204 status code to indicate that the operation has succeeded.
If you go for 200, you can return a representation of the new state of the recently updated resource. If you go for 204, no representation must be returned.
By representation I mean a JSON document, a XML document or any other content that can be used to represent the state of a given resource.
We normally return NoContentResult after update is successful. For example,
[HttpPut("{id}", Name = "UpdateUser")]
public IActionResult UpdateUser(Guid id, [FromBody] UserUpdateDto user)
{
if (user == null)
{
return BadRequest();
}
if (!_repository.UserExists(id))
{
return NotFound();
}
var entity = _repository.GetUser(id);
Mapper.Map(user, entity);
_repository.UpdateUser(entity);
return NoContent();
}
NoContent basically returns status code 204. The following is the source code of NoContentResult.
public class NoContentResult : StatusCodeResult
{
public NoContentResult()
: base(204)
{
}
}
Returning data from a PUT operation is optional, though not necessary. If theres anything you wanted to calculate in the model which will be useful for the client then return them, but otherwise a 204.

http delete with REST

I am currently using Jersey Framework (JAX-RS implementation) for building RESTful Web Services. The Resource classes in the project have implemented the standard HTTP operations - GET,POST & DELETE. I am trying to figure out how to send request parameters from client to these methods.
For GET it would be in the query string(extract using #QueryParam) and POST would be name/value pair list (extract using #FormParam) sent in with the request body. I tested them using HTTPClient and worked fine. For DELETE operation, I am not finding any conclusive answers on the parameter type/format. Does DELETE operation receive parameters in the query string(extract using #QueryParam) or in the body(extract using #FormParam)?
In most DELETE examples on the web, I observe the use of #PathParam annotation for parameter extraction(this would be from the query string again).
Is this the correct way of passing parameters to the DELETE method? I just want to be careful here so that I am not violating any REST principles.
Yes, its up to you, but as I get REST ideology, DELETE URL should delete something that is returned by a GET URL request. For example, if
GET http://server/app/item/45678
returns item with id 45678,
DELETE http://server/app/item/45678
should delete it.
Thus, I think it is better to use PathParam than QueryParam, when QueryParam can be used to control some aspects of work.
DELETE http://server/app/item/45678?wipeData=true
The DELETE method should use the URL to identify the resource to delete. This means you can use either path parameters or query parameters.
Beyond that, there is no right and wrong way to construct an URL as far as REST is concerned.
You can use like this
URL is http://yourapp/person/personid
#DELETE
#Path("/person/{id}")
#Produces(MediaType.APPLICATION_JSON)
public Response deletePerson(#PathParam("id") String id){
Result result = new Result();
try{
persenService.deletePerson(id);
result.setResponce("success");
}
catch (Exception e){
result.setResponce("fail");
e.printStackTrace();
}
return Response.status(200).entity(result).build();
}
#QueryParam would be the correct way. #PathParam is only for things before any url parameters (stuff after the '?'). And #FormParam is only for submitted web forms that have the form content type.