How to use custom (non-standard) HTTP status codes in ZF2 - http

I'm trying to send response with a custom http status code 498 - Token Invalid in a Zend Framework 2 application. This is obviously not working as standard Zend Response class does not allow for custom http codes.
So I have created my own response class that handles this http code and return it in my action:
$response = new CustomResponse();
$response->setStatusCode(498); //basic zend response objects throws InvalidArgumentException
return $response;
Although no exception is thrown, the browser says it returned 500 error.
How to get this working?

The HTTP Response class in ZF2 strictly follows the RFC 2616 for the status codes. This is a good practice and an exception will be thrown by setStatusCode() method when you pass an unknown status code.
Anyway, you don't need to create a custom response object to return a non-standard HTTP status code. There is a setCustomStatusCode() method exists for this requirement.
Try this in any controller action:
public function myAction()
{
$response = $this->getResponse();
$response->setCustomStatusCode(498);
$response->setReasonPhrase('Invalid token!');
return $response;
}

Related

Handle Unauthorized Request and Return Status Code 404

I am developing a standalone .Net Core API targeting framework .Net Core 2.2.The authentication scheme is JWTBearerTokens connecting to our ADFS Identify server.
When I call an API endpoing decorated with the [Authorize] attribute I am getting a 401 Unauthorized response, which is expected and default behaviour.
What I want to do next is instead of having that same call return a 401, I would like to return the status code to be 404. (I don't want to get into great details of why 404. Simply, I do not want to expose that the endpoint exists if a valid token is not included in request)
In previous .Net Framework WebAPI you could create your own attribute and override the HandleUnauthorizedRequest method and return the status code you want.
I have reviewed the documentation on policy-based authorization, but have not tried the sample or tried implementing it. The policy handler looks more to do with handling (return success or fail) if a policy is not fulfilled. I do not see anywhere where you can return a different status code on failure. So that only would make sense if I start checking against actual Policies.
Any insights?
Returning 404 instead of 401 is bad practice(as mentioned in the comments by #Chris Pratt) and must be avoided. Consider these cases,
You're leaving the project to someone else and they can't figure why 404 is returned
A 404 is returned when you call the homepage/Index page. Poor ideology.
Later on in the project, you decide to allow post requests without authentication. So on and so forth.
Anyways, as part of the community, I'll give you the answer...
Add this to your global.asax
void Application_EndRequest(object source, System.EventArgs args)
{
if (Response.StatusCode == 401)
{
Response.ClearContent();
Response.RedirectToRoute("ErrorH", (RouteTable.Routes["ErrorH"] as Route).Defaults);
}
}
And in routeConfig, create a route for your errorHandler :
routes.MapRoute(
"ErrorH",
"Error/{action}/{errMsg}",
new { controller = "CustomController", action = "Change401To404", errMsg = UrlParameter.Optional }
);
And in your custom controller :
public class CustomController : Controller //or Base
{
public ActionResult Change401To404(){
//Do whatever you want
}
}
PS: This is not the only way, there are many other ways to do it. But at least in this method, you can differentiate real 404 responses from 401 responses.

Best way to return added value on Http Status Code 404

At times I return, at server level, some extra information alongside with a HTTP 404
For example, instead of returning just a 404, which can puzzle my client whether the routing is correct or not, it will also receive something like
the identifier 'abc' is unknown
I usually set the content type to text/plain and return some text in the Content
Another alternative is to set the ReasonPhrase instead.
Which one is the best way / convention? Set Content or set ReasonPhrase?
The error message should be put in response body (Content), not in response Reason Phrase.
According to RFC 2616:
The Reason-Phrase is intended to give a short textual description of the Status-Code...The client is not required to examine or display the Reason-Phrase.
Some explanation:
Reason-Phrase is short, textual description of Status-Code, it should describe Status Code itself, not custom error message. If custom error message is very long, or the message has JSON structure, using Reason-Phrase certainly violates the specification.
As the specification indicate, the client (browser) is not required to examine the Reason-Phrase, which means Reason-Phrase may get ignored for some browsers, in some time.
You can use custom error responses and overrides the 404 and any other error you want
visit here
Spring MVC: How to return custom 404 errorpages?
Create a view and set this code in app/Exception/Handler.php :
/*Render an exception into a response.
*
* #param \Illuminate\Http\Request $request
* #param \Exception $e
* #return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
if($e instanceof NotFoundHttpException)
{
return response()->view('missing', [], 404);
}
return parent::render($request, $e);
}
Set this use to get it working :
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
For more info you can visit
https://httpd.apache.org/docs/2.4/custom-error.html
https://learn.microsoft.com/en-us/aspnet/web-forms/overview/older-versions-getting-started/deploying-web-site-projects/displaying-a-custom-error-page-cs

How to found out url with which the request arrived at error handler?

I send following http request:
http://localhost:8081/member/createCompany/getSmallThumbnail/
On server side I hit into controller method:
#RequestMapping("/error")
public String error(Model model, HttpServletRequest request){
if(request.getRequestURI().contains("thumbnail")){
System.out.println("thumbnail accepted");
}
request.toString();
model.addAttribute("message", "page not found");
return "errorPage";
}
At this method I want to know url with which the request arrived.
If in debug I stop inside this method I see information needed for me:
But I cannot find method in request which will return this.
Please help to return url which I want.
P.S.
Actually I have not mapped controller in my spring mvc application(url is broken) for http://localhost:8081/member/createCompany/getSmallThumbnail/. This url("/error") configured in web.xml as error page.
Your request got redispatched to /error (presumably for error processing).
If this framework follows the normal Servlet error dispatching behavior, then your original request can be found in the HttpServletRequest.getAttributes() under the various javax.servlet.RequestDispatcher.ERROR_* keys.
ERROR_EXCEPTION - The exception object
ERROR_EXCEPTION_TYPE - The type of exception object
ERROR_MESSAGE - the exception message
ERROR_REQUEST_URI - the original request uri that caused the error dispatch
ERROR_SERVLET_NAME - the name of the servlet that caused the error
ERROR_STATUS_CODE - the response status code determined for this error dispatch
What you want is
String originalUri = (String) request.getAttribute(
RequestDispatcher.ERROR_REQUEST_URI)

Spring MVC binding request parameters

I wrote a spring-mvc controller method to get an array of values in the request parameter.The method looks like below
/**
Trying to get the value for request param foo which passes multiple values
**/
#RequestMapping(method=RequestMethod.GET)
public void performActionXX(HttpServletRequest request,
HttpServletResponse response,
#RequestParam("foo") String[] foo) {
......
......
}
The above method works fine when the request url is in below format
...?foo=1234&foo=0987&foo=5674.
However when the request url is in below format the server returns 400 error
...?foo[0]=1234&foo[1]=0987&foo[2]=5674
Any idea how to fix the method to cater to the second format request url?
This is not possible with #RequestParam. What you can do is implement and register your own HandlerMethodArgumentResolver to perform to resolve request parameters like
...?foo[0]=1234&foo[1]=0987&foo[2]=5674
into an array. You can always checkout the code of RequestParamMethodArgumentResolver to see how Spring does it.
Note that I recommend you change how the client creates the URL.
The server is supposed to define an API and the client is meant to follow it, that's why we have the 400 Bad Request status code.
I resolved this issue using the request.getParameterMap().Below is code.
Map<String,String> parameterMap= request.getParameterMap();
for(String key :parameterMap.keySet()){
if(key.startsWith("nameEntry")){
nameEntryLst.add(request.getParameter(key));
}
}

Web API 2 - ApiController.InternalServerError() returns HTTP 400 status code

This Web API action returns an HTTP 500 (Internal Server Error) status code:
public IHttpActionResult Post()
{
return InternalServerError();
}
But this action returns an HTTP 400 (Bad Request) status code:
public IHttpActionResult Post()
{
return InternalServerError(new Exception());
}
I would expect both actions to return a 500 status code and the second action puts some of the error's details in the response body.
My first thought is that this is a bug but I wanted to get some other input. Is there any good reason why a 400 should be returned in the second action instead of a 500?
UPDATE:
The documentation on this method reads:
Creates an System.Web.Http.Results.ExceptionResult (500 Internal Server Error) with the specified exception.
I'm thinking more and more this is a bug.
Right, this was a known issue which was fixed after Web API 2 release...you can use the following workaround to fix this issue..example:
return new ResponseMessageResult(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, invalidOpException));
Following was the issue that was logged before:
https://aspnetwebstack.codeplex.com/workitem/1318

Resources