Best way to return added value on Http Status Code 404 - http

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

Related

How to programatically change the routing to add my own "filter" by keyword

My case is the following:
I have a Shopware Bundle and i need to change/extend the routing in such a way that if a request URL contains a keyword "xyz", the request is forwarded to a controller in my bundle without checking further if the route is available in "static routes" for example.
For instance: "/xyz/1/lorem/3" or "/xyz/5/3/ipsum" etc. all need to be rerouted to the controller in my bundle, since they contain the keyword /xyz.
Is there a service i can overwrite/decorate or something similar where i can implement this behaviour?
You can have a placeholder in your route with a default and a requirement allowing for all characters:
/**
* #Route("/xyz{anything}", name="frontend.my.action", methods={"GET"}, defaults={"anything"=""}, requirements={"anything"=".+"})
*/
public function myAction(Request $request): Response
{
$anything = $request->get('anything');
// ...
}
This will match any url starting with /xyz and every set of characters that follows afterwards is considered to be part of anything.

Symfony : Route PUT method

Anyone knows why the PUT method doesn't work using PHP Symfony?
If I replace PUT to POST everything works fine
/**
* #Route("/api/product/update", name="product_udpate", methods = {"PUT"})
*/
i am reading variables like that
$request = Request::createFromGlobals();
echo $request->request->get('name');
error:
No route found for "PUT /api/product/update/23" (404 Not Found)
The problem is you are not creating the route correctly. Basically, you need to add the "id" to the route.
/**
* #Route("/api/product/update/{id}", name="product_udpate", methods = {"PUT"})
*/
public function updateAction(Request $request, $id)
{
// Your logic here
$name = $request->get('name');
}
You got the following error because you have not configured route correctly.
error: No route found for "PUT /api/product/update/23" (404 Not Found)
If you want to add id along with your desire url, you have to define in your route.
Thus, you can update your route:
/**
* #Route("/api/product/update/{id}", name="product_udpate", methods = {"PUT"}, defaults={"id"=null})
*/
As stated in the symfony documentation How to Use HTTP Methods beyond GET and POST in Routes
Unfortunately, life isn't quite this simple, since most browsers do not support sending PUT and DELETE requests via the method attribute in an HTML form. Fortunately, Symfony provides you with a simple way of working around this limitation. By including a _method parameter in the query string or parameters of an HTTP request, Symfony will use this as the method when matching routes
So you have to fake the method like this one :
<form action='your route'>
<input type='hidden' name='_method' value='PUT'>
//do something.......
</form>

Symfony2: Passing "_format=xml" does not render responce in XML

Strange behavior with passing defaults={"_format" = "xml"} to controller (seemed to work before):
/**
* #Route("/orderxml/{orderguid}", name="_show_order_xml", defaults={"_format" = "xml"})
*/
public function showOrderXML($orderguid)
{
....
$xmloutput = $this->container->get('templating')
->render($templateName, $tpl_data);
$response = new Response($xmloutput);
}
Though I pass defaults={"_format" = "xml"}, the response is still received with content-type=text/html.
Tried to debug the Request - it comes with empty Content-Type header. Attributes of Request do contain _format=xml, but also contain media-type="text/html", which is not familiar to me. As stated in the docs, _format determines the content-type of Request and Response objects.
Currently the only thing I could do is $response->headers->set('Content-Type', 'text/xml');
How can this be fixed?
P.S.: symfony 2.3
_format define the content-type, but you set it only as default. Since the request goes with contant-type html, the default doesn't matter. you have also to set the _format in the requirements to xml only too.

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

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;
}

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));
}
}

Resources