A form is submitted using jQuery form plug-in to an action in MVC framework. In the action, if form validation fails a reply should be sent back to the client. jQuery form plug-in comes with error and success callbacks (like any other jQuery Ajax functions).
Isnt it a better practice to return an HTTP Exception with error-code 400 (Bad Request) and catch it in error callback rather than returning a successful HTTP response and catching it in success callback?
If the answer is yes, wouldn't it be more descriptive to have data attached to HTTP Exception?
From what I see right now, HTTPException.Data is readonly. One of the constructors seems to do the job (HttpException(SerializationInfo, StreamingContext)) but I cant wrap my head around it.
Would someone please explain for me how to add data to HTTP Exception?
No, it's not better practice to simply return an error code, even if you do manage to attach messages to the HTTPException.
Why? Well, you lose so much information that way. You have the option to return an arbitrary JSON object, which could include (for example) a list of all validation errors (or indeed, any pertinent info which may help the calling client out), which you then render on the client so that the user is able to correct.
Also, you've got to consider what happens when your call is successful. Is a 200 return code really enough for your purposes?
Related
I work on a number of Rails sites with forms and take advantage of Rails built-in authenticity token support. Works like a charm. Happy Happy Joy Joy.
It varies, but I would say I average about a SQL injection attack once a month that is successfully caught as having a failed authenticity token check. Wonderful.
The problem is the failed authenticity token check generates an ActionController::InvalidAuthenticityToken exception which returns an HTTP 5xx error because it is an unhandled exception. Good: the bad request is not allowed. Bad: The hacker is functionally informed that my server crashed which is hacker-code for KEEP ATTACKING THIS INTERFACE AT ALL COSTS because they aren't catching this error.
So what is the best way to handle this? If I simply try to wrap my controller method in a try/except, it doesn't even get to my method. It seems that if I want to respond with an access denied or some similar "bad user input" error (HTTP 4xx) then I would have to plug into the pipeline which seems like overkill for something the entire world has to deal with.
Also, what is the proper HTTP response? 400 (Bad Request)? Seems correct, but the other common scenario that generates this error is when a user pulls up your form from cache after the access token has timed out. In this case, the best user experience would be to simply refresh the form with a message saying it took too long for them to fill out the form or something like that. I suppose that could be in the body of an HTTP 400 response.
So how do I build this? Maybe something in the ApplicationController? Why isn't this the default? Maybe it is being handled properly and my "Unhandled Exception" reports are earlier in the pipeline?
Imagine you've got a form on a page, and you POST that form's data to the server in an AJAXian way, e.g. jQuery.post(). The server judges that the data is invalid because, say, the email address doesn't contain an '#' symbol.
I think that the spirit of HTTP says the server should return an "HTTP 400 Bad Request" status code with its response to indicate to the client that it couldn't process the request. The reason (data didn't validate) should be in the body of the response.
But I'm working in an ASP.NET MVC environment that has traditionally implemented "partial views"--HTML fragments sent as responses, meant to be substituted into the client's DOM when received from an AJAX request. In this paradigm, the server typically constructs an alternative version of the form, filled with the (invalid) submitted values and styled with red highlights and alerts indicating that the email address was invalid and should be corrected. The client substitutes that form into its DOM, and the user sees the problem.
This is a common enough pattern in MVC world, but I don't see anybody taking the care to set an appropriate HTTP status code. I can't figure out why.
Is it "okay" to include HTML markup in a non-HTTP-200 response so that the client can show a validation? I can't find anything that says it isn't.
Depends on the status code being returned and how you intend to use it, but generally you can.
If you know that the response could be parsed, send a json/xml document with the right mime type and informations inside. Else just send a human readable HTML content. In both cases obviously set the right HTTP status code.
I suppose it doesn't make sense to send HTML if a machine is getting the response.
But if what you're building has user interaction (e.g. via a browser), then sure.
Wondering if I should ALWAYS use the respond_to/format.xxx block in ALL of my actions in ALL of my controllers. This came up because I realized that, for apps using only HTML response format (no respond_to block), I could send some other type of request (say XML) and get a valid response. Is this considered insecure? Feels to me like it is, and it seems that the solution would be to ALWAYS add the respond_to/format.xxx block to EVERY action on EVERY controller even if you are just using HTML only. That way, any non-html requests will get rejected (as they should).
So, is there ever a situation where it would be OK to leave out the respond_to/format.xxx bits for any given action? Even if you were just doing a simple, standard, HTML-only app? It seems like different versions of rails code generators have generated different things regarding this over time. Just wondering what is considered best practice, and when you can get away without using it.
And if the answer is "Yes, you should use it all the time in every action to be secure", then would it not be considered boilerplate at that point? And shouldn't it be pushed down into rails somehow so we don't have to write it out over and over again every single time?
I don't think this has any impact on the security of your application. Presuming that the inbound HTTP request is well-formed and the client is authenticated to make the request, you as the server don't really care what the client receives. In fact, the client could be passing in all sorts of headers and parameters that you totally ignore and it's up to the client to handle unexpected formats or errors. This is integral to the underlying architecture of HTTP.
In any case, you can set the routes up to not accept the .format parameter, in which case a request for .xml will result in a 404 or other type of error.
If you only use one format, don't the respond_to block, it clutters code with unnecessary artifacts.
I am developing some SOAP web services using Ruby on Rails and considering how to handle generic failures. These generic errors are applicable to all the methods within the service and include the following :-
Missing Request element
Missing Authentication element (Custom)
Invalid Authentication details
I can intercept these errors within my controller before calling the relevant method and respond appropriately. My question is which implementation is easiest to manage from a Client perspective. My options for handling these errors seem to be as follows.
Raise an exception and let the SOAP service generate a SoapFault. This would be fine except I have little (no) control over the structure of the message contained within the SOAP fault.
Return an Http 400 response with an agreed data structure to indicate the error message. This structure would not be defined within the WSDL though.
Include a Status element in all responses, whether successful or not and have that status element include a code and an array of error data (Including error messages).
Option three seems like the best solution but is also the most error prone to implement as the implementation of web services in ROR precludes me from implementing this in a generic way and each method becomes responsible for checking the result of the checks and rendering an appropriate response. Admittedly this would be a single function call and return on failure but it is relying on the developer to remember to do this as we add more options.
I appreciate that most ROR developers will say that this should be implemented as a REST service and I agree, in fact we already have REST services to do this but the spread of SOAP in the corporate world, and its impressive tooling support means that we have to provide SOAP services to remain competitive.
In your experience what would be the easiest implementation for clients to handle and does this differ dependant upon the libraries/language of the client process.
A SoapFault would be the preferred way to signify errors. SoapFaults can contain additional information in their <detail> element.
The advantage of a SoapFault over some status element is that the caller can use standard exception handling, instead of checking for some status field.
I'm writing an actionscript library for an api. I use a URLLoader object to load data from the api. The problem I'm having is that whenever the api returns an http status in the 400s, actionscript treats this as an io error. This is all find and good, however, it seems like there is no way to access any data that was returned if this is the case. Consequently, any helpful xml about the cause of the error that gets returned is lost. Is there any way around this? It makes the library kind of a pain, if there can't be any useful information for developers when the api returns an error. Thanks for any help!
You can't get access to the data in an event of a 400. You can get the status code, however, by adding a listener for the HTTP status event.
If you control the back-end code, there are a couple of workarounds:
One option is to have the backend respond with 200s even in error cases when talking to a flash client, but with a special error code so the client knows that the 200 response is actually an error.
Another option is to set a cookie on the client containing the error message. Flash can't natively access cookies, but you can call out to javascript using ExternalInterface to read the cookie, or optionally the client can do another hit to a special back-end controller that reads the cookie and responds with an error message.