I am just new to rest api and need to create two api. both of them use post.
1) First one takes 2 parameters inside of the body
url is : /myapp/resources
2) Second one is doing the same function as the first one does but it needs 2 optional parameter. I thought using path or request param but as the parameters are optional it will be confusing when there is no paramaters. So there will be conflict with the first api.
/myapp/resources?param1=xx¶m2=xx ==> what if there is no parameter
/myapp/resources/param1/{xxx}/param2/{yyy} ==> so still what if there is no param:
So what is the best way to define second api without causing a conflict with the first api when optional parameters are not passed.
I would suggest going with the first approach (query params) so:
/myapp/resources?param1=xx¶m2=xx
The reason being - in this case you can define or extend the logic of just one endpoint, the /myapp/resources, that is going to verify if parameters exist and react accordingly.
With the second approach (path params), you would have to most likely define two (or more) separate endpoints (like /myapp/resources/, /myapp/resources/param1/{param1} and /myapp/resources/param1/{param1}/param2/{param2}
Related
Is it possible to make the same field compulsory for POST and optional for PUT requests for REST API? Or it depends on teqnology used to implement this request?
For example, there is a POST request to create Car objects and this object has a field model_id which is actually chosen from a dictionary of models. And the POST request requires model_id because the car must have model_id defined.
And I want to have a PUT method which changes some field e.g. serial_num, manufacture_date, color etc. even model_id. But I want this PUT method to change model_id as optional parameter, e.g. I just want to change color and it is Ok.
So is this possible in REST? Does some technologies that implement these request could not allow me to make different set of optional/compulsory params for POST ant PUT?
Well, you can do whatever you want here. Nobody will kill you if you check fields in the request body and return an error if model_id is specified (or not).
Some guys use POST method to update entities in API.
If you want to be closer to standards better use PATCH for partial updates.
You can find a lot of interesting info here:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
Use of PUT vs PATCH methods in REST API real life scenarios
https://www.rfc-editor.org/rfc/rfc7231#section-4.3.4
https://www.rfc-editor.org/rfc/rfc5789
One important thing from 4. source:
The PUT method is already defined to overwrite a resource with a
complete new body, and cannot be reused to do partial changes.
And another one sentence from 3. source:
Generally speaking, all implementation details behind the resource interface are intentionally hidden by the server.
My issue is a, I need only restaurant, bar using google API.
If you need code i'm send you.
this is my base url:- "https://maps.googleapis.com/maps/api/place/"
nearbyURLFragment :- let nearbyURLFragment = "nearbysearch/json?key=%#&location=%f,%f&rankby=distance&type=restaurant,bar"
a single type of proper working.
but here is I'm not getting a proper result.
Quoting the Google API Docs,
Restricts the results to places matching the specified type. Only one
type may be specified (if more than one type is provided, all types
following the first entry are ignored).
The only workaround of this would be to define one in the keyword attribute however this will return very inconsistent results.
The best way to do this is to do two separate API calls with differing types.
I have many crud operation.
User must be able to search by many field of the resource.
Some have around 10.
I could use RequestParam, but method will have a lot of parameter an habitually it's not a good pratice.
/card?id=2&imso=trx&icco=98x&type=23&scm=988&createat=2017-02-01
Is there another good solution?
There are two issues here and depending on what carries what importance to you - you can approach a solution.
Problem # 1 : Long REST URLs at client
Problem # 2 : Controller methods with long & complicated signatures
Solution 1 : You group your #RequestParam into optional & mandatory parameters and then you create a DTO only for optional parameters. Then You can have your controller method signature like controllerMethod(#RequestParam param1 , #RequestParam param2, DTO dto).
Note that, you don't use #RequestBody before DTO.
Values for DTO will be passed in client URL itself like before and Spring MVC automatically converts it into DTO.
This solves complicated controller method signature but not long URL problem while you retain your request type to be GET
It is assumed that usually mandatory parameters are only a few and there is always a long list of optional fields.
Solution 2: You change server side to convert your GET request to a POST and start accepting a #RequestBody DTO. This solves both the problems but your original API changes to POST type.
As far as I know, changing a GET to POST shouldn't be a problem in most cases but vice versa is not true.
I would like to modify an url parameter /resource/{VaRiAbLe} in an API gateway to S3 mapping so that it actually points to /my-bucket/{variable}. That is, it accepts mixed-case input, and maps it to a lower-case name. Mapping path variables is relatively simple enough to S3 integrations, but I can't seem to get a lower-case mapping working.
Reading through the documentation for mapping parameters, it looks like the path parameters are simple string values (and not templated values), and so defining a mapping as method.request.path.variable.toLowerCase() won't work.
Does anyone have any ideas how to implement this mapping?
Map path variables to a JSON body, and then call another API method that actually does the S3 call?
Bite the bullet, and implement a Lambda function to do the S3 get for me?
Find another api method for S3 that accepts a JSON body that I can use to get the data?
Update using Orchestrated calls
Following the info from Jack, I figured I should try doing the orchestrated call, since the traffic volume is low enough that I am sure that I won't be able to keep the lambda hot.
As a proof of concept, I added two methods to my resource (sitting at /resource/{variable} - GET and POST. The GET method chains to the POST, which does the actual retrieving of the data.
POST method configuration
This is a vanilla S3 proxying method, where you set the URL Path parameter for {variable} to be method.request.body.variable.
GET method configuration
This is a HTTPS proxying method. You'll need an URL for the POST method, so you'll need to deploy the API to get the URL. The only other configuration needed here is a body mapping template with content like:
{
"variable" : "$input.params('variable').toLowerCase()",
"something" : "$input.params('something')"
}
This should be enough to get this working.
The downside to this looks to be that I'm adding an extra method (POST) to my API for that resource that could confuse consumers of the API. I think it should be possible to make the POST on the /resource resource, which would at least make a bit more sense from an API design standpoint.
Depending on how frequently this API will be called, I'd either go with the Lambda proxy or chaining two API Gateway methods together. If the API is called frequently enough to keep a Lambda function warm (say once a minute), then go with Lambda. If not, go with the orchestrated API call.
The orchestrated API call would be interesting, I'd be happy to help with that if you have questions.
As far as I know the only S3 API for getting object data is the GET that is documented in their API reference.
I have code that contains several different DELETE methods, one of which takes a parameter, or at least ideally it would take a parameter. However when I make this request, either through CURL or through a web client, it doesn't work. The other DELETE requests function fine and I've hard-coded in the parameter that I want to pass just to see if the call works and it does. I've tried this with both PathParam and QueryParam and neither works. Here's how I'm using the PathParams, which I'm pretty sure is correct, QueryParams looks very similar so I don't want to post that too.
#DELETE
#Path("/byId/{id}")
public void deleteById(#PathParam("id") String id)
And then essentially the same thing for QueryParams but obviously the path is different
From what I understand a lot of RESTful APIs ignore any kind of request body with a DELETE request, or treat it as a PUT or POST. Is there any way around this? Basically I have a database that contains several objects and I need to delete one based on a unique identifier, to be passed in by the client. If there is no way around this is there some other way that I could do it?
Its possible that I'm missing something obvious here as I've only been using Jersey for a few weeks now and up to this point had never even heard of the concept of RESTful services.
You can send information to a RESTful service as either headers, path param, query param or message body.
If all the values go through as expected there is no problem with jax-rs/jersey. Now you need to debug the code and fix your implementation. jax-rs will only match a DELETE call with the DELETE http method you have implemented.
It is then your responsibility to actually perform a DELETE operation of the resource within the method. jax-rs or jersey is not going to complain if you do not DELETE or if you do some other action within the method.