Require JSON data in API request - rest

I am working on RESTful API in CakePHP 3 and I need to force that data and request Content-Type is application/json and not application/x-www-form-urlencoded. How to accomplish it?

You could add in your AppController.php in the beforeFilter
public function beforeFilter(event $event) {
$this->request->params['_ext'] = 'json';
}
That way you will treat every incomming request as it was done with the .json extension, That might set you of into the right direction

Related

{guzzle-services} How to use middlewares with GuzzleClient client AS OPPOSED TO directly with raw GuzzleHttp\Client?

My middleware need is to:
add an extra query param to requests made by a REST API client derived from GuzzleHttp\Command\Guzzle\GuzzleClient
I cannot do this directly when invoking APIs through the client because GuzzleClient uses an API specification and it only passes on "legal" query parameters. Therefore I must install a middleware to intercept HTTP requests after the API client prepares them.
The track I am currently on:
$apiClient->getHandlerStack()-push($myMiddleware)
The problem:
I cannot figure out the RIGHT way to assemble the functional Russian doll that $myMiddleware must be. This is an insane gazilliardth-order function scenario, and the exact right way the function should be written seems to be different from the extensively documented way of doing things when working with GuzzleHttp\Client directly. No matter what I try, I end up having wrong things passed to some layer of the matryoshka, causing an argument type error, or I end up returning something wrong from a layer, causing a type error in Guzzle code.
I made a carefully weighted decision to give up trying to understand. Please just give me a boilerplate solution for GuzzleHttp\Command\Guzzle\GuzzleClient, as opposed to GuzzleHttp\Client.
The HandlerStack that is used to handle middleware in GuzzleHttp\Command\Guzzle\GuzzleClient can either transform/validate a command before it is serialized or handle the result after it comes back. If you want to modify the command after it has been turned into a request, but before it is actually sent, then you'd use the same method of Middleware as if you weren't using GuzzleClient - create and attach middleware to the GuzzleHttp\Client instance that is passed as the first argument to GuzzleClient.
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Command\Guzzle\GuzzleClient;
use GuzzleHttp\Command\Guzzle\Description;
class MyCustomMiddleware
{
public function __invoke(callable $handler) {
return function (RequestInterface $request, array $options) use ($handler) {
// ... do something with request
return $handler($request, $options);
}
}
}
$handlerStack = HandlerStack::create();
$handlerStack->push(new MyCustomMiddleware);
$config['handler'] = $handlerStack;
$apiClient = new GuzzleClient(new Client($config), new Description(...));
The boilerplate solution for GuzzleClient is the same as for GuzzleHttp\Client because regardless of using Guzzle Services or not, your request-modifying middleware needs to go on GuzzleHttp\Client.
You can also use
$handler->push(Middleware::mapRequest(function(){...});
Of sorts to manipulate the request. I'm not 100% certain this is the thing you're looking for. But I assume you can add your extra parameter to the Request in there.
private function createAuthStack()
{
$stack = HandlerStack::create();
$stack->push(Middleware::mapRequest(function (RequestInterface $request) {
return $request->withHeader('Authorization', "Bearer " . $this->accessToken);
}));
return $stack;
}
More Examples here: https://hotexamples.com/examples/guzzlehttp/Middleware/mapRequest/php-middleware-maprequest-method-examples.html

How do you post to a Web API 2 OData Controller

I created a Web API 2 project and configured an OData4 controller following the steps here: Web API 2 Odata 4 Tutorial
However whenever I try and do a simple POST(with a JSON body to create an entity) using Postman I get the following error back:
The requested resource does not support http method 'POST'.
The POST action in the controller looks like this:
public async Task<IHttpActionResult> Post(Product product)
{
if(!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Products.Add(product);
await db.SaveChangesAsync();
return Created(product);
}
The JSON I am posting in the request body is as follows:
{
"Id":"lewisblack",
"Name":"Lewis",
"Price":"Black",
"Category":"Category 1"
}
And I included the following headers in the request as well:
OData-Version: 4.0
OData-MaxVersion: 4.0
Content-Type: application/json
Am I missing something here?
UPDATE: Figured out the issue. I was using an incorrect URI.
Not much information to go on:
I suspect you don't have a PostMethod on the related controller.
Otherwhise, some other things to think about:
OData is case sensitive
You are missing a property that is required
a datatype is wrong ( Id in the example project is an integer, it looks like a string in your project, Price should be a decimal and not a string, ...)
Whats the HTTP Response code ( if above didn't help), when you post the object. ( use a tool like fiddler). Tip, if your http response is a "bad request", then your data is probably invalid to continue in the action.
I incorrectly used http://localhost:/ for the POST instead of https://localhost:/Products

CakePHP: Distinguish between regular http and REST calls

I want the same Controller routines to serve both regular web-based page loads as well as REST calls. I have REST handling set-up in my routes.php:
// Setup REST Handling
Router::mapResources( '<ControllerName>' );
Router::parseExtensions();
Let's take for example, the add() method - how do I distinguish inside this method how the call is being made?
To elaborate on the issue:
public function add() {
$status = array();
if( $this->request->is( 'post' ) ) {
// Read POST body
$entityBody = file_get_contents( 'php://input' );
}
}
As you can see in the above code, I'm detecting POST requests and will deal with the request accordingly. What I need to figure is whether the post data is coming from a REST call of from a web-form. If the data comes from a web-form, it'll be in the request->data array whereas for a REST call, it'll be in XML form.
I'll deal with the data accordingly and dish out an appropriate response.
Thanks.
Use the CakeRequest object, see the documentation, works the same as with post.
$this->request->is('put');
is('get') Check to see if the current request is a GET.
is('put') Check to see if the current request is a PUT.
is('post') Check to see if the current request is a POST.
is('delete') Check to see if the current request is a DELETE.

Web API calls with RestSharp - prepends application/json to body causing null parameter on action

I have a Web API service that I'm trying to access via the console using RestSharp. My RestSharp code looks like this:
RestClient client = new RestClient(baseUrlString);
RestRequest request = new RestRequest("controllername/actionname");
request.RequestFormat = DataFormat.Json;
ProcessQuestion model = new ProcessQuestion()
{
Id = "123456",
InstanceId = "123",
UniqueId = "bfb16a18-d0d6-46ab-a5b3-2f0ebbfe8626",
PostedAnswer = new Dictionary<string, string>() { { "question_7907_1", "selected" }, { "question_7907_2", "selected" } }
};
request.AddBody(model);
var response = client.Execute(request)
My Web API action takes a model that has the same parameters as the above model. When the call executes, the binding fails and the parameter is null. I suspect this is due to the RestRequest.AddBody method prepending application/json to the body value as shown below:
{application/json={"Id":"123456","InstanceId":"123","UniqueId":"bfb16a18-d0d6-46ab-a5b3-2f0ebbfe8626","PostedAnswer":{"question_7907_1":"selected","question_7907_2":"selected"}}}
If I post using Fiddler the body binds to the model properly. Below is the body value I provided in Fiddler:
{'Id':'123456','InstanceId':'123','Uniqueid':'bfb16a18-d0d6-46ab-a5b3-2f0ebbfe8626','PostedAnswer':{'question_7907_1':'selected','question_7907_2':'selected'}}
Note that the body value in fiddler is the same with the exception of prepending the application/json key.
Also to note: I've tried what seems like everything...I've separated the parameters out in the action, used FromBody and FromUri attributes, tried custom DictionaryModelBinder's, tried custom ValueBinders, tried changing the way I'm using RestSharp (AddParameter with a RequestBody parameter, AddObject, different URL styles, etc.).
Has anyone else encountered this, and if so, did you solve it? I chose Web API for this service with hopes the model binding would work as it does in MVC, but I'm seeing that isn't the case.
Thanks
EDIT (resolved):
RestSharp automatically uses the JsonSerializer for objects passed in the AddBody method. I figured I was missing something simple, and indeed I was... Adding the Method.Post parameter to the RestRequest instantiation solved the problem.
Specify the method when creating the request:
RestRequest request = new RestRequest("controllername/actionname", Method.POST);
Not sure what the default serializer is for body - you can try making it explicit:
request.AddBody(request.JsonSerializer.Serialize(model));
I'm not sure where the 'application/json' is coming from - that's the Content-Type header you should be sending with your request, definitely not part of the body. So do this instead:
request.AddHeader("Content-type", "application/json; charset=utf-8");
If this doesn't help, try making your code as similar to the example on their site as possible. Try removing complexity (even if it means changing the required functionality) - get it to a point when it works and build additional functionality on that.
http://restsharp.org/

Can we add Json object to RequestHeader of HTTP GET method

I am developing a new REST-full webservice for our application,I wanted to send the reqest data in requestHeader instead of sending as query param, as my request data is large.
I have My jquery code like below to add json to the request header and call the REST service GET method.
$.ajax({
beforeSend: function(req) {
req.setRequestHeader("test", "{name:mouli, id:918}");},
type : "GET",
data :'',
dataType : "jsonp",
url : 'http://localhost:29801/RestFulJSONExample/rest/jobdesc?callback=?',
success : function(data) {
alert("invoked");
}
});
});
And my GET method in my REST service is like
#GET
#Produces("application/javascript")
public JSONWithPadding getJobDescription(#Context HttpHeaders headers) {
List<String> requestHeader = headers.getRequestHeader("test");
//some logic here.
}
i could able to get the JSON object from the request header which i have added in the jquery request.
My question is ..
Can i follow this approach? is it secure and safe?
If not please tell me the other way?
What appears at the right side of the ":" in a header is mostly free. You have to take into account character set restriction in HTTP, and possible carriage returns in the JSON value (you know, headers of more than one line have a specific syntax). If your JSON examples are relatively simple, then I see no problem in that. It is just another way of organizing the actual value of a header line.