I have a question about a simple REST API endpoint.
The endpoint can accept a value expressed in EURO then returns the corresponding value in DOLLAR, conversely it can accept a value in DOLLAR an return the value in EURO.
I would like to know how I should name this endpoint to respect REST API endpoint naming conventions and best practices.
So far, I have thought about:
-convert-euro-dollar (Probably bad because it uses a verb)
-euro-dollar (Good option?)
Thanks in advance!
I would like to know how I should name this endpoint to respect REST API endpoint naming conventions and best practices.
REST doesn't care what naming conventions you use for your resource identifiers. (Hint: URL shorteners work.)
See Tilkov 2014.
The motivation for choosing "good" resource identifiers is much the same as the motivation for choosing "good" variable names -- the machines don't care, therefore you have extra degrees of freedom that you can use to make things easy for some people.
Possible people you might want to make things easy for: folks looking at resource identifiers in their browser history, operators looking at identifiers in HTTP access logs, writers trying to document the API, etc.
https://www.merriam-webster.com/dictionary/put
Verbs are fine; notice that this URL works exactly the way that you and your browser expect it to, even though the identifier includes a HTTP method.
As suggested by https://stackoverflow.com/a/48692503/19060474 and https://stackoverflow.com/a/10883810/19060474, I would go with one of
GET /dollar/from-euro
GET /euro/to-dollar
GET /currency/usd/from/usd
GET /currency/eur/to/usd
as long as you stay consistent.
Keep in mind, that you should be able to easily deduce from the endpoint what it will likely do. So you should make clear in which direction the conversion will be performed.
With euro-dollar or convert-euro-dollar this is not clearly expressed because one can not determine if the endpoint expects dollar (which dollar by the way, there are quite some variants like USD, AUD, CAD, ...) and converts to EUR or vice versa.
I also suggest you consider using currency codes from the ISO 4217 standard to avoid ambiguity. You can find some of them at https://www.iban.com/currency-codes.
Be aware that answers to this are opinion based, because there is no REST constraint on URI design. All you need is following the URI standards which tells you that the path is hierarchical and the query is non-hierarchical, and that's all. Even that part is sort of flexible.
As of the URI design conventions, I like to describe the operation first and convert it into a verb and a noun. After that I choose HTTP method for the verb and try to describe the rest of it with a noun and attach that second noun to the first one and convert it to an URI template. So I like to name my resources with nouns.
The endpoint can accept a value expressed in EURO then returns the
corresponding value in DOLLAR, conversely it can accept a value in
DOLLAR an return the value in EURO.
Here the operation name would be convertEuroToDollarOrDollarToEuro. I think either we have two operations here convertEuroToDollar and convertDollarToEuro or we need a more general operation name something like convertCurrency and restrict it to the supported currencies, which are Euro and Dollar. Here either I would use POST /conversion to create a new conversion or I would use GET /conversion to read the conversion result.
POST /currency/conversion {"fromCurrency": "EUR", "toCurrency": "USD", "amount": 100}
POST /currency/conversion {"fromCurrency": "USD", "toCurrency": "EUR", "amount": 100}
GET /conversion/{amount}/{fromCurrency}/to/{toCurrency}
GET /conversion/100/EUR/to/USD
GET /conversion/100/USD/to/EUR
GET /currency/conversion?from={fromCurrency}&to={toCurrency}&amount={amount}
GET /currency/conversion?from=EUR&to=USD&amount=100
GET /currency/conversion?from=USD&to=EUR&amount=100
If your service meets the HATEOAS constraint, then this kind of URI structure matters only from service developer perspective, because it is relative easy to figure out the HTTP methods URI templates for the endpoints and bind them to controller methods.
From service consumer or REST client perspective what matters here is the operation name, which is convertCurrency and its parameters: fromCurrency, toCurrency, amount. You need to add these to the documentation and if you can with your actual MIME type attach the metadata to the hyperlink, which represent this operation. So at least do something like:
{
method: "GET",
uri: "/conversion/{amount}/{fromCurrency}/to/{toCurrency}",
type: "convertCurrency"
}
A more advanced solutions would describe the documentation of the convertCurrency operation in a machine readable way. For example Hydra does this: https://www.hydra-cg.com/ and maybe HAL forms can be another solution: https://rwcbook.github.io/hal-forms/ .
Related
How to get a rule like that working:
rule adminCanViewAllExams {
condition (integerOneAndOnly(my.company.attributes.subject.rights) & 0x00000040) == 0
permit
}
Syntax highlighter complains it doesn't know those items:
& (This is a binary math operation)
0x00000040 (this is the hexadecimal representation of an integer)
EDIT
(adding OP's comment inside the question)
I want to keep as much as possible in my current application. Meaning, I don't want to change a lot in my database model. I just want to implement the PEP and PDP part new. So, currently the rights of the user are stored in a Long. Each bit in the number represents a right. To get the right we do a binary &-operation which masks the other bits in the Long. We might redesign this part, but it's still good to know how far the support for mathematic operations goes
XACML does not support bitwise logic. It can do boolean logic (AND and OR) but that's about it.
To achieve what you are looking for, you could use a Policy Information Point which would take in my.company.attributes.subject.rights and 0x00000040. It would return an attribute called allowed.
Alternatively, you can extend XACML (and ALFA) to add missing datatypes and functions. But I would recommend going for human-readable policies.
If a REST API endpoint gets all, then filters are easy. Lack of a filter means "get all results".
GET /persons - gets all persons
GET /persons?name=john - gets all persons with name of "john"
But if there is a default, then I need some way to explicitly not set the default filter. Continuing the above example, if each person has a state, "approved" or "pending", and if my system is set such that if I do not explicitly specify a state, it will return all "approved":
GET /persons - gets all approved persons, because defaults to state=approved
GET /persons?state=approved - same thing, gets all approved persons
GET /persons?state=pending - gets all pending persons
How do I get all persons? What if there are 10 possible states? Or 100?
I can think of a few ways:
GET /persons?state=any - but then I can never use the actual state any
GET /persons?state=* - would work, but feels strange? Or is it?
GET /persons?state= - some URL parsing libraries would complain about a blank query parameter, and does this not imply "state is empty" as opposed to "state is anything"?
How do I say in my GET, "override the default for the state to be anything"?
Maybe this could work for you:
GET /persons?state - gets all persons that have a state name, no matter which value
GET /persons?state= - gets all persons that have an empty value for the state name
You probably don’t need to differentiate between these two situations, so you could use either one for getting all persons with the state name (I just think that the variant without = is more beautiful).
FWIW, the application/x-www-form-urlencoded format (i.e., typically used in HTML forms) doesn’t differ between an empty and no value.
As far as the URI standard is concerned, this name-value pair syntax in the query component is only a convention anyway, so you can use whichever syntax/semantics you wish.
I don't think there is one answer to this question. As long as you document that the default state is approved well I don't think it matter to the clients if you pass any, * etc. All of your proposals are fine except the last one. I don't think that is a good one.
If I was designing the API I would use all and keep this as a standard. I would also recommend to use paging for all endpoints that returns list of elements. I use offset and limit as paging query parameters. In my API I return 20 elements as default if the client haven't specified another paging criteria.
imagine a very simple flow with a HTTP inbound and a body-to-parameter-map. Payload contains something like {prop1=aaa, prop2=eee, prop3=iii}.
My question is, why if I try to access #[payload.prop1] sometimes (and I said sometimes) it gets null value, while #[payload['prop1']] seems to be allways correct?
Those are equivalent, the only different would be that the dot notation also support objects while the key one only support collections.
It's perhaps that the you are using the dot notation with keys that already contain a dot? Like http.status. In those cases you should either escape with 'http.status'.
I am new to REST and have some trouble finding the proper RESTful url for an API.
I have an API that, given a word, returns a JSON with a boolean that indicates if the word is a verb or not. So in a not restful universe, this API would be a isVerb method. I am having trouble with finding a proper RESTful noun for the url of my API (as verbs are not allowed in REST).
I already have an API that given a string returns the verbs in that string (the actual GET /verbs) so the option myapi.com/verbs is not possible (and wouldn't be 100% right for my problem, as I am not getting verbs, but getting a boolean).
Any hints? Thanks a lot!
If I understand you correctly, there are two use-cases:
1) Extracting verbs from a string and
2) Test if a word is a verb.
Here is how I would decompose the problem:
A) You have two inputs, a string and a word; but both can be abstracted out just as an array of words,
a strings = [‘word1’, ‘word2’, …]
B) To think of “/verbs/” as a space for all verbs
Then the problem becomes to just get a set of verbs out of the ‘virtual’ verbs space in ‘/verbs/’ by providing inputs (a string of words).
The API to access '/verbs/'could be in two forms:
A) GET /verbs/?text=‘word’,…
Return: OK with the subset of text that are verb
Return: Not found
B) GET /verbs/{word}/
Return: OK with the ‘word’ if it is a verb
Return: Not found
In my opinion '/verbs' path is very good in this scenario. But if it already has been taken consider something similar, for example: '/verbsResource', '/versSet', ...
This service will return (for GET request):
status code HTTP 200 OK when given string is a verb;
status code HTTP 404 Not Found when given string is NOT a verb.
So there are no boolean values.
Imagine you have a function that converts ints to roman string:
public String roman(int)
Only numbers from 1 to 3999 (inclusive) are valid for conversion.
So what do you do if someone passes 4000 in any OO language?
raise an exception
return “” or some other special string
write an assert
…
Number 1: raise an exception. That's what ArgumentOutOfRangeException is for (at least in .NET):
if (intToConvert >= 4000)
{
throw new ArgumentOutOfRangeException("intToConvert ", "Only numbers 1-3000 are valid for conversion.");
}
I find the validation topic very interesting in general. In my opinion option 2 (returning a special value) is not a good one, since you are forcing the client to do if/case to check for the returned value and that code must be repeated everywhere. Also, unlike exceptions that propagate through the calling stack, in this scenario the caller is almost always the one that has to handle that special value.
In the context of OOP raising an exception or having an assertion is, IMO, a more elegant way to cope with it. However i find that inlining verification code in every method doesn't scale well for some reasons:
Many times your validation logic ends up being greater than the method logic itself, so you end up cluttering your code with things that are not entirely relevant to it.
There is no proper validation code reuse (e.g. range validation, e-mail validation, etc).
This one depends on your tastes, but you will be doing defensive programming.
Some years ago I attended to a talk about validators (a similar talk slide's are here. The document explaining it used to be in http://www.caesarsystems.com/resources/caesarsystems/files/Extreme_Validation.pdf but now its a 404 :( ) and totally like the concept. IMHO having a validation framework that adopts the OO philosophy is the way to go. In case you want to read about it I've written a couple of posts about it here and here (disclaimer: the posts are part of the blog of the company I work for).
HTH