query parameter books accepts an array of enum values. Is there a way I can give 400 bad request if a particular combination of values is received? - api

books?:
type: array
items:
enum: [a,b,c,d]
Let's say I want to give a bad request whenever b,c come together. Eg:
[a,b,c,d] -> invalid request
[a,b,c] -> invalid request
[b,c] -> invalid
In short, if a request has both b & c together, can 400 be displayed using RAML ?

You can declare different types of valid combinations and then use them as possible input types.
Something like:
types:
validCombinationA:
type: array
items:
enum:
- a
- b
- d
validCombinationB:
type: array
items:
enum:
- a
- c
- d
And then:
books?:
type: validCombinationA | validCombinationB
That way is going to fail whenever you use an invalid combination.
If the valid combinations are static and the probability of new future values is small, then it's not a big deal using this approach but if that's not the case, you will need to create X number of types for each valid combination.
Maybe it worths a thought of consideration look for other possibilities for your use case (eg: with OAS that can be done with the usage of elements such as oneOf, anyOf, allOf, not).
If the validation is quite simple, then I'd prefer to do it that way instead of using the Validation Module or something else inside a flow given that probably has an impact on performance (do some quick tests to verify it).

That's not possible. RAML is not expected to be used to define data validation. RAML only define validations of types and the structure of requests. You need to implement that kind of rule in the implementation of the API. In this particular case it seems that you are using Mule to implement the API. Inside the Mule application project you need to perform the validation in the flows.

Related

Karate: Store result of a contains check into a variable OR define contains X || Y [duplicate]

Find the example here.
def a = condition ? " karate match statement " : "karate match statement"
Is it possible to do something like this??
This is not recommended practice for tests because tests should be deterministic.
The right thing to do is:
craft your request so that the response is 100% predictable. do not worry about code-duplication, this is sometimes necessary for tests
ignore the dynamic data if it is not relevant to the Scenario
use conditional logic to set "expected value" variables instead of complicating your match logic
use self-validation expressions or schema-validation expressions for specific parts of the JSON
use the if keyword and call a second feature file - or you can even set the name of the file to call dynamically via a variable
in some cases karate.abort() can be used to conditionally skip / exit early
That said, if you really insist on doing this in the same flow, Karate allows you to do a match via JS in 0.9.6.RC4 onwards.
See this thread for details: https://github.com/intuit/karate/issues/1202#issuecomment-653632397
The result of karate.match() will return a JSON in the form { pass: '#boolean', message: '#string' }
If none of the above options work - that means you are doing something really complicated, so write Java interop / code to handle this

Deserializing tuples with argument in Rust

I am a beginner in rust and working with some api that returns bytes that I can deserialize by defining their types.
result: (f64, f64, f64) = api.call();
Can I do the same by dynamically by passing a value n for the number of elements?
All elements of the tuple are of the same type. I would like to do something like this:
result: tuple(f64, 3) = api.call();
Here is the API of the call function.
Edit:
In case anyone ever encounters that issue in the future. I could deserialize the output by adopting this solution.
For reference: call() returns a Result<D: Detokenize, _>. Detokenize is mainly implemented for all T that implement Tokenizable.
All types that can receive the result are listed here.
Note that additional to tuples of various size, it's also implemented for:
impl<T: TokenizableItem + Clone, const N: usize> Tokenizable for [T; N]
Further, note that it is an async function with a Result, meaning you have to await it and deal with the potential error.
So you should(tm) be able to write:
result: [f64; 3] = api.call().await.unwrap();
Of course in a real project I would advise to replace unwrap() with some proper error handling.
Disclaimer: I don't know how to use the rest of ethers-core, so I'm unable to verify this in a test project. This information is purely derived from the documentation.
Static vs dynamic size
[f64; 3] requires you to know the number of elements at compile time.
Note that another Tokenizable is Vec<T>, meaning you could also specify Vec<T> as a result type. The length of this one will then be resolved at runtime, depending on how many elements of T the api.call() returns.
Further background information
Note that there is no such thing as a tuple that has N number of T elements, because a tuple is not a repetition of one type, it's a collection of types. Every element of a tuple can have a different type.
If you want to represent a repetition of one type, an array is what you really want. It's defined as one type T repeated N times: [T; N].

References to IDs in APIs responses, null or 0?

I consider myself that 0 is not a good thing to do when returning information from an API
e.g.
{
userId: int|null
}
I have a colleague that insists in that userId should be 0 or -1, but that forces a system to know that the 0 means "not set", instead of null which is universally known as not set.
The same happens with string params, like logoUrl. However, in this case I think it is acceptable to have an empty string instead of null if the variable is not set or was unset.
Is there bibliography, standards, etc, that I can refer to?
I'm not aware of any standard around that, but the way I take those kind of decisions is by thinking about the way consumer services would read this response, the goal being to provide a very smooth and clean consuming workflow. This exercise can even be transformed into a documentation for your API consumers.
In your case, instead of returning a null/0 field, I would simply remove that field altogether when it's empty and let the consumers explicitly mark that field as optional in the model they use to deserialize this response.
In that way, they'll explicitly have to deal with those optional fields, than relying on the API to always provide a value for them.

Where to validate parameters sent to an API?

In which place is best practice to validate parameters sent by the user in an API design? By parameter validation I refer to: checking required params are sent, ensure they have correct format and so... Here are a couple of simple examples that validate an id has been sent. It is Python using Flask to illustrate:
A) Add validation logic in the route definition, within the controller.
#api.route('/job', methods=['GET'])
def get_jobs():
try:
if params["id"] is None:
raise Exception("Invalid param ID parameters.")
job = job_manager.get_job(params["id"])
return jsonify(job)
B) In the core of the app. This is the business layer, where logic is applied to transform data.
class JobManager:
def get_job(self, job_id) -> None:
if job_id is None:
raise Exception("Invalid param ID parameters.")
In more complex scenarios a validator service or decorators could be used, but the question would be the same: At which point of the code is best practice to validate a user's input.
If the answer is none of the scenarios above (or both), please provide more details on your answer. If possible, try to be language agnostic as I'm looking for a best practice that can be applied anywhere.
Parsing, as a rule, should happen at the point where information enters your system, or as close to that point as is practical.
Therefore certainly "application layer" rather than "domain layer/business layer": either invoked by the controller itself, or very close to it. (Not typically "in" the controller, because you should be able to test the parser without being coupled to a bunch of HTTP ceremony.)
#api.route('/job', methods=['GET'])
def get_jobs():
try:
job_id = parse_job_id(params["id"])
job = job_manager.get_job(job_id)
return jsonify(job)
In typed languages, this can make your life a lot easier, because you greatly reduce the number of places you have to ask "does this general purpose data structure have the information I expect?"
Checks against business policy, on the other hand, normally belong in the domain layer.
For example: if your API requires a date, the checks that the date is actually present, and that the date is represented in the appropriate ISO-8601 format, and so on... these kinds of checks all happen as part of the parsing of the input by the controller.
On the other hand, checking that the date is "in the future", or that the date is within warranty, or ... these are checks that belong in your domain code.
Generally, I split validation into phases:
Immediate syntax validation of input data in the REST controller
Business-logic validation in the services
The first validation should only flag things that are definitely wrong; e.g. missing required fields, type mismatch, unparsable strings, any attempts of code injection and the presence (or lack of) of security tokens.
When this validation passes, the input data is at least syntactically correct and may be passed on to the services, where a more strict validation occurs; i.e. does the input data make sense business-wise, does the resource with that ID exist - and so on.
Short version: The first validation looks for things that are obviously wrong, while the following validation ensures input data is correct and meaningful business-wise.

Use encoded object query param for GET request

While designing the API with with the team a suggestion was forwarded in regards to some complex query parameters that we sent which need to be encoded as objects, arrays of objects, etc. Suppose I have a route GET /resource/ and I want to apply a set of filters directly in the query params. The object literal structure of this filter would be something like
filter: {
field1: {
contains: 'value',
notin: ['value2', 'value3']
},
field2: {
greaterThan: 10
}
}
Encoding this in the url, via a query string parser such as the qs node module that express.js uses internally, would be cheap on the backend. However 1) The generated url is very hard to read, if a client wants to connect with the API he would need to use an encoding library and 2) I don't think I ever encountered the use of query params like this, it looks a little bit of overengineered and I'm not sure how used it is and if it is really safe.
The example above would yield query params such as:
GET /resource/?field1%5Bcontains%5D=value&field1%5Bnotin%5D%5B0%5D=value2&field1%5Bnotin%5D%5B1%5D=value3&field2%5BgreaterThan%5D=10
Does this practice of sending url query parameters that happen to be complex objects have some standards or best practices?
We implemented a different solution for filtering, when the list of possible parameters was very long. We ended up doing it in two steps, posting the filter and returning a filter ID. The filter ID could then be used in the GET query.
We had trouble finding any best practices for this.