redstone-dart / redstone

A metadata driven microframework for Dart.
http://redstone-dart.github.io/redstone
MIT License
342 stars 42 forks source link

Dynamically change status code #125

Open marloncarvalho opened 9 years ago

marloncarvalho commented 9 years ago

I know that I can statically change the status code using the statusCode attribute from the Route annotation. Although I think it's not enough. There are specific situations where it's important to dynamically change the returned status code.

For example, consider the REST principle that says that a PUT request should UPDATE a resource when it exists but that it should CREATE it when it doesn't exist. With that principle in mind, I have to decide which status code to return (200OK or 201CREATED) dynamically, right after checking whether the provided ID exists or not.

I suggest creating a way to decide which status code to return, for example, using something like app.statusCode(StatusCode.CREATED).

cgarciae commented 9 years ago

I like the idea but there are two implementation details I am not sure how to solve

  1. That statusCode(...) would internally have to modify a top level variable which would have to be zoned (not sure if you get this for free in the current implementation)
  2. I dont know the exact place where the shelf response is created with the status code (but I can search for it)

Also, aro you using 0.6? Its beta but doesnt make sense to invest in 0.5 for this like this.

marloncarvalho commented 9 years ago

I started using Redstone just a few days ago and I'm still using version 0.5.

I haven't seen anything about the internal implementation until now but I feel that I can guess something about the first point. In version 0.5 we have access to the current response object in each request so, in this case, isn't it possible to implement this feature using the same implementation or idea? I'm just guessing because I don't know if there're big differences between the two versions that make it unfeasible.

Lastly, I'm gonna give version 0.6 a try! It seems great.

cgarciae commented 9 years ago

Yes you get access a response for your route but that is not the actual final response because it doesnt have your content, it might include the status code but its no use creating a response from that one unless you "respond" it (not good if you use plugins which expect normal objects).

marloncarvalho commented 9 years ago

Another possible way to solve this problem is to implement something like what JAX-RS does in Java. JAX-RS allows us to return either a domain object (that will be serialized to JSON or XML) or a javax.ws.rs.core.Response. If you decide to return a javax.ws.rs.core.Response then you can use the javax.ws.rs.core.Response.Builder to create responses like this:

Response.status(200).header("header","value").entity(domainObject);

I don't know if this idea goes against the core Redstones concepts, but it's simple and effective.

cgarciae commented 9 years ago

In redstone you can return a shelf.Response and it works as you want. You have to import the library shelf for this.

This approach has two main downsides:

  1. It become hard/ugly for you to reuse code by calling other methods/functions because shelf.Reponses are useless unless you parse them back to PODOs or something like that.
  2. You loose the benefits from plugins like redstone_mapper (converts the returned object into JSON) or the redstone_mvc (uses the returned object as a source for a mustache template and responds html - I am the author of this one) because they tend to ignore shelf.Responses assuming you want full control of the response in some occasions.

So what you proposed before is actually a good feature.